This commit is contained in:
Jon Eugster
2023-03-26 14:29:13 +02:00
parent 6cd71c93fe
commit 6e8911e5da
114 changed files with 3381 additions and 5 deletions
@@ -0,0 +1,93 @@
import NNG.Metadata
import NNG.MyNat.Addition
Game "NNG"
World "Addition"
Level 1
Title "the induction tactic."
open MyNat
set_option tactic.hygienic false
Introduction
"
OK so let's see induction in action. We're going to prove
```
zero_add (n : ℕ) : 0 + n = n
```
Wait… what is going on here? Didn't we already prove that adding zero to $n$ gave us $n$?
No we didn't! We proved $n + 0 = n$, and that proof was called `add_zero`. We're now
trying to establish `zero_add`, the proof that $0 + n = n$.
But aren't these two theorems the same?
No they're not! It is *true* that `x + y = y + x`, but we haven't *proved* it yet,
and in fact we will need both `add_zero` and `zero_add` in order
to prove this. In fact `x + y = y + x` is the boss level for addition world,
and `induction` is the only other tactic you'll need to beat it.
Now `add_zero` is one of Peano's axioms, so we don't need to prove it, we already have it.
To prove `0 + n = n` we need to use induction on $n$. While we're here,
note that `zero_add` is about zero add something, and `add_zero` is about something add zero.
The names of the proofs tell you what the theorems are. Anyway, let's prove `0 + n = n`.
"
Statement zero_add
"For all natural numbers $n$, we have $0 + n = n$."
(n : ℕ) : 0 + n = n := by
Hint "You can start a proof by induction over `n` by typing:
`induction n with d hd`.
If you use the `with` part, you can name your variable and induction hypothesis, otherwise
they get default names."
induction n with n hn
· Hint "Now you have two goals. Once you proved the first, you will jump to the second one.
This first goal is the base case $n = 0$.
Recall that you can use all lemmas that are visible in your inventory."
Hint (hidden := true) "try using `add_zero`."
rw [add_zero]
rfl
· Hint "Now you jumped to the second goal. Here you have the induction hypothesis
`{hn} : 0 + {n} = {n}` and you need to prove the statement for `succ {n}`."
Hint (hidden := true) "look at `add_succ`."
rw [add_succ]
Hint (hidden := true) "At this point you see the term `0 + {n}`, so you can use the
induction hypothesis with `rw [{hn}]`."
rw [hn]
rfl
NewTactic induction
Conclusion
"
## Now venture off on your own.
Those three tactics:
* `induction n with d hd`
* `rw [h]`
* `rfl`
will get you quite a long way through this game. Using only these tactics
you can beat Addition World level 4 (the boss level of Addition World),
all of Multiplication World including the boss level `a * b = b * a`,
and even all of Power World including the fiendish final boss. This route will
give you a good grounding in these three basic tactics; after that, if you
are still interested, there are other worlds to master, where you can learn
more tactics.
But we're getting ahead of ourselves, you still have to beat the rest of Addition World.
We're going to stop explaining stuff carefully now. If you get stuck or want
to know more about Lean (e.g. how to do much harder maths in Lean),
ask in `#new members` at
[the Lean chat](https://leanprover.zulipchat.com)
(login required, real name preferred). Kevin or Mohammad or one of the other
people there might be able to help.
Good luck! Click on \"Next\" to solve some levels on your own.
"
@@ -0,0 +1,70 @@
import NNG.Metadata
import NNG.MyNat.Addition
Game "NNG"
World "Addition"
Level 2
Title "add_assoc (associativity of addition)"
open MyNat
theorem MyNat.zero_add (n : ℕ) : 0 + n = n := by
induction n with n hn
· rw [add_zero]
rfl
· rw [add_succ]
rw [hn]
rfl
Introduction
"
It's well-known that $(1 + 2) + 3 = 1 + (2 + 3)$; if we have three numbers
to add up, it doesn't matter which of the additions we do first. This fact
is called *associativity of addition* by mathematicians, and it is *not*
obvious. For example, subtraction really is not associative: $(6 - 2) - 1$
is really not equal to $6 - (2 - 1)$. We are going to have to prove
that addition, as defined the way we've defined it, is associative.
See if you can prove associativity of addition.
"
Statement add_assoc
"On the set of natural numbers, addition is associative.
In other words, for all natural numbers $a, b$ and $c$, we have
$ (a + b) + c = a + (b + c). $"
(a b c : ℕ) : (a + b) + c = a + (b + c) := by
Hint "Because addition was defined by recursion on the right-most variable,
use induction on the right-most variable (try other variables at your peril!).
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
induction a
Hint "Good luck with that…"
rw [zero_add, zero_add]
rfl
Branch
induction b
Hint "Good luck with that…"
induction c with c hc
Hint (hidden := true) "look at the lemma `add_zero`."
rw [add_zero]
Hint "`rw [add_zero]` only rewrites one term of the form `… + 0`, so you might to
use it multiple times."
rw [add_zero]
rfl
Hint (hidden := true) "`add_succ` might help here."
rw [add_succ]
rw [add_succ]
rw [add_succ]
Hint (hidden := true) "Now you can use the induction hypothesis."
rw [hc]
rfl
Conclusion
"
"
NewLemma MyNat.zero_add
@@ -0,0 +1,66 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.Levels.Addition.Level_2
Game "NNG"
World "Addition"
Level 3
Title "succ_add"
open MyNat
theorem MyNat.add_assoc (a b c : ℕ) : (a + b) + c = a + (b + c) := by
induction c with c hc
· rw [add_zero]
rw [add_zero]
rfl
· rw [add_succ]
rw [add_succ]
rw [add_succ]
rw [hc]
rfl
Introduction
"
Oh no! On the way to `add_comm`, a wild `succ_add` appears. `succ_add`
is the proof that `succ(a) + b = succ(a + b)` for `a` and `b` in your
natural number type. We need to prove this now, because we will need
to use this result in our proof that `a + b = b + a` in the next level.
NB: think about why computer scientists called this result `succ_add` .
There is a logic to all the names.
Note that if you want to be more precise about exactly where you want
to rewrite something like `add_succ` (the proof you already have),
you can do things like `rw [add_succ (succ a)]` or
`rw [add_succ (succ a) d]`, telling Lean explicitly what to use for
the input variables for the function `add_succ`. Indeed, `add_succ`
is a function: it takes as input two variables `a` and `b` and outputs a proof
that `a + succ(b) = succ(a + b)`. The tactic `rw [add_succ]` just says to Lean \"guess
what the variables are\".
"
Statement succ_add
"For all natural numbers $a, b$, we have
$ \\operatorname{succ}(a) + b = \\operatorname{succ}(a + b)$."
(a b : ℕ) : succ a + b = succ (a + b) := by
Hint (hidden := true) "You might again want to start by induction
on the right-most variable."
Branch
induction a
Hint "Induction on `a` will not work."
induction b with d hd
· rw [add_zero]
rfl
· rw [add_succ]
rw [hd]
rw [add_succ]
rfl
NewLemma MyNat.add_assoc
Conclusion
"
"
@@ -0,0 +1,60 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.Levels.Addition.Level_3
Game "NNG"
World "Addition"
Level 4
Title "`add_comm` (boss level)"
open MyNat
theorem MyNat.succ_add (a b : ℕ) : succ a + b = succ (a + b) := by
induction b with d hd
· rw [add_zero]
rfl
· rw [add_succ]
rw [hd]
rw [add_succ]
rfl
Introduction
"
[boss battle music]
Look in your inventory to see the proofs you have available.
These should be enough.
"
Statement add_comm
"On the set of natural numbers, addition is commutative.
In other words, for all natural numbers $a$ and $b$, we have
$a + b = b + a$."
(a b : ℕ) : a + b = b + a := by
Branch
induction a with d hd
· rw [zero_add]
rw [add_zero]
rfl
· rw [succ_add]
rw [hd]
rw [add_succ]
rfl
induction b with d hd
· rw [zero_add]
rw [add_zero]
rfl
· rw [add_succ]
rw [hd]
rw [succ_add]
rfl
NewLemma MyNat.succ_add
Conclusion
"
If you got this far -- nice! You're nearly ready to make a choice:
Multiplication World or Function World. But there are just a couple
more useful lemmas in Addition World which you should prove first.
Press on to level 5.
"
@@ -0,0 +1,54 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.Levels.Addition.Level_4
Game "NNG"
World "Addition"
Level 5
Title "succ_eq_add_one"
open MyNat
theorem MyNat.add_comm (a b : ℕ) : a + b = b + a := by
induction b with d hd
· rw [zero_add]
rw [add_zero]
rfl
· rw [add_succ]
rw [hd]
rw [succ_add]
rfl
theorem MyNat.one_eq_succ_zero : (1 : ℕ) = succ 0 := by
rfl
NewLemma MyNat.add_comm MyNat.one_eq_succ_zero
Introduction
"
I've just added `one_eq_succ_zero` (a proof of $1 = \\operatorname{succ}(0)$)
to your list of theorems; this is true
by definition of $1$, but we didn't need it until now.
Levels 5 and 6 are the two last levels in Addition World.
Level 5 involves the number $1$. When you see a $1$ in your goal,
you can write `rw [one_eq_succ_zero]` to get back
to something which only mentions `0`. This is a good move because $0$ is easier for us to
manipulate than $1$ right now, because we have
some theorems about $0$ (`zero_add`, `add_zero`), but, other than `1 = succ 0`,
no theorems at all which mention $1$. Let's prove one now.
"
Statement succ_eq_add_one
"For any natural number $n$, we have
$ \\operatorname{succ}(n) = n+1$ ."
(n : ℕ) : succ n = n + 1 := by
rw [one_eq_succ_zero]
rw [add_succ]
rw [add_zero]
rfl
Conclusion
"
Well done! On to the last level!
"
@@ -0,0 +1,47 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.Levels.Addition.Level_5
Game "NNG"
World "Addition"
Level 6
Title "add_right_comm"
open MyNat
Introduction
"
Lean sometimes writes `a + b + c`. What does it mean? The convention is
that if there are no brackets displayed in an addition formula, the brackets
are around the left most `+` (Lean's addition is \"left associative\").
So the goal in this level is `(a + b) + c = (a + c) + b`. This isn't
quite `add_assoc` or `add_comm`, it's something you'll have to prove
by putting these two theorems together.
If you hadn't picked up on this already, `rw [add_assoc]` will
change `(x + y) + z` to `x + (y + z)`, but to change it back
you will need `rw [← add_assoc]`. Get the left arrow by typing `\\l`
then the space bar (note that this is L for left, not a number 1).
Similarly, if `h : a = b` then `rw [h]` will change `a`'s to `b`'s
and `rw [← h]` will change `b`'s to `a`'s.
Also, you can be (and will need to be, in this level) more precise
about where to rewrite theorems. `rw add_comm,` will just find the
first `? + ?` it sees and swap it around. You can target more specific
additions like this: `rw add_comm a` will swap around
additions of the form `a + ?`, and `rw add_comm a b,` will only
swap additions of the form `a + b`.
"
Statement add_right_comm
"For all natural numbers $a, b$ and $c$, we have
$a + b + c = a + c + b$."
(a b c : ℕ) : a + b + c = a + c + b := by
rw [add_assoc]
rw [add_comm b c]
rw [←add_assoc]
rfl
Conclusion
"
"