Verificação Formal de Software

4.3. Raciocínio sobre Conectivos e Quantificadores🔗

A Aula 1 apresentou as regras dos conectivos como figuras de inferência. Cada figura é um teorema ordinário de Lean. Uma regra de introdução tem o conectivo como símbolo mais externo da sua conclusão e diz como prová-lo, e uma regra de eliminação tem o conectivo em uma hipótese e diz como uma prova dele pode ser usada. O quadro abaixo lista as regras de ∧, ∨ e ↔, com metavariáveis nos lugares que as regras deixam em aberto.

And.intro : ?a → ?b → ?a ∧ ?b
And.left  : ?a ∧ ?b → ?a
And.right : ?a ∧ ?b → ?b
Or.inl    : ?a → ?a ∨ ?b
Or.inr    : ?b → ?a ∨ ?b
Or.elim   : ?a ∨ ?b → (?a → ?c) → (?b → ?c) → ?c
Iff.intro : (?a → ?b) → (?b → ?a) → (?a ↔ ?b)
Iff.mp    : (?a ↔ ?b) → ?a → ?b
Iff.mpr   : (?a ↔ ?b) → ?b → ?a

As regras do quantificador existencial, a verdade, a falsidade e os princípios clássicos completam o quadro. A implicação e o quantificador universal não aparecem em nenhum desses quadros, porque ambos são tipos de função dependentes, então a sua introdução é intro e a sua eliminação é a aplicação, a justaposição da Aula 2. A negação dispensa regras próprias, pois ¬a é definida como a → False, então intro se aplica a uma conclusão negada, como a Aula 1 mostrou. True.intro é a única regra da verdade, e False.elim é a única regra da falsidade. A lógica central de Lean é construtiva, e ela oferece o raciocínio clássico de forma explícita por meio de Classical.em e Classical.byContradiction, que repousam sobre axiomas adicionais. Ambos aparecem desde a Aula 1 e agora se aplicam regressivamente.

Exists.intro : ∀ (w : ?α), ?p w → ∃ x, ?p x
Exists.elim  : (∃ x, ?p x) → (∀ (w : ?α), ?p w → ?b) → ?b
True.intro   : True
False.elim   : False → ?c
Classical.em : ∀ (p : Prop), p ∨ ¬p
Classical.byContradiction : (¬?a → False) → ?a

Uma metavariável ?a representa um termo ainda por determinar. Quando apply casa a conclusão do objetivo com a conclusão de uma regra, a unificação determina algumas metavariáveis e deixa as demais como novos objetivos, que em geral desaparecem conforme a prova avança. A prova abaixo aplica a regra de introdução de ∧ regressivamente e fecha cada subobjetivo com uma regra de eliminação.

namespace Backward theorem And_swap (a b : Prop) : a b b a := a:Propb:Propa b b a a:Propb:Prophab:a bb a a:Propb:Prophab:a bba:Propb:Prophab:a ba a:Propb:Prophab:a b?left.a ba:Propb:Prophab:a bPropa:Propb:Prophab:a ba a:Propb:Prophab:a ba a:Propb:Prophab:a ba ?right.ba:Propb:Prophab:a bProp All goals completed! 🐙 end Backward

O marcador ·, usado desde a Aula 1, foca cada subobjetivo, e a justaposição instancia uma regra progressivamente, passando a hipótese diretamente em vez de esperar que ela apareça como subobjetivo. Esse é um pequeno passo progressivo dentro de uma prova regressiva, e ele evita as metavariáveis que apply deixa para trás.

namespace Backward theorem And_swap_braces : a b : Prop, a b b a := (a b : Prop), a b b a a:Propb:Prophab:a bb a a:Propb:Prophab:a bba:Propb:Prophab:a ba a:Propb:Prophab:a bb All goals completed! 🐙 a:Propb:Prophab:a ba All goals completed! 🐙 end Backward

A justaposição também instancia uma hipótese universal, exatamente como na Aula 2.

namespace Backward opaque f : theorem f5_if (h : n : , f n = n) : f 5 = 5 := h: (n : ), f n = nf 5 = 5 All goals completed! 🐙 end Backward

A regra de eliminação de ∨ realiza a análise de casos que a tática cases realizou na Aula 1, e modus_ponens e Not_Not_intro combinam as regras vistas até aqui.

namespace Backward theorem Or_swap (a b : Prop) : a b b a := a:Propb:Propa b b a a:Propb:Prophab:a bb a a:Propb:Prophab:a ba b aa:Propb:Prophab:a bb b a a:Propb:Prophab:a ba b a a:Propb:Prophab:a bha:ab a All goals completed! 🐙 a:Propb:Prophab:a bb b a a:Propb:Prophab:a bhb:bb a All goals completed! 🐙 theorem modus_ponens (a b : Prop) : (a b) a b := a:Propb:Prop(a b) a b a:Propb:Prophab:a bha:ab a:Propb:Prophab:a bha:aa All goals completed! 🐙 theorem Not_Not_intro (a : Prop) : a ¬¬ a := a:Propa ¬¬a a:Propha:ahna:¬aFalse a:Propha:ahna:¬aa All goals completed! 🐙 end Backward

Para provar enunciados de lógica proposicional, o guia oferece as estratégias a seguir.

  • Olhe a conclusão. Se ela é uma implicação ou uma negação, intro faz progresso.

  • Olhe as hipóteses. Uma conjunção oferece And.left e And.right, uma disjunção oferece Or.elim, e uma equivalência oferece Iff.mp e Iff.mpr.

  • Case a conclusão do objetivo com a conclusão de uma regra de introdução e a aplique com apply.

  • Prefira táticas que preservam a demonstrabilidade enquanto elas fizerem progresso, e registre os pontos de escolha em que uma tática se compromete com um lado.

  • Quando um subobjetivo repete uma hipótese, exact ou assumption o fecha.

  • Quando nada construtivo se aplica, considere uma análise de casos sobre Classical.em.

  • Se a prova não progride, retroceda até o último ponto de escolha e tente a outra opção.

4.3.1. Exemplos🔗

Os exemplos abaixo aplicam as regras regressivamente com apply, as instanciam progressivamente por justaposição e observam as metavariáveis que aparecem pelo caminho.

Example 1. apply And.intro divide a conjunção em dois objetivos, e o trace mostra os dois.

example (a b : Prop) (hab : a b) : b a := a:Propb:Prophab:a bb a a:Propb:Prophab:a bba:Propb:Prophab:a ba a b:Prophab:a bb a b:Prophab:a baa:Propb:Prophab:a bba:Propb:Prophab:a ba a:Propb:Prophab:a bb All goals completed! 🐙 a:Propb:Prophab:a ba All goals completed! 🐙
a b:Prophab:a  bb

a b:Prophab:a  ba

Example 2. A justaposição fecha um objetivo em um passo, passando a hipótese à regra de eliminação.

example (a b : Prop) (hab : a b) : b := a:Propb:Prophab:a bb All goals completed! 🐙

Example 3. Aplicar a regra de eliminação regressivamente deixa uma metavariável ?a na conclusão, e até um segundo objetivo pedindo a própria ?a. O exact final instancia os dois de uma vez.

example (a b : Prop) (hab : a b) : b := a:Propb:Prophab:a bb a:Propb:Prophab:a b?a ba:Propb:Prophab:a bProp a b:Prophab:a b?a b a b:Prophab:a bPropa:Propb:Prophab:a b?a ba:Propb:Prophab:a bProp All goals completed! 🐙
a b:Prophab:a  b?a  b

a b:Prophab:a  bProp

Example 4. apply Or.inl escolhe o lado esquerdo e deixa a sua prova como objetivo.

example (a b : Prop) (ha : a) : a b := a:Propb:Propha:aa b a:Propb:Propha:aa All goals completed! 🐙

Example 5. apply Or.elim h produz um subobjetivo por disjunto, e um marcador fecha cada um.

example (a b c : Prop) (h : a b) (hac : a c) (hbc : b c) : c := a:Propb:Propc:Proph:a bhac:a chbc:b cc a:Propb:Propc:Proph:a bhac:a chbc:b ca ca:Propb:Propc:Proph:a bhac:a chbc:b cb c a:Propb:Propc:Proph:a bhac:a chbc:b ca c a:Propb:Propc:Proph:a bhac:a chbc:b cha:ac All goals completed! 🐙 a:Propb:Propc:Proph:a bhac:a chbc:b cb c a:Propb:Propc:Proph:a bhac:a chbc:b chb:bc All goals completed! 🐙

Example 6. apply Iff.intro divide uma equivalência nas suas duas implicações.

example (a : Prop) : a a a := a:Propa a a a:Propa a aa:Propa a a a:Propa a a a:Prophaa:a aa All goals completed! 🐙 a:Propa a a a:Propha:aa a All goals completed! 🐙

Example 7. Iff.mp e Iff.mpr extraem as duas direções de uma hipótese de equivalência por justaposição.

example (a b : Prop) (hab : a b) (ha : a) : b := a:Propb:Prophab:a bha:ab All goals completed! 🐙 example (a b : Prop) (hab : a b) (hb : b) : a := a:Propb:Prophab:a bhb:ba All goals completed! 🐙

Example 8. apply Exists.intro fornece uma testemunha, e a hipótese na testemunha fecha o que resta.

example (P : Prop) (h : P 3) : n, P n := P: Proph:P 3 n, P n P: Proph:P 3P 3 All goals completed! 🐙

Example 9. apply Exists.elim h consome uma hipótese existencial e nomeia a sua testemunha.

example (α : Type) (P : α Prop) (Q : Prop) (hex : x, P x) (h : x, P x Q) : Q := α:TypeP:α PropQ:Prophex: x, P xh: (x : α), P x QQ α:TypeP:α PropQ:Prophex: x, P xh: (x : α), P x Q (x : α), P x Q α:TypeP:α PropQ:Prophex: x, P xh: (x : α), P x Qa:αhPa:P aQ All goals completed! 🐙

Example 10. Três provas de uma linha. intro se aplica a uma conclusão negada, True.intro é a única regra da verdade, e apply False.elim fecha qualquer objetivo a partir de uma prova de False, pois a falsidade não tem regra de introdução.

example : ¬False := ¬False h:FalseFalse All goals completed! 🐙 example : True := True All goals completed! 🐙 example (a : Prop) (h : False) : a := a:Proph:Falsea a:Proph:FalseFalse All goals completed! 🐙