move all WIP files to level-rewrite branch
This commit is contained in:
41
Game/Levels/OldAdvProposition/Level_1.lean
Normal file
41
Game/Levels/OldAdvProposition/Level_1.lean
Normal file
@@ -0,0 +1,41 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 1
|
||||
Title "the `split` tactic"
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
The logical symbol `∧` means \"and\". If $P$ and $Q$ are propositions, then
|
||||
$P\\land Q$ is the proposition \"$P$ and $Q$\".
|
||||
"
|
||||
namespace MySet
|
||||
|
||||
/-- If $P$ and $Q$ are true, then $P\\land Q$ is true. -/
|
||||
Statement
|
||||
(P Q : Prop) (p : P) (q : Q) : P ∧ Q := by
|
||||
Hint "If your *goal* is `P ∧ Q` then
|
||||
you can make progress with the `constructor` tactic, which turns one goal `P ∧ Q`
|
||||
into two goals, namely `P` and `Q`."
|
||||
constructor
|
||||
Hint "Now you have two goals. The first one is `P`, which you can proof now. The
|
||||
second one is `Q` and you see it in the queue \"Other Goals\". You will have to prove it afterwards."
|
||||
Hint (hidden := true) "This first goal can be proved with `exact p`."
|
||||
exact p
|
||||
-- Hint "Observe that now the first goal has been proved, so it disappears and you continue
|
||||
-- proving the second goal."
|
||||
-- Hint (hidden := true) "Like the first goal, this is a case for `exact`."
|
||||
-- -- TODO: It looks like these hints get shown above as well, but weirdly the hints from
|
||||
-- -- above to not get shown here.
|
||||
exact q
|
||||
|
||||
NewTactic constructor
|
||||
NewDefinition And
|
||||
|
||||
Conclusion
|
||||
"
|
||||
"
|
||||
64
Game/Levels/OldAdvProposition/Level_10.lean
Normal file
64
Game/Levels/OldAdvProposition/Level_10.lean
Normal file
@@ -0,0 +1,64 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 10
|
||||
Title "The law of the excluded middle."
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
We proved earlier that `(P → Q) → (¬ Q → ¬ P)`. The converse,
|
||||
that `(¬ Q → ¬ P) → (P → Q)` is certainly true, but trying to prove
|
||||
it using what we've learnt so far is impossible (because it is not provable in
|
||||
constructive logic).
|
||||
|
||||
"
|
||||
|
||||
/-- If $P$ and $Q$ are true/false statements, then
|
||||
$$(\\lnot Q\\implies \\lnot P)\\implies(P\\implies Q).$$
|
||||
-/
|
||||
Statement
|
||||
(P Q : Prop) : (¬ Q → ¬ P) → (P → Q) := by
|
||||
Hint "For example, you could start as always with
|
||||
|
||||
```
|
||||
intro h p
|
||||
```
|
||||
"
|
||||
intro h p
|
||||
Hint "From here there is no way to continue with the tactics you've learned so far.
|
||||
|
||||
Instead you can call `by_cases q : Q`. This creates **two goals**, once under the assumption
|
||||
that `Q` is true, once assuming `Q` is false."
|
||||
by_cases q : Q
|
||||
Hint "This first case is trivial."
|
||||
exact q
|
||||
Hint "The second case needs a bit more work, but you can get there with the tactics you've already
|
||||
learned beforehand!"
|
||||
have j := h q
|
||||
exfalso
|
||||
apply j
|
||||
exact p
|
||||
|
||||
NewTactic by_cases
|
||||
|
||||
Conclusion
|
||||
"
|
||||
This approach assumed that `P ∨ ¬ P` is true, which is called \"law of excluded middle\".
|
||||
It cannot be proven using just tactics like `intro` or `apply`.
|
||||
`by_cases p : P` just does `rcases` on this result `P ∨ ¬ P`.
|
||||
|
||||
|
||||
OK that's enough logic -- now perhaps it's time to go on to Advanced Addition World!
|
||||
Get to it via the main menu.
|
||||
"
|
||||
|
||||
-- TODO: I cannot really import `tauto` because of the notation `ℕ` that's used
|
||||
-- for `MyNat`.
|
||||
-- ## Pro tip
|
||||
|
||||
-- In fact the tactic `tauto` just kills this goal (and many other logic goals) immediately. You'll be
|
||||
-- able to use it from now on.
|
||||
48
Game/Levels/OldAdvProposition/Level_2.lean
Normal file
48
Game/Levels/OldAdvProposition/Level_2.lean
Normal file
@@ -0,0 +1,48 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 2
|
||||
Title "the `rcases` tactic"
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
If `P ∧ Q` is in the goal, then we can make progress with `constructor`.
|
||||
But what if `P ∧ Q` is a hypothesis? In this case, the `rcases` tactic will enable
|
||||
us to extract proofs of `P` and `Q` from this hypothesis.
|
||||
"
|
||||
|
||||
/-- If $P$ and $Q$ are true/false statements, then $P\\land Q\\implies Q\\land P$. -/
|
||||
Statement -- and_symm
|
||||
(P Q : Prop) : P ∧ Q → Q ∧ P := by
|
||||
Hint "The lemma below asks us to prove `P ∧ Q → Q ∧ P`, that is,
|
||||
symmetry of the \"and\" relation. The obvious first move is
|
||||
|
||||
```
|
||||
intro h
|
||||
```
|
||||
|
||||
because the goal is an implication and this tactic is guaranteed
|
||||
to make progress."
|
||||
intro h
|
||||
Hint "Now `{h} : P ∧ Q` is a hypothesis, and
|
||||
|
||||
```
|
||||
rcases {h} with ⟨p, q⟩
|
||||
```
|
||||
|
||||
will change `{h}`, the proof of `P ∧ Q`, into two proofs `p : P`
|
||||
and `q : Q`.
|
||||
|
||||
You can write `⟨p, q⟩` with `\\<>` or `\\<` and `\\>`. Note that `rcases h` by itself will just
|
||||
automatically name the new assumptions."
|
||||
rcases h with ⟨p, q⟩
|
||||
Hint "Now a combination of `constructor` and `exact` will get you home."
|
||||
constructor
|
||||
exact q
|
||||
exact p
|
||||
|
||||
NewTactic rcases
|
||||
46
Game/Levels/OldAdvProposition/Level_3.lean
Normal file
46
Game/Levels/OldAdvProposition/Level_3.lean
Normal file
@@ -0,0 +1,46 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 3
|
||||
Title "and_trans"
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
Here is another exercise to `rcases` and `constructor`.
|
||||
"
|
||||
|
||||
/-- If $P$, $Q$ and $R$ are true/false statements, then $P\\land Q$ and
|
||||
$Q\\land R$ together imply $P\\land R$. -/
|
||||
Statement --and_trans
|
||||
(P Q R : Prop) : P ∧ Q → Q ∧ R → P ∧ R := by
|
||||
Hint "Here's a trick:
|
||||
|
||||
Your first steps would probably be
|
||||
```
|
||||
intro h
|
||||
rcases h with ⟨p, q⟩
|
||||
```
|
||||
i.e. introducing a new assumption and then immediately take it appart.
|
||||
|
||||
In that case you could do that in a single step:
|
||||
|
||||
```
|
||||
intro ⟨p, q⟩
|
||||
```
|
||||
"
|
||||
intro hpq
|
||||
rcases hpq with ⟨p, q⟩
|
||||
intro hqr
|
||||
rcases hqr with ⟨q', r⟩
|
||||
constructor
|
||||
exact p
|
||||
exact r
|
||||
|
||||
Conclusion
|
||||
"
|
||||
|
||||
"
|
||||
45
Game/Levels/OldAdvProposition/Level_4.lean
Normal file
45
Game/Levels/OldAdvProposition/Level_4.lean
Normal file
@@ -0,0 +1,45 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 4
|
||||
Title ""
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
The mathematical statement $P\\iff Q$ is equivalent to $(P\\implies Q)\\land(Q\\implies P)$. The `rcases`
|
||||
and `constructor` tactics work on hypotheses and goals (respectively) of the form `P ↔ Q`. If you need
|
||||
to write an `↔` arrow you can do so by typing `\\iff`, but you shouldn't need to.
|
||||
|
||||
"
|
||||
|
||||
/-- If $P$, $Q$ and $R$ are true/false statements, then
|
||||
$P\\iff Q$ and $Q\\iff R$ together imply $P\\iff R$. -/
|
||||
Statement --iff_trans
|
||||
(P Q R : Prop) : (P ↔ Q) → (Q ↔ R) → (P ↔ R) := by
|
||||
Hint "Similar to \"and\", you can use `intro` and `rcases` to add the `P ↔ Q` to your
|
||||
assumptions and split it into its constituent parts."
|
||||
Branch
|
||||
intro hpq
|
||||
intro hqr
|
||||
Hint "Now you want to use `rcases {hpq} with ⟨pq, qp⟩`."
|
||||
rcases hpq with ⟨hpq, hqp⟩
|
||||
rcases hqr with ⟨hqr, hrq⟩
|
||||
intro ⟨pq, qp⟩
|
||||
intro ⟨qr, rq⟩
|
||||
Hint "If you want to prove an iff-statement, you can use `constructor` to split it
|
||||
into its two implications."
|
||||
constructor
|
||||
· intro p
|
||||
apply qr
|
||||
apply pq
|
||||
exact p
|
||||
· intro r
|
||||
apply qp
|
||||
apply rq
|
||||
exact r
|
||||
|
||||
NewDefinition Iff
|
||||
76
Game/Levels/OldAdvProposition/Level_5.lean
Normal file
76
Game/Levels/OldAdvProposition/Level_5.lean
Normal file
@@ -0,0 +1,76 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 5
|
||||
Title "Easter eggs."
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
Let's try this again. Try proving it in other ways. (Note that `rcases` is temporarily disabled.)
|
||||
|
||||
### A trick.
|
||||
|
||||
Instead of using `rcases` on `h : P ↔ Q` you can just access the proofs of `P → Q` and `Q → P`
|
||||
directly with `h.1` and `h.2`. So you can solve this level with
|
||||
|
||||
```
|
||||
intro hpq hqr
|
||||
constructor
|
||||
intro p
|
||||
apply hqr.1
|
||||
…
|
||||
```
|
||||
|
||||
### Another trick
|
||||
|
||||
Instead of using `rcases` on `h : P ↔ Q`, you can just `rw [h]`, and this will change all `P`s to `Q`s
|
||||
in the goal. You can use this to create a much shorter proof. Note that
|
||||
this is an argument for *not* running the `rcases` tactic on an iff statement;
|
||||
you cannot rewrite one-way implications, but you can rewrite two-way implications.
|
||||
|
||||
|
||||
"
|
||||
-- TODO
|
||||
-- ### Another trick
|
||||
-- `cc` works on this sort of goal too.
|
||||
|
||||
/-- If $P$, $Q$ and $R$ are true/false statements, then `P ↔ Q` and `Q ↔ R` together imply `P ↔ R`.
|
||||
-/
|
||||
Statement --iff_trans
|
||||
(P Q R : Prop) : (P ↔ Q) → (Q ↔ R) → (P ↔ R) := by
|
||||
intro hpq hqr
|
||||
Hint "Make a choice and continue either with `constructor` or `rw`.
|
||||
|
||||
* if you use `constructor`, you will use `{hqr}.1, {hqr}.2, …` later.
|
||||
* if you use `rw`, you can replace all `P`s with `Q`s using `rw [{hpq}]`"
|
||||
Branch
|
||||
rw [hpq]
|
||||
Branch
|
||||
exact hqr
|
||||
rw [hqr]
|
||||
Hint "Now `rfl` can close this goal.
|
||||
|
||||
TODO: Note that the current modification of `rfl` is too weak to prove this. For now, you can
|
||||
use `simp` instead (which calls the \"real\" `rfl` internally)."
|
||||
simp
|
||||
constructor
|
||||
intro p
|
||||
Hint "Now you can directly `apply {hqr}.1`"
|
||||
apply hqr.1
|
||||
apply hpq.1
|
||||
exact p
|
||||
intro r
|
||||
apply hpq.2
|
||||
apply hqr.2
|
||||
exact r
|
||||
|
||||
DisabledTactic rcases
|
||||
|
||||
Conclusion
|
||||
"
|
||||
|
||||
"
|
||||
38
Game/Levels/OldAdvProposition/Level_6.lean
Normal file
38
Game/Levels/OldAdvProposition/Level_6.lean
Normal file
@@ -0,0 +1,38 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 6
|
||||
Title "Or, and the `left` and `right` tactics."
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
`P ∨ Q` means \"$P$ or $Q$\". So to prove it, you
|
||||
need to choose one of `P` or `Q`, and prove that one.
|
||||
If `P ∨ Q` is your goal, then `left` changes this
|
||||
goal to `P`, and `right` changes it to `Q`.
|
||||
"
|
||||
-- Note that you can take a wrong turn here. Let's
|
||||
-- start with trying to prove $Q\\implies (P\\lor Q)$.
|
||||
-- After the `intro`, one of `left` and `right` leads
|
||||
-- to an impossible goal, the other to an easy finish.
|
||||
|
||||
/-- If $P$ and $Q$ are true/false statements, then $Q\\implies(P\\lor Q)$. -/
|
||||
Statement
|
||||
(P Q : Prop) : Q → (P ∨ Q) := by
|
||||
Hint (hidden := true) "Let's start with an initial `intro` again."
|
||||
intro q
|
||||
Hint "Now you need to choose if you want to prove the `left` or `right` side of the goal."
|
||||
Branch
|
||||
left
|
||||
-- TODO: This message is also shown on the correct track. Need strict hints.
|
||||
-- Hint "That was an unfortunate choice, you entered a dead end that cannot be proved anymore.
|
||||
-- Hit \"Undo\"!"
|
||||
right
|
||||
exact q
|
||||
|
||||
NewTactic left right
|
||||
NewDefinition Or
|
||||
55
Game/Levels/OldAdvProposition/Level_7.lean
Normal file
55
Game/Levels/OldAdvProposition/Level_7.lean
Normal file
@@ -0,0 +1,55 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 7
|
||||
Title "`or_symm`"
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
Proving that $(P\\lor Q)\\implies(Q\\lor P)$ involves an element of danger.
|
||||
"
|
||||
|
||||
/-- If $P$ and $Q$ are true/false statements, then
|
||||
$$P\\lor Q\\implies Q\\lor P.$$ -/
|
||||
Statement --or_symm
|
||||
(P Q : Prop) : P ∨ Q → Q ∨ P := by
|
||||
Hint "`intro h` is the obvious start."
|
||||
intro h
|
||||
Branch
|
||||
left
|
||||
Hint "This is a dead end that is not provable anymore. Hit \"undo\"."
|
||||
Branch
|
||||
right
|
||||
Hint "This is a dead end that is not provable anymore. Hit \"undo\"."
|
||||
Hint "But now, even though the goal is an `∨` statement, both `left` and `right` put
|
||||
you in a situation with an impossible goal. Fortunately,
|
||||
you can do `rcases h with p | q`. (that is a normal vertical slash)
|
||||
"
|
||||
rcases h with p | q
|
||||
Hint " Something new just happened: because
|
||||
there are two ways to prove the assumption `P ∨ Q` (namely, proving `P` or proving `Q`),
|
||||
the `rcases` tactic turns one goal into two, one for each case.
|
||||
|
||||
So now you proof the goal under the assumption that `P` is true, and waiting under \"Other Goals\"
|
||||
there is the same goal but under the assumption that `Q` is true.
|
||||
|
||||
You should be able to make it home from there. "
|
||||
right
|
||||
exact p
|
||||
Hint "Note how now you finished the first goal and jumped to the one, where you assume `Q`."
|
||||
left
|
||||
exact q
|
||||
|
||||
Conclusion
|
||||
"
|
||||
Well done! Note that the syntax for `rcases` is different whether it's an \"or\" or an \"and\".
|
||||
|
||||
* `rcases h with ⟨p, q⟩` splits an \"and\" in the assumptions into two parts. You get two assumptions
|
||||
but still only one goal.
|
||||
* `rcases h with p | q` splits an \"or\" in the assumptions. You get **two goals** which have different
|
||||
assumptions, once assumping the lefthand-side of the dismantled \"or\"-assumption, once the righthand-side.
|
||||
"
|
||||
53
Game/Levels/OldAdvProposition/Level_8.lean
Normal file
53
Game/Levels/OldAdvProposition/Level_8.lean
Normal file
@@ -0,0 +1,53 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 8
|
||||
Title "`and_or_distrib_left`"
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
We know that $x(y+z)=xy+xz$ for numbers, and this
|
||||
is called distributivity of multiplication over addition.
|
||||
The same is true for `∧` and `∨` -- in fact `∧` distributes
|
||||
over `∨` and `∨` distributes over `∧`. Let's prove one of these.
|
||||
"
|
||||
|
||||
/-- If $P$. $Q$ and $R$ are true/false statements, then
|
||||
$$P\\land(Q\\lor R)\\iff(P\\land Q)\\lor (P\\land R).$$ -/
|
||||
Statement --and_or_distrib_left
|
||||
(P Q R : Prop) : P ∧ (Q ∨ R) ↔ (P ∧ Q) ∨ (P ∧ R) := by
|
||||
constructor
|
||||
intro h
|
||||
rcases h with ⟨hp, hqr⟩
|
||||
rcases hqr with q | r
|
||||
left
|
||||
constructor
|
||||
exact hp
|
||||
exact q
|
||||
right
|
||||
constructor
|
||||
exact hp
|
||||
exact r
|
||||
intro h
|
||||
rcases h with hpq | hpr
|
||||
rcases hpq with ⟨p, q⟩
|
||||
constructor
|
||||
exact p
|
||||
left
|
||||
exact q
|
||||
rcases hpr with ⟨hp, hr⟩
|
||||
constructor
|
||||
exact hp
|
||||
right
|
||||
exact hr
|
||||
|
||||
|
||||
Conclusion
|
||||
"
|
||||
You already know enough to embark on advanced addition world. But the next two levels comprise
|
||||
just a couple more things.
|
||||
"
|
||||
52
Game/Levels/OldAdvProposition/Level_9.lean
Normal file
52
Game/Levels/OldAdvProposition/Level_9.lean
Normal file
@@ -0,0 +1,52 @@
|
||||
import Game.Metadata
|
||||
import Game.MyNat.Addition
|
||||
|
||||
|
||||
World "AdvProposition"
|
||||
Level 9
|
||||
Title "`exfalso` and proof by contradiction. "
|
||||
|
||||
open MyNat
|
||||
|
||||
Introduction
|
||||
"
|
||||
It's certainly true that $P\\land(\\lnot P)\\implies Q$ for any propositions $P$
|
||||
and $Q$, because the left hand side of the implication is false. But how do
|
||||
we prove that `False` implies any proposition $Q$? A cheap way of doing it in
|
||||
Lean is using the `exfalso` tactic, which changes any goal at all to `False`.
|
||||
You might think this is a step backwards, but if you have a hypothesis `h : ¬ P`
|
||||
then after `rw not_iff_imp_false at h,` you can `apply h,` to make progress.
|
||||
Try solving this level without using `cc` or `tauto`, but using `exfalso` instead.
|
||||
"
|
||||
|
||||
/-- If $P$ and $Q$ are true/false statements, then
|
||||
$$(P\\land(\\lnot P))\\implies Q.$$ -/
|
||||
Statement --contra
|
||||
(P Q : Prop) : (P ∧ ¬ P) → Q := by
|
||||
Hint "Start as usual with `intro ⟨p, np⟩`."
|
||||
Branch
|
||||
exfalso
|
||||
-- TODO: This hint needs to be strict
|
||||
-- Hint "Not so quick! Now you just threw everything away."
|
||||
intro h
|
||||
Hint "You should also call `rcases` on your assumption `{h}`."
|
||||
rcases h with ⟨p, np ⟩
|
||||
-- TODO: This hint should before the last `exact p` step again.
|
||||
Hint "Now you can call `exfalso` to throw away your goal `Q`. It will be replaced with `False` and
|
||||
which means you will have to prove a contradiction."
|
||||
Branch
|
||||
-- TODO: Would `contradiction` not be more useful to introduce than `exfalso`?
|
||||
contradiction
|
||||
exfalso
|
||||
Hint "Recall that `{np} : ¬ P` means `np : P → False`, which means you can simply `apply {np}` now.
|
||||
|
||||
You can also first call `rw [Not] at {np}` to make this step more explicit."
|
||||
Branch
|
||||
rw [Not] at np
|
||||
apply np
|
||||
exact p
|
||||
|
||||
-- TODO: `contradiction`?
|
||||
NewTactic exfalso
|
||||
-- DisabledTactic cc
|
||||
LemmaTab "Prop"
|
||||
Reference in New Issue
Block a user