This commit is contained in:
Jon Eugster
2023-08-07 13:16:14 +02:00
parent 749e24d6c0
commit 50682613c6
18 changed files with 110 additions and 93 deletions

View File

@@ -5,7 +5,6 @@ World "Addition"
Level 1
Title "Two add one is three."
--namespace MyNat
namespace MyNat
Introduction
@@ -28,8 +27,7 @@ Can you prove `2 + 1 = 3`?
"
/-- $2+1=3$. -/
Statement
: (2 : ) + 1 = 3 := by
Statement : (2 : ) + 1 = 3 := by
Hint "Which one of Peano's axioms do we ultimately want to use to rewrite that addition?"
Hint (hidden := true) "change `1` to `succ 0` with a rewrite, and then
think about Peano's axioms."
@@ -39,9 +37,11 @@ Statement
rw [three_eq_succ_two]
rfl
NewLemma MyNat.two_eq_succ_one MyNat.three_eq_succ_two
MyNat.four_eq_succ_three MyNat.five_eq_succ_four
LemmaTab "Add"
Conclusion
"
Are you up for `2 + 2 = 4`?
Are you up for `2 + 2 = 4`?
"

View File

@@ -5,7 +5,6 @@ World "Addition"
Level 2
Title "One add one is two."
--namespace MyNat
namespace MyNat
Introduction
@@ -16,8 +15,7 @@ strategy.
"
/-- $1+1=2$. -/
Statement
: (1 : ) + 1 = 2 := by
Statement : (1 : ) + 1 = 2 := by
Hint "Go ahead and start with `rw [one_eq_succ_zero]`. Do you see what it does?"
Branch
rw [one_eq_succ_zero]
@@ -39,5 +37,5 @@ LemmaTab "Add"
Conclusion
"
Are you now up for the first sub-boss `2 + 2 = 4`?
Are you now up for the first sub-boss `2 + 2 = 4`?
"

View File

@@ -5,7 +5,6 @@ World "Addition"
Level 3
Title "Two add two is four."
--namespace MyNat
namespace MyNat
Introduction
@@ -15,8 +14,7 @@ about succ 3 and 4, just look at the blah blah I have no idea.
"
/-- $2+2=4$. -/
Statement
: (2 : ) + 2 = 4 := by
Statement : (2 : ) + 2 = 4 := by
nth_rewrite 2 [two_eq_succ_one]
rw [add_succ, one_eq_succ_zero, add_succ, add_zero, four_eq_succ_three, three_eq_succ_two]
rfl
@@ -25,7 +23,7 @@ LemmaTab "Add"
Conclusion
"
Nice. In the next level we'll prove `29 + 35 = 64`.
Nice. In the next level we'll prove `29 + 35 = 64`.
In one line.
In one line.
"

View File

@@ -18,6 +18,7 @@ on `MyNat` in `Game.MyNat.DecidableEq`. The implementation
is not at all optimised: I just wanted to get something which could beat
humans easily.
"
NewTactic decide
example : (20 : ) + 20 = 40 := by
@@ -25,17 +26,16 @@ example : (20 : ) + 20 = 40 := by
Introduction
"
Oh did I mention there was a new tactic? Find it in the blah blah blah.
Oh did I mention there was a new tactic? Find it highlighted in your inventory.
"
/-- $29+35=64. -/
Statement
: (29 : ) + 35 = 64 := by
/-- $29+35=64$. -/
Statement : (29 : ) + 35 = 64 := by
decide
LemmaTab "Add"
Conclusion
"
The `decide` tactic destroys sub-bosses such as `2 + 2 = 4`.
The `decide` tactic destroys sub-bosses such as `2 + 2 = 4`.
"

View File

@@ -47,13 +47,12 @@ because we have formulas for adding `0` and adding successors. See if you
can do your first induction proof in Lean.
"
LemmaDoc MyNat.zero_add as "zero_add" in "MyNat" "`zero_add x` is the proof that `0 + x = x`. It's
LemmaDoc MyNat.zero_add as "zero_add" in "Add" "`zero_add x` is the proof that `0 + x = x`. It's
a `simp` lemma, because replacing `0 + x` by `x` is almost always what you want
to do if you're simplifying. "
/-- For all natural numbers $n$, we have $0 + n = n$. -/
Statement zero_add
(n : ) : 0 + n = n := by
Statement zero_add (n : ) : 0 + n = n := by
Hint "You can start a proof by induction over `n` by typing:
`induction n with d hd`."
induction n with d hd

View File

@@ -28,11 +28,14 @@ that `a + succ(b) = succ(a + b)`. The tactic `rw [add_succ]` just says to Lean \
what the variables are\".
"
LemmaDoc MyNat.succ_add as "succ_add" in "MyNat" "`succ_add a b` is a proof that `succ a + b = succ (a + b)`."
/-- For all natural numbers $a, b$, we have
$ \\operatorname{succ}(a) + b = \\operatorname{succ}(a + b)$. -/
Statement succ_add
(a b : ) : succ a + b = succ (a + b) := by
LemmaDoc MyNat.succ_add as "succ_add" in "Add"
"`succ_add a b` is a proof that `succ a + b = succ (a + b)`."
/--
For all natural numbers $a, b$, we have
$ \operatorname{succ}(a) + b = \operatorname{succ}(a + b)$.
-/
Statement succ_add (a b : ) : succ a + b = succ (a + b) := by
Hint (hidden := true) "You might want to think about whether induction
on `a` or `b` is the best idea."
Branch

View File

@@ -15,12 +15,13 @@ Look in your inventory to see the proofs you have available.
These should be enough.
"
LemmaDoc MyNat.add_comm as "add_comm" in "MyNat" "`add_comm x y` is a proof of `x + y = y + x`."
LemmaDoc MyNat.add_comm as "add_comm" in "Add"
"`add_comm x y` is a proof of `x + y = y + x`."
/-- On the set of natural numbers, addition is commutative.
In other words, if `a` and `b` are arbitrary natural numbers, then
$a + b = b + a$. -/
Statement add_comm
(a b : ) : a + b = b + a := by
Statement add_comm (a b : ) : a + b = b + a := by
Hint (hidden := true) "Induction on `a` or `b` -- it's all the same in this one."
Branch
induction a with d hd
@@ -30,6 +31,9 @@ Statement add_comm
· simp
· simp_all [succ_add, add_succ]
-- Adding this instance to make `ac_rfl` work.
instance : Lean.IsCommutative (α := ) (·+·) := add_comm
LemmaTab "Add"
Conclusion

View File

@@ -21,7 +21,7 @@ See if you can prove associativity of addition. Note that now we have
it probably doesn't matter which variable we induct on. Take your pick!
"
LemmaDoc MyNat.add_assoc as "add_assoc" in "MyNat" "`add_assoc a b c` is a proof
LemmaDoc MyNat.add_assoc as "add_assoc" in "Add" "`add_assoc a b c` is a proof
that `(a + b) + c = a + (b + c)`. Note that in Lean `(a + b) + c` prints
as `a + b + c`, because the notation for addition is defined to be left
associative. "
@@ -29,8 +29,7 @@ associative. "
/-- On the set of natural numbers, addition is associative.
In other words, if $a, b$ and $c$ are arbitrary natural numbers, we have
$ (a + b) + c = a + (b + c). $ -/
Statement add_assoc
(a b c : ) : (a + b) + c = a + (b + c) := by
Statement add_assoc (a b c : ) : (a + b) + c = a + (b + c) := by
Hint "Note that when Lean writes `a + b + c`, it means `(a + b) + c`. If it wants to talk
about `a + (b + c)` it will put the brackets in explictly."
Branch
@@ -45,6 +44,9 @@ Statement add_assoc
simp
simp [hc, succ_add, add_succ]
-- Adding this instance to make `ac_rfl` work.
instance : Lean.IsAssociative (α := ) (·+·) := add_assoc
NewLemma MyNat.add_assoc
LemmaTab "Add"

View File

@@ -21,12 +21,12 @@ like `(d + f) + (h + (a + c)) + (g + e + b) = a + b + c + d + e + f + g + h`.
Let's start with a simpler one. Can you do it in three rewrites?
"
LemmaDoc MyNat.add_left_comm as "add_left_comm" in "MyNat" "`add_left_comm a b c` is a proof that `a + (b + c) = b + (a + c)`."
LemmaDoc MyNat.add_left_comm as "add_left_comm" in "Add"
"`add_left_comm a b c` is a proof that `a + (b + c) = b + (a + c)`."
/-- If $a, b$ and $c$ are arbitrary natural numbers, we have
$a + (b + c) = b + (a + c)$. -/
Statement add_left_comm
(a b c : ) : a + (b + c) = b + (a + c) := by
Statement add_left_comm (a b c : ) : a + (b + c) = b + (a + c) := by
Hint "Don't use induction; `add_assoc` and `add_comm` are all the tools you need.
Remember that to rewrite `h : X = Y` backwards (i.e. to change `Y`s to `X`s
rather than `X`s to `Y`s) use `rw [←h]`"

View File

@@ -13,12 +13,11 @@ where the order of the variables needs to be changed
and the brackets need to be moved around. In this level we learn
an algorithm which will work for an arbitrary such problem. Let's
prove `a + b + (c + d) = a + c + d + b`.
"
/-- If $a, b$, $c$ and $d$ are arbitrary natural numbers, we have
$(a + b) + (c + d) = ((a + c) + d) + b. -/
Statement
(a b c d : ) : a + d + (b + c) = a + b + c + d := by
Statement (a b c d : ) : a + d + (b + c) = a + b + c + d := by
Hint "We no longer have to use inducion; `add_assoc` and `add_comm` are
all the tools we need.
Start with `repeat rw [add_assoc]` to push all the brackets to the right."
@@ -32,10 +31,11 @@ Statement
`d` and `b` on the left hand side."
rw [add_left_comm d b, add_comm d c]
rfl
LemmaTab "Add"
Conclusion
"
In the last level we use automation to perform this algorithm
automatically.
In the last level we use automation to perform this algorithm
automatically.
"

View File

@@ -19,15 +19,17 @@ numbers. Let's now write a tactic which automates this.
/-- If $a, b,\\ldots h$ are arbitrary natural numbers, we have
$(d + f) + (h + (a + c)) + (g + e + b) = a + b + c + d + e + f + g + h$. -/
Statement
(a b c d e f g h : ) : (d + f) + (h + (a + c)) + (g + e + b) = a + b + c + d + e + f + g + h := by
simp only [add_assoc, add_left_comm, add_comm]
Statement (a b c d e f g h : ) :
(d + f) + (h + (a + c)) + (g + e + b) = a + b + c + d + e + f + g + h := by
ac_rfl
NewTactic ac_rfl
LemmaTab "Add"
Conclusion
"
Congratulations! You finished addition world. Now go back to the overworld by clicking the
home button in the top left. If you want to press on to the final boss
of the game then go to Multiplication world next. If you are in no hurry, and would like
to learn some more tactics, then you can try Advanced Addition World.
Congratulations! You finished addition world. Now go back to the overworld by clicking the
home button in the top left. If you want to press on to the final boss
of the game then go to Multiplication world next. If you are in no hurry, and would like
to learn some more tactics, then you can try Advanced Addition World.
"

View File

@@ -44,14 +44,20 @@ If the goal looks like this:
⊢ x^37+691*y^24+1=x^37+691*y^24+1
```
then `rfl` will close it. But if it looks like `0 + x = x` then `rfl` won't work, because even though $0+x$ is *equal* to $x$, it is not *exactly the same thing* as *x*. The only thing which is exactly the same as `0 + x` is `0 + x`.
then `rfl` will close it. But if it looks like `0 + x = x` then `rfl` won't work,
because even though $0+x$ is *equal* to $x$, it is not *exactly the same thing* as *x*.
The only thing which is exactly the same as `0 + x` is `0 + x`.
"
NewTactic rfl
DefinitionDoc MyNat as "Nat" "The natural numbers, defined as an inductive type, with two constructors:
* `0 : Nat`
* `succ (n : Nat) : Nat`
DefinitionDoc MyNat as ""
"The natural numbers, defined as an inductive type, with two constructors:
* `0 : `
* `succ (n : ) : `
"
NewTactic rfl
NewDefinition MyNat
Conclusion

View File

@@ -24,7 +24,6 @@ by replacing `y` by `x + 7` and then using `rfl`. The tactic which we use to
do this kind of \"substituting in\" is called the *rewrite* tactic `rw`.
The tactic `rw [h]` will replace all occurences of the left hand side $y$ of `h`
in the goal, with the right hand side $x+7$. Try it and see.
"
/-- If $x$ and $y$ are natural numbers, and $y = x + 7$, then $2y = 2(x + 7)$. -/
@@ -108,6 +107,7 @@ h2 : 2 * y = x
then `rw h1 at h2` will turn `h2` into `h2 : 2 * y = y + 3`.
-/
"
NewTactic rw
Conclusion

View File

@@ -18,14 +18,15 @@ Use the `rw` tactic to prove that $ab + 2c^3 + 7 = pq + 2r^3 + 7$. Here are some
"
/-- If $a=p$, $b=q$ and $c=r$, then $ab+2c^3+7=pq+2r^3+7.$ -/
Statement
(a b c p q r : ) (hap : a = p) (hbq : b = q) (hcr : c = r) : a * b + 2 * c ^ 3 + 7 = p * q + 2 * r ^ 3 + 7 := by
Statement (a b c p q r : ) (hap : a = p) (hbq : b = q) (hcr : c = r) :
a * b + 2 * c ^ 3 + 7 = p * q + 2 * r ^ 3 + 7 := by
Hint "Switch to editor mode to make it easier to experiment with the `rw` tactic. Note that each tactic needs to start at the beginning of a line."
rw [hap, hbq, hcr]
rfl
Conclusion
"
In editor mode,you can click around the proof and see the state of Lean's brain at any point in the proof.
In editor mode,you can click around the proof and see the state of Lean's brain at
any point in the proof.
You can also edit your proof and experiment more with it.
"

View File

@@ -8,7 +8,9 @@ Title "Peano axioms"
namespace MyNat
LemmaDoc MyNat.one_eq_succ_zero as "foobar" in "bazqux" "`one_eq_succ_zero is a proof of `1 = succ 0`."
LemmaDoc MyNat.one_eq_succ_zero as "one_eq_succ_zero" in ""
"`one_eq_succ_zero is a proof of `1 = succ 0`."
NewLemma MyNat.one_eq_succ_zero
Introduction
@@ -35,7 +37,8 @@ function `succ` taking numbers to numbers. We could apply the function to the nu
We could define `2` to either be `succ 1` or `succ (succ 0)`. Are these two choices definitely
equal? Let's see if we can prove it.
"
/-- $\\operatorname{succ}(1)=\\operatorname{succ}(\\operatorname{succ}(0))$. -/
/-- $\operatorname{succ}(1)=\operatorname{succ}(\operatorname{succ}(0))$. -/
Statement
: succ 1 = succ (succ 0) := by
Hint "You can use `rw` and `one_eq_succ_zero` your assumption `h` to substitute `succ a` with `b`.
@@ -55,6 +58,8 @@ Statement
Hint (hidden := true) "Now both sides are identical…"
rfl
NewLemma MyNat.one_eq_succ_zero
Conclusion
"
We can now go on to define `2`, `3`, `4` and `5` and create associated

View File

@@ -22,37 +22,14 @@ and returns a proof `add_zero a` of `a + 0 = a`.
Let me show you how to use Lean's simplifier `simp`
to do a lot of work for us."
LemmaDoc MyNat.add_zero as "add_zero" in "Add"
"`add_zero n` is a proof that `n + 0 = n`.
This is one of the two axioms for addition."
NewLemma MyNat.add_zero
namespace MyNat
TacticDoc simp "The simplifier. `rw` on steroids.
A bunch of lemmas like `add_zero : ∀ a, a + 0 = a`
are tagged with the `@[simp]` tag. If the `simp` tactic
is run by the user, the simplifier will try and rewrite
as many of the lemmas tagged `@[simp]` as it can.
`simp` is a *finishing tactic*. After you run `simp`,
the goal should be closed. If it is not, it is best
practice to write `simp?` instead and then replace the
output with the appropriate `simp only` call. Inappropriate
use of `simp` can make for very slow code.
"
NewTactic simp -- TODO: Do we want it to be unlocked here?
/-- $(a+(0+0)+(0+0+0)=a.$ -/
Statement
(a : ) : (a + (0 + 0)) + (0 + 0 + 0) = a := by
Statement (a : ) : (a + (0 + 0)) + (0 + 0 + 0) = a := by
Hint "I will walk you through this level so I can show you some
techniques which will speed up your proving.
This is an annoying goal. One of rw [add_zero a]` amd `rw [add_zero 0]`
This is an annoying goal. One of `rw [add_zero a]` and `rw [add_zero 0]`
will work, but not the other. Can you figure out which? Try the one
that works."
Branch
@@ -79,16 +56,38 @@ Statement
start once more, and this time just try `simp`."
simp
DefinitionDoc Add as "Add" "`Add a b`, with notation `a + b`, is
LemmaDoc MyNat.add_zero as "add_zero" in "Add"
"`add_zero n` is a proof that `n + 0 = n`.
This is one of the two axioms for addition."
TacticDoc simp "The simplifier. `rw` on steroids.
A bunch of lemmas like `add_zero : ∀ a, a + 0 = a`
are tagged with the `@[simp]` tag. If the `simp` tactic
is run by the user, the simplifier will try and rewrite
as many of the lemmas tagged `@[simp]` as it can.
`simp` is a *finishing tactic*. After you run `simp`,
the goal should be closed. If it is not, it is best
practice to write `simp?` instead and then replace the
output with the appropriate `simp only` call. Inappropriate
use of `simp` can make for very slow code.
"
DefinitionDoc Add as "+" "`Add a b`, with notation `a + b`, is
the usual sum of natural numbers. Internally it is defined by
induction on one of the variables, but that is an implementation issue;
All you need to know is that `add_zero` and `zero_add` are both theorems."
NewLemma MyNat.add_zero
NewTactic simp «repeat» -- TODO: Do we want it to be unlocked here?
NewDefinition Add
Conclusion
" The simplifier atempts to solve goals by using *repeated rewriting* of
*equalities* and *iff statements*, and then trying `rfl` at the end.
Let's now learn about Peano's second axiom for addition, `add_succ`.
"
The simplifier atempts to solve goals by using *repeated rewriting* of
*equalities* and *iff statements*, and then trying `rfl` at the end.
Let's now learn about Peano's second axiom for addition, `add_succ`.
"

View File

@@ -24,9 +24,8 @@ LemmaDoc MyNat.add_succ as "add_succ" in "Add"
NewLemma MyNat.add_succ
/-- For all natural numbers $a$, we have $a + \\operatorname{succ}(0) = \\operatorname{succ}(a)$. -/
Statement
: a + succ 0 = succ a := by
/-- For all natural numbers $a$, we have $a + \operatorname{succ}(0) = \operatorname{succ}(a)$. -/
Statement : a + succ 0 = succ a := by
Hint "You find `{a} + succ …` in the goal, so you can use `rw` and `add_succ`
to make progress."
Hint (hidden := true) "Explicitely, you can type `rw [add_succ a 0]`

View File

@@ -17,7 +17,8 @@ If `a` is a natural number, then `add_zero a` is the proof that `a + 0 = a`.
`add_zero` is a `simp` lemma, because if you see `a + 0`
you usually want to simplify it to `a`.
-/
@[simp] theorem add_zero (a : MyNat) : a + 0 = a := by rfl
@[simp]
theorem add_zero (a : MyNat) : a + 0 = a := by rfl
/--
If `a` and `d` are natural numbers, then `add_succ a d` is the proof that