pull/43/head
Jon 2 years ago
parent ac29c83e79
commit 44b8edbec3

@ -41,6 +41,10 @@ function LemmaDocs({ lemmas }) {
const [categories, setCategories] = useState(new Map()) const [categories, setCategories] = useState(new Map())
const [curCategory, setCurCategory] = useState("") const [curCategory, setCurCategory] = useState("")
const changeTab = (event: React.SyntheticEvent, newValue : string) => {
setCurCategory(newValue);
};
useEffect(() => { useEffect(() => {
const cats = new Map() const cats = new Map()
lemmas.forEach(function (item) { lemmas.forEach(function (item) {
@ -56,6 +60,7 @@ function LemmaDocs({ lemmas }) {
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}> <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs <Tabs
value={curCategory} value={curCategory}
onChange={changeTab}
aria-label="Categories" variant="scrollable" scrollButtons="auto"> aria-label="Categories" variant="scrollable" scrollButtons="auto">
{(Array.from(categories)).map(([category, _]) => <Tab value={category} label={category} key={category} wrapped />)} {(Array.from(categories)).map(([category, _]) => <Tab value={category} label={category} key={category} wrapped />)}
</Tabs> </Tabs>
@ -69,8 +74,8 @@ function LeftPanel({ spells, inventory, showSidePanel, setShowSidePanel }) {
return ( return (
<List className="side"> <List className="side">
<ListItem key="tactics" disablePadding sx={{ display: 'block' }}> <ListItem key="tactics" disablePadding sx={{ display: 'block' }}>
<ListItemButton sx={{ minHeight: 48, justifyContent: open ? 'initial' : 'center', px: 2.5 }} onClick={() => setShowSidePanel(true)}> <ListItemButton sx={{ minHeight: 48, justifyContent: showSidePanel ? 'initial' : 'center', px: 2.5 }} onClick={() => setShowSidePanel(true)}>
<ListItemIcon sx={{minWidth: 0, mr: open ? 3 : 'auto', justifyContent: 'center' }}> <ListItemIcon sx={{minWidth: 0, mr: showSidePanel ? 3 : 'auto', justifyContent: 'center' }}>
<FontAwesomeIcon icon={faHammer}></FontAwesomeIcon> <FontAwesomeIcon icon={faHammer}></FontAwesomeIcon>
</ListItemIcon> </ListItemIcon>
<ListItemText primary="Known Tactics" sx={{ display: showSidePanel ? null : "none" }} /> <ListItemText primary="Known Tactics" sx={{ display: showSidePanel ? null : "none" }} />
@ -81,8 +86,8 @@ function LeftPanel({ spells, inventory, showSidePanel, setShowSidePanel }) {
</Paper>} </Paper>}
</ListItem> </ListItem>
<ListItem key="lemmas" disablePadding sx={{ display: 'block' }}> <ListItem key="lemmas" disablePadding sx={{ display: 'block' }}>
<ListItemButton sx={{ minHeight: 48, justifyContent: open ? 'initial' : 'center', px: 2.5 }} > <ListItemButton sx={{ minHeight: 48, justifyContent: showSidePanel ? 'initial' : 'center', px: 2.5 }} >
<ListItemIcon sx={{minWidth: 0, mr: open ? 3 : 'auto', justifyContent: 'center' }}> <ListItemIcon sx={{minWidth: 0, mr: showSidePanel ? 3 : 'auto', justifyContent: 'center' }}>
<FontAwesomeIcon icon={faBook}></FontAwesomeIcon> <FontAwesomeIcon icon={faBook}></FontAwesomeIcon>
</ListItemIcon> </ListItemIcon>
<ListItemText primary="Known Lemmas" sx={{ display: showSidePanel ? null : "none" }} /> <ListItemText primary="Known Lemmas" sx={{ display: showSidePanel ? null : "none" }} />

@ -65,6 +65,10 @@ mjx-container[jax="CHTML"][display="true"] {
padding-right: .5em; padding-right: .5em;
} }
span.katex-display {
margin: 0;
}
p, table { p, table {
margin-block-start: 1em; margin-block-start: 1em;
margin-block-end: 1em; margin-block-end: 1em;

@ -4,6 +4,7 @@ import TestGame.Levels.Logic.L02_Rfl
import TestGame.Levels.Logic.L03_Assumption import TestGame.Levels.Logic.L03_Assumption
import TestGame.Levels.Logic.L03b_Assumption import TestGame.Levels.Logic.L03b_Assumption
import TestGame.Levels.Logic.L04_Rewrite import TestGame.Levels.Logic.L04_Rewrite
import TestGame.Levels.Logic.L04b_Rewrite
import TestGame.Levels.Logic.L05_Apply import TestGame.Levels.Logic.L05_Apply
import TestGame.Levels.Logic.L05b_Apply import TestGame.Levels.Logic.L05b_Apply
import TestGame.Levels.Logic.L05c_Apply import TestGame.Levels.Logic.L05c_Apply
@ -32,3 +33,62 @@ import TestGame.Levels.Negation.L06_ByContra
import TestGame.Levels.Negation.L07_Contrapose import TestGame.Levels.Negation.L07_Contrapose
import TestGame.Levels.Negation.L08_Contrapose import TestGame.Levels.Negation.L08_Contrapose
import TestGame.Levels.Negation.L09_PushNeg import TestGame.Levels.Negation.L09_PushNeg
Game "TestGame"
Title "Lean 4 game"
Introduction
"Work in progress. Hier sind die Kommentare, aufgeteilt in drei Kategorien
### Levels / Spielinhalt
Levels, die spielbar sind:
- Logic
- Contradiction
Die anderen Levels gehen noch grössere Veränderungen durch.
Kommentare zu den spielbaren Levels:
- Taktik-Beschreibungen sind nicht gemacht, aber es sollten die richtigen
Taktiken & Lemmas angezeigt werden
- Noch mehr kurze Aufgaben?
- Mehr zur Implikation `→`?
- Ringschluss (noch nicht in Lean4)
- `tauto` (noch nicht in Lean4). Am Anfang?
- `trivial`: wann einführen? Ist ja ein Mix von verschiedenen Taktiken.
- Wann führen wir `have h : f ha` ein? (ist jetzt mal in `by_contra` reingequetscht, sollte
aber eigenständig sein)
- Nicht erklärt, wann `rw` nur eines umschreibt und wann mehrere Male. Sollten wir das tun?
### Spieler-Führung
- Keine Möglichkeit zurück zu gehen und nach dem letzten Level kann man trotzdem
\"Next Level\" klicken
- Fehlermeldungen sind nicht besonders Benutzerfreundlich: Ganz unverständliche sammeln,
damit wir diese später modifizieren können.
- Kann man Taktiken blockieren?
- Ich (J) bin kein Fan von der Autoergänzung, da diese im Moment viel unrelevantes anbietet.
- BUG: Kann `suffices` & `have` nicht als Taktik anzeigen.
- BUG: `¬ odd n` wird als Objekt gelistet, nicht als Assumption.
- FEAT: Brauche ein `Message'` das nur aktiv ist, wenn keine zusätzlichen Annahmen vorhanden
sind.
### Benutzerinterface
Das graphische wurde noch nicht wirklich angegangen, hier sind vorallem gröbere
Ideen wie Seitenaufteilung hilfreich. Details werden dann aber später angegangen.
- Spielstand wir noch nicht gespeichert.
- Die Lean-Version der Aufgaben sieht rudimentär aus: Syntax highlighting?
"
Conclusion
"There is nothing else so far. Thanks for rescuing natural numbers!"
Path Logic → Nat → Contradiction
Path Nat → Nat2

@ -16,9 +16,11 @@ zero_add add_zero
LemmaDoc not_not as not_not in "Logic" LemmaDoc not_not as not_not in "Logic"
"`∀ (A : Prop), ¬¬A ↔ A`." "`∀ (A : Prop), ¬¬A ↔ A`."
LemmaDoc not_forall as not_forall in "Logic"
"`∀ (A : Prop), ¬(∀ x, A) ↔ ∃x, (¬A)`."
LemmaDoc not_exists as not_exists in "Logic"
"`∀ (A : Prop), ¬(∃ x, A) ↔ ∀x, (¬A)`."
LemmaDoc even as even in "Nat" LemmaDoc even as even in "Nat"
" "
@ -46,4 +48,4 @@ LemmaSet natural : "Natürliche Zahlen" :=
even odd not_odd not_even even odd not_odd not_even
LemmaSet logic : "Logik" := LemmaSet logic : "Logik" :=
not_not not_not not_forall not_exists

@ -14,8 +14,8 @@ Zum Beispiel
\"und angenommen, dass $n$ strikt grösser als $1$ ist\". \"und angenommen, dass $n$ strikt grösser als $1$ ist\".
In Lean schreibt man beides mit dem gleichen Syntax: `(n : ) (h : 1 < n)` definiert In Lean schreibt man beides mit dem gleichen Syntax: `(n : ) (h : 1 < n)` definiert
zuerst eine natürliche Zahl $n$ und eine Annahme dass $1 < n$ (die Annahme kriegt zuerst eine natürliche Zahl $n$ und eine Annahme dass $1 < n$ gilt
den Namen `h`). (welche den Namen `h` kriegt).
Wenn das Goal genau einer Annahme entspricht, kann man diese mit `assumption` beweisen. Wenn das Goal genau einer Annahme entspricht, kann man diese mit `assumption` beweisen.
" "

@ -19,11 +19,11 @@ kann die Taktik `rw [h]` im Goal $X$ durch $Y$ ersetzen.
Statement umschreiben Statement umschreiben
"Angenommen man hat die Gleichheiten "Angenommen man hat die Gleichheiten
$$ \\begin{aligned}
a &= b \\\\\\\\ $$
a &= d \\\\\\\\ \\begin{aligned} a &= b \\\\ a &= d \\\\ c &= d \\end{aligned}
c &= d $$
\\end{aligned} $$
Zeige dass $b = c$." Zeige dass $b = c$."
(a b c d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : a = d) : b = c := by (a b c d : ) (h₁ : c = d) (h₂ : a = b) (h₃ : a = d) : b = c := by
rw [h₁] rw [h₁]

@ -0,0 +1,39 @@
import TestGame.Metadata
import Mathlib
Game "TestGame"
World "Logic"
Level 6
Title "Rewrite"
Introduction
"
Mit `rw` kann man nicht nur das Goal sondern auch andere Annahmen umschreiben:
Wenn `(h : X = Y)` ist, dann ersetzt `rw [h] at g` in der Annahme
`g` das `X` durch `Y`.
"
Statement umschreiben
"Angenommen man hat die Gleichheiten
$$
\\begin{aligned} a &= b \\\\ a + a ^ 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
rw [h] at g
assumption
Message (a : ) (b : ) (h : a = b) (g : a + a ^ 2 = b + 1) : b + b ^ 2 = b + 1 =>
"`rw [ ... ] at g` schreibt die Annahme `g` um."
Message (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."
Tactics assumption rw

@ -3,32 +3,32 @@ import Mathlib
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 6 Level 7
Title "Implikation" Title "Implikation"
Introduction Introduction
"Als nächstes widmen wir uns der Implikation $A \\Rightarrow B$. "Als nächstes widmen wir uns der Implikation $A \\Rightarrow B$.
Mit zwei logischen Aussagen `(A : Prop) (B : Prop)` schreibt man eine Implikation
Mit zwei logischen Aussagen `(A : Prop)`, `(B : Prop)` schreibt man eine Implikation
als `A → B` (`\\to`). als `A → B` (`\\to`).
Wenn man als Goal $B$ hat und eine Impikation `(g : A → B)` kann man mit `apply g` diese Wenn man als Goal $B$ beweisen möchte und eine Impikation `(g : A → B)`
anwenden, worauf das Goal $A$ ist. Auf Papier würde man an der Stelle hat, kann man mit `apply g` diese
folgendes zu schreiben: \"Es genügt $A$ zu zeigen, denn $A$ impliziert $B$\". 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 *Bemerke:* Das ist der selbe Pfeil, der später auch für Funktionen wie `` gebraucht
wird, deshalb heisst er `\\to`." wird, deshalb heisst er `\\to`."
Statement Statement
"Seien $A$, $B$ logische Aussagen, wobei $A$ wahr ist und $A$ impliziert $B$. "Seien $A, B$ logische Aussagen, wobei $A$ wahr ist und $A \\Rightarrow B$.
Zeige, dass $B$ wahr ist." Zeige, dass $B$ wahr ist."
(A B : Prop) (hA : A) (g : A → B) : B := by (A B : Prop) (hA : A) (g : A → B) : B := by
apply g apply g
assumption assumption
Hint (A : Prop) (B : Prop) (hA : A) (g : A → B) : A => Hint (A : Prop) (B : Prop) (hA : A) (g : A → B) : B =>
"Mit `apply g` kannst du die Implikation `g` anwenden." "Mit `apply g` kannst du die Implikation `g` anwenden."
Hint (A : Prop) (B : Prop) (hA : A) (g : A → B) : A => Hint (A : Prop) (B : Prop) (hA : A) (g : A → B) : A =>
@ -37,8 +37,8 @@ dafür hast du bereits einen Beweis in den Annahmen."
Tactics apply assumption Tactics apply assumption
-- Mathjax notes -- Katex notes
-- `\\\\( \\\\)` or `$ $` for inline -- `\\( \\)` or `$ $` for inline
-- and `$$ $$` block. -- and `$$ $$` block.
-- align block: -- align block:
-- $$\\begin{aligned} 2x - 4 &= 6 \\\\\\\\ 2x &= 10 \\\\\\\\ x &= 5 \\end{aligned}$$ -- $$\\begin{aligned} 2x - 4 &= 6 \\\\ 2x &= 10 \\\\ x &= 5 \\end{aligned}$$

@ -2,7 +2,7 @@ import TestGame.Metadata
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 7 Level 8
Title "Implikation" Title "Implikation"
@ -28,6 +28,11 @@ Statement
apply f apply f
assumption assumption
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 =>
"Versuch mit `apply` den richtigen Weg zu finden."
Message (A : Prop) (B : Prop) (C : Prop) (D : Prop) (E : Prop) (F : Prop) Message (A : Prop) (B : Prop) (C : Prop) (D : Prop) (E : Prop) (F : Prop)
(hA : A) (f : A → B) (g : C → B) (h : B → E) (hA : A) (f : A → B) (g : C → B) (h : B → E)
(i : D → E) (k : E → F) (m : C → F) : C => (i : D → E) (k : E → F) (m : C → F) : C =>

@ -4,7 +4,7 @@ set_option tactic.hygienic false
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 8 Level 9
Title "Implikation" Title "Implikation"
@ -15,7 +15,7 @@ Wenn das Goal eine Implikation $A \\Rightarrow B$ ist, kann man mit
" "
Statement Statement
"" "Angenommen man weiss $A \\Rightarrow B \\Rightarrow C$, zeige dass $A \\Rightarrow C$."
(A B C : Prop) (f : A → B) (g : B → C) : A → C := by (A B C : Prop) (f : A → B) (g : B → C) : A → C := by
intro hA intro hA
apply g apply g
@ -23,7 +23,7 @@ Statement
assumption assumption
Message (A : Prop) (B : Prop) (C : Prop) (f : A → B) (g : B → C) : A → C => Message (A : Prop) (B : Prop) (C : Prop) (f : A → B) (g : B → C) : A → C =>
"mit `intro hA` kann man eine Implikation angehen." "Mit `intro hA` kann man eine Implikation angehen."
Message (A : Prop) (B : Prop) (C : Prop) (hA : A) (f : A → B) (g : B → C) : C => Message (A : Prop) (B : Prop) (C : Prop) (hA : A) (f : A → B) (g : B → C) : C =>
"Jetzt ist es ein altbekanntes Spiel von `apply`-Anwendungen." "Jetzt ist es ein altbekanntes Spiel von `apply`-Anwendungen."

@ -5,7 +5,7 @@ import Init.Data.ToString
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 9 Level 10
Title "Genau dann wenn" Title "Genau dann wenn"

@ -2,7 +2,7 @@ import TestGame.Metadata
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 10 Level 11
Title "Genau dann wenn" Title "Genau dann wenn"

@ -4,7 +4,7 @@ set_option tactic.hygienic false
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 11 Level 12
Title "Genau dann wenn" Title "Genau dann wenn"

@ -4,7 +4,7 @@ import Mathlib.Tactic.Cases
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 12 Level 13
Title "Genau dann wenn" Title "Genau dann wenn"

@ -5,7 +5,7 @@ set_option tactic.hygienic false
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 13 Level 14
Title "Und" Title "Und"

@ -6,7 +6,7 @@ import Mathlib.Tactic.LeftRight
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 14 Level 15
Title "Oder" Title "Oder"

@ -9,7 +9,7 @@ import Mathlib.Tactic.LeftRight
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 15 Level 16
Title "Oder - Bonus" Title "Oder - Bonus"

@ -6,7 +6,7 @@ set_option tactic.hygienic false
Game "TestGame" Game "TestGame"
World "Logic" World "Logic"
Level 16 Level 17
Title "Oder" Title "Oder"

@ -18,9 +18,14 @@ bereits mit `rfl` bewiesen werden können.
Algemeinere Gleichungen mit Variablen kann man mit der Taktik `ring` lösen. Algemeinere Gleichungen mit Variablen kann man mit der Taktik `ring` lösen.
" "
Statement "" (x y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 := by 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 ring
Message (x : ) (y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 =>
"`ring` übernimmt den ganzen Spaß."
Conclusion Conclusion
" "
Die Taktik heisst übrigens `ring` weil sie dafür entwickelt wurde, Gleichungen in einem abstrakten Die Taktik heisst übrigens `ring` weil sie dafür entwickelt wurde, Gleichungen in einem abstrakten

@ -12,10 +12,19 @@ Introduction
Ring setzt aber nicht selbständig Annahmen ein, diese muss man zuerst manuell mit `rw` verwenden. Ring setzt aber nicht selbständig Annahmen ein, diese muss man zuerst manuell mit `rw` verwenden.
" "
Statement "" (x y : ) (h : x = 2 * y + 1) : x ^ 2 = 4 * y ^ 2 + 3 * y + 1 + y := by 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] rw [h]
ring ring
Message (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."
Message (y : ) : (2 * y + 1) ^ 2 = 4 * y ^ 2 + 3 * y + 1 + y =>
"Jetzt kann `ring` übernehmen."
Conclusion "" Conclusion ""
Tactics ring Tactics ring rw

@ -33,15 +33,15 @@ Hierzu gibt es 3 wichtige Taktiken:
soll. Das macht man mit `use y` soll. Das macht man mit `use y`
" "
Statement even_square "" (n : ) (h : even n) : even (n ^ 2) := by Statement even_square
"Wenn $n$ gerade ist, dann ist $n^2$ gerade."
(n : ) (h : even n) : even (n ^ 2) := by
unfold even at * unfold even at *
rcases h with ⟨x, hx⟩ rcases h with ⟨x, hx⟩
use 2 * x ^ 2 use 2 * x ^ 2
rw [hx] rw [hx]
ring ring
-- TODO: Server PANIC because of the `even`.
--
Message (n : ) (h : even n) : even (n ^ 2) => Message (n : ) (h : even n) : even (n ^ 2) =>
"Wenn du die Definition von `even` nicht kennst, kannst du diese mit `unfold even` oder "Wenn du die Definition von `even` nicht kennst, kannst du diese mit `unfold even` oder
`unfold even at *` ersetzen. `unfold even at *` ersetzen.
@ -68,3 +68,4 @@ Message (n : ) (x : ) (hx : n = x + x) : (x + x) ^ 2 = 2 * x ^ 2 + 2 * x ^
"Die Taktik `ring` löst solche Gleichungen." "Die Taktik `ring` löst solche Gleichungen."
Tactics unfold rcases use rw ring Tactics unfold rcases use rw ring
Lemmas even odd

@ -19,7 +19,9 @@ Zum `∃` gehört auch das \"für alle\" `∀` (`\\forall`).
Ein `∀` im Goal kann man mit `intro` angehen, genau wie bei einer Implikation `→`. Ein `∀` im Goal kann man mit `intro` angehen, genau wie bei einer Implikation `→`.
" "
Statement "" : ∀ (x : ), (even x) → odd (1 + x) := by 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 intro x h
unfold even at h unfold even at h
unfold odd unfold odd

@ -22,8 +22,13 @@ Der einfachste Widerspruch ist wenn man einen Beweis von `False` hat:
" "
Statement Statement
"Ein Widerspruch impliziert alles." "Sei $A$ eine Aussage und angenommen man hat einen Beweis für `False`.
Zeige, dass daraus $A$ folgt."
(A : Prop) (h : False) : A := by (A : Prop) (h : False) : A := by
contradiction contradiction
Message (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."
Tactics contradiction Tactics contradiction

@ -16,9 +16,10 @@ Introduction
also `(h : A)` und `(g : ¬ A)`. (`\\not`) also `(h : A)` und `(g : ¬ A)`. (`\\not`)
" "
Statement Statement absurd
"Ein Widerspruch impliziert alles." "Sei $n$ eine natürliche Zahl die sowohl gerade wie auch nicht gerade ist.
(n : ) (h : even n) (g : ¬ (even n)) : n = 128 := by Zeige, dass daraus $n = 42$ folgt. (oder, tatsächlich $n = x$ für jedes beliebige $x$)"
(n : ) (h : even n) (g : ¬ (even n)) : n = 42 := by
contradiction contradiction
Conclusion Conclusion

@ -14,28 +14,24 @@ Level 3
Title "Ad absurdum" Title "Ad absurdum"
Introduction Introduction
" "Aber, die Aussagen müssen wirklich exakte Gegenteile sein.
Aber, die Aussagen müssen wirklich exakte Gegenteile sein.
Hier musst du zuerst eines der Lemmas `not_odd : ¬ odd n ↔ even n` oder Hier musst du zuerst eines der Lemmas `(not_odd : ¬ odd n ↔ even n)` oder
`not_even : ¬ even n ↔ odd n` benützen, um einer der Terme umzuschreiben. `(not_even : ¬ even n ↔ odd n)` benützen, um einer der Terme umzuschreiben."
"
Statement Statement
"Ein Widerspruch impliziert alles." "Sei $n$ eine natürliche Zahl die sowohl gerade wie auch ungerade ist.
(n : ) (h₁ : even n) (h₂ : odd n) : n = 128 := by Zeige, dass daraus $n = 42$ folgt. (oder, tatsächlich $n = x$ für jedes beliebige $x$)."
rw [← not_even] at h₂ (n : ) (h_even : even n) (h_odd : odd n) : n = 42 := by
rw [← not_even] at h_odd
contradiction contradiction
Message (n : ) (h₁ : even n) (h₂ : odd n) : n = 128 => Message (n : ) (h_even : even n) (h_odd : odd n) : n = 42 =>
"Schreibe zuerst eine der Aussagen mit `rw [←not_even] at h` um, damit diese genaue "Schreibe zuerst eine der Aussagen mit `rw [←not_even] at h_odd` um, damit diese genaue
Gegenteile sind." Gegenteile werden."
Conclusion Conclusion ""
"
Detail: `¬ A` ist übrigens als `A → false` implementiert, was aussagt, dass
\"falls `A` wahr ist, impliziert das `false` und damit einen Widerspruch\".
"
-- TODO: Oder doch ganz entfernen?
Tactics contradiction Tactics contradiction rw
Lemmas even odd not_even not_odd

@ -11,21 +11,25 @@ Title "Ad absurdum"
Introduction Introduction
" "
Im weiteren kann man auch Widersprüche erhalten, wenn man Annahmen der Form Im weiteren kann man auch Widersprüche erhalten, wenn man Annahmen der Form
`A = B` hat, wo Lean weiss, dass `A und `B` unterschiedlich sind, z.B. `0 = 1` in `` `A ≠ A` (`\\ne`) hat, oder Aussagen der Form
oder auch Annahmen der Form `A ≠ A` (`\\ne`). `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 Statement
"Ein Widerspruch impliziert alles." "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 (A : Prop) (a b c : ) (g₁ : a = b) (g₂ : b = c) (h : a ≠ c) : A := by
rw [g₁] at h rw [g₁] at h
contradiction contradiction
Message (A : Prop) (a : ) (b : ) (c : ) (g₁ : a = b) (g₂ : b = c) (h : a ≠ c) : A => Message (A : Prop) (a : ) (b : ) (c : ) (g₁ : a = b) (g₂ : b = c) (h : a ≠ c) : A =>
"Recap: `rw [...] at h` hilft dir hier." "Benütze `rw [...] at ...` um zwei Aussagen zu bekommen die genau das Gegenteil
aussagen."
Message (A : Prop) (a : ) (b : ) (c : ) (g₁ : a = b) (g₂ : b = c) (h : b ≠ c) : A => Hint (A : Prop) (a : ) (b : ) (g₁ : a = b) (h : a ≠ b) : A =>
"`b ≠ c` muss man als `¬ (b = c)` lesen. Deshalb findet `contradiction` hier direkt "`X ≠ Y` muss man als `¬ (X = Y)` lesen. Deshalb findet `contradiction` hier direkt
einen Widerspruch." einen Widerspruch."
Tactics contradiction Tactics contradiction

@ -11,14 +11,23 @@ Introduction
" "
Wenn man ein Nicht (`¬`) im Goal hat, will man meistens einen Widerspruch starten, Wenn man ein Nicht (`¬`) im Goal hat, will man meistens einen Widerspruch starten,
wie im nächsten Level dann gezeigt wird. Manchmal aber hat man Terme der Form wie im nächsten Level dann gezeigt wird. Manchmal aber hat man Terme der Form
`¬ (¬ A)`, in welchem Fall das Lemma `not_not` nützlich ist. `¬ (¬ A)`, in welchem Fall das Lemma `not_not` nützlich ist, welches du mit
`rw` oder `apply` benützen kannst.
" "
Statement Statement
"" "Zeige, dass $\\neg(\\neg A)$ äquivalent zu $A$ ist."
(A : Prop) : ¬ (¬ A) ↔ A := by (A : Prop) : ¬ (¬ A) ↔ A := by
rw [not_not] rw [not_not]
Tactics rw Message (A : Prop) : ¬ (¬ A) ↔ A => "Da `not_not` ein Lemma der Form `X ↔ Y` ist,
kannst du wahlweise `rw [not_not]` oder `apply not_not` benützen.
- `rw` ersetzt `¬ (¬ A)` mit `A` und schliesst dann `A ↔ A` mit `rfl`.
- `apply` hingegen funktioniert hier nur, weil das gesamte Goal
genau mit der Aussage des Lemmas übereinstimmt.
"
Tactics rw apply
Lemmas not_not Lemmas not_not

@ -14,35 +14,68 @@ Title "Widerspruch"
Introduction Introduction
" "
Zwei wichtige Beweisformen sind per Widerspruch und per Kontraposition. Hier
schauen wir beide an und auch den Unterschied.
Um einen Beweis per Widerspruch zu führen, kann man mit `by_contra h` annehmen, Um einen Beweis per Widerspruch zu führen, kann man mit `by_contra h` annehmen,
dass das Gegenteil des Goals wahr sei, und dann einen Widerspruch erzeugen. dass das Gegenteil des Goals wahr sei, und dann einen Widerspruch erzeugen.
**Bemerkung:** Besonders beim Beweis durch Widerspruch ist es hilfreich, wenn man
Zwischenresultate erstellen kann.
`suffices h₁ : ¬(odd (n ^ 2))` erstellt zwei neue Goals:
1) Ein Beweis, wieso es genügt `¬(odd (n ^ 2))` zu zeigen (\"weil das einen Widerspruch zu
`h` bewirkt\").
2) Einen Beweis des Zwischenresultats `suffices h₁ : ¬(odd (n ^ 2))`
Alternativ macht `have h₁ : ¬(odd (n ^ 2))` genau das gleiche, vertauscht aber die
Beweise (1) und (2), so dass man zuerst `h₁` beweist, und dann den eigentlichen Beweis
fortsetzt.
" "
Statement Statement
"Ist n² ungerade, so ist auch n ungerade. Beweise durch Widerspruch." "Ist n² ungerade, so ist auch n ungerade. Beweise durch Widerspruch."
(n : ) (h : odd (n ^ 2)) : odd n := by (n : ) (h : odd (n ^ 2)) : odd n := by
by_contra g by_contra g
rw [not_odd] at g suffices d : ¬ odd (n ^ 2) -- TODO: I don't like this
contradiction
suffices ¬ odd (n ^ 2) by contradiction -- TODO: I don't like this
rw [not_odd] at g
rw [not_odd] rw [not_odd]
apply even_square apply even_square
assumption assumption
Message : false => Message (n : ) (h : odd (n^2)) : odd n =>
"Es gibt mehrere Möglichkeiten, wie man nach einem `by_contra` weitergeht. "Schreibe `by_contra h₁` um einen Beweis durch Widerspruch zu starten."
Hier wollen wir einen Widerspruch zu `h` machen. Wir machen das mit Message (n : ) (g : ¬ odd n) (h : odd (n^2)) : False =>
`suffices ¬ odd (n ^ 2) by contradiction`, worauf man dann nur noch `¬ odd (n ^ 2)` "Nun *genügt es zu zeigen, dass* `¬odd (n ^ 2)` wahr ist,
zeigen muss." denn dann erhalten wir einen Widerspruch zu `h`.
Hint (n : ) : ¬ (odd (n ^ 2)) => Benütze dafür `suffices h₂ : ¬odd (n ^ 2)`.
"Das Lemma `not_odd` ist hilfreich." "
Message (n : ) (g : ¬ odd (n^2)) (h : odd (n^2)) : False =>
"Hier musst du rechtfertigen, wieso das genügt. In unserem Fall, weil
dadurch einen Widerspruch entsteht."
Hint (n : ) (g : ¬ odd (n^2)) (h : odd (n^2)) : False =>
"Also `contradiction`..."
Message (n : ) (g : ¬ odd n) (h : odd (n^2)) : ¬ odd (n^2) =>
"Das Zwischenresultat `¬odd (n^2)` muss auch bewiesen werden.
Hier ist wieder das Lemma `not_odd` hilfreich."
Hint (n : ) (g : ¬ odd n) (h : odd (n^2)) : even (n^2) =>
"Mit `rw [not_odd] at *` kannst du im Goal und allen Annahmen gleichzeitig umschreiben."
Message (n: ) (h : odd (n ^ 2)) (g : even n) : even (n ^ 2) => Message (n: ) (h : odd (n ^ 2)) (g : even n) : even (n ^ 2) =>
"Das haben wir schon gezeigt. Mit `apply even_square` kannst du das Lemma anwenden." "Diese Aussage hast du bereits als Lemma bewiesen."
Hint (n: ) (h : odd (n ^ 2)) (g : even n) : even (n ^ 2) =>
"Probiers mit `apply ...`"
Tactics contradiction by_contra rw apply assumption -- TODO: suffices Tactics contradiction by_contra rw apply assumption -- TODO: suffices, have
Lemmas odd even not_odd not_even even_square Lemmas odd even not_odd not_even even_square

@ -29,5 +29,22 @@ Statement
rw [not_odd] rw [not_odd]
apply even_square apply even_square
Message (n : ) (h : odd (n ^ 2)) : odd n =>
"`intro` wär generell ein guter Ansatz! Aber hier wollen wir `contrapose` benützen, was eine
Implikation benötigt, deshalb ist `intro` hier der falsche Weg!"
Message (n : ) : odd (n ^ 2) → odd n =>
"Mit `contrapose` kann man die Implikation zu
`¬ (even n) → ¬ (even n^2)` umkehren."
Hint (n : ) : ¬odd n → ¬odd (n ^ 2) => "Du kennst bereits ein Lemma um `¬ odd ...` mit `rw`
umzuschreiben"
Message (n : ) : even n → ¬odd (n ^ 2) => "rw [not_odd] muss hier zweimal angewendet werden,
da rw das erste Mal `not_odd n` gebraucht hat und das zweite Mal `not_odd (n^2)` benützt."
Message (n : ) : even n → even (n ^ 2) => "Diese Aussage hast du bereits als Lemma bewiesen."
Tactics contrapose rw apply Tactics contrapose rw apply
Lemmas even odd not_even not_odd even_square Lemmas even odd not_even not_odd even_square

@ -13,8 +13,7 @@ Level 8
Title "Kontraposition" Title "Kontraposition"
Introduction Introduction
" "**Lean Trick:** Wenn das Goal nicht bereits eine Implikation ist, sondern man eine Annahme `h` hat, die
Lean Trick: Wenn das Goal nicht bereits eine Implikation ist, sondern man eine Annahme `h` hat, die
Man gerne für die Kontraposition benützen würde, kann man mit `revert h` diese als Man gerne für die Kontraposition benützen würde, kann man mit `revert h` diese als
Implikationsannahme ins Goal schreiben. Implikationsannahme ins Goal schreiben.
" "
@ -28,5 +27,11 @@ Statement
rw [not_odd] rw [not_odd]
apply even_square apply even_square
Hint (n : ) (h : odd (n ^ 2)) : odd n =>
"Benutze `revert h` um das Goal in eine Implikation umzuschreiben."
Message (n : ) : odd (n ^ 2) → odd n =>
"Jetzt ist es genau das gleiche wie bei der letzten Aufgabe."
Tactics contrapose rw apply revert Tactics contrapose rw apply revert
Lemmas even odd not_even not_odd even_square Lemmas even odd not_even not_odd even_square

@ -14,23 +14,53 @@ Introduction
" "
Zum Schluss, immer wenn man irgendwo eine Verneinung `¬∃` oder `¬∀` sieht (`\\not`), kann man Zum Schluss, immer wenn man irgendwo eine Verneinung `¬∃` oder `¬∀` sieht (`\\not`), kann man
mit `push_neg` das `¬` durch den Quantor hindurchschieben. 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 Statement
"Es existiert keine natürliche Zahl, die grösser als alle anderen.": "Es existiert keine natürliche Zahl $n$, sodass $n + k$ immer ungerade ist.":
¬ ∃ (n : ), ∀ (k : ) , odd (n + k) := by ¬ ∃ (n : ), ∀ (k : ) , odd (n + k) := by
push_neg push_neg
intro n intro n
use 3*n + 6 use n
rw [not_odd] rw [not_odd]
unfold even unfold even
use 2*n + 3 use n
ring ring
Message (n : ) : (Exists fun k ↦ ¬odd (n + k)) => Message : ¬ ∃ (n : ), ∀ (k : ) , odd (n + k) =>
"An dieser Stelle musst du nun ein `k` angeben, sodass `n + k` gerade ist... Benutz `use ...` "`push_neg` schiebt die Negierung an den Quantoren vorbei."
Message (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." mit der richtigen Zahl."
Hint (n : ) : ¬odd (n + n) =>
"Du kennst ein Lemma um mit `¬odd` umzugehen."
-- Hint (n : ) (k : ) : ¬odd (n + k) =>
-- "Du kennst ein Lemma um mit `¬odd` umzugehen."
Hint (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."
-- Hint (n : ) (k : ) : even (n + k) =>
-- "`unfold even` hilft hier weiter."
Message (n : ) : n + n = 2 * n => "Recap: `ring` löst Gleichungen in ``."
Conclusion "" Conclusion ""
Tactics push_neg intro use rw unfold ring Tactics push_neg intro use rw unfold ring
Lemmas even odd not_even not_odd not_exists not_forall

@ -2,24 +2,3 @@ import GameServer.Commands
import TestGame.TacticDocs import TestGame.TacticDocs
import TestGame.LemmaDocs import TestGame.LemmaDocs
import Mathlib.Init.Data.Nat.Basic -- Imports the notation . import Mathlib.Init.Data.Nat.Basic -- Imports the notation .
Game "TestGame"
Title "The Natural Number Game"
Introduction
"This is a sad day for mathematics. While trying to find glorious new foundations for mathematics,
someone removed the law of excluded middle and the axiom of choice. Unsurprisingly,
everything collapsed. A brave rescue team managed to retrieve our precious axioms from the wreckage
but now we need to rebuild all of mathematics from scratch.
As a beginning mathematics wizard, you've been tasked to rebuild the theory of natural numbers from
the axioms that Giuseppe Peano found under the collapsed tower of number theory. You've been equipped
with a level 1 spell book. Good luck."
Conclusion
"There is nothing else so far. Thanks for rescuing natural numbers!"
Path Logic → Nat → Contradiction
Path Nat → Nat2

Loading…
Cancel
Save