story world 2 and 3

pull/54/head
Jon Eugster 2 years ago
parent 18f16bfe1c
commit 93114620c4

@ -6,7 +6,7 @@ import TestGame.Levels.Predicate
import TestGame.Levels.Contradiction
import TestGame.Levels.Prime
import TestGame.Levels.Sum
import TestGame.Levels.Induction
-- import TestGame.Levels.Induction
import TestGame.Levels.Numbers
import TestGame.Levels.Inequality
@ -34,9 +34,9 @@ Path Proposition → Implication → Predicate
Path Predicate → Contradiction → Sum → LeanStuff
Path LeanStuff → SetTheory → SetTheory2 → SetFunction
Path Predicate → Prime → Induction
Path Sum → Inequality → Induction
Path Inequality → LeanStuff
Path Predicate → Prime -- → Induction
Path Sum → Inequality -- → Induction
Path Inequality → Function
Path SetTheory2 → Numbers
Path Module → Basis → Module2

@ -34,8 +34,10 @@ hier bei `(h : A ↔ B)` heissen sie `h.mp` und `h.mpr`.
**Du**: Also `h.mp` ist `A → B`? Wieso `mp`?
**Operationsleiter**: Das steht Modulo Ponens, aber das ist doch nicht wichtig. Und das \"r\"
steht für \"reverse\" weils die Gegenrichtung ist.
**Operationsleiter**: \"Modulo Ponens\" ist ein lokaler Begriff hier,
aber das ist doch nicht wichtig.
**Robo**: Und das \"r\" in `mpr` stünde für \"reverse\" weils die Rückrichtung ist.
"
NewTactic constructor

@ -24,6 +24,11 @@ Statement (A B : Prop) : (A ↔ B) → (A → B) := by
**Robo**: Was du machen könntest ist mit `rcases h with ⟨mp, mpr⟩` die Annahme in zwei
Teile aufteilen."
Branch
intro a
Hint "**Robo**: Hier müsstest du jetzt `rw [←h]` oder `apply h.mp` benützen, aber der
Gehilfe will, dass du zwingend eine dritte Variante benützt. Geh doch einen
Schritt zurück so dass das Goal `A → B` ist."
rcases h with ⟨mp, mpr⟩
Hint (hidden := true) "**Du**: Ah und jetzt ist das Resultat in den Annahmen."
assumption
@ -32,7 +37,7 @@ Conclusion
"
**Gehilfe**: Ah danke! Und jetzt versteh ich auch die Zusammenhänge!
"
OnlyTactic intro rcases assumption
DisabledTactic rw apply tauto
-- -- TODO: The new `cases` works differntly. There is also `cases'`

@ -15,28 +15,6 @@ Ihr setzt euch hin und der Gehilfe bringt euch allen Suppe. Neben euch sitzt ein
über ihre Suppe geneigt.
**Mechanikerin**: Sagt mal, ich hab unten über folgendes tiefgründiges Problem nachgedacht:
Bewiesene Resultate möchte man in späteren Aufgaben als Sätze wieder verwenden.
In Lean sind das Lemmas und Theoreme (wobei es keinen Unterschied zwischen `lemma` und `theorem`
gibt).
Links in der Bibliothek findest du bekannte Lemmas. Wenn das Goal mit der Aussage des Lemmas
übereinstimmt, kannst du es mit `apply [Lemma-Name]` anwenden, wie du das mit Implikationen auch
machst.
Zum Beispiel gibt es ein Lemma, das sagt, dass wenn
$A \\Rightarrow B$ dann $(\\neg A \\lor B)$:
```
lemma not_or_of_imp : (A B : Prop) (h : A → B) :
¬A B := by
...
```
Wenn also dein Goal `¬A B` ist, kannst du mit `apply not_or_of_imp` dieses
Lemma anwenden. Danach musst du noch alle Annahmen zeigen.
"
Statement (A : Prop) : ¬A A := by
@ -45,6 +23,18 @@ Statement (A : Prop) : ¬A A := by
**Robo**: Ich glaube, sie will eine detailierte Antwort. Ich kenne ein Lemma
`not_or_of_imp`, was sagt `(A → B) → ¬ A B`. Da das Resultat des Lemmas mit
deinem Goal übreinstimmt, kannst du es mit `apply not_or_of_imp` anwenden."
Branch
right
Hint "**Du**: Und jetzt?
**Robo**: `right/left` funktioniert hier nicht, da du nicht weisst ob `A` wahr oder falsch
ist."
Branch
left
Hint "**Du**: Und jetzt?
**Robo**: `right/left` funktioniert hier nicht, da du nicht weisst ob `A` wahr oder falsch
ist."
apply not_or_of_imp
Hint (hidden := true) "**Robo**: Ich würd wieder mit `intro` weitermachen."
intro

@ -18,7 +18,7 @@ habe ich noch ein Problem, an dem ich mir die Zähne ausbeisse. Wir haben die
Herleitung eines unserer Programme `imp_iff_not_or` verloren, und wissen nicht mehr
ob es einwandfrei funktioniert.
**Du**: Nah gut, al sehen. Robo, was hab ich denn alles hier gelernt?
**Du**: Nah gut, mal sehen. Robo, was hab ich denn alles hier gelernt?
**Robo**: Hier ist die Übersicht:
@ -61,3 +61,17 @@ Statement imp_iff_not_or (A B : Prop) : (A → B) ↔ ¬ A B := by
assumption
DisabledTactic tauto
Conclusion "**Operationsleiter**: Damit gehen unsere Wege auseinander. Da fällt mir ein, seit
ihr auf dem Weg zu unserem Schwestermond?
**Du**: Könnten wir sein…
**Operationsleiter**: Ich hab hier einen Brief für *Evenine*, könntet ihr diesen mit euch führen?
**Du**: Klar! Robo, halt den mal.
Robo nimmt den Brief und lässt ihn irgendwo in seinem Innern verschwinden. Dabei bemerkt er
den besorgten Blick des Operationsleiters.
**Robo**: Keine Angst, ich verdaue nichts!"

@ -4,10 +4,24 @@ import TestGame.Levels.Predicate.L03_Rewrite
import TestGame.Levels.Predicate.L04_Ring
import TestGame.Levels.Predicate.L05_Rfl
import TestGame.Levels.Predicate.L06_Exists
import TestGame.Levels.Predicate.L07_Forall
import TestGame.Levels.Predicate.L08_PushNeg
import TestGame.Levels.Predicate.L09_Summary
import TestGame.Levels.Predicate.L07_Exists
import TestGame.Levels.Predicate.L08_Forall
import TestGame.Levels.Predicate.L09_PushNeg
Game "TestGame"
World "Predicate"
Title "Prädikate"
Introduction "Eure Reise geht weiter zum zweiten Mond. Dieser ist etwas grösser und
komplett mit buschartigen Pflanzen überwachsen. Der Landeanflug sit etwas kniffliger,
aber offenbar kann Robo nicht nur Lean übersetzen, sondern auch mit maschineller Genauigkeit
navigieren.
Ihr werdet sofort empfangen und man führt euch zur lokalen Machthaberin.
Ihr kommt an verschiedensten riesigen Büschen vorbei, die offensichtlich innen Ausgehöhlt sind
und so als Wände für Behausungen der Wesen hier dienen.
Man führt euch in einen der Büsche. Nun entdecksts du dass das Blätterdach künstlich verstärkt ist,
offensichtlich um Regen abzuweisen.
Vor euch steht eine Frau, die euch als Machthabering *Evenine* vorgestellt wird."

@ -11,34 +11,26 @@ Title "Natürliche Zahlen"
Introduction
"
Wir sind den narürlichen Zahlen `` (`\\N`) schon kurz begegnet.
**Evenine**: Willkommen Reisende! Wir leben hier in Einklang mit der Natur und allem natürlichen,
so sagt mir, könnt ihr mit natürlichen Zahlen umgehen?
"
Gleichungen, die nur die Operationen `+, -, *, ^` (Addition, Subtraktion, Multiplikation, Potenz)
und Variablen enthalten, kann Lean mit der Taktik `ring` beweisen.
Statement (x y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 := by
Hint "**Du**: Das hab ich in der Schule gelernt, man rechnet das einfach aus,
indem man die Terme umsortiert.
Diese Taktik funktioniert nicht nur über den natürlichen Zahlen,
sondern auch in (kommutativen) Gruppen, Ringen, und Körpern. Sie heisst `ring`, weil sie für Ringe
entwickelt wurde.
**Robo**: Behaupte doch mit `ring`, dass das so ist.
(Note: Division `/` ignorieren wir hier erst einmal, weil diese auf ``
nicht kanonisch definiert ist.)
"
**Du**: Aber `` ist doch gar kein Ring?
Statement
"Zeige $(x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2$."
(x y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 := by
**Robo**: `ring` funktioniert schon für Halbringe, aber sie heisst ring, weil sie auf
(kommutativen) Ringen am besten funktioniert.
"
ring
HiddenHint (x : ) (y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 =>
"`ring` übernimmt den ganzen Spaß."
Conclusion
"
Die Taktik heisst übrigens `ring` weil sie dafür entwickelt wurde, Gleichungen in einem abstrakten
Ring zu lösen, funktioniert aber auch auf ``, auch wenn dieses kein Ring ist
(erst `` ist ein Ring).
*Evenine: Ja das stimmt schon. Und das genügt uns auf diesem Planet auch als Antwort.*
"
NewTactic ring
#eval 4 / 6

@ -9,62 +9,31 @@ Title "Rewrite"
Introduction
"
Wir haben gesehen, dass man mit `rw` Äquivalenzen wie `A ↔ B` brauchen kann, um im Goal
$A$ durch $B$ zu ersetzen.
Robo spuckt den Brief aus, den er dabei hatte, und gibt ihn *Evenine*.
Genau gleich kann man auch Gleichungen `a = b` mit `rw` verwenden.
**Evenine**: Das verstehe ich nicht, wisst ihr was damit gemeint ist?
Und sie händigt Dir den Brief:
"
Statement umschreiben
"Angenommen man hat die Gleichheiten
Statement (a b c d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : a = d) : b = c := by
Hint "**Du**: Schau mal, das ist ja fast genau, was wir auf *Implis* gemacht haben,
nur jetzt mit Gleichheiten von Zahlen anstatt Genau-Dann-Wenn-Aussagen!
$$
\\begin{aligned} a &= b \\\\ a &= d \\\\ c &= d \\end{aligned}
$$
**Robo**: `=` und `↔` kannst du praktisch gleich behandeln wenns um `rw` geht."
Hint (hidden := true) "**Du**: Also auch `rw [hₓ]` und `rw [← hₓ]`?
Zeige dass $b = c$."
(a b c d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : a = d) : b = c := by
**Robo**: Probiers doch einfach."
rw [h₁]
Hint (hidden := true) "**Du**: Wie war das nochmals mit rückwärts umschreiben?
**Robo**: `←` ist `\\l`. Und dann `rw [← hₓ]`"
rw [←h₂]
assumption
HiddenHint (a : ) (b : ) (c : ) (d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : a = d) : b = c =>
"Im Goal kommt `c` vor und `h₁` sagt `c = d`.
Probiers doch mit `rw [h₁]`."
HiddenHint (a : ) (b : ) (c : ) (d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : a = d) : a = c =>
"Im Goal kommt `C` vor und `h₁` sagt `C ↔ D`.
Probiers doch mit `rw [h₁]`."
HiddenHint (a : ) (b : ) (c : ) (d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : a = d) : b = d =>
" Man kann auch rückwärts umschreiben: `h₂` sagt `a = b` mit
`rw [←h₂]` ersetzt man im Goal `b` durch `a` (`\\l`, also ein kleines L)"
HiddenHint (a : ) (b : ) (h : a = b) : a = b =>
"Schau mal durch die Annahmen durch."
-- These should not be necessary if they don't use `rw [] at`.
HiddenHint (a : ) (b : ) (c : ) (d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : a = c) : b = c =>
"Auch eine Möglichkeit... Kannst du das Goal so umschreiben,
dass es mit einer Annahme übereinstimmt?"
HiddenHint (a : ) (b : ) (c : ) (d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : b = d) : b = c =>
"Auch eine Möglichkeit.. Kannst du das Goal so umschreiben, dass es mit einer Annahme übereinstimmt?"
Hint (a : ) (b : ) (h : b = a) : a = b =>
"Naja auch Umwege führen ans Ziel... Wenn du das Goal zu `a = a` umschreibst, kann man es mit
`rfl` beweisen (rsp. das passiert automatisch.)"
Hint (a : ) (b : ) (c : ) (d : ) (h₁ : c = d) (h₂ : d = b) (h₃ : d = a) : b = c =>
"das ist nicht der optimale Weg..."
Hint (a : ) (b : ) (c : ) (d : ) (h₁ : c = d) (h₂ : d = b) (h₃ : a = d) : b = c =>
"das ist nicht der optimale Weg..."
Conclusion "Übrigens, mit `rw [h₁, ←h₂]` könnte man mehrere `rw` zusammenfassen."
Conclusion
"
**Evenine**: Danke viemals, das hilft uns vermutlich, jetzt Frage ich mich aber…
"
NewTactic assumption rw

@ -9,32 +9,28 @@ Title "Rewrite"
Introduction
"
Als Übung erinnern wir daran, dass man mit `rw [h] at g` auch in anderen Annahmen umschreiben
kann:
Wenn `(h : X = Y)` ist, dann ersetzt `rw [h] at g` in der Annahme
`g` das `X` durch `Y`.
**Evenine**: Mit diesem neuen Wissen, könnt ihr mir bei folgendem helfen:
"
Statement umschreiben
"Angenommen man hat die Gleichheiten
Statement
"
$$
\\begin{aligned} a &= b \\\\ a + a ^ 2 &= b + 1 \\end{aligned}
\\begin{aligned}
a &= b \\\\
a + a ^ 2 &= b + 1 \\\\
\\vdash b + b ^ 2 = b + 1
\\end{aligned}
$$
Zeige dass $b + b ^ 2 = b + 1$."
"
(a b : ) (h : a = b) (g : a + a ^ 2 = b + 1) : b + b ^ 2 = b + 1 := by
Hint "**Du**: Ah da ersetzt man ja einfach `{a}` durch `{b}` in der anderen Annahme!
**Robo**: Genau! Das machst du mit `rw [{h}] at {g}`."
rw [h] at g
Hint (hidden := true) "**Robo**: Schau mal durch die Annahmen."
assumption
Hint (a : ) (b : ) (h : a = b) (g : a + a ^ 2 = b + 1) : b + b ^ 2 = b + 1 =>
"`rw [ ... ] at g` schreibt die Annahme `g` um."
Hint (a : ) (b : ) (h : a = b) (g : a + a ^ 2 = b + 1) : a + a ^ 2 = a + 1 =>
"Sackgasse. probiers doch mit `rw [h] at g` stattdessen."
Conclusion "Übrigens, mit `rw [h] at *` kann man im weiteren `h` in **allen** Annahmen und
dem Goal umschreiben."
NewTactic assumption rw
Conclusion "
**Robo**: Noch ein Trick: Mit `rw [h] at *` kann man im weiteren `h` in **allen** Annahmen und
dem Goal umschreiben.
"

@ -9,25 +9,27 @@ Title "Natürliche Zahlen"
Introduction
"
Oft braucht man eine Kombination von `rw` und `ring` um Gleichungen zu lösen.
*Evenines* Berater meldet sich.
Zuerst setzt man mit `rw` die vorhandenen Annahmen ein, und sobald die beiden Seiten
einer Gleichung im Goal rechnerisch gleich sind, kan `ring` dies beweisen.
**Berater**: Das stimmt wohl, aber das Problem, das uns eigentlich beschäftigt hat, eure
Natürlichkeit, war folgendes:
"
Statement
"Angenommen, man hat die Gleichung $x = 2 * y + 1$, zeige
$x ^ 2 = 4 * y ^ 2 + 3 * y + 1 + y$. "
(x y : ) (h : x = 2 * y + 1) : x ^ 2 = 4 * y ^ 2 + 3 * y + 1 + y := by
rw [h]
ring
(x y z : ) (h : x = 2 * y + 1) (g : z = 3 * y + 1): x ^ 2 = 4 * y ^ 2 + z + y := by
Hint "**Du**: Ich versteh das Pattern. Wenn ich zuerst alles so umschreibe, dass
das Goal nur noch rechnen und umsortieren ist, dann kann `ring` den Rest machen!
Hint (x : ) (y : ) (h : x = 2 * y + 1) : x ^ 2 = 4 * y ^ 2 + 3 * y + 1 + y =>
"Die Annahme `h` kannst du mit `rw [h]` benützen."
**Robo**: Noch ein Trick: Entweder kannst du zwei Befehle `rw [h₁]` und `rw [h₂]` schreiben,
oder du kannst das gleich in einem machen : rw [h₁, h₂]."
rw [h, g]
ring
Hint (y : ) : (2 * y + 1) ^ 2 = 4 * y ^ 2 + 3 * y + 1 + y =>
"Jetzt kann `ring` übernehmen."
Conclusion ""
Conclusion
"
*Evenine* bedankt sich nochmals für die Botschaft und ihr werdet zu einem kleineren Busch geführt,
der ein gemütlich warmes Innenleben an den Tag legt.
"
NewTactic ring rw

@ -8,24 +8,29 @@ Title "Definitionally equal"
Introduction
"
Als kleine Nebenbemerkung:
Müde ruht ihr euch in eurer Bleibe aus. Du schaust doch eine Lücke in den Blättern vielen
kleinen Vögeln bei der Nahrungssuche zu.
Auf Grund der Implementation in Lean brauchst du die Taktik `ring` gar nicht, wenn
du Gleichungen über `` hast, die keine Variablen enthalten:
So ist zum Beispiel `2` als `1 + 1` definiert, deshalb kannst du $1 + 1 = 2$ einfach mit
`rfl` beweisen.
**Du**: Sag mal Robo, ich hab vorhin ein Kind überhört, dass seinem Spielgefährten erklärt hat,
folgendes sei mit `rfl` zu beweisen:
"
Statement
"Zeige dass $1 + 1$ zwei ist." :
1 + 1 = 2 := by
Statement : 1 + 1 = 2 := by
Hint "**Du**: Wieso nicht `ring`?
**Robo**: Klar, `ring` geht auch und ist intuitiver.
Für `rfl` kommt es darauf an, wie die Sachen genau definiert sind: `1 + 1` ist als
`(0.succ).succ` definiert und `2` halt ebenfalls.
"
rfl
OnlyTactic rfl
Conclusion
"
**Notiz:** Die meisten anderen Taktiken versuchen am Schluss automatisch `rfl`
aufzurufen, deshalb brauchst du das nur noch selten.
"
**Du**: Dann war das mehr Glück?
**Robo**: Das ist eine Art die Welt zu sehen…
NewTactic rfl
Damit fällst du in einen ruhigen Schlaf.
"

@ -6,6 +6,8 @@ import Mathlib.Tactic.Ring
import Mathlib.Algebra.Parity
set_option tactic.hygienic false
Game "TestGame"
World "Predicate"
Level 6
@ -14,58 +16,58 @@ Title "Gerade/Ungerade"
Introduction
"
Gerade/ungerade werden in Lean wie folgt definiert:
Am nächsten Tag erklärt euch *Evenine*, dass es auf dem Mond zwei Gruppierungen gibt,
ihre und die ihres Halbbruders *Oddeus*. Die Mottos sind
```
def Even (n : ) : Prop := ∃ r, n = r + r
def Odd (n : ) : Prop := ∃ r, n = r + r + 1
```
Also dadurch, dass ein `(r : )` existiert sodass `n = r + r (+1)`.
Beachte das Komma `,` welches die Variablen des `∃` (`\\exists`) von der Aussage trennen.
Hierzu gibt es 3 wichtige Taktiken:
1) Definitionen wie `Even` kann man mit `unfold Even at *` im Infoview einsetzen.
Das ändert Lean-intern nichts und ist nur für den Benutzer. Man kann auch einen
Term `(h : Even x)` einfach so behandeln als wäre es ein Term `(h : ∃ r, x = 2 * r)`.
2) Bei einer Annahme `(h : ∃ r, ...)` kann man mit `rcases h with ⟨y, hy⟩` ein solches `y`
Auswählen, dass die Annahme `h` erfüllt.
3) Bei einem `∃` im Goal muss man ein Element `y` angeben, welches diese Aussage erfüllen
soll. Das macht man mit `use y`
"
Statement even_square
"Wenn $n$ gerade ist, dann ist $n^2$ gerade."
(n : ) (h : Even n) : Even (n ^ 2) := by
unfold Even at *
rcases h with ⟨x, hx⟩
use 2 * x ^ 2
rw [hx]
ring
und
```
def Odd (n : ) : Prop := ∃ r, n = 2 * r + 1
```
Hint (n : ) (h : Even n) : Even (n ^ 2) =>
"Wenn du die Definition von `Even` nicht kennst, kannst du diese mit `unfold Even` oder
`unfold Even at *` ersetzen.
Note: Der Befehl macht erst mal nichts in Lean sondern nur in der Anzeige. Der Beweis funktioniert
genau gleich, wenn du das `unfold` rauslöscht."
**Evenine**: Hier, ich zeige euch mal etwas was man bei uns machen kann:
"
Hint (n : ) (h : ∃ r, n = r + r) : ∃ r, n ^ 2 = r + r =>
"Ein `∃ x, ..` in den Annahmen kann man wieder mit `rcases h with ⟨x, hx⟩` aufteilen, und
ein `x` erhalten, dass die Aussage erfüllt."
Statement even_square (n : ) (h : Even n) : Even (n ^ 2) := by
Branch
unfold Even
Hint "Rob**: Am besten machst du auch noch `unfold Even at h`, damit du verstehst was los ist."
Hint "**Robo**: Wie du oben siehst, ist `Even n` dadurch definiert,
dass ein `r` existiert so dass `r + r = n`. Am besten
öffnest du diese Definition mit `unfold Even at *` einmal, dann siehst du besser, was los ist. "
unfold Even at *
Hint "**Du**: Also von `{h}` weiss ich jetzt dass ein `r` existiert, so dass `r + r = n`…
Hint (n : ) (x : ) (hx : n = x + x) : ∃ r, n ^ 2 = r + r =>
"Bei einem `∃ x, ..` im Goal hingegen, muss man mit `use y` das Element angeben, dass
die Aussage erfüllen soll."
**Robo**: Mit `rcases h with ⟨r, hr⟩` kannst du dieses `r` tatsächlich einführen."
rcases h with ⟨r, hr⟩
Hint "**Du**: Und jetzt muss ich eine passende Zahl finden, so dass `x + x = n^2`?
Hint (n : ) (x : ) (hx : n = x + x) : ∃ r, (x + x) ^ 2 = r + r =>
"Bei einem `∃ x, ..` im Goal hingegen, muss man mit `use y` das Element angeben, dass
die Aussage erfüllen soll."
**Robo**: Genau. Und mit `use _` gibst du diese Zahl an."
Hint (hidden := true) "**Robo**: Also sowas ähnliches wie `use 4 * r ^ 3`, aber ich kann
dir leider nicht sagen, welche Zahl passt.
"
Branch
rw [hr]
Hint "**Robo**: Das geht auch, jetzt musst du aber wirklich `use` verwenden."
use 2 * r ^ 2
ring
use 2 * r ^ 2
Hint "**Du**: Ah und jetzt `ring`!
Hint (n : ) (x : ) (hx : n = x + x) : n ^ 2 = 2 * x ^ 2 + 2 * x ^ 2 =>
"Prinzipiell löst `ring` simple Gleichungen wie diese. Allerdings musst du zuerst `n` zu
`x + x` umschreiben..."
**Robo**: Aber zuerst must du noch mit
`rw` `n` durch `r + r` ersetzen, da `ring` das sonst nicht weiss."
rw [hr]
ring
Hint (n : ) (x : ) (hx : n = x + x) : (x + x) ^ 2 = 2 * x ^ 2 + 2 * x ^ 2 =>
"Die Taktik `ring` löst solche Gleichungen."
-- TODO: [Comment] For me the expected behaviour of `(strict := true)` would
-- be that it distinguishes between the defEq states while `(strict := false)`
-- would show the hint regardless of a `unfold Even`.
NewTactic unfold rcases use rw ring
NewTactic unfold use
NewDefinition Even Odd
Conclusion "**Evenine**: Seht ihr?"

@ -0,0 +1,43 @@
import TestGame.Metadata
import Std.Tactic.RCases
import Mathlib.Tactic.Contrapose
import Mathlib.Tactic.Use
import Mathlib.Tactic.Ring
import Mathlib.Algebra.Parity
set_option tactic.hygienic false
Game "TestGame"
World "Predicate"
Level 7
Title "Gerade/Ungerade"
Introduction
"
**Du**: Aber, das sagt doch gar nichts aus, genau das gleiche könnte ich für `Odd`
auch sagen. Hier seht!
"
Statement odd_square (n : ) (h : Odd n) : Odd (n ^ 2) := by
unfold Odd at *
rcases h with ⟨r, hr⟩
Hint "**Robo**: Ich hab noch einen Trick auf Lager:
Wenn du jetzt herausfinden willst, welche Zahl du einsetzen musst, könntest
du schon jetzt mit `rw [{hr}]` weitermachen…"
rw [hr]
Hint "**Robo**: Wenn du jetzt `ring` benötigst, dann schreibt es einfach alles in
Normalform um, das hilft beim vergleichen."
ring
Hint "**Du**: Was bedeutet `ring_nf`?
**Robo**: Wenn man `ring` nicht am Schluss benützt, sollte man stattdessen `ring_nf`
schreiben, aber die funktionieren praktisch gleich."
use 2 * (r + r ^ 2)
ring
-- TODO: Allow `ring_nf` as part of `ring`.
Conclusion "**Evenine**: Tatsächlich. Vielleicht sind wir gar nich tso unterschiedlich. Könntet
ihr mal mit ihm reden gehen?"

@ -1,53 +0,0 @@
import TestGame.Metadata
import Std.Tactic.RCases
import Mathlib.Tactic.Contrapose
import Mathlib.Tactic.Use
import Mathlib.Tactic.Ring
import Mathlib.Algebra.Parity
import Mathlib
Game "TestGame"
World "Predicate"
Level 7
Title "Für alle"
Introduction
"
Zum `∃` gehört auch das \"für alle\" `∀` (`\\forall`).
Der Syntax ist `∀ (n : ), 0 ≤ n` also wie beim `∃` trennt ein Komma die Annahmen von der Aussage.
Eine `∀`-Aussage in den Annahmen verhält sich so wie ein Lemma. Das heisst man kann
auch diese mit `apply` und `rw` anwenden, je nachdem was die Aussage nach dem Komma ist.
Also folgende Annahme und Lemma sind genau :
- `(le_square : ∀ (n : ), n ≤ n^2)`
- `lemma le_square (n : ) : n ≤ n^2`
Ein `∀` im Goal kann man mit `intro` angehen, genau wie bei einer Implikation `→`.
TODO: 1-2 Aufgaben mehr.
"
Statement
" Für alle natürlichen Zahlen $x$ gilt, falls $x$ gerade ist, dann ist $x + 1$
ungerade." : ∀ (x : ), (Even x) → Odd (1 + x) := by
intro x h
unfold Even at h
unfold Odd
rcases h with ⟨y, hy⟩
use y
rw [hy]
ring
Hint (n : ) (hn : Odd n) (h : ∀ (x : ), (Odd x) → Even (x + 1)) : Even (n + 1) =>
"`∀ (x : ), (odd x) → even (x + 1)` ist eigentlich das gleiche wie
`(x : ) → `"
Conclusion "Für-alle-Statements, Implikationen und Lemmas/Theoreme verhalten sich alle
praktisch gleich. Mehr dazu später."
NewTactic ring intro unfold

@ -0,0 +1,53 @@
import TestGame.Metadata
import Std.Tactic.RCases
import Mathlib.Tactic.Contrapose
import Mathlib.Tactic.Use
import Mathlib.Tactic.Ring
import Mathlib.Algebra.Parity
import Mathlib
Game "TestGame"
World "Predicate"
Level 8
Title "Für alle"
Introduction
"
Ihr macht euch also auf den Weg. Unterwegs trefft ihr einen Händler und ihr lässt euch von
ihm den Weg zeigen, sowie einige Tipps zu den beiden Geschwistern geben.
**Händler**: Also seht, die beiden sind gar nicht so verschieden. Ein altes Sprichwort sagt:
"
-- Zum `∃` gehört auch das \"für alle\" `∀` (`\\forall`).
-- Der Syntax ist `∀ (n : ), 0 ≤ n` also wie beim `∃` trennt ein Komma die Annahmen von der Aussage.
-- Eine `∀`-Aussage in den Annahmen verhält sich so wie ein Lemma. Das heisst man kann
-- auch diese mit `apply` und `rw` anwenden, je nachdem was die Aussage nach dem Komma ist.
-- Also folgende Annahme und Lemma sind genau :
-- - `(le_square : ∀ (n : ), n ≤ n^2)`
-- - `lemma le_square (n : ) : n ≤ n^2`
-- Ein `∀` im Goal kann man mit `intro` angehen, genau wie bei einer Implikation `→`.
-- TODO: 1-2 Aufgaben mehr.
Statement : ∀ (x : ), (Even x) → Odd (1 + x) := by
Hint "**Du**: Das `∀` heisst sicher \"für alle\".
**Robo**: Und man schreibt `\\forall`. Ein `∀ x, …` im Goal kannst du wie eine
Implikation mit `intro x` angehen."
intro x h
unfold Even at h
unfold Odd
rcases h with ⟨y, hy⟩
use y
rw [hy]
ring
Conclusion "**Händler**: Sichere Reise!"

@ -1,67 +0,0 @@
import TestGame.Metadata
import Mathlib.Tactic.PushNeg
import Mathlib
import Mathlib.Algebra.Parity
import TestGame.ToBePorted
Game "TestGame"
World "Predicate"
Level 8
Title "PushNeg"
Introduction
"
Zum Schluss, immer wenn man irgendwo eine Verneinung `¬∃` oder `¬∀` sieht (`\\not`), kann man
mit `push_neg` das `¬` durch den Quantor hindurchschieben.
Das braucht intern die Lemmas
- `not_exists (A : Prop) : ¬ (∃ x, A) ↔ ∀x, (¬A)`
- `not_forall (A : Prop) : ¬ (∀ x, A) ↔ ∃x, (¬A)`
(welche man auch mit `rw` explizit benutzen könnte.)
"
Statement
"Es existiert keine natürliche Zahl $n$, sodass $n + k$ immer ungerade ist.":
¬ ∃ (n : ), ∀ (k : ) , Odd (n + k) := by
push_neg
intro n
use n
rw [not_odd]
unfold Even
use n
Hint : ¬ ∃ (n : ), ∀ (k : ) , Odd (n + k) =>
"`push_neg` schiebt die Negierung an den Quantoren vorbei."
Hint (n : ) : (∃ k, ¬Odd (n + k)) =>
"An dieser Stelle musst du nun ein `k` angeben, sodass `n + k` gerade ist... Benutze `use`
mit der richtigen Zahl."
HiddenHint (n : ) : ¬Odd (n + n) =>
"Du kennst ein Lemma um mit `¬odd` umzugehen."
-- HiddenHint (n : ) (k : ) : ¬odd (n + k) =>
-- "Du kennst ein Lemma um mit `¬odd` umzugehen."
HiddenHint (n : ) : Even (n + n) =>
"`unfold even` hilft, anzuschauen, was hinter `even` steckt.
Danach musst du wieder mit `use r` ein `(r : )` angeben, dass du benützen möchtest."
-- HiddenHint (n : ) (k : ) : even (n + k) =>
-- "`unfold even` hilft hier weiter."
Hint (n : ) : n + n = 2 * n => "Recap: `ring` löst Gleichungen in ``."
Conclusion ""
NewTactic push_neg intro use rw unfold ring
NewDefinition Even Odd
NewLemma not_even not_odd not_exists not_forall

@ -0,0 +1,106 @@
import TestGame.Metadata
import Mathlib.Tactic.PushNeg
import Mathlib
import Mathlib.Algebra.Parity
import TestGame.ToBePorted
Game "TestGame"
World "Predicate"
Level 9
Title "PushNeg"
Introduction
"
Das Dorf von *Oddeus* scheint stärker befestigt zu sein, all jenes von *Evenine*. Ihr kommt
and eine Wand aus Dornenranken. Beim Eingang steht eine Wache, die auch zuruft:
"
-- Zum Schluss, immer wenn man irgendwo eine Verneinung `¬∃` oder `¬∀` sieht (`\\not`), kann man
-- mit `push_neg` das `¬` durch den Quantor hindurchschieben.
-- Das braucht intern die Lemmas
-- - `not_exists (A : Prop) : ¬ (∃ x, A) ↔ ∀x, (¬A)`
-- - `not_forall (A : Prop) : ¬ (∀ x, A) ↔ ∃x, (¬A)`
-- (welche man auch mit `rw` explizit benutzen könnte.)
Statement : ¬ ∃ (n : ), ∀ (k : ) , Odd (n + k) := by
Hint "**Du**: Also ich kann mal das `¬` durch die Quantifier hindurchschieben.
**Robo**: `push_neg` macht genau das!
**Robo**: Intern braucht das zwei Lemmas
```
not_exists (A : Prop) : ¬ (∃ x, A) ↔ ∀x, (¬A)
not_forall (A : Prop) : ¬ (∀ x, A) ↔ ∃x, (¬A)
```
die du natürlich auch mit `rw` gebrauchen könntest."
Branch
unfold Odd
push_neg
Hint "**Robo**: Der Weg ist etwas schwieriger. Ich würde nochmals zurück und schauen,
dass du irgendwann `¬Odd` kriegst, was du dann mit `rw [not_odd]` zu `Even` umwandeln
kannst."
push_neg
intro n
Hint "**Robo**: Welche Zahl du jetzt mit `use` brauchst, danach wirst du vermutlich das
Lemma `not_odd` brauchen.
**Du**: Könnte ich jetzt schon `rw [not_odd]` machen?
**Robo**: Ne, `rw` kann nicht innerhalb von Quantifiern umschreiben.
**Du**: Aber wie würde ich das machen?
**Robo**: Zeig ich dir später, die Wache wird schon ganz ungeduldig!"
Branch
use n + 2
Hint "**Robo**: Gute Wahl! Jetzt kannst du `not_odd` verwenden."
Branch
use n + 4
Hint "**Robo**: Gute Wahl! Jetzt kannst du `not_odd` verwenden."
use n
Hint "**Robo**: Gute Wahl! Jetzt kannst du `not_odd` verwenden."
rw [not_odd]
unfold Even
use n
--ring
Conclusion "Damit werdet ihr eingelassen.
**Robo**: Entweder wir suchen direkt diesen *Oddeus*, oder wir schauen uns einmal um. Die Wahl
ist deine!
**Du**: Kannst du mir nochmals einen Überblick geben, was wir gelernt haben?
**Robo**:
| | Beschreibung |
|:--------------|:----------------------------|
| `` | Die natürlichen Zahlen. |
| `∃` | Existential-Quantifier |
| `∀` | Forall-Quantifier |
| `Even n` | `n` ist gerade |
| `Odd n` | `n` ist ungerade |
| | Taktik | Beispiel |
|:------|:--------------------------|:-------------------------------------------------------|
| *12ᶜ* | `rw` | Umschreiben mit Gleichungen. |
| 13 | `ring` | Löst Gleichungen mit `+, -, *, ^`. |
| 14 | `unfold` | Setzt visuell die Bedeutung einer Definition ein. |
| 15 | `use` | Um ein `∃` im Goal anzugehen. |
| *7ᶜ* | `rcases h with ⟨x, hx⟩` | Um ein `∃` in den Annahmen zu zerlegen. |
| *8ᵇ* | `intro` | Um ein `∀` im Goal anzugehen. |
| 16 | `push_neg` | Für `¬∃` und `¬∀` im Goal. |
"
NewTactic push_neg
NewLemma not_even not_odd not_exists not_forall

@ -1,55 +0,0 @@
import TestGame.Metadata
import Mathlib.Tactic.PushNeg
import Mathlib
import TestGame.ToBePorted
Game "TestGame"
World "Predicate"
Level 9
Title "Zusammenfassung"
Introduction
"
Damit bist du am Ende der dritten Lektion angekommen.
Hier ein Überblick über alles was in diesem Kapitel eingeführt wurde und eine
Abschlussaufgabe.
## Notationen / Begriffe
| | Beschreibung |
|:--------------|:----------------------------|
| `` | Die natürlichen Zahlen. |
| `∃` | Existential-Quantifier |
| `∀` | Forall-Quantifier |
| `Even n` | `n` ist gerade |
| `Odd n` | `n` ist ungerade |
## Taktiken
| | Taktik | Beispiel |
|:------|:--------------------------|:-------------------------------------------------------|
| *11ᶜ* | `rw` | Umschreiben mit Gleichungen. |
| 12 | `ring` | Löst Gleichungen mit `+, -, *, ^`. |
| 13 | `unfold` | Setzt visuell die Bedeutung einer Definition ein. |
| 14 | `use` | Um ein `∃` im Goal anzugehen. |
| *7ᶜ* | `rcases h with ⟨x, hx⟩` | Um ein `∃` in den Annahmen zu zerlegen. |
| *8ᵇ* | `intro` | Um ein `∀` im Goal anzugehen. |
| 15 | `push_neg` | Für `¬∃` und `¬∀` im Goal. |
Als Abschlussübung kannst du folgende Äquivalenz zeigen:
"
Statement
"TODO":
True := by
trivial
Conclusion ""
NewTactic push_neg intro use rw unfold ring
NewDefinition Even Odd
NewLemma not_even not_odd not_exists not_forall
Loading…
Cancel
Save