story world 2 and 3
This commit is contained in:
@@ -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.
|
||||
|
||||
Gleichungen, die nur die Operationen `+, -, *, ^` (Addition, Subtraktion, Multiplikation, Potenz)
|
||||
und Variablen enthalten, kann Lean mit der Taktik `ring` beweisen.
|
||||
|
||||
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.
|
||||
|
||||
(Note: Division `/` ignorieren wir hier erst einmal, weil diese auf `ℕ`
|
||||
nicht kanonisch definiert ist.)
|
||||
**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?
|
||||
"
|
||||
|
||||
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
|
||||
ring
|
||||
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.
|
||||
|
||||
HiddenHint (x : ℕ) (y : ℕ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 =>
|
||||
"`ring` übernimmt den ganzen Spaß."
|
||||
**Robo**: Behaupte doch mit `ring`, dass das so ist.
|
||||
|
||||
**Du**: Aber `ℕ` ist doch gar kein Ring?
|
||||
|
||||
**Robo**: `ring` funktioniert schon für Halbringe, aber sie heisst ring, weil sie auf
|
||||
(kommutativen) Ringen am besten funktioniert.
|
||||
"
|
||||
ring
|
||||
|
||||
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]
|
||||
(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!
|
||||
|
||||
**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 (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."
|
||||
|
||||
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?
|
||||
|
||||
NewTactic rfl
|
||||
**Robo**: Das ist eine Art die Welt zu sehen…
|
||||
|
||||
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:
|
||||
und
|
||||
|
||||
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`
|
||||
```
|
||||
def Odd (n : ℕ) : Prop := ∃ r, n = 2 * r + 1
|
||||
```
|
||||
|
||||
**Evenine**: Hier, ich zeige euch mal etwas was man bei uns machen kann:
|
||||
"
|
||||
|
||||
Statement even_square
|
||||
"Wenn $n$ gerade ist, dann ist $n^2$ gerade."
|
||||
(n : ℕ) (h : Even n) : Even (n ^ 2) := by
|
||||
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 *
|
||||
rcases h with ⟨x, hx⟩
|
||||
use 2 * x ^ 2
|
||||
rw [hx]
|
||||
Hint "**Du**: Also von `{h}` weiss ich jetzt dass ein `r` existiert, so dass `r + r = n`…
|
||||
|
||||
**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`?
|
||||
|
||||
**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`!
|
||||
|
||||
**Robo**: Aber zuerst must du noch mit
|
||||
`rw` `n` durch `r + r` ersetzen, da `ring` das sonst nicht weiss."
|
||||
rw [hr]
|
||||
ring
|
||||
|
||||
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."
|
||||
-- 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`.
|
||||
|
||||
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."
|
||||
|
||||
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."
|
||||
|
||||
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."
|
||||
|
||||
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..."
|
||||
|
||||
Hint (n : ℕ) (x : ℕ) (hx : n = x + x) : (x + x) ^ 2 = 2 * x ^ 2 + 2 * x ^ 2 =>
|
||||
"Die Taktik `ring` löst solche Gleichungen."
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user