84 lines
2.8 KiB
Text
84 lines
2.8 KiB
Text
|
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.
|
||
|
*)
|