nng levels
This commit is contained in:
@@ -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
|
||||
"
|
||||
|
||||
@@ -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
|
||||
"
|
||||
|
||||
@@ -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
|
||||
"
|
||||
|
||||
@@ -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
|
||||
"
|
||||
|
||||
@@ -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
|
||||
"
|
||||
|
||||
@@ -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
|
||||
"
|
||||
|
||||
@@ -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
|
||||
"
|
||||
|
||||
|
||||
@@ -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
|
||||
"
|
||||
|
||||
@@ -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
|
||||
"
|
||||
|
||||
Reference in New Issue
Block a user