Stefano M. Nicoletti

Lezione 2: Proposizioni, dimostrazioni e regole logiche

Registrazione video della Lezione 2

1. Scopo della lezione

Questa lezione riprende il ruolo del kernel e del typechecker, poi introduce il modo in cui Lean legge proposizioni e dimostrazioni. Il punto centrale è la corrispondenza tra proposizioni e tipi: una proposizione P : Prop è un tipo, e una dimostrazione di P è un termine che abita quel tipo Theorem Proving in Lean 4, Propositions and Proofs.

Valuteremo esempi minimali per osservare, nel proof state, le regole di introduzione ed eliminazione dei connettivi logici e di alcuni costrutti specifici:

2. Kernel e typechecker

Abbiamo visto che Lean permette di costruire dimostrazioni con tattiche, supporto di librerie, e tramite interfacce interattive. Questi strumenti aiutano l'utente, ma in ultima analisi, il kernel controlla l'oggetto formale prodotto e verifica che abbia il tipo richiesto de Moura and Ullrich, Lean 4.

Il typechecker controlla se un termine ha un certo tipo. Nelle dimostrazioni, il tipo atteso è la proposizione che vogliamo dimostrare. Un teorema viene accettato quando Lean riesce a controllare il termine di dimostrazione rispetto all'enunciato. Per questo, dal punto di vista del sistema, dimostrare significa costruire un termine ben tipato.

Questa prospettiva spiega perché il proof state è così utile. Il goal mostra il tipo che dobbiamo abitare. Le assunzioni mostrano i termini già disponibili nel contesto. Una tattica è un modo interattivo per trasformare questa situazione fino a chiudere tutti i goal.

3. Proposizioni come tipi

In Lean, P : Prop dice che P è una proposizione. Se nel contesto compare hP : P, allora hP è una dimostrazione di P. Non è solo un'etichetta informale: è un oggetto formale che può essere usato per costruire altre dimostrazioni.

L'implicazione è l'esempio più diretto. Un termine di tipo P → Q si comporta come una funzione: prende una dimostrazione di P e restituisce una dimostrazione di Q. Se abbiamo

hPQ : P → Q
hP : P

allora hPQ hP è una dimostrazione di Q.

4. Regole di introduzione ed eliminazione

Per ogni connettivo logico distinguiamo due domande.

Guardare il goal significa chiedersi quale regola di introduzione può costruirlo. Guardare le assunzioni significa chiedersi quale regola di eliminazione può usarle. Questa terminologia segue la presentazione standard delle regole di deduzione naturale Logic and Proof, Natural Deduction Rules.

5. Implicazione

Per introdurre P → Q, assumiamo temporaneamente P e costruiamo Q.

-- Leggere i connettivi attraverso le loro regole di introduzione ed eliminazione. -- Introduzione dell'implicazione. -- Per dimostrare `P → Q`, assumiamo temporaneamente `P` e costruiamo `Q`. -- Regola: se assumendo P riusciamo a dimostrare Q, allora abbiamo P → Q. theorem lecture02_imp_intro (P Q : Prop) (hQ : Q) : P Q := P:PropQ:ProphQ:QP Q P:PropQ:ProphQ:QhP:PQ -- hP : P è l'assunzione temporanea introdotta dalla regola. All goals completed! 🐙

La riga intro hP introduce l'assunzione temporanea hP : P. In questo esempio la conclusione Q è già disponibile come hQ, quindi possiamo chiudere il goal con exact hQ.

Per eliminare P → Q, applichiamo l'implicazione a una dimostrazione di P.

-- Eliminazione dell'implicazione. -- Regola: da P → Q e P otteniamo Q. Questo è il modus ponens. theorem lecture02_imp_elim (P Q : Prop) : (P Q) P Q := P:PropQ:Prop(P Q) P Q P:PropQ:ProphPQ:P QP Q P:PropQ:ProphPQ:P QhP:PQ P:PropQ:ProphPQ:P QhP:PhQ:QQ All goals completed! 🐙

Qui hPQ hP è applicazione di funzione: da P → Q e P otteniamo Q. Siamo di nuovo al modus ponens!

6. Congiunzione

Una congiunzione P ∧ Q contiene entrambe le informazioni. Per introdurla, dobbiamo fornire una dimostrazione di entrambe le componenti (qui sotto le abbiamo inserite come assunzioni nell'enunciato).

theorem lecture02_and_intro (P Q : Prop) (hP : P) (hQ : Q) : P Q := P:PropQ:ProphP:PhQ:QP Q -- Regola di introduzione: da P e Q otteniamo P ∧ Q. P:PropQ:ProphP:PhQ:QhPAndQ:P QP Q All goals completed! 🐙

La stessa regola And.intro può essere usata come tattica. Il goal P ∧ Q si divide in due subgoal, uno per P e uno per Q.

theorem lecture02_and_intro_with_apply (P Q : Prop) (hP : P) (hQ : Q) : P Q := P:PropQ:ProphP:PhQ:QP Q -- Stessa regola, usando esplicitamente il costruttore come tattica. Notare qui la creazione di più subgoals. P:PropQ:ProphP:PhQ:QPP:PropQ:ProphP:PhQ:QQ P:PropQ:ProphP:PhQ:QP All goals completed! 🐙 P:PropQ:ProphP:PhQ:QQ All goals completed! 🐙

Per eliminare una congiunzione usiamo le sue componenti, e preleviamo il congiunto sulla sinistra/destra.

theorem lecture02_and_elim_left (P Q : Prop) : P Q P := P:PropQ:PropP Q P P:PropQ:ProphPAndQ:P QP -- Regola di eliminazione sinistra: da P ∧ Q otteniamo P. All goals completed! 🐙
theorem lecture02_and_elim_right (P Q : Prop) : P Q Q := P:PropQ:PropP Q Q P:PropQ:ProphPAndQ:P QQ -- Regola di eliminazione destra: da P ∧ Q otteniamo Q. All goals completed! 🐙

7. Disgiunzione

Una disgiunzione P ∨ Q contiene una delle due informazioni. Per introdurla, basta fornire uno dei due lati (con Or.inl/inr: injection left/right).

theorem lecture02_or_intro_left (P Q : Prop) : P P Q := P:PropQ:PropP P Q P:PropQ:ProphP:PP Q -- Regola di introduzione sinistra: da P otteniamo P ∨ Q. All goals completed! 🐙
theorem lecture02_or_intro_right (P Q : Prop) : Q P Q := P:PropQ:PropQ P Q P:PropQ:ProphQ:QP Q -- Regola di introduzione destra: da Q otteniamo P ∨ Q. All goals completed! 🐙

Per eliminare una disgiunzione dobbiamo ragionare per casi. Se abbiamo P ∨ Q, non sappiamo in generale quale lato sia disponibile (in altri termini, non sappiamo se la disgiunzione sia vera per via di P o di Q). Per ottenere una conclusione dobbiamo produrla in entrambi i rami: se riusciamo a concludere la stessa proposizione sia nel caso in cui sia P a essere vero, sia nel caso in cui lo sia Q, allora possiamo eliminare la disgiunzione. In questo caso, vogliamo concludere che Q ∨ P da P ∨ Q: dobbiamo quindi ragionare valutando i due casi, P è vero oppure Q è vero, e per entrambi dimostrare che riusciamo a concludere Q ∨ P.

theorem lecture02_or_elim (P Q : Prop) : P Q Q P := P:PropQ:PropP Q Q P P:PropQ:ProphPOrQ:P QQ P -- Regola di eliminazione: da P ∨ Q dobbiamo trattare il caso P e il caso Q. In ciascuno di questi due casi dobbiamo dimostrare lo stesso goal (Q ∨ P nella fattispecie). cases hPOrQ with P:PropQ:ProphP:PQ P -- Caso 1: abbiamo una dimostrazione di P. All goals completed! 🐙 P:PropQ:ProphQ:QQ P -- Caso 2: abbiamo una dimostrazione di Q. All goals completed! 🐙

La stessa struttura si può scrivere con Or.elim.

theorem lecture02_or_elim_with_or_elim (P Q : Prop) : P Q Q P := P:PropQ:PropP Q Q P P:PropQ:ProphPOrQ:P QQ P -- `Or.elim` è la stessa regola: una dimostrazione per il caso P e una per il caso Q. Notare come si modifica il goal. P:PropQ:ProphPOrQ:P QP Q PP:PropQ:ProphPOrQ:P QQ Q P P:PropQ:ProphPOrQ:P QP Q P P:PropQ:ProphPOrQ:P QhP:PQ P All goals completed! 🐙 P:PropQ:ProphPOrQ:P QQ Q P P:PropQ:ProphPOrQ:P QhQ:QQ P All goals completed! 🐙

8. False e negazione

False rappresenta uno stato contraddittorio. Se abbiamo una dimostrazione di False, possiamo chiudere qualunque goal.

theorem lecture02_false_elim (P : Prop) : False P := P:PropFalse P P:ProphFalse:FalseP -- Stessa regola, usando `exact`. All goals completed! 🐙

In Lean la negazione è definita come implicazione verso False: ¬P significa P → False. Per eliminare una negazione, la applichiamo a una dimostrazione positiva di P.

-- Vediamo ora la forma che la negazione assume in Lean. Come dimostriamo che P e la sua negazione producono una contraddizione? theorem lecture02_not_elim (P : Prop) : P ¬P False := P:PropP ¬P False P:ProphP:P¬P False P:ProphP:PhNonP:¬PFalse -- Regola di eliminazione: P e ¬P producono False. All goals completed! 🐙

Per introdurre ¬P, assumiamo temporaneamente P e deriviamo False. Il seguente esempio è lo schema di ragionamento del modus tollens. intro hP svolge la seguente funzione: per dimostrare ¬P, assumiamo P e deriviamo False (una contraddizione). Osservate come cambia il goal:

-- Come è fatto ¬P? Equivale a P → False. Vediamolo con un esempio: theorem lecture02_not_intro (P Q : Prop) : (P Q) ¬Q ¬P := P:PropQ:Prop(P Q) ¬Q ¬P P:PropQ:ProphPQ:P Q¬Q ¬P P:PropQ:ProphPQ:P QhNonQ:¬Q¬P -- Regola di introduzione: per dimostrare ¬P, assumiamo P e deriviamo False (una contraddizione). Osservare come cambia il goal P:PropQ:ProphPQ:P QhNonQ:¬QhP:PFalse P:PropQ:ProphPQ:P QhNonQ:¬QhP:PhQ:QFalse All goals completed! 🐙

9. Tattiche, comandi e scorciatoie

In questa lezione abbiamo usato soprattutto tattiche che corrispondono alle regole di introduzione ed eliminazione dei connettivi.

Abbiamo inoltre usato alcuni costruttori ed eliminatori espliciti:

10. Esercizi e soluzioni

Trovate i file con esercizi e soluzioni (Exercises.lean e Solutions.lean) sul sito di riferimento.

11. Fonti e letture