doc(examples/lean): add a new example with even/odd numbers

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-01-03 18:45:10 -08:00
parent f5cc2458a9
commit 31bacd8631

83
examples/lean/even.lean Normal file
View file

@ -0,0 +1,83 @@
Import macros.
(*
In this example, we prove two simple theorems about even/odd numbers.
First, we define the predicates even and odd.
*)
Definition even (a : Nat) := ∃ b, a = 2*b.
Definition odd (a : Nat) := ∃ b, a = 2*b + 1.
(*
Prove that the sum of two even numbers is even.
Notes: we use the macro
Obtain [bindings] ',' 'from' [expr]_1 ',' [expr]_2
It is syntax sugar for existential elimination.
It expands to
ExistsElim [expr]_1 (fun [binding], [expr]_2)
It is defined in the file macros.lua.
We also use the calculational proof style.
See doc/lean/calc.md for more information.
We use the first two Obtain-expressions to extract the
witnesses w1 and w2 s.t. a = 2*w1 and b = 2*w2.
We can do that because H1 and H2 are evidence/proof for the
fact that 'a' and 'b' are even.
We use a calculational proof 'calc' expression to derive
the witness w1+w2 for the fact that a+b is also even.
That is, we provide a derivation showing that a+b = 2*(w1 + w2)
*)
Theorem EvenPlusEven {a b : Nat} (H1 : even a) (H2 : even b) : even (a + b)
:= Obtain (w1 : Nat) (Hw1 : a = 2*w1), from H1,
Obtain (w2 : Nat) (Hw2 : b = 2*w2), from H2,
ExistsIntro (w1 + w2)
(calc a + b = 2*w1 + b : { Hw1 }
... = 2*w1 + 2*w2 : { Hw2 }
... = 2*(w1 + w2) : Symm (Nat::Distribute 2 w1 w2)).
(*
In the following example, we omit the arguments for Nat::PlusAssoc, Refl and Nat::Distribute.
Lean can infer them automatically.
Refl is the reflexivity proof. (Refl a) is a proof that two
definitionally equal terms are indeed equal.
"Definitionally equal" means that they have the same normal form.
We can also view it as "Proof by computation".
The normal form of (1+1), and 2*1 is 2.
Another remark: '2*w + 1 + 1' is not definitionally equal to '2*w + 2*1'.
The gotcha is that '2*w + 1 + 1' is actually '(2*w + 1) + 1' since +
is left associative. Moreover, Lean normalizer does not use
any theorems such as + associativity.
*)
Theorem OddPlusOne {a : Nat} (H : odd a) : even (a + 1)
:= Obtain (w : Nat) (Hw : a = 2*w + 1), from H,
ExistsIntro (w + 1)
(calc a + 1 = 2*w + 1 + 1 : { Hw }
... = 2*w + (1 + 1) : Symm (Nat::PlusAssoc _ _ _)
... = 2*w + 2*1 : Refl _
... = 2*(w + 1) : Symm (Nat::Distribute _ _ _)).
(*
The following command displays the proof object produced by Lean after
expanding macros, and infering implicit/missing arguments.
*)
Show Environment 2.
(*
By default, Lean does not display implicit arguments.
The following command will force it to display them.
*)
SetOption pp::implicit true.
Show Environment 2.
(*
As an exercise, prove that the sum of two odd numbers is even,
and other similar theorems.
*)