rename testgame to adam
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 1
|
||||
|
||||
Title "Anonyme Funktionen"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Auf die Frage hin, ob sie von einem Bibliothek wisse, erzählt euch das kleine Mädchen,
|
||||
dass es auf der Insel nur einen gäbe, aber sie bedrängt euch so mit einer Frage,
|
||||
dass sie euch gar nicht sagt, wo dieser zu finden sei.
|
||||
"
|
||||
|
||||
Statement "" : ∃ f : ℤ → ℤ, ∀ x, f x < x := by
|
||||
use (fun x ↦ x - 1)
|
||||
simp
|
||||
|
||||
Hint : ∃ f : ℤ → ℤ, ∀ x, f x < x =>
|
||||
"
|
||||
**Robo**: `f : ℤ → ℤ` ist die Notation für eine Funktion und `f x` ist diese Funktion
|
||||
angewendet auf ein Element `(x : ℤ)`.
|
||||
|
||||
**Du**: War `→` nicht eben noch eine Implikation?
|
||||
|
||||
**Robo**: Doch, die brauchen das gleiche Zeichen für beides.
|
||||
|
||||
**Du**: Dann ist `f : ℤ → ℤ` also einfach abstrakt irgendeine Funktion,
|
||||
wie definier ich aber jetzt konkret eine Abbildungsvorschrift?
|
||||
|
||||
**Robo**: Man kennt hier eine Notation für eine anonyme Funktion:
|
||||
`fun (x : ℤ) ↦ x ^ 2` ist
|
||||
|
||||
$$
|
||||
\\begin\{aligned}
|
||||
f : \\mathbb\{ℤ} &\\to \\mathbb\{ℤ} \\\\
|
||||
x &\\mapsto x ^ 2
|
||||
\\end\{aligned}
|
||||
$$
|
||||
|
||||
**Robo**: PS, `↦` ist `\\mapsto`. Aber man kann auch stattdessen `=>` benützen.
|
||||
"
|
||||
|
||||
HiddenHint : ∃ f : ℕ → ℤ, ∀ x, f x < x =>
|
||||
"
|
||||
**Du**: Ja aber was mach ich damit?
|
||||
|
||||
**Robo**: Wie immer gehst du ein `∃` mit `use …` an.
|
||||
"
|
||||
|
||||
-- TODO: Why does this not show?
|
||||
HiddenHint : ∀ (x : ℤ), (fun (y : ℤ) => y - 1) x < x =>
|
||||
"**Du**: Zu was sich das wohl vereinfacht?"
|
||||
|
||||
HiddenHint (x : ℤ) : (fun y => y - 1) x < x =>
|
||||
"**Du**: Zu was sich das wohl vereinfacht?"
|
||||
|
||||
Conclusion "Das Mädchen wird kurz ruhig, dann beginnt es zu lächeln und zeigt strahlend
|
||||
in eine Richtung. Ihr folgt ihrem Finger und euch fällt in weiter ferne eine pompöse Struktur
|
||||
auf einem flachen Hügel auf.
|
||||
"
|
||||
@@ -0,0 +1,82 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 2
|
||||
|
||||
Title "let"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Ihr macht euch auf Richtung Bibliothek entlang kleiner Pfade zwischen verschiedenster Behausungen.
|
||||
|
||||
**Du**: Sag mal, ich weiss jetzt dass ich eine Funktion als `fun x ↦ x - 1` definieren kann,
|
||||
aber wie kann ich der einen Namen geben?
|
||||
|
||||
**Robo**: Wenn jemand hier eine Funktion definiert, werden die dir
|
||||
`def f (x : ℤ) : ℤ := x - 1` oder `def f : ℤ → ℤ := (fun x ↦ x - 1)` geben.
|
||||
|
||||
**Du**: Und das bedeutet beides das gleiche?
|
||||
|
||||
**Robo**: Praktisch, ja. Aber! Wenn du eine Funktion in einer Aufgabe benennen willst,
|
||||
schreibst du `let f := fun (x : ℤ) ↦ x - 1`!
|
||||
|
||||
**Du**: Und was ist der Unterschied?
|
||||
|
||||
**Robo**: Deines mit `let` ist für innerhalb von einem Beweis, das andere mit `def`
|
||||
ist für ausserhalb von einem Beweis. Hier, ich geb dir mal eine Aufgabe:
|
||||
|
||||
```
|
||||
def f (x : ℤ) : ℤ := (x + 4)
|
||||
```
|
||||
und:
|
||||
"
|
||||
|
||||
def f (x : ℤ) : ℤ := (x + 4)
|
||||
|
||||
Statement "" (x : ℤ) : ∃ (g : ℤ → ℤ), (g ∘ f) x = x + 1 := by
|
||||
let g := fun (x : ℤ) ↦ x - 3
|
||||
use g
|
||||
simp
|
||||
unfold f
|
||||
ring
|
||||
|
||||
NewTactic «let»
|
||||
NewLemma Function.comp_apply
|
||||
|
||||
Hint (x : ℤ) : ∃ g, (g ∘ f) x = x + 1 =>
|
||||
"**Du**: Ist `g ∘ f` Komposition von Funktionen?
|
||||
|
||||
**Robo**: Richtig! Das schreibt man mit `\\comp`.
|
||||
|
||||
**Du** Und hier könnte ich also zuerst
|
||||
`let g := fun (x : ℤ) ↦ _` definieren, anstatt direkt
|
||||
`use fun (x : ℤ) ↦ _`?
|
||||
|
||||
**Robo**: Genau! Das ist zwar praktisch das gleiche, aber kann manchmal nützlich sein.
|
||||
"
|
||||
|
||||
-- TODO: Make some hints work here
|
||||
Hint (x : ℤ) : ((fun (x : ℤ) ↦ x - 3) ∘ f) x = x + 1 =>
|
||||
"**Robo**: Manchmal must du nachhelfen und Funktionen mit `unfold f` öffnen, manchmal nicht.
|
||||
Um erlich zu sein, sagt mein Programm nicht genau wann man das machen muss…"
|
||||
|
||||
-- TODO : Make this work
|
||||
Hint (x : ℤ) (g := (fun (x : ℤ) ↦ x - 3)) : (g ∘ f) x = x + 1 =>
|
||||
"**Robo**: `(g ∘ f) x` ist per Definition `g (f x)`, aber mit
|
||||
`rw [Function.comp_apply]` kann man das explizit umschreiben, aber `simp` kennt das
|
||||
Lemma auch."
|
||||
|
||||
Hint (x : ℤ) : f x - 3 = x + 1 =>
|
||||
"**Robo**: Manchmal must du nachhelfen und Definitionen mit `unfold f` öffnen, mamchmal klappts
|
||||
ohne.
|
||||
Um erlich zu sein, sagt mein Programm nicht genau wann man das machen muss…"
|
||||
|
||||
-- TODO: Block simp-Lemma
|
||||
|
||||
Conclusion "**Du**: Dann verstehst du etwas Mathe?
|
||||
|
||||
**Robo**: Ich hatte ja keine Ahnung ob die generierte Aufgabe beweisbar ist…
|
||||
|
||||
Und damit erreicht ihr den Hügel mit der Bibliothek."
|
||||
@@ -0,0 +1,177 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 3
|
||||
|
||||
Title "Komposition"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Endlich kommt ihr zur Bibliothek. Komischerweise stehen an der Tür
|
||||
zwei Wächtern. Der eine zeigt euch ein Blatt mit
|
||||
|
||||
```
|
||||
def f : ℚ → ℚ := fun x ↦ 5 * x
|
||||
```
|
||||
|
||||
der andere eines mit
|
||||
|
||||
```
|
||||
def g : ℚ → ℚ := fun x ↦ if 0 ≤ x then 2*x else 0
|
||||
```
|
||||
|
||||
und gibt Dir ein Blatt mit einer einzelnen Zeile am oberen Ende.
|
||||
"
|
||||
|
||||
open Set
|
||||
|
||||
namespace LevelFunction4
|
||||
|
||||
def f : ℚ → ℚ := fun x ↦ 5 * x
|
||||
def g : ℚ → ℚ := fun x ↦ if 0 ≤ x then 2*x else 0
|
||||
|
||||
Statement ""
|
||||
: f ∘ g = g ∘ f := by
|
||||
funext x
|
||||
simp_rw [Function.comp_apply]
|
||||
unfold g
|
||||
by_cases 0 ≤ x
|
||||
have h' : 0 ≤ f x
|
||||
unfold f
|
||||
linarith
|
||||
rw [if_pos h', if_pos h]
|
||||
unfold f
|
||||
ring
|
||||
have h' : ¬ (0 ≤ f x)
|
||||
unfold f
|
||||
linarith
|
||||
rw [if_neg h, if_neg h']
|
||||
unfold f
|
||||
ring
|
||||
|
||||
NewTactic funext by_cases simp_rw linarith
|
||||
|
||||
NewLemma not_le if_pos if_neg
|
||||
|
||||
|
||||
Hint : f ∘ g = g ∘ f =>
|
||||
"
|
||||
**Robo**: Schau mal, die beiden haben zwei Funktionen, eine davon mit stückweiser Definition.
|
||||
|
||||
**Du**: Und ich soll zeigen, dass die beiden vertauschbar sind?
|
||||
|
||||
**Robo**: Genau, am besten wählst du mit `funext x` ein beliebiges Element aus, und zeigst das
|
||||
dann für dieses.
|
||||
"
|
||||
|
||||
-- TODO : This does not trigger.
|
||||
-- TODO: These 5 hints should be mutually exclusive. i.e. they should not trigger
|
||||
-- if a assumption is missing.
|
||||
Hint (x : ℚ) : (f ∘ g) x = (g ∘ f) x =>
|
||||
"
|
||||
**Du**: Ah und jetzt kann ich erst einmal `(g ∘ f) {x}` zu `g (f {x})` umschreiben?
|
||||
|
||||
**Robo**: Mit `simp_rw` geht das übrigens schneller.
|
||||
|
||||
**Robo**: Und danach willst du eien Fallunterscheidung
|
||||
machen, `by_cases h : 0 ≤ {x}`.
|
||||
|
||||
**Du**: Damit krieg ich die Fälle `0 ≤ {x}` und `{x} < 0`?
|
||||
|
||||
**Robo**: Genau! Oder präziser `0 ≤ {x}` und `¬(0 ≤ {x})`. Das ist nicht ganz das gleiche, und man
|
||||
könnte mit dem Lemma `not_le` zwischen `¬(0 ≤ {x})` und `0 < {x}` wechseln.
|
||||
"
|
||||
|
||||
Hint (x : ℚ) (h : 0 ≤ x) : f (g x) = g (f x) =>
|
||||
"
|
||||
**Robo**: Um das ausrechnen zu können, brauchst du nicht nur `0 ≤ x` sondern auch noch
|
||||
eine neue Annahme `0 ≤ f x`.
|
||||
|
||||
**Du**: Also `have h₂ : _`?
|
||||
"
|
||||
|
||||
Hint (x : ℚ) (h : 0 ≤ x) (h₂ : 0 ≤ f x) : f (g x) = g (f x) =>
|
||||
"
|
||||
**Du**: Mit den beiden Annahmen sagt die Definition von `g` ja z.B.
|
||||
`(if 0 ≤ x then _)` wobei ich weiss dass `0 ≤ x` wahr ist,
|
||||
kann ich das dann einfach vereinfachen?
|
||||
|
||||
**Robo**: Dafür must du zuerst die Definition von `g` öffnen, also `unfold`. Und dann mit
|
||||
dem Lemma `if_pos {h}` das umschreiben.
|
||||
"
|
||||
|
||||
Hint (x : ℚ) (h : ¬ 0 ≤ x) : f (g x) = g (f x) =>
|
||||
"
|
||||
**Du**: Ich sehe, das ist jetzt der zweite Fall, da brauch ich sicher wieder eine zweite Annahme
|
||||
`¬(0 ≤ f x)`…
|
||||
"
|
||||
|
||||
Hint (x : ℚ) (h : ¬ 0 ≤ x) (h₂ : ¬ 0 ≤ f x) : f (g x) = g (f x) =>
|
||||
"
|
||||
**Robo**: Jetzt ist der Zeitpunkt wo die Definition von `g` geöffnet sein sollte.
|
||||
|
||||
**Robo**: Wenn man ein If-Statement mit wahrer Prämisse mit `if_pos` vereinfacht, dann
|
||||
braucht man für eine falsche Prämisse…
|
||||
|
||||
**Du**: `if_neg`?
|
||||
"
|
||||
-- END TODO
|
||||
HiddenHint (x : ℚ) (h : 0 ≤ x) (h₂ : 0 ≤ f x) : f (2 * x) = g (f x) =>
|
||||
"
|
||||
**Robo**: Jetzt das Gleiche noch mit `if_pos {h₂}`.
|
||||
"
|
||||
|
||||
HiddenHint (x : ℚ) (h : 0 ≤ x) (h₂ : 0 ≤ f x) : f (g x) = 2 * f x =>
|
||||
"
|
||||
**Robo**: Jetzt das Gleiche noch mit `if_pos {h}`.
|
||||
"
|
||||
|
||||
Hint (x : ℚ) (h : 0 ≤ x) (h₂ : 0 ≤ f x) : f (2 * x) = 2 * f x =>
|
||||
"
|
||||
**Robo**: Wenn du jetzt noch die Definition von `f` öffnest, dann kann `ring` den
|
||||
Rest ausrechnen.
|
||||
"
|
||||
|
||||
|
||||
-- TODO: This are also showing in the case of the Hint below
|
||||
-- Proof of `0 ≤ f x`.
|
||||
Hint (x : ℚ) (h : 0 ≤ x) : 0 ≤ f x =>
|
||||
" **Robo**: Wenn du die Definition von `f` öffnest, dann hast du schon das wissen,
|
||||
um das zu beweisen."
|
||||
HiddenHint (x : ℚ) (h : 0 ≤ x) : 0 ≤ f x =>
|
||||
"**Du** *(in Gedanken)*: Was war das nochmals... Ungleichungen... `linarith`!"
|
||||
|
||||
HiddenHint (x : ℚ) (h : ¬0 ≤ x) : ¬ 0 ≤ f x =>
|
||||
" **Robo**: Das ist das selbe wie vorhin…"
|
||||
|
||||
|
||||
-- Hint for modifying `h` wrongly.
|
||||
Hint (x : ℚ) (h : x < 0) : f (g x) = g (f x) =>
|
||||
"
|
||||
**Robo**: Das war nicht so ideal, hier brauchst du die Annahme in der Form `({h} : ¬ 0 ≤ {x})`!
|
||||
"
|
||||
|
||||
-- TODO: In this case we get to see the Hints above
|
||||
Hint (x : ℚ) (h : 0 ≤ x) : 0 ≤ x =>
|
||||
"**Robo**: Dieses Goal ist entstanden, als du `rw [if_pos]` anstatt `rw [if_pos {h}]`
|
||||
geschrieben hast."
|
||||
|
||||
Hint (x : ℚ) (h : 0 ≤ f x) : 0 ≤ f x =>
|
||||
"**Robo**: Dieses Goal ist entstanden, als du `rw [if_pos]` anstatt `rw [if_pos {h}]`
|
||||
geschrieben hast."
|
||||
|
||||
Hint (x : ℚ) (h : ¬ 0 ≤ x) : ¬ 0 ≤ x =>
|
||||
"**Robo**: Dieses Goal ist entstanden, als du `rw [if_neg]` anstatt `rw [if_neg {h}]`
|
||||
geschrieben hast."
|
||||
|
||||
Hint (x : ℚ) (h : ¬ 0 ≤ f x) : ¬ 0 ≤ f x =>
|
||||
"**Robo**: Dieses Goal ist entstanden, als du `rw [if_neg]` anstatt `rw [if_neg {h}]`
|
||||
geschrieben hast."
|
||||
|
||||
Conclusion
|
||||
"Zufrieden tauschen die beiden Wächter ihren Platz und geben so dabei den
|
||||
Durchgang frei."
|
||||
|
||||
end LevelFunction4
|
||||
@@ -0,0 +1,38 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 4
|
||||
|
||||
Title ""
|
||||
|
||||
Introduction
|
||||
"
|
||||
Ihr läuft durch verschiedenste Gänge der Bibliothek, allesamt mit Büchern entlang der Wände.
|
||||
|
||||
**Du**: Wenn wir wüssten, dass nur ein möglicher Weg hierhin führt, könnten wir
|
||||
ausschliessen, dass wir im Kreis laufen.
|
||||
|
||||
Plötzlich begegnet ihr einem älteren Wesen mit Fakel. Auf die Frage antwortet es mit
|
||||
"
|
||||
open Set Function
|
||||
|
||||
Statement "" : Injective (fun (n : ℤ) ↦ n + 3) := by
|
||||
intro a b
|
||||
simp
|
||||
|
||||
NewDefinition Injective
|
||||
|
||||
Hint : Injective (fun (n : ℤ) ↦ n + 3) =>
|
||||
"**Robo**: `Injective` ist als `∀ \{a b : U}, f a = f b → a = b`
|
||||
definiert, also kannst du mit `intro` anfangen.
|
||||
"
|
||||
|
||||
Hint (a b : ℤ) : (fun n => n + 3) a = (fun n => n + 3) b → a = b =>
|
||||
"**Du**: Kann man das wohl vereinfachen?"
|
||||
|
||||
Hint (a b : ℤ) (hab : (fun n => n + 3) a = (fun n => n + 3) b) : a = b =>
|
||||
"**Robot**: Jetzt musst du wohl `{hab}` vereinfachen."
|
||||
|
||||
Conclusion "**Du** Woa das war ja einfach!"
|
||||
@@ -0,0 +1,79 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
set_option tactic.hygienic false
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 5
|
||||
|
||||
Title ""
|
||||
|
||||
Introduction
|
||||
"
|
||||
Sofort hackt die ältere Gestalt nach:
|
||||
"
|
||||
open Set Function
|
||||
|
||||
example (f : ℤ → ℤ) (h : StrictMono f) : Injective f := by
|
||||
apply StrictMono.injective
|
||||
assumption
|
||||
|
||||
-- Odd.strictMono_pow
|
||||
|
||||
Statement "" : Injective (fun (n : ℤ) ↦ n^3 + (n + 3)) := by
|
||||
apply StrictMono.injective
|
||||
apply StrictMono.add
|
||||
apply Odd.strictMono_pow
|
||||
trivial
|
||||
intro a b
|
||||
simp
|
||||
|
||||
NewDefinition Injective
|
||||
NewLemma StrictMono.injective StrictMono.add Odd.strictMono_pow
|
||||
|
||||
|
||||
Hint : Injective fun (n : ℤ) => n ^ 3 + (n + 3) =>
|
||||
"**Du**: Hmm, das ist etwas schwieriger…
|
||||
|
||||
**Robo**: Aber ich hab einen Trick auf Lager:
|
||||
Das Lemma `StrictMono.injective` sagt, dass jede strikt monotone Funktion injektive ist,
|
||||
und ich habe das Gefühl Monotonie ist hier einfacher zu zeigen."
|
||||
|
||||
HiddenHint : Injective fun (n : ℤ) => n ^ 3 + (n + 3) =>
|
||||
"**Robo**: `apply` ist wonach du suchst."
|
||||
|
||||
Hint : StrictMono fun (n : ℤ) => n ^ 3 + (n + 3) =>
|
||||
"**Du**: Jetzt möchte ich strikte Monotonie von `n ^ 3` und `n + 3` separat zeigen,
|
||||
schliesslich scheint es mir als wär das zweite wieder einfach.
|
||||
|
||||
**Robo**: Dafür hab ich `StrictMono.add` bereit!"
|
||||
|
||||
Hint : StrictMono fun (x : ℤ) => x ^ 3 =>
|
||||
"**Du**: Hmm, darauf hab ich jetzt wenig Lust. Gibt's dafür auch was? Das gilt ja nur
|
||||
wenn der Exponent ungerade ist.
|
||||
|
||||
**Robo**: Du könntest mal `Odd.strictMono_pow` versuchen…"
|
||||
|
||||
HiddenHint : Odd 3 =>
|
||||
"**Du**: Ist das nicht ne Trivialität? Warte mal!"
|
||||
|
||||
Hint : StrictMono fun (x : ℤ) => x + 3 =>
|
||||
"**Du**: Ha! Und dieser Teil funktioniert sicher gleich wie Injektivität vorhin!"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Hint (a b : ℤ) : a ^ 3 + (a + 3) = b ^ 3 + (b + 3) → a = b =>
|
||||
"**Robo**: Ich glaube, dieser Weg ist zu steinig. Fang doch nochmals von vorne an!
|
||||
"
|
||||
|
||||
Hint (a b : ℤ) (h : a ^ 3 + (a + 3) = b ^ 3 + (b + 3)) : a = b =>
|
||||
"**Robo**: Ich glaube, dieser Weg ist zu steinig. Fang doch nochmals von vorne an!
|
||||
"
|
||||
|
||||
Conclusion "**Du**: Danke vielmals!
|
||||
|
||||
Und damit lässt das Wesen mitten im Gang stehen, wo es weiter über Injektivität nachdenkt."
|
||||
@@ -0,0 +1,76 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 6
|
||||
|
||||
Title "Injektive"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Weiterirrend kommt ihr an eine Verzweigung.
|
||||
|
||||
**Robo**: Sieht beides gleich aus.
|
||||
|
||||
Ein paar Schritte in den linken Korridor hinein seht ihr auf dem Boden ein Blatt mit Gekritzel:
|
||||
|
||||
```
|
||||
def f : ℕ → ℕ := fun n ↦ if Even n then n^2 else n+1
|
||||
```
|
||||
|
||||
**Du**: Hier haben wir wieder eine stückweise Funktion
|
||||
|
||||
$$
|
||||
f(n) = \\begin{cases}
|
||||
n^2 & \\text{falls } n \\text{ gerade} \\\\
|
||||
n+1 & \\text{andernfalls.}
|
||||
\\end{cases}
|
||||
$$
|
||||
|
||||
|
||||
Darunter steht in leicht leuchtender Schrift:
|
||||
"
|
||||
|
||||
namespace FunctionLvl7
|
||||
|
||||
open Function
|
||||
|
||||
def f : ℕ → ℕ := fun n ↦ if Even n then n^2 else n+1
|
||||
|
||||
Statement "" : ¬ (f + f).Injective := by
|
||||
unfold Injective
|
||||
push_neg
|
||||
use 2
|
||||
use 3
|
||||
simp
|
||||
|
||||
Hint : ¬ (Injective (f + f)) =>
|
||||
"
|
||||
**Robo**: Das ist sicher ein Hinweis.
|
||||
|
||||
**Du**: Aber `¬ Injective` sagt mir nichts…
|
||||
|
||||
**Robo**: Könntest du etwas mit `¬ ∀` anfangen? Dann könntest du ja `Injektive` zuerst öffnen.
|
||||
|
||||
**Du**: Darüber haben wir doch mal was gelernt…
|
||||
"
|
||||
|
||||
HiddenHint : ¬ (Injective (f + f)) =>
|
||||
"
|
||||
**Robo**: Das war `push_neg`.
|
||||
"
|
||||
|
||||
Hint : ∃ a b, (f + f) a = (f + f) b ∧ a ≠ b =>
|
||||
"**Du** Jetzt muss ich einfach ein Gegenbeispiel nennen, oder?
|
||||
|
||||
**Robo** Genau! Welche beiden Zahlen möchtest du denn verwenden?"
|
||||
|
||||
Conclusion
|
||||
"
|
||||
Als ihr das Problem gelöst habt, erschleicht euch ein starkes
|
||||
Gefühl, dass dies der falsche Weg ist.
|
||||
Also geht ihr zurück und nehmt die rechte Gabelung.
|
||||
"
|
||||
|
||||
end FunctionLvl7
|
||||
@@ -0,0 +1,37 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 7
|
||||
|
||||
Title "Surjektive"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Endlich kommt ihr in einen große, beleuchteten zentralen Raum.
|
||||
Alle Wände sind voll mit Büchern und
|
||||
in der Mitte sitzt an einem einsamen
|
||||
Tisch ein Gelehrter, der tatsächlich das gesuchte Buch zeigen kann.
|
||||
|
||||
Bevor er dieses aushändigt, will er aber folgendes wissen:
|
||||
"
|
||||
|
||||
open Function
|
||||
|
||||
Statement "" : Surjective (fun (n : ℤ) ↦ n + 1) := by
|
||||
intro y
|
||||
use y-1
|
||||
simp
|
||||
|
||||
NewDefinition Surjective
|
||||
|
||||
Hint : Surjective (fun (n : ℤ) ↦ n + 1) =>
|
||||
"**Robo**: Die Definition von `Surjective f` ist `∀ y, (∃ x, f x = y)`.
|
||||
|
||||
**Du**: Dann kann ich das auch einfach wie Quantifier behandeln?
|
||||
|
||||
**Robo**: Schieß drauf los!"
|
||||
|
||||
Conclusion
|
||||
"Der Gelehrte händigt euch schmunzelnd das Buch aus."
|
||||
@@ -0,0 +1,38 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 8
|
||||
|
||||
Title ""
|
||||
|
||||
Introduction
|
||||
"
|
||||
**Du**: Ehm, und wie kommen wir da wieder raus?
|
||||
|
||||
**Gelehrter**: Gerne zeige ich euch den Weg, nachdem ihr mir auch noch folgendes erklärt:
|
||||
"
|
||||
|
||||
open Function
|
||||
|
||||
Statement "" : Bijective (fun (n : ℤ) ↦ n + 1) := by
|
||||
unfold Bijective
|
||||
constructor
|
||||
intro a b
|
||||
simp
|
||||
intro y
|
||||
use y-1
|
||||
simp
|
||||
|
||||
Hint : Bijective (fun (n : ℤ) ↦ n + 1) =>
|
||||
"**Robo** *(flüsternd)*: `Bijectve f` ist als `Injective f ∧ Surjective f` definiert.
|
||||
|
||||
**Du**: Dann ist das ja ganz simpel!
|
||||
"
|
||||
|
||||
Conclusion
|
||||
"Zufrieden drückt euch der Gelehrte eine neue Fackel in die Hand und
|
||||
zeigt euch den Weg nach draußen."
|
||||
|
||||
NewDefinition Bijective
|
||||
@@ -0,0 +1,61 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 9
|
||||
|
||||
Title "Inverse"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Eigentlich hast du nur beiläufig Robo gefragt, ob bijektiv nicht auch bedeute, dass
|
||||
eine Inverse Funktion bestehe. Jetzt steht ihr aber schon seit einer halben Stunde rum
|
||||
und der Gelehrte möchte wissen, wie das den genau ginge.
|
||||
|
||||
Offensichtlich kennt er diese Aussage als `Function.bijective_iff_has_inverse` aus seinen Büchern,
|
||||
aber er möchte, dass Du ihm das hier und jetzt nochmals von Grund auf zeigst.
|
||||
"
|
||||
|
||||
open Function
|
||||
|
||||
--TODO: This is a really hard proof
|
||||
Statement bijective_iff_has_inverse "" {A B : Type} (f : A → B) :
|
||||
Bijective f ↔ ∃ g, LeftInverse g f ∧ RightInverse g f := by
|
||||
constructor
|
||||
intro h
|
||||
use fun x => (h.2 x).choose
|
||||
constructor
|
||||
· intro x
|
||||
simp
|
||||
apply h.1
|
||||
apply Exists.choose_spec (h.2 (f x))
|
||||
· intro x
|
||||
simp
|
||||
apply Exists.choose_spec (h.2 x)
|
||||
intro ⟨g, h₁, h₂⟩
|
||||
constructor
|
||||
· intro a b hab
|
||||
have h : g (f a) = g (f b)
|
||||
· apply congrArg
|
||||
assumption
|
||||
rw [h₁, h₁] at h
|
||||
assumption
|
||||
· intro x
|
||||
use g x
|
||||
rw [h₂]
|
||||
|
||||
NewDefinition LeftInverse RightInverse
|
||||
NewLemma Exists.choose Exists.choose_spec congrArg congrFun
|
||||
DisabledLemma Function.bijective_iff_has_inverse
|
||||
|
||||
Hint {A B : Type} (f : A → B) : Bijective f ↔ ∃ g, LeftInverse g f ∧ RightInverse g f =>
|
||||
"**Du**: Nah da sagt mir so manches nichts, aber ich kann ja mal mit dem `↔` anfangen, das kenn
|
||||
ich ja schon."
|
||||
|
||||
Conclusion
|
||||
"Endlich entkommt ihr der Bibliothek.
|
||||
|
||||
**Robo**: Da würden mich keine zehn Pferde nochmals hineinbringen!
|
||||
|
||||
**Du**: Von wegen Pferden, wie viele PS hat eigentlich unser Raumschiff?"
|
||||
@@ -0,0 +1,93 @@
|
||||
import TestGame.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "TestGame"
|
||||
World "Function"
|
||||
Level 10
|
||||
|
||||
Title "Inverse"
|
||||
|
||||
Introduction
|
||||
"
|
||||
Eigentlich hast du nur beiläufig Robo gefragt, ob bijektiv nicht auch bedeute, dass
|
||||
eine Inverse Funktion bestehe. Jetzt steht ihr aber schon seit einer halben Stunde rum
|
||||
und der Gelehrte möchte wissen, wie das den genau ginge.
|
||||
|
||||
Offensichtlich kennt er diese Aussage als `Function.bijective_iff_has_inverse` aus seinen Büchern,
|
||||
aber er möchte, dass Du ihm das hier und jetzt nochmals von Grund auf zeigst.
|
||||
"
|
||||
|
||||
open Function
|
||||
set_option pp.rawOnError true
|
||||
Statement bijective_iff_has_inverse "" {A B : Type} (f : A → B) :
|
||||
Bijective f ↔ ∃ g, LeftInverse g f ∧ RightInverse g f := by
|
||||
Branch
|
||||
exfalso
|
||||
Hint "Das war eine blöde Idee
|
||||
dd
|
||||
|
||||
ddds
|
||||
"
|
||||
Hint (hidden := true) "constructor"
|
||||
constructor
|
||||
Hint "intro h" -- does not show
|
||||
intro h
|
||||
Hint "rcases h with ⟨h₁, h₂⟩" -- shows too late: 1, 2 after
|
||||
rcases h with ⟨h₁, h₂⟩
|
||||
Hint (strict := true) "let g := fun x => (h₂ x).choose" -- shows correct + 1 after
|
||||
let g := fun x => (h₂ x).choose
|
||||
Hint "use g"
|
||||
use g
|
||||
Hint "constructor" -- does not show
|
||||
constructor
|
||||
Hint "intro x" -- does not show
|
||||
intro x
|
||||
Hint "simp" -- Error updating: Error fetching goals: Rpc error: InternalError: unknown universe metavariable '?_uniq.286465'. Try again.
|
||||
simp
|
||||
Hint "apply h₁"
|
||||
apply h₁
|
||||
Hint "apply Exists.choose_spec (h₂ (f x))"
|
||||
apply Exists.choose_spec (h₂ (f x))
|
||||
Hint "intro y" -- Error updating: Error fetching goals: Rpc error: InternalError: unknown universe metavariable '?_uniq.286465'. Try again.
|
||||
intro y
|
||||
Hint "simp"
|
||||
simp
|
||||
Hint "apply Exists.choose_spec (h₂ y)"
|
||||
apply Exists.choose_spec (h₂ y)
|
||||
Hint "intro ⟨g, h₁, h₂⟩"
|
||||
intro ⟨g, h₁, h₂⟩
|
||||
Hint "constructor"
|
||||
constructor
|
||||
Hint "intro a b hab"
|
||||
intro a b hab
|
||||
Hint (strict := true) "have h : g (f a) = g (f b)"
|
||||
have h : g (f a) = g (f b)
|
||||
Hint "apply congrArg"
|
||||
apply congrArg
|
||||
Hint "assumption"
|
||||
assumption
|
||||
Hint "rw [h₁, h₁] at h"
|
||||
rw [h₁, h₁] at h
|
||||
Hint "assumption"
|
||||
assumption
|
||||
Hint "intro x"
|
||||
intro x
|
||||
Hint "use g x"
|
||||
use g x
|
||||
Hint "rw [h₂]"
|
||||
rw [h₂]
|
||||
|
||||
-- NewDefinition LeftInverse RightInverse
|
||||
-- NewLemma Exists.choose Exists.choose_spec congrArg congrFun
|
||||
-- DisabledLemma Function.bijective_iff_has_inverse
|
||||
|
||||
Hint (A B: Type) (f : A → B) (h : Bijective f) :
|
||||
(∃ g, LeftInverse g f ∧ RightInverse g f) → Bijective f =>
|
||||
"Test"
|
||||
|
||||
Conclusion
|
||||
"Endlich entkommt ihr dem Tempel.
|
||||
|
||||
**Robo**: Da würden mich keine zehn Pferde nochmals hineinbringen!
|
||||
|
||||
**Du**: Von wegen Pferden, wie viele PS hat eigentlich unser Raumschiff?"
|
||||
Reference in New Issue
Block a user