Profondità contro profonde decorazioni


47

Quando si codifica una logica in un assistente di prova come Coq o Isabelle, è necessario fare una scelta tra l'uso di un incorporamento superficiale e uno profondo . In un incorporamento superficiale le formule logiche sono scritte direttamente nella logica del proverore del teorema, mentre in un incorporamento profondo le formule logiche sono rappresentate come un tipo di dati.

  • Quali sono i vantaggi e i limiti dei vari approcci?
  • Sono disponibili linee guida per determinare quale utilizzare?
  • È possibile passare tra le due rappresentazioni in modo sistematico?

Come motivazione, vorrei codificare varie logiche relative alla sicurezza in Coq e mi chiedo quali siano i pro e i contro dei diversi approcci.

Risposte:


28

Quali sono i vantaggi e i limiti dei vari approcci?

  • Pro di matrimoni profondi: puoi provare e definire le cose inducendo la struttura delle formule. Esempi di interessi sono le dimensioni di una formula.

  • Contro di incorporamenti profondi: hai affrontato esplicitamente l'associazione di variabili. Di solito è molto laborioso.

Sono disponibili linee guida per determinare quale utilizzare?

Gli incastri poco profondi sono molto utili per importare risultati dimostrati nella logica dell'oggetto. Ad esempio, se hai dimostrato qualcosa in una piccola logica (ad esempio la logica di separazione) gli incastri superficiali possono essere uno strumento di scelta per importare il tuo risultato in Coq.

Dall'altro lato, l'incorporamento profondo è quasi obbligatorio quando si desidera dimostrare i meta-teoremi sulla logica dell'oggetto (come l'eliminazione del taglio, ad esempio).

È possibile passare tra le due rappresentazioni in modo sistematico?

L'idea alla base dell'incorporamento superficiale è davvero di lavorare direttamente in un modello delle formule degli oggetti. Di solito le persone mappano direttamente una formula oggetto P (usando le notazioni o eseguendo la traduzione a mano) su un abitante di Prop. Naturalmente, ci sono abitanti di Prop che non possono essere ottenuti incorporando una formula della logica dell'oggetto. Pertanto perdi una sorta di completezza.

Quindi è possibile inviare tutti i risultati ottenuti in un'impostazione di incorporamento profondo tramite una funzione di interpretazione.

Ecco un piccolo esempio di coq:

Formula induttiva: Set: =
    Vero: formula
  | Ffalse: formula
  | Fand: formula -> formula -> formula
  | Per: formula -> formula -> formula.

Fixpoint interpret (F: formula): Prop: = corrisponde a F con 
    Ftrue => True
  | Ffalse => False
  | Fand ab => (interpretare a) / \ (interpretare b)
  | Per ab => (interpretare a) \ / (interpretare b)
 fine.

Derivabile induttivo: formula -> Prop: = 
    deep_axiom: derivable Ftrue
  | deep_and: forall ab, derivable a -> derivable b -> derivable (Fand ab)
  | deep_or1: forall ab, derivabile a -> derivabile (per ab)
  | deep_or2: forall ab, derivabile b -> derivabile (per ab).

Sderivabile induttivo: Prop -> Prop: = 
    shallow_axiom: sderivable True 
  | shallow_and: forall ab, sderivable a -> sderivable b -> sderivable (a / \ b)
  | shallow_or1: forall ab, sderivable a -> sderivable (a \ / b)
  | shallow_or2: forall ab, sderivable b -> sderivable (a \ / b).

(* Puoi provare il seguente lemma: *)
Lemma shallow_deep: 
   forall F, derivable F -> sderivable (interpretare F).

(* NON puoi provare il seguente lemma: *)
Lemma t: 
   forall P, sderivabile P -> esiste F, interpreta F = P.

22

In parole povere, con un profondo incorporamento di una logica, tu (1) definisci un tipo di dati che rappresenta la sintassi per la tua logica, e (2) fornisci un modello della sintassi e (3) dimostra che gli assiomi sulla tua sintassi sono solidi con rispetto al modello. Con un incorporamento superficiale, si saltano i passaggi (1) e (2) e si inizia con un modello e si dimostrano le implicazioni tra le formule. Ciò significa che gli incastri poco profondi di solito sono meno lavori per scendere da terra, poiché rappresentano lavori che in genere finiresti per fare comunque con un radicamento profondo.

Tuttavia, se hai un profondo incorporamento, di solito è più facile scrivere procedure di decisione riflessiva, poiché stai lavorando con formule che in realtà hanno una sintassi su cui puoi ricorrere. Inoltre, se il tuo modello è strano o complicato, di solito non vuoi lavorare direttamente con la semantica. (Ad esempio, se si utilizza la bionegalità per forzare la chiusura ammissibile o si utilizzano modelli in stile Kripke per forzare le proprietà dei frame nelle logiche di separazione o giochi simili.) Tuttavia, gli incorporamenti profondi quasi certamente ti costringeranno a pensare molto al binding e alle sostituzioni variabili , che riempirà il tuo cuore di rabbia, poiché questa è (a) banale e (b) una fonte infinita di fastidio.

La sequenza corretta che dovresti prendere è: (1) prova a cavartela con un incorporamento superficiale. (2) Quando questo si esaurisce, prova a usare tattiche e preventivi per eseguire le procedure decisionali che desideri eseguire. (3) Se anche questo esaurisce il vapore, rinuncia e usa una sintassi tipizzata in modo dipendente per l'incorporamento profondo.

  • Prevedi di prendere un paio di mesi su (3) se è la prima volta che esci. Si avrà bisogno di acquisire familiarità con la fantasia caratteristiche del vostro assistente prova a rimanere sani di mente. (Ma questo è un investimento che pagherà in generale.)
  • Se il tuo assistente di prova non ha tipi dipendenti, resta al livello 2.
  • Se il linguaggio degli oggetti stesso viene tipizzato in modo dipendente, resta al livello 2.

Inoltre, non provare a salire gradualmente sulla scala. Quando decidi di salire la scala della complessità, fai un passo alla volta. Se fai le cose bit per bit, otterrai molti teoremi che sono strani e inutilizzabili (ad esempio, otterrai più sintassi a metà assolo e teoremi che mescolano sintassi e semantica in modi strani), che otterrai alla fine devono buttare via.

EDIT: Ecco un commento che spiega perché salire gradualmente la scala è così allettante e perché porta (in generale) alla sofferenza.

ABIABBA(AB)CA(BC)(IA)(BC)A(B(CI))

Questo è vero e funziona! Tuttavia, si noti che la congiunzione è anche ACUI, così come la disgiunzione. Quindi passerai attraverso lo stesso processo in altre prove, con tipi di dati di elenco diversi, quindi avrai tre sintassi per diversi frammenti di logica di separazione e avrai metateoremi per ciascuno di essi, che sarà inevitabilmente diverso, e ti ritroverai a desiderare un metateorema che hai dimostrato per separare la congiunzione per disgiunzione, e poi vorrai mescolare le sintassi e poi diventerai pazzo.

È meglio prendere di mira il frammento più grande che è possibile gestire con uno sforzo ragionevole e farlo.


Grazie per questa fantastica risposta, Neel. Vorrei poter accettare due risposte (ho deciso in base ai voti degli altri).
Dave Clarke,

Nessun problema. Ho appena ricordato qualcosa che devo aggiungere a questa risposta, sul perché andare in modo incrementale è così allettante.
Neel Krishnaswami,

Trattare con le proprietà ACUI è sempre una seccatura. Perché Coq non può prendere una foglia dal libro di Maude?
Dave Clarke,

14

È importante capire che esiste uno spettro dal profondo al poco profondo. Modellate profondamente le parti del vostro linguaggio che dovrebbero in qualche modo partecipare a qualche argomento induttivo sulla sua costruzione, il resto è meglio lasciarlo nella visione superficiale della semantica diretta del substrato della logica.

Ad esempio, quando si desidera ragionare su Hoare Logic, è possibile modellare il linguaggio delle espressioni in modo superficiale, ma lo schema del linguaggio assegnate if-while dovrebbe essere un tipo di dati concreto. Non è necessario inserire la struttura di x + y o a <b, ma è necessario lavorare con whileecc.

Nelle altre risposte c'erano allusioni a tipi dipendenti. Ciò ricorda l'antico problema di rappresentare le lingue con i raccoglitori in modo sano, in modo che siano il più superficiali possibile, ma ammettano ancora alcuni argomenti induttivi. La mia impressione è che la giuria sia ancora fuori a giudicare tutti i diversi approcci e documenti emersi negli ultimi 10-20 anni su questo argomento. Anche la "sfida POPLmark" per le diverse comunità di assistenti di prova era in qualche modo al riguardo.

Stranamente, nel classico HOL senza tipi dipendenti, l'approccio HOL-nominale di C. Urban ha funzionato abbastanza bene per un legame superficiale, anche se non ha recuperato i cambiamenti culturali in queste comunità di formalizzazione del linguaggio di programmazione.

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.