Durezza computazionale di programmi per computer "reali"


10

Ho sentito spesso dire che non è possibile scrivere un programma per rilevare bug in un browser Web, elaboratore di testi o sistema operativo, a causa del teorema di Rice: qualsiasi proprietà semantica per un linguaggio completo di Turing è indecidibile.

Tuttavia, non sono sicuro fino a che punto questo si applichi ai programmi operativi come i programmi del mondo reale. Questi tipi di programmi necessitano della piena forza della completezza di Turing? Esistono modelli più semplici di calcolo (come PR) in cui è possibile scrivere queste applicazioni? In tal caso, in che misura ciò consente la decidibilità della correttezza del programma?


non è possibile controllare proprietà universali non banali (ad es. qualcosa vale per tutti gli input) di modelli molto più deboli, ad esempio non è possibile verificare se due TM calcolabili Polytime stanno calcolando la stessa funzione (sebbene l'arresto sia decidibile per loro perché un TM Polytime si ferma sempre). D'altra parte, se il dominio degli input è limitato, è possibile verificare alcune proprietà in alcuni modelli, ad esempio il programma non si arresta in modo anomalo su input di dimensioni inferiori a 1.000, almeno in teoria (in pratica potrebbe essere intrattabile).
Kaveh,

Risposte:


14

Sicuramente puoi scrivere programmi che catturano i bug: esiste una comunità ampia e attiva di persone che scrivono programmi per fare esattamente questo. Tuttavia, ciò che il teorema di Rice ti impedisce di scrivere è quello di scrivere acchiappasogni che siano allo stesso tempo sani e completi (cioè, cattura tutti i bug di una certa classe senza falsi positivi).

Detto questo, ingenui limiti al modello di calcolo non ti aiutano molto a migliorare la praticità dell'analisi del programma. Il motivo è che è possibile ottenere programmi che "fanno quasi la stessa cosa" girando mentre sono in loop

while P do 
   C

in for-loop con una grande costante di iterazione:

for i = 0 to BIGNUM do 
  if P then 
    C
  else
    break

Ora questo programma non ha nemmeno bisogno di tutta la forza del ricorsivo primitivo (dal momento che il for-loop può essere espanso in macro in un'enorme istruzione if-then-else nidificata), ma nella maggior parte dei casi pratici si comporterà esattamente come prima. Nota che in teoria aiuta la decidibilità: il programma è totale, quindi puoi rispondere alle domande eseguendo il programma e vedendo cosa succede. Questo non è ciò che vogliamo effettivamente, ovvero ottenere risposte più velocemente dell'esecuzione del programma: la terminazione artificiale introdotta non aiuta in realtà l'analisi del programma in pratica, poiché i bug si verificano a causa di errori nella logica del programma reale e non abbiamo " Non l'ho toccato affatto.

Inoltre, l'aggiunta di strutture di astrazione a un linguaggio di programmazione può peggiorare radicalmente la complessità del problema di analisi, facilitando nel contempo la verifica pratica dei programmi. Ad esempio, la dimostrazione della terminazione del calcolo lambda tipizzato in modo semplice con numeri naturali richiede l'induzione fino a , ma aggiungendo il polimorfismo del tipo si ottiene il Sistema F, la cui prova di terminazione è forte quanto la coerenza dell'aritmetica di secondo ordine. Tuttavia, in pratica i programmi scritti in F sono molto più facili da verificare, poiché le proprietà di modularità della quantificazione del secondo ordine rendono molto più semplice la scrittura di programmi strutturati e prove di correttezza.ε0


Cosa intendi con "questo programma non è nemmeno ricorsivo primitivo"?
Ryan Williams,

@RyanWilliams probabilmente solo che può essere scritto in un sistema che consente meno dell'intera gamma di funzioni ricorsive primitive, ad esempio programmi che richiedono limiti espliciti (tempo di compilazione) sui loop.
cody,

Puoi espandere macro i loop, lasciandoti con un programma di ramificazione (cioè con solo if-then-else e composizione sequenziale).
Neel Krishnaswami,

Forse sarebbe più chiaro dire qualcosa del tipo "questo programma non ha nemmeno bisogno della piena forza della ricorsione primitiva".
Max

@Max: suggerimento accettato!
Neel Krishnaswami,

5

Dato che hai chiesto informazioni sulla correttezza del programma di programmi del mondo reale come i sistemi operativi, potresti essere interessato al progetto seL4 ( journal , pdf , conference ).

Il team NICTA ha preso un microkernel di terza generazione di 8700 linee di C e 600 linee di assemblatore implementate secondo una specifica astratta in Haskell. Hanno fornito una prova formale, controllata a macchina (in Isabelle / HOL) che l'implementazione segue rigorosamente le specifiche. Dimostrando così che il loro programma è privo di bug.

Quindi, proprio come il problema di arresto, anche se non può essere risolto in generale, può essere risolto per alcuni casi specifici. In questo caso, sebbene non sia possibile dimostrare che il codice C arbitrario sia privo di bug, potrebbero farlo nel caso del microkernel seL4.


Nota che il codice certificato è ancora vulnerabile agli errori nelle sue specifiche, quindi puoi solo dire che il codice è privo di bug relativamente alla specifica.
nponeccop,

@nponeccop è sicuramente vero, ma quando inizi a dubitare delle specifiche, inizierai anche a confondere la famigerata linea di bug. Per chiamare qualcosa un 'bug' devi avere in mente alcune specifiche implicite, catturare l'intuizione dietro una specifica così implicita inizia a scavare molto in profondità fino a quando non si toccano le domande alla base della filosofia della matematica (nello stile di Brouwer vs. Hilbert) .
Artem Kaznatcheev

Per "specifica" intendevo la specifica formale, cioè i teoremi formali che dimostrate. Potresti ancora fare errori nel trasformare i tuoi requisiti testuali in teoremi. Le uniche cose che ottieni con la certificazione sono la riduzione della tua base di codice attendibile (dovresti fidarti solo dei tuoi teoremi e non del tuo codice o delle tue prove) e della coerenza del tuo codice con i tuoi teoremi.
nponeccop,

Ecco una citazione dal sito web seL4: "Il codice C del microkernel seL4 implementa correttamente il comportamento descritto nelle sue specifiche astratte e niente di più".
nponeccop,

2

Le domande che fai sono in realtà abbastanza diverse.

Tuttavia, non sono sicuro fino a che punto questo si applichi ai programmi operativi come i programmi del mondo reale. Questi tipi di programmi necessitano della piena forza della completezza di Turing?

Ci vuole davvero poco perché un modello di calcolo sia completo di Turing. Ad esempio, vari modelli con contatori possono simulare le macchine di Turing. Se ritieni che il tuo software richieda più di due contatori che puoi manipolare arbitrariamente, stai usando un linguaggio completo Turing. Sebbene i numeri interi di macchina siano limitati ad apriori, le strutture dati allocate in heap di solito non lo sono. Se il tuo software necessita di elenchi, alberi e altri dati allocati dinamicamente, stai utilizzando un linguaggio completo Turing.

Esistono modelli più semplici di calcolo (come PR) in cui è possibile scrivere queste applicazioni? In tal caso, in che misura ciò consente la decidibilità della correttezza del programma?

È importante riconoscere che non vogliamo controllare le proprietà arbitrarie del nostro software. Il controllo di proprietà molto specifiche e ristrette (nessun overflow del buffer, nessuna dereferenza con puntatore nullo, nessun loop infinito, ecc.) Migliora immensamente la qualità e l'usabilità del software. In teoria, tali problemi sono ancora indecidibili. In pratica, concentrarsi su proprietà specifiche ci consente di scoprire la struttura dei nostri programmi che spesso possiamo sfruttare per risolvere il problema.

In particolare, è possibile modificare la domanda originale in

Esiste un'astrazione del mio software che posso analizzare in modo efficiente in un modello completo senza Turing?

Un'astrazione è un modello che include il comportamento del software originale e probabilmente molti altri comportamenti. Esistono modelli come macchine a un contatore o sistemi pushdown che non sono completi di Turing e che possiamo analizzare. L'approccio standard nella verifica del programma con strumenti automatizzati consiste nel costruire un'astrazione in un tale modello e verificarlo algoritmicamente.

Ci sono applicazioni in cui le persone si preoccupano delle proprietà sofisticate del loro hardware o software. Le aziende produttrici di hardware desiderano che i loro chip implementino correttamente algoritmi aritmetici, le aziende automobilistiche e avioniche desiderano software correttamente certi. Se è così importante, è meglio usare un essere umano (addestrato).


Penso che tu abbia risposto alla domanda opposta, vale a dire è possibile che un elaboratore di testi sia Turing completo? Con un'adeguata gestione dei registri, lo è. Tuttavia, è possibile imporre regole di manipolazione dei registri per sconfiggere la completezza di Turing. La mia domanda è quanto puoi programmare praticamente in questi vincoli ristretti.
David Harris,

Stavo rispondendo alla domanda se scrivere sistemi operativi e altri software applicativi richiedesse un linguaggio di programmazione completo Turing. Se sono necessari più contatori o strutture di dati illimitate, sarà necessario un linguaggio di programmazione completo Turing.
Vijay D,

@Vijay: no, questo non è vero. Esistono molte teorie del tipo (ad esempio, Agda e Coq) che sono entrambe estremamente espressive e non consentono la ricorsione illimitata.
Neel Krishnaswami,

@Neel: Per chiarire, sto solo parlando della completezza di Turing. Non è possibile simulare una macchina di Turing in queste teorie?
Vijay D,

Esatto, non sono completi di Turing. Nella logica costruttiva, la completezza di Turing consente di programmare un analogo del paradosso di Russell.
Neel Krishnaswami,
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.