reorganise world Implication

pull/43/head
Jon Eugster 3 years ago
parent 966db8a159
commit 420f913e69

@ -1,32 +1,8 @@
import TestGame.Metadata
import TestGame.Levels.Logic.L02_Rfl
import TestGame.Levels.Logic.L04_Rewrite
import TestGame.Levels.Logic.L04b_Rewrite
import TestGame.Levels.Logic.L05_Apply
import TestGame.Levels.Logic.L05b_Apply
import TestGame.Levels.Logic.L05c_Apply
import TestGame.Levels.Logic.L06_Iff
import TestGame.Levels.Logic.L06b_Iff
import TestGame.Levels.Logic.L06c_Iff
import TestGame.Levels.Logic.L06d_Iff
import TestGame.Levels.Naturals.L01_Ring
import TestGame.Levels.Naturals.L02_Ring
import TestGame.Levels.Naturals.L03_Exists
import TestGame.Levels.Naturals.L04_Forall
import TestGame.Levels.Naturals.L31_Sum
import TestGame.Levels.Naturals.L32_Induction
import TestGame.Levels.Naturals.L33_Prime
import TestGame.Levels.Naturals.L34_ExistsUnique
import TestGame.Levels.Negation.L03_Contra
import TestGame.Levels.Negation.L04_Contra
import TestGame.Levels.Negation.L05_Not
import TestGame.Levels.Negation.L06_ByContra
import TestGame.Levels.Negation.L07_Contrapose
import TestGame.Levels.Negation.L08_Contrapose
import TestGame.Levels.Negation.L09_PushNeg
import TestGame.Levels.Proposition
import TestGame.Levels.Implication
import TestGame.Levels.Predicate
Game "TestGame"

@ -1,5 +1,48 @@
import GameServer.Commands
-- import TestGame.MyNat
-- Wird im Level "Implication 11" ohne Beweis angenommen.
LemmaDoc not_not as not_not in "Logic"
"
### Aussage
`¬¬A ↔ A`
### Annahmen
`(A : Prop)`
"
-- Wird im Level "Implication 10" ohne Beweis angenommen.
LemmaDoc not_or_of_imp as not_or_of_imp in "Logic"
"
### Aussage
`¬A B`
### Annahmen
`(A B : Prop)`\\
`(h : A → B)`
"
-- Wird im Level "Implication 12" bewiesen.
LemmaDoc imp_iff_not_or as imp_iff_not_or in "Logic"
"
### Aussage
`(A → B) ↔ ¬A B`
### Annahmen
`(A B : Prop)`
"
LemmaDoc zero_add as zero_add in "Addition"
"This lemma says `∀ a : , 0 + a = a`."
@ -13,9 +56,6 @@ LemmaDoc add_succ as add_succ in "Addition"
LemmaSet addition : "Addition lemmas" :=
zero_add add_zero
LemmaDoc not_not as not_not in "Logic"
"`∀ (A : Prop), ¬¬A ↔ A`."
LemmaDoc not_forall as not_forall in "Logic"
"`∀ (A : Prop), ¬(∀ x, A) ↔ ∃x, (¬A)`."

@ -0,0 +1,12 @@
import TestGame.Levels.Implication.L01_Intro
import TestGame.Levels.Implication.L02_Revert
import TestGame.Levels.Implication.L03_Apply
import TestGame.Levels.Implication.L04_Apply
import TestGame.Levels.Implication.L05_Apply
import TestGame.Levels.Implication.L06_Iff
import TestGame.Levels.Implication.L07_Rw
import TestGame.Levels.Implication.L08_Iff
import TestGame.Levels.Implication.L09_Iff
import TestGame.Levels.Implication.L10_Apply
import TestGame.Levels.Implication.L11_Rw
import TestGame.Levels.Implication.L12_Summary

@ -0,0 +1,40 @@
import TestGame.Metadata
set_option tactic.hygienic false
Game "TestGame"
World "Implication"
Level 1
Title "Intro"
Introduction
"
## Implikationen
In diesem Kapitel lernst du Implikation ($\\Rightarrow$) und Genau-dann-wenn
($\\Leftrightarrow$) kennen.
Dazu lernst du, wie man bereits bewiesene Sätze verwendet.
Seien `(A B : Prop)` zwei logische Aussagen. Eine Implikation $A \\Rightarrow B$ schreibt
man in Lean als `A → B` (`\\to`).
Wenn das Goal eine Implikation $A \\Rightarrow B$ ist, kann man mit
`intro ha` annehmen, dass $A$ wahr ist. Dann muss man $B$ beweisen.
"
Statement
"Wenn $B$ wahr ist, dann ist die Implikation $A \\Rightarrow (A ∧ B)$ wahr."
(A B : Prop) (hb : B) : A → (A ∧ B) := by
intro hA
constructor
assumption
assumption
Hint (A : Prop) (B : Prop) (hb : B) : A → (A ∧ B) =>
"Mit `intro ha` kann man annehmen, dass $A$ wahr ist. danach muss man $A \\land B$ zeigen."
Message (A : Prop) (B : Prop) (ha : A) (hb : B) : (A ∧ B) =>
"Jetzt kannst du die Taktiken aus dem letzten Kapitel verwenden."
Tactics intro constructor assumption

@ -0,0 +1,42 @@
import TestGame.Metadata
set_option tactic.hygienic false
Game "TestGame"
World "Implication"
Level 2
Title "Revert"
Introduction
"
Mit `intro` kann man also eine Implikation aus dem Goal entfernen, indem man
die Implikationsprämisse zu den *Annahmen* hinzufügt:
```
example : A → B :=
[Beweis]
```
wird zu
```
example (ha : A) : B :=
[Beweis]
```
Seltener kann auch die andere Richtung nützlich sein. Mit `revert ha` kann man die Annahme
`ha` entfernen und als Implikationsprämisse vor's Goal hängen.
"
Statement
"Angenommen $A$ ist eine wahre Aussage und man hat eine Implikation $A \\Rightarrow B$, zeige
dass $B$ wahr ist."
(A B : Prop) (ha : A) (h : A → B) : B := by
revert ha
assumption
Hint (A : Prop) (B : Prop) (ha : A) (h : A → B): B =>
"Mit `revert ha` kann man die Annahme `ha` als Implikationsprämisse vorne ans Goal anhängen."
Tactics revert assumption

@ -5,21 +5,18 @@ Game "TestGame"
World "Implication"
Level 3
Title "Implikation"
Title "Apply"
Introduction
"Als nächstes widmen wir uns der Implikation $A \\Rightarrow B$.
Mit zwei logischen Aussagen `(A : Prop) (B : Prop)` schreibt man eine Implikation
als `A → B` (`\\to`).
"
`revert` ist aber nur selten der richtige Weg.
Wenn man als Goal $B$ beweisen möchte und eine Impikation `(g : A → B)`
hat, kann man mit `apply g` diese
anwenden, worauf das zu beweisende Goal $A$ wird. Auf Papier würde man an der Stelle
folgendes zu schreiben: \"Es genügt $A$ zu zeigen, denn $A \\Rightarrow B$\".
*Bemerke:* Das ist der selbe Pfeil, der später auch für Funktionen wie `` gebraucht
wird, deshalb heisst er `\\to`."
Im vorigen Beispiel würde man besser die Implikation $A \\Rightarrow B$ *anwenden*, also
sagen \"Es genügt $A$ zu zeigen, denn $A \\Rightarrow B$\" und danach $A$ beweisen.
Wenn man eine Implikation `(g : A → B)` in den Annahmen hat, bei welcher die Konsequenz
(also $B$) mit dem Goal übereinstimmt, kann man `apply g` genau dies machen.
"
Statement
"Seien $A, B$ logische Aussagen, wobei $A$ wahr ist und $A \\Rightarrow B$.

@ -4,14 +4,14 @@ set_option tactic.hygienic false
Game "TestGame"
World "Implication"
Level 1
Level 4
Title "Implikation"
Introduction
"
Wenn das Goal eine Implikation $A \\Rightarrow B$ ist, kann man mit
`intro hA` annehmen, dass $A$ wahr ist. Dann muss man $B$ beweisen.
Hier eine Übung zu Implikationen.
Fast immer ist es der richtige Weg, wenn du mit `intro` anfängst.
"
Statement
@ -22,7 +22,7 @@ Statement
apply f
assumption
Message (A : Prop) (B : Prop) (C : Prop) (f : A → B) (g : B → C) : A → C =>
Hint (A : Prop) (B : Prop) (C : Prop) (f : A → B) (g : B → C) : A → C =>
"Mit `intro hA` kann man annehmen, dass $A$ wahr ist. danach muss man $B$ zeigen."
Message (A : Prop) (B : Prop) (C : Prop) (hA : A) (f : A → B) (g : B → C) : C =>
@ -32,4 +32,4 @@ Hint (A : Prop) (B : Prop) (C : Prop) (hA : A) (f : A → B) (g : B → C) : C =
"Du willst $C$ beweisen. Suche also nach einer Implikation $\\ldots \\Rightarrow C$ und wende
diese mit `apply` an."
Tactics intro apply assumption
Tactics intro apply assumption revert

@ -2,13 +2,13 @@ import TestGame.Metadata
Game "TestGame"
World "Implication"
Level 4
Level 5
Title "Implikation"
Introduction
"
Angenommen man hat folgende Implikationen
Noch eine Übung: Angenommen man hat folgende Implikationen:
$$
\\begin{CD}
A @>{f}>> B @<{g}<< C \\\\
@ -16,18 +16,23 @@ $$
D @>{i}>> E @>{k}>> F
\\end{CD}
$$
und weiss, dass Aussage $A$ wahr ist.
"
Statement
"Beweise Aussage $F$."
(A B C D E F : Prop) (hA : A) (f : A → B) (g : C → B) (h : B → E)
(i : D → E) (k : E → F) (m : C → F) : F := by
"Beweise $A \\Rightarrow F$."
(A B C D E F : Prop) (f : A → B) (g : C → B) (h : B → E)
(i : D → E) (k : E → F) (m : C → F) : A → F := by
intro ha
apply k
apply h
apply f
assumption
Hint (A : Prop) (B : Prop) (C : Prop) (D : Prop) (E : Prop) (F : Prop)
(f : A → B) (g : C → B) (h : B → E)
(i : D → E) (k : E → F) (m : C → F) : A → F =>
"Wieder ist es schlau, mit `intro` anzufangen."
Hint (A : Prop) (B : Prop) (C : Prop) (D : Prop) (E : Prop) (F : Prop)
(hA : A) (f : A → B) (g : C → B) (h : B → E)
(i : D → E) (k : E → F) (m : C → F) : F =>
@ -43,6 +48,6 @@ Message (A : Prop) (B : Prop) (C : Prop) (D : Prop) (E : Prop) (F : Prop)
(i : D → E) (k : E → F) (m : C → F) : D =>
"Sackgasse. Probier doch einen anderen Weg."
Tactics apply assumption
Tactics apply assumption revert intro
-- https://www.jmilne.org/not/Mamscd.pdf

@ -2,17 +2,20 @@ import TestGame.Metadata
Game "TestGame"
World "Implication"
Level 5
Level 6
Title "Genau dann wenn"
Introduction
"
Ein $A \\iff B$ besteht intern aus zwei Implikationen, $\\textrm{mp} : A \\Rightarrow B$
und $\\textrm{mpr} : B \\Rightarrow A$.
Genau-dann-wenn, $A \\Leftrightarrow B$, wird als `A ↔ B` (`\\iff`) geschrieben.
`A ↔ B` ist eine Struktur (ähnlich wie das logische UND), die aus zwei Teilen besteht:
Wenn man ein `A ↔ B` zeigen will (im Goal), kann man dieses mit `constructor` in die
Einzelteile zerlegen.
- `mp`: die Implikation $A \\Rightarrow B$.
- `mpr`: die Implikation $B \\Rightarrow A$.
Hat man ein $\\Leftrightarrow$ im Goal, nimmt man dieses ebenfalls mit der Taktik
`constructor` auseinander und zeigt dann beide Richtungen einzeln.
"
Statement
@ -22,7 +25,7 @@ Statement
assumption
assumption
Message (A : Prop) (B : Prop) : A ↔ B =>
Hint (A : Prop) (B : Prop) : A ↔ B =>
"Eine Struktur wie `A ↔ B` kann man mit `constructor` zerlegen."
Hint (A : Prop) (B : Prop) (h : A → B) : A → B =>

@ -0,0 +1,74 @@
import TestGame.Metadata
import Init.Data.ToString
-- #check List UInt8
Game "TestGame"
World "Implication"
Level 7
Title "Genau dann wenn"
Introduction
"
Hat man ein `(h : A ↔ B)` in den Annahmen, hat man die gleichen beiden Optionen wie beim
logischen UND plus noch eine neue:
1. Mit `h.mp` und `h.mpr` (oder `h.1` und `h.2`) kann man die einzelnen Implikationen
direkt auswählen.
2. Mit `rcases h with ⟨h₁, h₂⟩` könnte man die Struktur `h` zerlegen und man erhält zwei
separate Annahmen `(h₁ : A → B)` und `(h₂ : B → A)`
3. **Mit** `rw [h]` **kann man im Goal `A` durch `B` ersetzen.**
Wir widmen uns zuerst `rw`. Dies steht für \"rewrite\". Da $A$ und $B$ logisch äquivalent
sind, kann man beliebig das eine mit dem anderen vertauschen.
`rw [h]` ersetzt $A$ durch $B$.
Dabei gibt es noch einige Tricks:
- `rw [← h]` ersetzt umgekehrt $B$ durch $A$ (`\\l`, kleines L).
- `rw [h, g]` ist das gleiche wie `rw [h]` gefolgt von `rw [g]`.
"
Statement
"Zeige dass `B ↔ C`."
(A B C D : Prop) (h₁ : C ↔ D) (h₂ : A ↔ B) (h₃ : A ↔ D) : B ↔ C := by
rw [h₁]
rw [←h₂]
assumption
Hint (A : Prop) (B : Prop) (C : Prop) (D : Prop) (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₁]`."
Hint (A : Prop) (B : Prop) (C : Prop) (D : Prop) (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₁]`."
Message (A : Prop) (B : Prop) (C : Prop) (D : Prop) (h₁ : C ↔ D) (h₂ : A ↔ B) (h₃ : A ↔ D) : B ↔ D =>
"Man kann auch rückwärts umschreiben:
`rw [←h₂]` ersetzt man im Goal `B` durch `a` (`\\l`, also ein kleines L)"
Hint (A : Prop) (B : Prop) (h : A ↔ B) : A ↔ B =>
"Schau mal durch die Annahmen durch."
-- These should not be necessary if they don't use `rw [] at`.
Hint (A : Prop) (B : Prop) (C : Prop) (D : Prop) (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?"
Hint (A : Prop) (B : Prop) (C : Prop) (D : Prop) (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?"
Message (A : Prop) (B : Prop) (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.)"
Message (A : Prop) (B : Prop) (C : Prop) (D : Prop) (h₁ : C ↔ D) (h₂ : D ↔ B) (h₃ : D ↔ A) : B ↔ C =>
"Das ist nicht der optimale Weg..."
Message (A : Prop) (B : Prop) (C : Prop) (D : Prop) (h₁ : C ↔ D) (h₂ : D ↔ B) (h₃ : A ↔ D) : B ↔ C =>
"Das ist nicht der optimale Weg..."
Tactics rw assumption

@ -0,0 +1,44 @@
import TestGame.Metadata
set_option tactic.hygienic false
Game "TestGame"
World "Implication"
Level 8
Title "Genau dann wenn"
Introduction
"
Nun schauen wir uns Option 1) an, die du schon von UND kennst:
1. Mit `h.mp` und `h.mpr` (oder `h.1` und `h.2`) kann man die einzelnen Implikationen
direkt auswählen.
`h.mp` und `h.mpr` (oder `h.1` und `h.2`) sind die einzelnen Implikationen, und du kannst
mit denen ensprechend arbeiten. Insbesondere kannst du mit `apply h.mp` die Implikation
$A \\Rightarrow B$ anwenden, wenn das Goal $B$ ist.
*(PS: das `.mp` kommt von \"Modus Ponens\", ein Ausdruck as der Logik.)*
"
Statement
"Angenommen man hat $A \\iff B$ und $B \\Rightarrow C$, zeige $A \\Rightarrow C$."
(A B C : Prop) (h : A ↔ B) (g : B → C) : A → C := by
intro hA
apply g
apply h.mp
assumption
Hint (A : Prop) (B : Prop) (C : Prop) (h : A ↔ B) (g : B → C) : A → C =>
"Fange wie immer mit `intro` an."
Hint (A : Prop) (B : Prop) (C : Prop) (h : A ↔ B) (g : B → C) (hA : A) : C =>
"Wie im Implikationen-Level kannst du nun `apply` verwenden."
Message (A : Prop) (B : Prop) (C : Prop) (h : A ↔ B) (g : B → C) (hA : A) : B =>
"Mit `apply h.mp` kannst du nun die Implikation `A → B` anwenden."
Conclusion "Im nächsten Level findest du die zweite Option."
Tactics apply assumption

@ -4,38 +4,36 @@ import Mathlib.Tactic.Cases
Game "TestGame"
World "Implication"
Level 8
Level 9
Title "Genau dann wenn"
Introduction
"
Als zweite Option, kann man eine Annahme `(h : A ↔ B)` in zwei neue Annahmen
`(h₁ : A → B)` und `(h₂ : B → A)` aufteilen.
Und noch die letzte Option:
2.) Mit `rcases h` teilt man die Annahme `h` auf.
(Mit `rcases h with ⟨h₁, h₂⟩` (`\\<`, `\\>`) kann man zudem die neuen Annahmen benennen.)
2. Mit `rcases h with ⟨h₁, h₂⟩` könnte man die Struktur `h` zerlegen und man erhält zwei
separate Annahmen `(h₁ : A → B)` und `(h₂ : B → A)`
Als letzte Option kannst du `rcases h with ⟨h₁, h₂⟩` auch auf eine Annahme `(h : A ↔ B)`
anwenden, genau wie du dies bei einer Annahme `(h' : A ∧ B)` gemacht hast.
"
Statement
"Angenommen man hat $A \\iff B$ und $B \\Rightarrow C$, zeige $A \\Rightarrow C$."
"Angenommen man hat $A \\iff B$ und $B \\Rightarrow C$, zeige $A \\Rightarrow C$."
(A B : Prop) : (A ↔ B) → (A → B) := by
intro h
rcases h
assumption
Message (A : Prop) (B : Prop) : (A ↔ B) → A → B =>
Hint (A : Prop) (B : Prop) : (A ↔ B) → A → B =>
"Angefangen mit `intro h` kannst du annehmen, dass `(h : A ↔ B)` wahr ist."
Message (A : Prop) (B : Prop) (h : A ↔ B): A → B =>
Hint (A : Prop) (B : Prop) (h : A ↔ B) : A → B =>
"Mit `rcases h with ⟨h₁, h₂⟩` kannst du jetzt die Annahme `(h : A ↔ B)` zerlegen."
Conclusion
"
Note: In der Mathematik definieren wir oft Strukturen als Tupels, z.B. \"Sei (G, +) eine Gruppe\".
In Lean brauchen wir dafür immer die Klammern von oben: `⟨_, _⟩`.
"
Tactics intro apply rcases assumption

@ -0,0 +1,55 @@
import TestGame.Metadata
import Std.Tactic.RCases
import Mathlib.Tactic.Cases
import Mathlib
Game "TestGame"
World "Implication"
Level 10
Title "Lemmas"
Introduction
"
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
"Benutze `not_or_of_imp` um zu zeigen, dass $\\neg A \\lor A$ wahr ist."
(A : Prop) : ¬A A := by
apply not_or_of_imp
intro
assumption
Hint (A : Prop) : ¬A A =>
"Das Lemma wendest du mit `apply not_or_of_imp` an."
Hint (A : Prop) : A → A =>
"Wie immer, `intro` ist dein Freund."
Conclusion
"
"
Tactics apply left right assumption
Lemmas not_or_of_imp

@ -0,0 +1,39 @@
import TestGame.Metadata
import Std.Tactic.RCases
import Mathlib.Tactic.Cases
import Mathlib.Logic.Basic
Game "TestGame"
World "Implication"
Level 11
Title "Lemmas"
Introduction
"
Wenn die Aussage eines Lemmas eine Äquivalenz ist, kann man dieses auch mit `rw` brauchen,
wie du es von Äquivalenzen kennst.
Ein wichtiges Lemma ist dass $\\neg(\\neg A))$ und $A$ äquivalent sind:
```
lemma not_not (A : Prop) : ¬¬A ↔ A := by
...
```
Mit `rw [not_not]` sucht Lean also im Goal ein Term `¬¬(·)` und entfernt dort das `¬¬`.
"
Statement
"Zeige, dass $A (¬¬B) ∧ C$ und $A B ∧ C$ äquivalent sind."
(A B C : Prop) : A (¬¬B) ∧ C ↔ A B ∧ C := by
rw [not_not]
Conclusion
"
`rw` hat automatisch `rfl` ausgeführt und dadurch den Beweis beendet.
"
Tactics rw
Lemmas not_not not_or_of_imp

@ -0,0 +1,81 @@
import TestGame.Metadata
import Std.Tactic.RCases
import Mathlib.Tactic.LeftRight
import Mathlib
set_option tactic.hygienic false
Game "TestGame"
World "Implication"
Level 12
Title "Zusammenfassung"
Introduction
"
Damit bist du am Ende der zweiten Lektion angekommen.
Hier ein Überblick über alles was in diesem Kapitel eingeführt wurde und eine
Abschlussaufgabe.
## Notationen / Begriffe
| | Beschreibung |
|:--------------|:---------------------------------------------------------|
| → | Eine Implikation. |
| ↔ | Genau-dann-wenn / Äquivalenz. |
| `lemma` | Ein Resultat mit einem Namen. |
| `theorem` | Das gleiche wie ein Lemma. |
| `example` | Wie ein Lemma aber ohne Namen (nicht weiter verwendbar.) |
## Taktiken
| | Taktik | Beispiel |
|:----|:--------------------------|:-------------------------------------------------------|
| 8 | `intro` | Für eine Implikation im Goal. |
| 9 | `revert` | Umkehrung von `intro`. |
| 10 | `apply` | Wendet eine Implikation auf das Goal an. |
| 10ᵇ | `apply` | Wendet ein Lemma an. |
| 11 | `rw` | Umschreiben zweier äquivalenter Aussagen. |
| 11ᵇ | `rw` | Benutzt ein Lemma, dessen Aussage eine Äquivalenz ist. |
Als Abschlussübung kannst du folgende Äquivalenz zeigen:
"
Statement imp_iff_not_or
"$A \\Rightarrow B$ ist äquivalent zu $\\neg A \\lor B$."
(A B : Prop) : (A → B) ↔ ¬ A B := by
constructor
apply not_or_of_imp
intro h ha
rcases h with h | h
contradiction
assumption
Hint (A : Prop) (B: Prop) : (A → B) ↔ ¬ A B =>
"Eine Äquivalenz im Goal geht man immer mit `constructor` an."
Hint (A : Prop) (B: Prop) : (A → B) → ¬ A B =>
"Diese Aussage hast du vorhin bereits als Lemma kennengelernt und angewendet."
Hint (A : Prop) (B: Prop) (h : A → B) : ¬ A B =>
"Diese Aussage hast du vorhin bereits als Lemma kennengelernt und angewendet."
Hint (A : Prop) (B: Prop) : ¬ A B → (A → B) =>
"Eine Implikation geht man fast immer mit `intro h` an."
Hint (A : Prop) (B: Prop) (h : ¬ A B) : (A → B) =>
"Nochmals `intro`."
Hint (A : Prop) (B: Prop) (h : ¬ A B) : (A → B) =>
"Das ODER in den Annahmen kannst du mit `rcases h with h | h` aufteilen."
Hint (A : Prop) (B: Prop) (h : ¬ A B) (ha : A) : B =>
"Das ODER in den Annahmen kannst du mit `rcases h with h | h` aufteilen."
Hint (A : Prop) (B: Prop) (ha : A) (ha' : ¬A) : B =>
"Findest du einen Widerspruch?"
Tactics rfl assumption trivial left right constructor rcases
Lemmas not_not not_or_of_imp

@ -8,7 +8,7 @@ import TestGame.ToBePorted
Game "TestGame"
World "Implication"
Level 2
Level 102
Title "Kontraposition"

@ -1,28 +0,0 @@
import TestGame.Metadata
Game "TestGame"
World "Old"
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

@ -1,38 +0,0 @@
import TestGame.Metadata
Game "TestGame"
World "Old"
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

@ -1,83 +0,0 @@
import TestGame.Metadata
Game "TestGame"
World "Old"
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

@ -1,64 +0,0 @@
import TestGame.Metadata
Game "TestGame"
World "Old"
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

@ -1,128 +0,0 @@
import TestGame.Metadata
import TestGame.Tactics
Game "TestGame"
World "Old"
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
sorry
-- 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

@ -1,27 +0,0 @@
import TestGame.Metadata
Game "TestGame"
World "Predicate"
Level 6
Title "Definitionally equal"
Introduction
"
**Vorsicht:** `rfl` kann auch Gleichungen beweisen, wenn die beiden Terme Lean-intern gleich
definiert sind, auch wenn diese unterschiedlich dargestellt werden. Das kann anfänglich
zu Verwirrung führen.
So ist `2` als `1 + 1` definiert, deshalb funktioniert `rfl` auch hier.
"
Statement "Zeige dass $1 + 1$ zwei ist." : 1 + 1 = 2 := by
rfl
Conclusion
"
**Notiz:** Die meisten anderen Taktiken versuchen am Schluss automatisch `rfl`
aufzurufen, deshalb brauchst du das nur noch selten.
"
Tactics rfl

@ -1,44 +0,0 @@
import TestGame.Metadata
import Init.Data.ToString
-- #check List UInt8
Game "TestGame"
World "Implication"
Level 6
Title "Genau dann wenn"
Introduction
"
Genau-dann-wenn, $A \\iff B$, wird als `A ↔ B (`\\iff`) geschrieben.
Als erstes kann man mit `rw` Annahmen der Form `(h : A ↔ B)` genau gleich wie Gleichungen
`(h : a = b)` benützen, um das Goal umzuschreiben.
Hier also nochmals die Gleiche Aufgabe wie zuvor,
aber diesmal mit Iff-Statements von Aussagen anstatt
Gleichungen von natürlichen Zahlen.
"
Statement
"Zeige dass `B ↔ C`."
(A B C D : Prop) (h₁ : C ↔ D) (h₂ : A ↔ B) (h₃ : A ↔ D) : B ↔ C := by
rw [h₁]
rw [←h₂]
assumption
Hint (A : Prop) (B : Prop) (C : Prop) (D : Prop) (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₁]`."
Hint (A : Prop) (B : Prop) (C : Prop) (D : Prop) (h₁ : C ↔ D) (h₂ : A ↔ B) (h₃ : A ↔ D) : B ↔ D =>
"Zur Erinnerung: 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)"
Hint (A : Prop) (B : Prop) (h : A ↔ B) : A ↔ B =>
"Schau mal durch die Annahmen durch."
Tactics rw assumption

@ -1,44 +0,0 @@
import TestGame.Metadata
set_option tactic.hygienic false
Game "TestGame"
World "Implication"
Level 7
Title "Genau dann wenn"
Introduction
"
Wenn man eine Annahme `(h : A ↔ B)` hat, kann man auch davon die beiden einzelnen
Implikationen $\\textrm{mp} : A \\Rightarrow B$ und $\\textrm{mpr} : B \\Rightarrow A$
brauchen.
Dazu gibt es zwei Methoden:
1.) `h.mp` (oder `h.1`) und `h.mpr` (oder `h.2`) sind direkt die einzelnen Richtungen.
Man kann also z.B. mit `apply h.mp` die Implikation `A → B` auf ein Goal `B` anwenden.
(PS: das `.mp` kommt von \"Modus Ponens\", ein Ausdruck as der Logik.)
"
Statement
"Angenommen man hat $A \\iff B$ und $B \\Rightarrow C$, zeige $A \\Rightarrow C$."
(A B C : Prop) (h : A ↔ B) (g : B → C) : A → C := by
intro hA
apply g
apply h.mp
assumption
Message (A : Prop) (B : Prop) (C : Prop) (h : A ↔ B) (g : B → C) : A → C =>
"Zuerst kannst du wieder `intro` benützen um die Implikation anzugehen."
Message (A : Prop) (B : Prop) (C : Prop) (h : A ↔ B) (g : B → C) (hA : A) : C =>
"Der nächste Schritt kommt auch noch aus dem Implikationen-Level."
Message (A : Prop) (B : Prop) (C : Prop) (h : A ↔ B) (g : B → C) (hA : A) : B =>
"Mit `apply h.mp` kannst du nun die Implikation `A → B` anwenden."
Conclusion "Im nächsten Level findest du die zweite Option."
Tactics apply assumption

@ -1,35 +0,0 @@
import TestGame.Metadata
import Std.Tactic.RCases
import Mathlib.Tactic.LeftRight
Game "TestGame"
World "Predicate"
Level 2
Title "Widerspruch"
Introduction
"
Im weiteren kann man auch Widersprüche erhalten, wenn man Annahmen der Form
`A ≠ A` (`\\ne`) hat, oder Aussagen der Form
`A = B` hat, wo Lean weiss, dass `A` und `B` unterschiedlich sind, wie zum Beispiel `0 = 1` in ``.
*Bemerkung:* `X ≠ Y` muss man als `¬ (X = Y)` lesen, und auch so behandeln.
"
Statement
"Angenommen man hat $a = b = c$ und $a \\ne c$ natürliche Zahlen $a, b, c$.
Zeige, dass man daraus jede beliebige Aussage beweisen kann."
(A : Prop) (a b c : ) (g₁ : a = b) (g₂ : b = c) (h : a ≠ c) : A := by
rw [g₁] at h
contradiction
Message (A : Prop) (a : ) (b : ) (c : ) (g₁ : a = b) (g₂ : b = c) (h : a ≠ c) : A =>
"Benütze `rw [...] at ...` um zwei Aussagen zu bekommen die genau das Gegenteil
aussagen."
Hint (A : Prop) (a : ) (b : ) (g₁ : a = b) (h : a ≠ b) : A =>
"`X ≠ Y` muss man als `¬ (X = Y)` lesen. Deshalb findet `contradiction` hier direkt
einen Widerspruch."
Tactics contradiction

@ -0,0 +1 @@
import TestGame.Levels.Predicate.L01_Ring

@ -11,11 +11,14 @@ Title "Natürliche Zahlen"
Introduction
"
Wir sind den narürlichen Zahlen `` (`\\N`) schon begegnet. Dabei haben wir
gesehen, dass explizite Gleichungen wie `2 + 3 * 5 = 17` implementationsbedingt
bereits mit `rfl` bewiesen werden können.
Wir sind den narürlichen Zahlen `` (`\\N`) schon kurz begegnet.
Algemeinere Gleichungen mit Variablen kann man mit der Taktik `ring` lösen.
Gleichungen, die nur die Operationen `+, -, *, ^` 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.
"
Statement
@ -23,7 +26,7 @@ Statement
(x y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 := by
ring
Message (x : ) (y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 =>
Hint (x : ) (y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 =>
"`ring` übernimmt den ganzen Spaß."
Conclusion

@ -0,0 +1,31 @@
import TestGame.Metadata
Game "TestGame"
World "Predicate"
Level 6
Title "Definitionally equal"
Introduction
"
Als kleine Nebenbemerkung:
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.
"
Statement
"Zeige dass $1 + 1$ zwei ist." :
1 + 1 = 2 := by
rfl
Conclusion
"
**Notiz:** Die meisten anderen Taktiken versuchen am Schluss automatisch `rfl`
aufzurufen, deshalb brauchst du das nur noch selten.
"
Tactics rfl

@ -22,15 +22,17 @@ Seite.
Wenn der Beweis komplett ist, erscheint \"Level completed! 🎉\".
Deine erste Taktik ist `rfl`, welche dazu da ist, ein Goal der Form $X = X$ zu schliessen.
Deine erste Taktik ist `rfl` (für \"reflexivity\"), welche dazu da ist,
ein Goal der Form $X = X$ zu schliessen.
Gib die Taktik ein gefolgt von Enter ⏎.
"
Statement "Zeige $ 42 = 42 $." : 42 = 42 := by
Statement
"Zeige $ 42 = 42 $." : 42 = 42 := by
rfl
Message : 42 = 42 =>
"Die Taktik `rfl` beweist ein Goal der Form `X = X`."
-- Message : 42 = 42 =>
-- "Die Taktik `rfl` beweist ein Goal der Form `X = X`."
Hint : 42 = 42 =>
"Man schreibt eine Taktik pro Zeile, also gib `rfl` ein und geh mit Enter ⏎ auf eine neue Zeile."

@ -22,13 +22,14 @@ Wenn das Goal genau einer Annahme entspricht, kann man diese mit `assumption` be
"
Statement
"Angenommen $1 < n$. dann ist $1 < n$."
"Angenommen $1 < n$. dann ist $1 < n$."
(n : ) (h : 1 < n) : 1 < n := by
assumption
Message (n : ) (h : 1 < n) : 1 < n =>
Hint (n : ) (h : 1 < n) : 1 < n =>
"`assumption` sucht nach einer Annahme, die dem Goal entspricht."
Conclusion ""
Tactics assumption

@ -17,8 +17,8 @@ Mit einer Annahme `(hA : A)` nimmt man an, dass $A$ wahr ist:
"
Statement
"Sei $A$ eine logische Aussage und sei `hA` ein Beweis für $A$.
Zeige, dass $A$ wahr ist."
"Sei $A$ eine logische Aussage und sei `hA` ein Beweis für $A$.
Zeige, dass $A$ wahr ist."
(A : Prop) (hA : A) : A := by
assumption

@ -26,7 +26,9 @@ Wir können `True` aus dem nichts mit der Taktik `trivial` beweisen.
aber manchmal ist sie nützlich.*
"
Statement "" : True := by
Statement
"Zeige, dass die logische Aussage `True` immer wahr ist." :
True := by
trivial
Conclusion ""

@ -14,7 +14,9 @@ geschrieben `¬A` (`\\not`), gegenteilig falsch oder wahr.
Da die Aussage `False` nie wahr ist, ist die Aussage `¬False` immer wahr, genau wie `True`.
"
Statement "Zeige dass die Aussage `¬False` immer wahr ist." : ¬False := by
Statement
"Zeige dass die Aussage `¬False` immer wahr ist." :
¬False := by
trivial
Conclusion ""

@ -18,12 +18,12 @@ Der erste Widerspruch, den `contradiction` erkennt, ist ein Beweis von `False`.
"
Statement
"Sei $A$ eine Aussage und angenommen man hat einen Beweis für `False`.
Zeige, dass daraus $A$ folgt."
"Sei $A$ eine Aussage und angenommen man hat einen Beweis für `False`.
Zeige, dass daraus $A$ folgt."
(A : Prop) (h : False) : A := by
contradiction
Message (A : Prop) (h : False) : A =>
Hint (A : Prop) (h : False) : A =>
"Wenn man einen Beweis von `False` hat, kann man mit `contradiction` das Goal beweisen,
unabhängig davon, was das Goal ist."

@ -18,7 +18,7 @@ Zweitens kann `contradiction` auch aus Annahmen der Form `a ≠ a` einen Widersp
"
Statement
"Sei $n$ eine natürliche Zahl die ungleich sich selbst ist. Dann ist $n = 37$."
"Sei $n$ eine natürliche Zahl die ungleich sich selbst ist. Dann ist $n = 37$."
(n : ) (h : n ≠ n) : n = 37 := by
contradiction

@ -20,8 +20,8 @@ Da `≠` als `¬(· = ·)` gelesen wird, gilt dasselbe für Annahmen `(h : a = b
"
Statement
"Sei $n$ eine natürliche Zahl die sowohl gleich als auch ungleich `10` ist.
Zeige, dass daraus $n = 42$ folgt. (oder, tatsächlich $n = x$ für jedes beliebige $x$)"
"Sei $n$ eine natürliche Zahl die sowohl gleich als auch ungleich `10` ist.
Zeige, dass daraus $n = 42$ folgt. (oder, tatsächlich $n = x$ für jedes beliebige $x$)"
(n : ) (h : n = 10) (g : (n ≠ 10)) : n = 42 := by
contradiction

@ -26,7 +26,7 @@ Statement "" (A B : Prop) (hA : A) (hB : B) : A ∧ B := by
assumption
assumption
Message (A : Prop) (B : Prop) (hA : A) (hB : B) : A ∧ B =>
Hint (A : Prop) (B : Prop) (hA : A) (hB : B) : A ∧ B =>
"`constructor` zerlegt die Struktur in Einzelteile."
Hint (A : Prop) (hA : A) : A =>

@ -26,9 +26,9 @@ Statement "Benutze `rcases` um das UND in `(h : A ∧ (B ∧ C))` zu zerlegen un
rcases h with ⟨_, ⟨g , _⟩⟩
assumption
Message (A : Prop) (B : Prop) (C : Prop) (h : A ∧ (B ∧ C)) : B =>
"Du kannst mit `rcases` auch verschachtelt mehrere Strukturen in einem Schritt zerlegen:
`rcases h with ⟨h₁, ⟨h₂ , h₃⟩⟩`."
Hint (A : Prop) (B : Prop) (C : Prop) (h : A ∧ (B ∧ C)) : B =>
"Du kannst mit `rcases` auch verschachtelt mehrere Strukturen in einem Schritt zerlegen:
`rcases h with ⟨h₁, ⟨h₂ , h₃⟩⟩`."
Hint (A : Prop) (hA : A) : A =>
"Du hast einen Beweis dafür in den *Annahmen*."

@ -19,7 +19,7 @@ welche Seite man beweisen möchte.
"
Statement
"Angenommen $A$ ist wahr, zeige $A \\lor (\\neg B))$."
"Angenommen $A$ ist wahr, zeige $A \\lor (\\neg B))$."
(A B : Prop) (hA : A) : A (¬ B) := by
left
assumption

@ -24,17 +24,21 @@ wir in beiden Fälle (linke oder rechte Seite wahr) diese Seite wieder `h` nenne
Der Unterschied ist, dass man beim UND eine Annahme in zwei Einzelteile zerlegt (mit `⟨h₁, h₂⟩`).
Beim ODER hingegen, kriegt man stattdessen zwei *Goals*, nämlich eines wo man annimmt,
die linke Seite sei wahr und eines wo man annimmt, rechts sei wahr.
*Notiz:* UND hat stärkere Bindung als ODER, und beide binden rechts, d.h.
`A B ∧ C` wird als `A (B ∧ C)` gelesen. Zudem binden beide nach rechts,
also `A B C` ist `A (B C)`.
"
Statement
"Angenommen \"$A$ oder ($A$ und $B$)\" wahr ist, zeige, dass $A$ wahr ist."
"Angenommen \"$A$ oder ($A$ und $B$)\" wahr ist, zeige, dass $A$ wahr ist."
(A B : Prop) (h : A (A ∧ B)) : A := by
rcases h with h | h
assumption
rcases h with ⟨h₁, h₂⟩
assumption
Message (A : Prop) (B : Prop) (h : A (A ∧ B)) : A =>
Hint (A : Prop) (B : Prop) (h : A (A ∧ B)) : A =>
"Als erstes kannst du das ODER in den Annahmen mit `rcases h with h | h` zerlegen."
Message (A : Prop) (B : Prop) (h : A ∧ B) : A =>

@ -24,8 +24,8 @@ umzugehen um folgende Aussage zu beweisen.
-- Note: The other direction would need arguing by cases.
Statement
"Angenommen $A \\lor (B \\land C)$ ist wahr, zeige dass
$(A \\lor B) \\land (A \\lor C)$ wahr ist."
"Angenommen $A \\lor (B \\land C)$ ist wahr, zeige dass
$(A \\lor B) \\land (A \\lor C)$ wahr ist."
(A B C : Prop) (h : A (B ∧ C)) : (A B) ∧ (A C) := by
constructor
rcases h with h | h
@ -41,26 +41,26 @@ Statement
right
assumption
Message (A : Prop) (B : Prop) (C : Prop) (h : B ∧ C) : (A B) ∧ (A C) =>
Hint (A : Prop) (B : Prop) (C : Prop) (h : B ∧ C) : (A B) ∧ (A C) =>
"Das `∧` in der Annahme kann mit `rcases h with ⟨h₁, h₂⟩` zerlegt werden."
Message (A : Prop) (B : Prop) (C : Prop) : (A B) ∧ (A C) =>
Hint (A : Prop) (B : Prop) (C : Prop) : (A B) ∧ (A C) =>
"Das `∧` im Goal kann mit `constructor` zerlegt werden."
Message (A : Prop) (B : Prop) (C : Prop) (h : A (B ∧ C)) : (A B) ∧ (A C) =>
Hint (A : Prop) (B : Prop) (C : Prop) (h : A (B ∧ C)) : (A B) ∧ (A C) =>
"Das `` in der Annahme kann mit `rcases h with h | h` zerlegt werden."
Message (A : Prop) (B : Prop) (C : Prop) (h : A (B ∧ C)) : (A B) =>
Hint (A : Prop) (B : Prop) (C : Prop) (h : A (B ∧ C)) : (A B) =>
"Das `` in der Annahme kann mit `rcases h with h | h` zerlegt werden."
Message (A : Prop) (B : Prop) (C : Prop) (h : A (B ∧ C)) : (A C) =>
Hint (A : Prop) (B : Prop) (C : Prop) (h : A (B ∧ C)) : (A C) =>
"Das `` in der Annahme kann mit `rcases h with h | h` zerlegt werden."
Message (A : Prop) (B : Prop) (C : Prop) (h : B ∧ C) : (A B) =>
Hint (A : Prop) (B : Prop) (C : Prop) (h : B ∧ C) : (A B) =>
"Das `∧` in der Annahme kann mit `rcases h with ⟨h₁, h₂⟩` zerlegt werden."
Message (A : Prop) (B : Prop) (C : Prop) (h : B ∧ C) : (A C) =>
Hint (A : Prop) (B : Prop) (C : Prop) (h : B ∧ C) : (A C) =>
"Das `∧` in der Annahme kann mit `rcases h with ⟨h₁, h₂⟩` zerlegt werden."
-- TODO: Message nur Anhand der Annahmen?

@ -37,34 +37,30 @@ eingeführt wurden.
| `(ha : A)` | Ein Beweis, dass die logische Aussage `(A : Prop)` wahr ist. |
| `(h : A ∧ B)` | Eine Annahme, die den Namen `h` bekommen hat. |
| `⟨·,·⟩` | Schreibweise für Struktur mit mehreren Feldern (kommt später im Detail). |
| `h.1, h.2, …` | Die einzelnen Felder der Stuktur. Auch `h.[Name des Feldes]` |
Im weiteren haben wir gesehen, wie wir in Lean Aufgaben/Sätze formulieren :
Im weiteren haben wir gesehen, wie wir in Lean Aufgaben formulieren :
```
example [Annahmen] : [Aussage] := by
[Beweis]
lemma [Name] [Annahmen] : [Aussage] := by
[Beweis]
```
Der Unterschied ist lediglich, dass Lemmas einen Namen haben und darum später
wiederverwendet werden können (siehe spätere Kapitel). \"Examples\" kriegen keinen Namen.
## Taktiken
Für die Beweise haben wir verschiedene Taktiken kennengelernt.
| | Taktik | Beispiel |
|:--|:--------------------------|:--------------------------------------------------|
| 1 | `rfl` | Beweist `A = A`. |
| 2 | `assumption` | Sucht das Goal in den Annahmen. |
| 3 | `contradiction` | Sucht einen Widerspruch. |
| 4 | `trivial` | Kombiniert die obigen drei Taktiken (und mehr). |
| 5 | `constructor` | Teilt ein UND im Goal auf. |
| 6 | `left`/`right` | Beweist eine Seite eines ODER im Goal. |
| 7ᵃ | `rcases h with ⟨h₁, h₂⟩` | Teilt ein UND in den Annahmen auf. |
| 7ᵇ | `rcases h with h \\| h` | Teilt ein ODER in den Annahmen in zwei Fälle auf. |
| | Taktik | Beispiel |
|:---|:--------------------------|:--------------------------------------------------|
| 1 | `rfl` | Beweist `A = A`. |
| 2 | `assumption` | Sucht das Goal in den Annahmen. |
| 3 | `contradiction` | Sucht einen Widerspruch. |
| 4 | `trivial` | Kombiniert die obigen drei Taktiken (und mehr). |
| 5 | `constructor` | Teilt ein UND im Goal auf. |
| 6 | `left`/`right` | Beweist eine Seite eines ODER im Goal. |
| 7ᵃ | `rcases h with ⟨h₁, h₂⟩` | Teilt ein UND in den Annahmen auf. |
| 7ᵇ | `rcases h with h \\| h` | Teilt ein ODER in den Annahmen in zwei Fälle auf. |
Zum Schluss gibt es noch eine kleine Übungsaufgabe:

Loading…
Cancel
Save