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:
parent
f5cc2458a9
commit
31bacd8631
1 changed files with 83 additions and 0 deletions
83
examples/lean/even.lean
Normal file
83
examples/lean/even.lean
Normal 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.
|
||||
*)
|
Loading…
Reference in a new issue