nng levels

This commit is contained in:
Jon Eugster
2023-04-13 16:43:45 +02:00
parent 66fd600462
commit fec4005476
63 changed files with 1119 additions and 184 deletions
+31 -7
View File
@@ -1,24 +1,42 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 1
Title ""
Title "`succ_inj`. A function."
open MyNat
Introduction
"
Peano's original collection of axioms for the natural numbers contained two further
assumptions, which have not yet been mentioned in the game:
```
succ_inj {a b : mynat} :
succ(a) = succ(b) → a = b
zero_ne_succ (a : mynat) :
zero ≠ succ(a)
```
The reason they have not been used yet is that they are both implications,
that is,
of the form $P\\implies Q$. This is clear for `succ_inj a b`, which
says that for all $a$ and $b$ we have $succ(a)=succ(b)\\implies a=b$.
For `zero_ne_succ` the trick is that $X\ne Y$ is *defined to mean*
$X = Y\\implies{\\tt false}$. If you have played through Proposition world,
you now have the required Lean skills (i.e., you know the required
tactics) to work with these implications.
Let's finally learn how to use `succ_inj`. You should know a couple
of ways to prove the below -- one directly using an `exact`,
and one which uses an `apply` first. But either way you'll need to use `succ_inj`.
"
theorem MyNat.succ_inj {a b : ℕ} : succ a = succ b → a = b := by simp only [succ.injEq, imp_self]
theorem MyNat.zero_ne_succ (a : ℕ) : zero ≠ succ a := by simp only [ne_eq, not_false_iff]
Statement -- MyNat.succ_inj'
""
"For all naturals $a$ and $b$, if we assume $succ(a)=succ(b)$, then we can
deduce $a=b$."
{a b : ℕ} (hs : succ a = succ b) : a = b := by
exact succ_inj hs
@@ -26,5 +44,11 @@ NewLemma MyNat.succ_inj MyNat.zero_ne_succ
Conclusion
"
## Important thing.
You can rewrite proofs of *equalities*. If `h : A = B` then `rw h` changes `A`s to `B`s.
But you *cannot rewrite proofs of implications*. `rw succ_inj` will *never work*
because `succ_inj` isn't of the form $A = B$, it's of the form $A\\implies B$. This is one
of the most common mistakes I see from beginners. $\\implies$ and $=$ are *two different things*
and you need to be clear about which one you are using.
"
@@ -1,22 +1,74 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
import NNG.MyNat.Multiplication
Game "NNG"
World "AdvAddition"
Level 10
Title ""
Title "add_left_eq_zero"
open MyNat
Introduction
"
In Lean, `a ≠ b` is *defined to mean* `(a = b) → false`.
This means that if you see `a ≠ b` you can *literally treat
it as saying* `(a = b) → false`. Computer scientists would
say that these two terms are *definitionally equal*.
The following lemma, $a+b=0\\implies b=0$, will be useful in inequality world.
Let me go through the proof, because it introduces several new
concepts:
* `cases b`, where `b : mynat`
* `exfalso`
* `apply succ_ne_zero`
We're going to prove $a+b=0\\implies b=0$. Here is the
strategy. Each natural number is either `0` or `succ(d)` for
some other natural number `d`. So we can start the proof
with
`cases b with d,`
and then we have two goals, the case `b = 0` (which you can solve easily)
and the case `b = succ(d)`, which looks like this:
```
a d : mynat,
H : a + succ d = 0
⊢ succ d = 0
```
Our goal is impossible to prove. However our hypothesis `H`
is also impossible, meaning that we still have a chance!
First let's see why `H` is impossible. We can
`rw add_succ at H,`
to turn `H` into `H : succ (a + d) = 0`. Because
`succ_ne_zero (a + d)` is a proof that `succ (a + d) ≠ 0`,
it is also a proof of the implication `succ (a + d) = 0 → false`.
Hence `succ_ne_zero (a + d) H` is a proof of `false`!
Unfortunately our goal is not `false`, it's a generic
false statement.
Recall however that the `exfalso` command turns any goal into `false`
(it's logically OK because `false` implies every proposition, true or false).
You can probably take it from here.
"
Statement
""
: true := by
trivial
Statement -- add_left_eq_zero
"If $a$ and $b$ are natural numbers such that
$$ a + b = 0, $$
then $b = 0$."
{{a b : ℕ}} (H : a + b = 0) : b = 0 := by
induction b with d
rfl
rw [add_succ] at H
exfalso
apply succ_ne_zero (a + d)
exact H
Conclusion
"
@@ -1,22 +1,29 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 11
Title ""
Title "add_right_eq_zero"
open MyNat
theorem MyNat.add_left_eq_zero {{a b : ℕ}} (H : a + b = 0) : b = 0 := by sorry
Introduction
"
We just proved `add_left_eq_zero (a b : mynat) : a + b = 0 → b = 0`.
Hopefully `add_right_eq_zero` shouldn't be too hard now.
"
Statement
""
: true := by
trivial
"If $a$ and $b$ are natural numbers such that
$$ a + b = 0, $$
then $a = 0$."
{a b : ℕ} : a + b = 0 → a = 0 := by
intro H
rw [add_comm] at H
exact add_left_eq_zero H
Conclusion
"
@@ -1,22 +1,30 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 12
Title ""
Title "add_one_eq_succ"
open MyNat
Introduction
"
We have
* `succ_eq_add_one (n : mynat) : succ n = n + 1`
but sometimes the other way is also convenient.
"
theorem succ_eq_add_one (d : ℕ) : succ d = d + 1 := by sorry
Statement
""
: true := by
trivial
"For any natural number $d$, we have
$$ d+1 = \\operatorname{succ}(d). $$"
(d : ℕ) : d + 1 = succ d := by
rw [succ_eq_add_one]
rfl
Conclusion
"
@@ -1,22 +1,32 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 13
Title ""
Title "ne_succ_self"
open MyNat
Introduction
"
The last level in Advanced Addition World is the statement
that $n\\not=\\operatorname{succ}(n)$. When you've done this
you've completed Advanced Addition World and can move on
to Advanced Multiplication World (after first doing
Multiplication World, if you didn't do it already).
"
Statement
""
: true := by
trivial
Statement --ne_succ_self
"For any natural number $n$, we have
$$ n \\neq \\operatorname{succ}(n). $$"
(n : ℕ) : n ≠ succ n := by
induction n with d hd
apply zero_ne_succ
intro hs
apply hd
apply succ_inj
assumption
Conclusion
"
+35 -6
View File
@@ -1,24 +1,53 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 2
Title ""
Title "succ_succ_inj"
open MyNat
Introduction
"
In the below theorem, we need to apply `succ_inj` twice. Once to prove
$succ(succ(a))=succ(succ(b))\\implies succ(a)=succ(b)$, and then again
to prove $succ(a)=succ(b)\\implies a=b$. However `succ(a)=succ(b)` is
nowhere to be found, it's neither an assumption or a goal when we start
this level. You can make it with `have` or you can use `apply`.
"
Statement
""
: true := by
trivial
"For all naturals $a$ and $b$, if we assume $succ(succ(a))=succ(succ(b))$, then we can
deduce $a=b$. "
{a b : ℕ} (h : succ (succ a) = succ ( succ b )) : a = b := by
apply succ_inj
apply succ_inj
assumption
Conclusion
"
## Sample solutions to this level.
Make sure you understand them all. And remember that `rw` should not be used
with `succ_inj` -- `rw` works only with equalities or `↔` statements,
not implications or functions.
example {a b : mynat} (h : succ(succ(a)) = succ(succ(b))) : a = b :=
begin
apply succ_inj,
apply succ_inj,
exact h
end
example {a b : mynat} (h : succ(succ(a)) = succ(succ(b))) : a = b :=
begin
apply succ_inj,
exact succ_inj(h),
end
example {a b : mynat} (h : succ(succ(a)) = succ(succ(b))) : a = b :=
begin
exact succ_inj(succ_inj(h)),
end
"
+12 -6
View File
@@ -1,22 +1,28 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 3
Title ""
Title "succ_eq_succ_of_eq"
open MyNat
Introduction
"
We are going to prove something completely obvious: if $a=b$ then
$succ(a)=succ(b)$. This is *not* `succ_inj`!
This is trivial -- we can just rewrite our proof of `a=b`.
But how do we get to that proof? Use the `intro` tactic.
"
Statement
""
: true := by
trivial
"For all naturals $a$ and $b$, $a=b\\implies succ(a)=succ(b)$.
"
{a b : ℕ} : a = b → succ a = succ b := by
intro h
rw [h]
rfl
Conclusion
"
+23 -5
View File
@@ -1,22 +1,40 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 4
Title ""
Title "eq_iff_succ_eq_succ"
open MyNat
Introduction
"
Here is an `iff` goal. You can split it into two goals (the implications in both
directions) using the `split` tactic, which is how you're going to have to start.
`split,`
Now you have two goals. The first is exactly `succ_inj` so you can close
it with
`exact succ_inj,`
and the second one you could solve by looking up the name of the theorem
you proved in the last level and doing `exact <that name>`, or alternatively
you could get some more `intro` practice and seeing if you can prove it
using `intro`, `rw` and `refl`.
"
Statement
""
: true := by
trivial
"Two natural numbers are equal if and only if their successors are equal.
"
(a b : ℕ) : succ a = succ b ↔ a = b := by
constructor
exact succ_inj
intro H
rw [H]
rfl
Conclusion
"
+20 -6
View File
@@ -1,22 +1,36 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 5
Title ""
Title "add_right_cancel"
open MyNat
Introduction
"
The theorem `add_right_cancel` is the theorem that you can cancel on the right
when you're doing addition -- if `a + t = b + t` then `a = b`. After `intro h`
I'd recommend induction on `t`. Don't forget that `rw add_zero at h` can be used
to do rewriting of hypotheses rather than the goal.
"
Statement
""
: true := by
trivial
"On the set of natural numbers, addition has the right cancellation property.
In other words, if there are natural numbers $a, b$ and $c$ such that
$$ a + t = b + t, $$
then we have $a = b$."
(a t b : ℕ) : a + t = b + t → a = b := by
intro h
induction t with d hd
rw [add_zero] at h
rw [add_zero] at h
exact h
apply hd
rw [add_succ] at h
rw [add_succ] at h
exact succ_inj h
Conclusion
"
+15 -5
View File
@@ -1,22 +1,32 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 6
Title ""
Title "add_left_cancel"
open MyNat
Introduction
"
The theorem `add_left_cancel` is the theorem that you can cancel on the left
when you're doing addition -- if `t + a = t + b` then `a = b`.
There is a three-line proof which ends in `exact add_right_cancel a t b` (or even
`exact add_right_cancel _ _ _`); this
strategy involves changing the goal to the statement of `add_right_cancel` somehow.
"
Statement
""
: true := by
trivial
"On the set of natural numbers, addition has the left cancellation property.
In other words, if there are natural numbers $a, b$ and $t$ such that
$$ t + a = t + b, $$
then we have $a = b$."
(t a b : ℕ) : t + a = t + b → a = b := by
rw [add_comm]
rw [add_comm t]
exact add_right_cancel a t b
Conclusion
"
+18 -7
View File
@@ -1,23 +1,34 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 7
Title ""
Title "add_right_cancel_iff"
open MyNat
Introduction
"
It's sometimes convenient to have the \"if and only if\" version
of theorems like `add_right_cancel`. Remember that you can use `split`
to split an `↔` goal into the `→` goal and the `←` goal.
## Pro tip:
`exact add_right_cancel _ _ _` means \"let Lean figure out the missing inputs\"
"
Statement
""
: true := by
trivial
Statement --add_right_cancel_iff
"For all naturals $a$, $b$ and $t$,
$$ a + t = b + t\\iff a=b. $$
"
(t a b : ℕ) : a + t = b + t ↔ a = b := by
constructor
exact add_right_cancel _ _ _ -- done that way already,
intro H -- H : a = b,
rw [H]
rfl
Conclusion
"
+14 -7
View File
@@ -1,22 +1,29 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 8
Title ""
Title "eq_zero_of_add_right_eq_self"
open MyNat
Introduction
"
The lemma you're about to prove will be useful when we want to prove that $\\leq$ is antisymmetric.
There are some wrong paths that you can take with this one.
"
Statement
""
: true := by
trivial
Statement --eq_zero_of_add_right_eq_self
"If $a$ and $b$ are natural numbers such that
$$ a + b = a, $$
then $b = 0$."
{a b : ℕ} : a + b = a → b = 0 := by
intro h
apply add_left_cancel a
rw [h]
rw [add_zero]
rfl
Conclusion
"
+16 -6
View File
@@ -1,22 +1,32 @@
import NNG.Metadata
import NNG.MyNat.Addition
import NNG.MyNat.AdvAddition
Game "NNG"
World "AdvAddition"
Level 9
Title ""
Title "succ_ne_zero"
open MyNat
Introduction
"
Levels 9 to 13 introduce the last axiom of Peano, namely
that $0\\not=\\operatorname{succ}(a)$. The proof of this is called `zero_ne_succ a`.
`zero_ne_succ (a : mynat) : 0 ≠ succ(a)`
The `symmetry` tactic will turn any goal of the form `R x y` into `R y x`,
if `R` is a symmetric binary relation (for example `=` or `≠`).
In particular, you can prove `succ_ne_zero` below by first using
`symmetry` and then `exact zero_ne_succ a`.
"
Statement
""
: true := by
trivial
Statement -- succ_ne_zero
"Zero is not the successor of any natural number."
(a : ℕ) : succ a ≠ 0 := by
apply Ne.symm
exact zero_ne_succ a
Conclusion
"