Algoritmo per risolvere il "problema di arresto" di Turing


23

"Alan Turing ha dimostrato nel 1936 che un algoritmo generale per risolvere il problema di arresto per tutte le possibili coppie di input del programma non può esistere"

Posso trovare un algoritmo generale per risolvere il problema di arresto per alcune possibili coppie di input del programma?

Posso trovare un linguaggio di programmazione (o lingue), in cui per ogni tipo di programma in questo linguaggio, posso decidere se il programma termina o funziona per sempre?



3
CACM ha pubblicato un articolo molto interessante a maggio: Proving Termination Program
Christoph Walesch,

3
"un algoritmo generale [...] per alcune possibili coppie di input di programma" - che è quasi contraddittorio. Immagino che tu voglia limitarti a una sottoclasse infinita di tutti i programmi?
Raffaello

Risposte:


25

Posso trovare un algoritmo generale per risolvere il problema di arresto per alcune possibili coppie di input del programma?

Si certo. Ad esempio, potresti scrivere un algoritmo che restituisce "Sì, termina" per qualsiasi programma che non contiene né loop né ricorsione e "No, non termina" per qualsiasi programma che contenga un while(true)loop che sarà sicuramente raggiunto e non contiene una dichiarazione di rottura, e "Non lo so" per tutto il resto.

Posso trovare un linguaggio di programmazione (o lingue), in cui per ogni tipo di programma in questo linguaggio, posso decidere se il programma termina o funziona per sempre?

Non se quella lingua è completa di Turing, no.

Tuttavia ci sono linguaggi completi non Turing come ad esempio Coq , Agda o Microsoft Dafny per i quali il problema Halting è decidibile (e in effetti è deciso dai rispettivi sistemi di tipo, rendendoli linguaggi totali (cioè un programma che potrebbe non terminare non lo farà compilare)).


1
La classe delle funzioni primitive-ricorsive è un noto "linguaggio di programmazione" per il quale il problema dell'arresto è banalmente decidibile.
Raffaello

Esistono diversi linguaggi di " programmazione funzionale totale " in cui tutti i programmi stanno terminando in modo dimostrabile.
Anderson Green,

3

Penso che tutte le risposte qui mancino completamente e completamente il punto. La risposta alla domanda è: supponendo che il programma sia destinato a fermarsi, quindi sì, è meglio essere in grado di mostrarlo. Se non riesci a mostrare che si arresta facilmente, il programma dovrebbe essere considerato molto male scritto e rifiutato dal controllo di qualità in quanto tale.

Il fatto che tu possa effettivamente scrivere un algoritmo di macchina adatto dipende dal linguaggio di programmazione di input e da quanto sei ambizioso. È un ragionevole obiettivo di progettazione per un linguaggio di programmazione rendere facilmente possibile la risoluzione.

Se il linguaggio è C ++ probabilmente non puoi scrivere lo strumento, anzi è improbabile che tu avresti mai avviato il parser, figuriamoci provare la fine. Per un linguaggio meglio strutturato, dovresti essere in grado di generare una prova, o almeno farlo con determinati presupposti: in quest'ultimo caso lo strumento dovrebbe produrre questi presupposti. Un approccio simile sarebbe quello di includere asserzioni di terminazione nella lingua e usarle in situazioni complesse in cui lo strumento si fiderebbe delle asserzioni.

La linea di fondo è che nessuno sembra capire che la prova che un programma si interrompe è davvero possibile perché i (buoni) programmatori che intendono scrivere tali programmi di arresto lo fanno sempre intenzionalmente e con un quadro mentale del motivo per cui terminano e agiscono correttamente: tale codice è deliberatamente scritto quindi è chiaro che si fermano e sono corretti e se un algoritmo ragionevole non può dimostrarlo, possibilmente con alcuni suggerimenti, il programma dovrebbe essere respinto.

Il punto: i programmatori non scrivono programmi arbitrari, quindi la tesi del teorema di arresto non è soddisfatta e la conclusione non si applica.


4
Penso che sei tu che hai completamente e completamente perso il punto. Il primo paragrafo della tua risposta non si applica alla domanda perché si tratta di algoritmi, non di ciò che un essere umano può o non può provare. Il resto della risposta risponde al primo paragrafo della domanda, ovvero se un algoritmo potrebbe provare la chiusura di alcuni programmi. Tutte le risposte precedenti hanno già detto "sì" a quella.
sepp2k,

3
La tua affermazione che è possibile scrivere un algoritmo in grado di provare la chiusura di ogni programma ben scritto in un linguaggio Turing sufficientemente semplice è completamente falsa. Per ogni possibile algoritmo che tenta di provare la terminazione, ci sono problemi in cui ogni programma che risolve quel problema non può essere fermato da quell'algoritmo. Quindi, a meno che tu non stia dicendo che ogni programma che risolve quel problema è scritto male per definizione (il che sarebbe ridicolo), ciò smentisce il tuo punto.
sepp2k,

1
@Sam Se qualcuno mi chiede se un po 'di codice si ferma, guarderò il codice e cercherò di capirlo. Ma non sono un algoritmo. E sì, è possibile scrivere un algoritmo in grado di verificare se un programma si arresta per molti programmi. Ma non è quello che ha detto Yttrill. Yttrill ha detto che è possibile per tutti i programmi ben scritti. E come ho detto nel mio commento precedente, questo è semplicemente falso a meno che non affermi che alcuni problemi possono essere risolti solo con programmi scritti male (che di nuovo sarebbe ridicolo).
sepp2k,

1
@Sam "Mi sembra chiaro che i programmi scritti intenzionalmente per arrestare possano essere facilmente analizzati per arrestare le condizioni" - se così fosse, perché non abbiamo tali strumenti? Non è come se la gente non ci provasse. (Un colpevole è l'override del metodo: al momento della compilazione, non si conosce tutto il codice che verrà eseguito.)
Raffaello

1
@Sam "c'è un ciclo infinito" è una cosa difficile da affrontare, anche per il ciclo del mondo reale. Naturalmente mi è stato insegnato come trovare gli invarianti di loop, ma ciò non significa che riesco a trovarne uno (facilmente) in molti casi. Per quanto ne so, indovinare e dimostrare è il gold standard in questi giorni. Anche in questo caso, se non ci fossero gli algoritmi ragionevolmente generali, mi aspetterei loro di essere inclusi nelle principali compila o IDE (che fanno eseguire alcune banali, controlli sintattici). Puoi dare un riferimento a un algoritmo ragionevolmente forte?
Raffaello

3

domanda eccellente e (probabilmente involontariamente profonda). ci sono davvero programmi di arresto-rilevazione che possono avere successo su insiemi limitati di input. è un'area attiva di ricerca. ha legami molto stretti con le aree di prova del teorema (automatizzato).

tuttavia l'informatica non sembra avere un termine esatto per "programmi" che "a volte" hanno successo. la parola "algoritmo" è di solito riservata ai programmi che si fermano sempre.

il concetto sembra essere nettamente diverso dagli algoritmi probabilistici in cui i teorici del CS insistono che ci sono alcune probabilità note o calcolabili sul loro successo.

esiste un termine semialgoritmi che viene talvolta utilizzato ma apparentemente sinonimo di enumerazione ricorsiva o non calcolabile.

quindi ai fini qui, chiamali quasialgorithms . il concetto è diverso da decidibile vs indecidibile.

si potrebbe dire che non si possono confrontare i quasialgoritmi. ma in effetti sembra esserci una gerarchia naturale (un ordinamento parziale) di questi algoritmi quasialistici. Supponiamo che un quasialgorithm grado di rilevare arresto di un insieme limitato di programmi di ingresso dicono X . altro B può rilevare arresto di un insieme Y . se X Y, ovvero X è un sottoinsieme proprio di Y, allora B è "più potente" di AUNXBYXYXYBUN .

in CS questa "gerarchia quasi algoritmica" sembra essere stata studiata principalmente finora solo in modo informale.

si presenta nella ricerca di castori indaffarati [1] e nel problema PCP [2]. in effetti un attacco informatico basato su DNA su PCP può essere visto come un quasialgorithm. [3] e si vede in altre aree già notate come dimostrazione del teorema [4].

[1] Nuovo attacco millenario al problema del castoro indaffarato

[2] Affrontare il problema di corrispondenza dei messaggi di Zhao (v2?)

[3] Usare il DNA per risolvere il problema della corrispondenza posta vincolata di Kari et al

[4] prova del termine del programma di Cook et al, Comm. dell'ACM

(quindi questa è in realtà una domanda molto profonda che sicuramente merita di essere su ims TCS.SE ... forse qualcuno può chiedere di nuovo lì in modo tale che si adatti e rimanga)


ps come esempio impressionante di quanto possano essere potenti i quasialgoritmi, l'ACM afferma che la funzione ackermanns può essere fermata da un quasialgoritmo, ma è più grande di (non calcolabile da) tutte le primitive funzioni ricorsive.
vzn

1
"la parola" algoritmo "è di solito riservata ai programmi che si fermano sempre". - Non sono sicuro che sia vero. Ci sono molti algoritmi parzialmente terminanti in giro (specialmente nella verifica) e non ho mai sentito nessuno non dire "algoritmo".
Raffaello

ci sono usi informali di "algoritmo". "parzialmente terminato" è ok ma probabilmente nonstd. come detto, non sembra esserci ancora un termine standardizzato. wikipedia definisce un algoritmo come un metodo efficace, cioè decidibile con le seguenti caratteristiche (1) sempre dare una risposta piuttosto che non dare mai una risposta; (2) dare sempre la risposta giusta e mai dare una risposta sbagliata; (3) essere sempre completato in un numero finito di passaggi, piuttosto che in un numero infinito; (4) lavorare per tutti i casi di problemi della classe.
vzn

e poi più avanti nello stesso articolo dice "Un'ulteriore spiegazione del termine" metodo efficace "può includere il requisito che, quando viene dato un problema al di fuori della classe per la quale il metodo è efficace, il metodo può arrestarsi o scorrere per sempre senza arrestarsi , ma non deve restituire un risultato come se fosse la risposta al problema. " cioè quasi si contraddice!?! così chiaramente, notevolmente, c'è una certa confusione sulla questione chiave e la terminologia esistente non è rigorosa. nota che la parola "algoritmo" è vicina a più di un millennio circa e si è sostanzialmente spostata ....
vzn

È vero: il significato tradizionale è probabilmente "metodo efficace" nel modo in cui Wikipedia dice (non c'è contraddizione nella frase che citi; è un po 'poco chiaro, però) - le persone non hanno concepito funzioni / algoritmi che non sono terminati (per alcuni input). Penso che questo sia cambiato dagli anni '50; come ho detto, oggi la gente chiama chiaramente un algoritmo "parzialmente terminante".
Raffaello

2

Finché il linguaggio di programmazione in questione è sufficientemente complesso (cioè se è Turing completo), allora ci sono sempre programmi nella lingua che nessun programma può provare a terminare.

Dal momento che tutte le lingue tranne quelle primitive sono Turing complete (ci vogliono solo variabili e condizioni), potresti davvero costruire solo linguaggi giocattolo molto piccoli per i quali potresti risolvere il problema di arresto.

Modificare: luce dei commenti, vorrei essere più esplicito: qualsiasi linguaggio che potresti progettare per il quale potresti risolvere il problema di arresto dovrebbe necessariamente essere Turing incompleto. Questo esclude qualsiasi linguaggio che contenga un insieme adatto di ingredienti di base (ad esempio "variabili, condizionali e salti", o come dice @ sepp2k, un generico "while" -loop).

Apparentemente esistono diversi linguaggi "semplici" pratici come quello (ad esempio solutori di teoremi come Coq e Agda). Se soddisfano la tua nozione di "linguaggio di programmazione", potresti verificare se soddisfano una sorta di completezza o se il problema dell'arresto è risolvibile per loro.


3
"Dal momento che tutti i linguaggi primitivi, tranne quelli primitivi, sono completi di Turing (ci vogliono solo qualcosa come variabili e condizionali)" Non è vero. Prima di tutto avresti almeno bisogno di ricorsione o di qualche forma di costrutto per il loop (che dovrebbe essere potente come un ciclo while - un semplice conteggio non è sufficiente). In secondo luogo, non penso che ci siano molte persone che chiamerebbero lingue primitive o giocattolo come lingue Coq o Agda (che sono totali e quindi non turing complete).
sepp2k,

@ sepp2k: bene sì. Anche l'aritmetica di Peano è abbastanza utile e non completa di Turing. Un'affermazione semplificata, suppongo. Se l'OP è sufficientemente a conoscenza del problema, si spera che sarà in grado di compilare i dettagli tecnici.

3
C'è un enorme divario tra l'essere "sufficientemente complesso" e l'essere completo di Turing. Coq è davvero complesso ed è adatto per una vasta gamma di compiti pratici.

1
@Kerrek SB Beh, è ​​possibile che il linguaggio completo di Turing sia usato in modi che possono essere dimostrati fino alla fine. Se puoi provare che una formula ricorsiva si avvicina sempre alla sua condizione terminale (come la funzione fattoriale), potresti provare che termina anche se non saresti in grado di gestire ogni tipo di ricorsione.

@ArtB: Certo, ci sono sempre alcuni programmi che possono essere provati per terminare. La prima domanda del PO potrebbe suggerire ciò, anche se non sono sicuro di seguirlo fino in fondo. Per esempio, non si poteva avere un "algoritmo generico" che determina se un dato famiglia di programmi termina, mentre al contrario si potrebbe probabilmente costruire una famiglia ristretta di funzioni tale da assumere una funzione appartiene a quella famiglia, si potrebbe dire che si tratti algoritmicamente termina. (Non sono sicuro che quella famiglia possa essere non banale, però. Immagino che possa, ma non posso fare un esempio.)

2

TT

Questo è abbastanza banale. Se prendiamo l'unione di un sottoinsieme ce di TM di arresto e di un sottoinsieme ce di TM di non arresto, il risultato sarà impostato di TM per i quali il problema di arresto è decidibile (eseguiamo entrambe le macchine in parallelo, se il primo accetta il TM si ferma, se il secondo accetta, la macchina non si ferma). Tuttavia, ciò non porterà a lingue molto interessanti.

ALogTimecM


1

Sì, puoi, ma dubito che sarà utile. Probabilmente dovresti fare l'analisi del caso e poi potresti solo cercare i casi più ovvi. Ad esempio, potresti grep un file per il codice while(true){}. Se il file ha quel codice, non terminerà mai ^. Più in generale si potrebbe dire che un programma senza loop o ricorsione terminerà sempre e ci sono diversi casi che si potrebbero fare che potrebbero garantire che un programma terminerà o meno, ma anche per un programma di medie dimensioni sarebbe molto difficile e in molti casi non sarebbe in grado di darti una risposta.

tl; dr: Sì, ma non sarai in grado di renderlo utile per i programmi più utili.


^ Sì, tecnicamente se quel codice non è sul percorso del codice o ci sono altri thread che potrebbe ancora terminare, ma sto facendo un punto generale qui.


4
Perché pensi che Coq e Agda non siano utili? Stai sopravvalutando il valore della completezza di Turing.

Ho usato Coq, ma la mia affermazione rimane poiché la maggior parte dei software commerciali è scritta in Java / C ++ / Ruby / C # per cui le mie affermazioni sono vere. Il tipo di programmi che il 90% delle persone è interessato a scrivere non gioverebbe. Fondamentalmente, se non conosci Coq / Agda ecc. Non sei il mercato di riferimento per questo.

5
Direi che il 99% dei programmi del mondo reale trarrebbe beneficio dall'attuazione in un sottoinsieme non linguistico di Turing di una lingua. Ad esempio, non implementerai la funzione Ackermann ogni giorno. Il 100% di CRUD non ha bisogno di un linguaggio "reale". L'elaborazione dei dati è quasi sempre banale. Guarda il progetto Terminator - stanno persino servendo un discreto sottoinsieme di possibili programmi C ++, che è più che sufficiente per le cose del mondo reale (inclusi driver e altri codici di basso livello).

La maggior parte dei progetti del mondo reale vuole riutilizzare le librerie scritte in lingue complete di Turing e utilizzare i loro IDE, debugger ed esercitazioni. Sì, potresti realizzare cose in lingue diverse da Turing, ma non riesco a immaginare che qualcuno stia effettivamente dicendo "Voglio fare X" e la mia risposta è "Usa Coq". grazie per avermi presentato a The Terminator Project .

4
una parte inimmaginabilmente enorme della logica aziendale è già implementata in un SQL non completo di Turing. E DSL e eDSL sono in aumento ora. Quindi, presto la maggior parte dei programmatori di app aziendali dimenticherà tutte le lingue "per scopi generali".
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.