split off test game
still need to adapt the call to the lean binary to provide two arguments
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import TestGame.Metadata
|
||||
|
||||
Level 1
|
||||
|
||||
Title "The reflexivity spell"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Let's learn a first spell: the `rfl` spell. `rfl` stands for \"reflexivity\", which is a fancy
|
||||
way of saying that it will prove any goal of the form `A = A`. It doesn't matter how
|
||||
complicated `A` is, all that matters is that the left hand side is *exactly equal* to the
|
||||
right hand side (a computer scientist would say \"definitionally equal\"). I really mean
|
||||
\"press the same buttons on your computer in the same order\" equal.
|
||||
For example, `x * y + z = x * y + z` can be proved by `rfl`, but `x + y = y + x` cannot.
|
||||
This is a very low level spell, but you need to start somewhere.
|
||||
|
||||
After closing this message, type rfl in the invocation zone and hit Enter or click
|
||||
the \"Cast spell\" button.
|
||||
"
|
||||
|
||||
Statement (x y z : ℕ) : x * y + z = x * y + z := by
|
||||
rfl
|
||||
|
||||
Conclusion "Congratulations for completing your first level! You can now click on the *Go to next level* button."
|
||||
|
||||
Tactics rfl
|
||||
@@ -0,0 +1,36 @@
|
||||
import TestGame.Metadata
|
||||
|
||||
Level 2
|
||||
|
||||
Title "The rewriting spell"
|
||||
|
||||
Introduction
|
||||
"
|
||||
The rewrite spell is the way to \"substitute in\" the value
|
||||
of an expression. In general, if you have a hypothesis of the form `A = B`, and your
|
||||
goal mentions the left hand side `A` somewhere, then
|
||||
the `rewrite` tactic will replace the `A` in your goal with a `B`.
|
||||
|
||||
The documentation for `rewrite` just appeared in your spell book.
|
||||
Play around with the menus and see what is there currently.
|
||||
More information will appear as you progress.
|
||||
|
||||
Take a look in the top right box at what we have.
|
||||
The variables $x$ and $y$ are natural numbers, and we have
|
||||
an assumption `h` that $y = x + 7$. Our goal
|
||||
is to prove that $2y=2(x+7)$. This goal is obvious -- we just
|
||||
substitute in $y = x+7$ and we're done. In Lean, we do
|
||||
this substitution using the `rewrite` spell. This spell takes a list of equalities
|
||||
or equivalences so you can cast `rewrite [h]`.
|
||||
"
|
||||
|
||||
Statement (x y : ℕ) (h : y = x + 7) : 2 * y = 2 * (x + 7) := by
|
||||
rewrite [h]
|
||||
rfl
|
||||
|
||||
Message (x : ℕ) (y : ℕ) (h : y = x + 7) : 2*(x + 7) = 2*(x + 7) =>
|
||||
"Great! Now the goal should be easy to reach using the `rfl` spell."
|
||||
|
||||
Conclusion "Congratulations for completing your second level!"
|
||||
|
||||
Tactics rfl rewrite
|
||||
@@ -0,0 +1,81 @@
|
||||
import TestGame.Metadata
|
||||
|
||||
Level 3
|
||||
|
||||
Title "Peano's axioms"
|
||||
|
||||
Introduction
|
||||
"
|
||||
The team that salvaged the type `ℕ` of natural numbers actually got us three things:
|
||||
|
||||
* a term `0 : ℕ`, interpreted as the number zero.
|
||||
* a function `succ : ℕ → ℕ`, with `succ n` interpreted as \"the number after $n$\".
|
||||
* The principle of mathematical induction.
|
||||
|
||||
These are essentially the axioms isolated by Peano which uniquely characterise
|
||||
the natural numbers (we also need recursion, but we can ignore it for now).
|
||||
The first axiom says that $0$ is a natural number. The second says that there
|
||||
is a `succ` function which eats a number and spits out the number after it,
|
||||
so $\\operatorname{succ}(0)=1$, $\\operatorname{succ}(1)=2$ and so on.
|
||||
|
||||
Peano's last axiom is the principle of mathematical induction. This is a deeper
|
||||
fact. It says that if we have infinitely many true/false statements $P(0)$, $P(1)$,
|
||||
$P(2)$ and so on, and if $P(0)$ is true, and if for every natural number $d$
|
||||
we know that $P(d)$ implies $P(\\operatorname{succ}(d))$, then $P(n)$ must be true for every
|
||||
natural number $n$. It's like saying that if you have a long line of dominoes, and if
|
||||
you knock the first one down, and if you know that if a domino falls down then the one
|
||||
after it will fall down too, then you can deduce that all the dominos will fall down.
|
||||
One can also think of it as saying that every natural number
|
||||
can be built by starting at `0` and then applying `succ` a finite number of times.
|
||||
|
||||
Peano's insights were firstly that these axioms completely characterise
|
||||
the natural numbers, and secondly that these axioms alone can be used to build
|
||||
a whole bunch of other structure on the natural numbers, for example
|
||||
addition, multiplication and so on.
|
||||
|
||||
This game is all about seeing how far these axioms of Peano can take us.
|
||||
|
||||
Let's practice our use of the `rewrite` tactic in the following example.
|
||||
Our hypothesis `h` is a proof that `succ(a) = b` and we want to prove that
|
||||
`succ(succ(a))=succ(b)`. In words, we're going to prove that if
|
||||
`b` is the number after `a` then `succ(b)` is the number after `succ(a)`.
|
||||
Note that the system drops brackets when they're not
|
||||
necessary, so `succ b` just means `succ(b)`.
|
||||
|
||||
Now here's a tricky question. Knowing that our goal is `succ (succ a) = succ b`,
|
||||
and our assumption is `h : succ a = b`, then what will the goal change
|
||||
to when we type
|
||||
|
||||
`rewrite [h]`
|
||||
|
||||
and hit enter? Remember that `rewrite [h]` will
|
||||
look for the *left* hand side of `h` in the goal, and will replace it with
|
||||
the *right* hand side. Try and figure out how the goal will change, and
|
||||
then try it.
|
||||
"
|
||||
|
||||
Statement (a b : ℕ) (h : succ a = b) : succ (succ a) = succ b := by
|
||||
rewrite [h]
|
||||
rfl
|
||||
|
||||
Message (a : ℕ) (b : ℕ) (h : succ a = b) : succ b = succ b =>
|
||||
"
|
||||
Look: Lean changed `succ a` into `b`, so the goal became `succ b = succ b`.
|
||||
That goal is of the form `X = X`, so you know what to do.
|
||||
"
|
||||
|
||||
|
||||
Conclusion "Congratulations for completing the third level!
|
||||
You may be wondering whether we could have just substituted in the definition of `b`
|
||||
and proved the goal that way. To do that, we would want to replace the right hand
|
||||
side of `h` with the left hand side. You do this in Lean by writing `rewrite [<- h]`. You get the
|
||||
left-arrow by typing `\\l` and then a space; note that this is a small letter L,
|
||||
not a number 1. You can just edit your proof and try it.
|
||||
|
||||
You may also be wondering why we keep writing `succ(b)` instead of `b+1`. This
|
||||
is because we haven't defined addition yet! On the next level, the final level
|
||||
of the tutorial, we will introduce addition, and then
|
||||
we'll be ready to enter Addition World.
|
||||
"
|
||||
|
||||
Tactics rfl rewrite
|
||||
@@ -0,0 +1,62 @@
|
||||
import TestGame.Metadata
|
||||
|
||||
Level 4
|
||||
|
||||
Title "Addition"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Peano defined addition `a + b` by induction on `b`, or,
|
||||
more precisely, by *recursion* on `b`. He first explained how to add 0 to a number:
|
||||
this is the base case.
|
||||
|
||||
* `add_zero (a : ℕ) : a + 0 = a`
|
||||
|
||||
We will call this theorem `add_zero`. It has just appeared in your inventory!
|
||||
Mathematicians sometimes call it \"Lemma 2.1\" or \"Hypothesis P6\" or something. But
|
||||
computer scientists call it `add_zero` because it tells you
|
||||
what the answer to \"$x$ add zero\" is. It's a *much* better name than \"Lemma 2.1\".
|
||||
Even better, we can use the rewrite tactic with `add_zero`.
|
||||
If you ever see `x + 0` in your goal, `rewrite [add_zero]` will simplify it to `x`.
|
||||
This is because `add_zero` is a proof that `x + 0 = x` (more precisely,
|
||||
`add_zero x` is a proof that `x + 0 = x` but Lean can figure out the `x` from the context).
|
||||
|
||||
Now here's the inductive step. If you know how to add `d` to `a`, then
|
||||
Peano tells you how to add `succ(d)` to `a`. It looks like this:
|
||||
|
||||
* `add_succ (a d : ℕ) : a + succ(d) = succ (a + d)`
|
||||
|
||||
What's going on here is that we assume `a + d` is already
|
||||
defined, and we define `a + succ(d)` to be the number after it.
|
||||
This is also in your inventory now -- `add_succ` tells you
|
||||
how to add a successor to something. If you ever see `... + succ ...`
|
||||
in your goal, you should be able to use `rewrite [add_succ]` to make
|
||||
progress. Here is a simple example where we shall see both. Let's prove
|
||||
that $x$ add the number after $0$ is the number after $x$.
|
||||
|
||||
Observe that the goal mentions `... + succ ...`. So type
|
||||
|
||||
`rewrite [add_succ]`
|
||||
|
||||
and hit enter; see the goal change.
|
||||
"
|
||||
|
||||
Statement (a : ℕ ) : a + succ 0 = succ a := by
|
||||
rewrite [add_succ]
|
||||
rewrite [add_zero]
|
||||
rfl
|
||||
|
||||
Message (a : ℕ) : succ (a + 0) = succ a => "
|
||||
Do you see that the goal now mentions ` ... + 0 ...`? So type
|
||||
|
||||
`rewrite [add_zero]`
|
||||
|
||||
and try to finish the level alone from there.
|
||||
"
|
||||
|
||||
Conclusion "Congratulations for completing your fourth level! This is the end of the tutorial part
|
||||
of the game. Serious things start in the next level."
|
||||
|
||||
Tactics rfl rewrite
|
||||
|
||||
Lemmas add_succ add_zero
|
||||
@@ -0,0 +1,125 @@
|
||||
import TestGame.Metadata
|
||||
import TestGame.Tactics
|
||||
|
||||
Level 5
|
||||
|
||||
Title "The induction_on spell"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Welcome to Addition World. If you've done all four levels in tutorial world
|
||||
and know about `rewrite` and `rfl`, then you're in the right place. Here's
|
||||
a reminder of the things you're now equipped with which we'll need in this world.
|
||||
|
||||
## Data:
|
||||
|
||||
* a type called `ℕ`
|
||||
* a term `0 : ℕ`, interpreted as the number zero.
|
||||
* a function `succ : ℕ → ℕ`, with `succ n` interpreted as \"the number after `n`\".
|
||||
* Usual numerical notation 0,1,2 etc (although 2 onwards will be of no use to us until much later ;-) ).
|
||||
* Addition (with notation `a + b`).
|
||||
|
||||
## Theorems:
|
||||
|
||||
* `add_zero (a : ℕ) : a + 0 = a`. Use with `rewrite [add_zero]`.
|
||||
* `add_succ (a b : ℕ) : a + succ(b) = succ(a + b)`. Use with `rewrite [add_succ]`.
|
||||
* The principle of mathematical induction. Use with `induction_on` (see below)
|
||||
|
||||
|
||||
## Spells:
|
||||
|
||||
* `rfl` : proves goals of the form `X = X`
|
||||
* `rewrite [h]` : if h is a proof of `A = B`, changes all A's in the goal to B's.
|
||||
* `induction_on n with d hd` : we're going to learn this right now.
|
||||
|
||||
# Important thing:
|
||||
|
||||
This is a *really* good time to check you understand about the spell book and the inventory on
|
||||
the left. Eveything you need is collected in those lists. They
|
||||
will prove invaluable as the number of theorems we prove gets bigger. On the other hand,
|
||||
we only need to learn one more spell to really start going places, so let's learn about
|
||||
that spell right now.
|
||||
|
||||
OK so let's see induction in action. We're going to prove
|
||||
|
||||
`zero_add (n : ℕ) : 0 + n = n`.
|
||||
|
||||
That is: for all natural numbers $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_on` is the only other spell 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
|
||||
(indeed, if you've opened the Addition World theorem statements on the left, you can even see 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`.
|
||||
|
||||
Start by casting `induction_on n`.
|
||||
"
|
||||
|
||||
Statement (n : ℕ) : 0 + n = n := by
|
||||
induction_on n
|
||||
rewrite [add_zero]
|
||||
rfl
|
||||
rewrite [add_succ]
|
||||
rewrite [ind_hyp]
|
||||
rfl
|
||||
|
||||
Message : (0 : ℕ) + 0 = 0 => "
|
||||
We now have *two goals!* The
|
||||
induction spell has generated for us a base case with `n = 0` (the goal at the top)
|
||||
and an inductive step (the goal underneath). The golden rule: **spells operate on the current goal** --
|
||||
the goal at the top. So let's just worry about that top goal now, the base case `0 + 0 = 0`.
|
||||
|
||||
Remember that `add_zero` (the proof we have already) is the proof of `x + 0 = x`
|
||||
(for any $x$) so we can try
|
||||
|
||||
`rewrite [add_zero]`
|
||||
|
||||
What do you think the goal will change to? Remember to just keep
|
||||
focussing on the top goal, ignore the other one for now, it's not changing
|
||||
and we're not working on it.
|
||||
"
|
||||
|
||||
Message (n : ℕ) (ind_hyp: 0 + n = n) : 0 + succ n = succ n =>
|
||||
"
|
||||
Great! You solved the base case. We are now be back down
|
||||
to one goal -- the inductive step.
|
||||
|
||||
We have a fixed natural number `n`, and the inductive hypothesis `ind_hyp : 0 + n = n`
|
||||
saying that we have a proof of `0 + n = n`.
|
||||
Our goal is to prove `0 + succ n = succ n`. In words, we're showing that
|
||||
if the lemma is true for `n`, then it's also true for the number after `n`.
|
||||
That's the inductive step. Once we've proved this inductive step, we will have proved
|
||||
`zero_add` by the principle of mathematical induction.
|
||||
|
||||
To prove our goal, we need to use `add_succ`. We know that `add_succ 0 n`
|
||||
is the result that `0 + succ n = succ (0 + n)`, so the first thing
|
||||
we need to do is to replace the left hand side `0 + succ n` of our
|
||||
goal with the right hand side. We do this with the `rewrite` spell. You can write
|
||||
|
||||
`rewrite [add_succ]`
|
||||
|
||||
(or even `rewrite [add_succ 0 n]` if you want to give Lean all the inputs instead of making it
|
||||
figure them out itself).
|
||||
"
|
||||
|
||||
Message (n : ℕ) (ind_hyp: 0 + n = n) : succ (0 + n) = succ n =>
|
||||
"Well-done! We're almost there. It's time to use our induction hypothesis.
|
||||
Cast
|
||||
|
||||
`rewrite [ind_hyp]`
|
||||
|
||||
and finish by yourself.
|
||||
"
|
||||
|
||||
Conclusion "Congratulations for completing your first inductive proof!"
|
||||
|
||||
Tactics rfl rewrite induction_on
|
||||
|
||||
Lemmas add_succ add_zero
|
||||
Reference in New Issue
Block a user