levels
This commit is contained in:
@@ -15,47 +15,45 @@ dass sie euch gar nicht sagt, wo dieser zu finden sei.
|
||||
"
|
||||
|
||||
Statement "" : ∃ f : ℤ → ℤ, ∀ x, f x < x := by
|
||||
Hint
|
||||
"
|
||||
**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.
|
||||
"
|
||||
Hint (hidden := true)
|
||||
"
|
||||
**Du**: Ja aber was mach ich damit?
|
||||
|
||||
**Robo**: Wie immer gehst du ein `∃` mit `use …` an.
|
||||
"
|
||||
use (fun x ↦ x - 1)
|
||||
Hint (hidden := true) "**Du**: Zu was sich das wohl vereinfacht?"
|
||||
Branch
|
||||
intro x
|
||||
Hint (hidden := true) "**Du**: Zu was sich das wohl vereinfacht?"
|
||||
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?"
|
||||
NewDefinition Symbol.function
|
||||
LemmaTab "Function"
|
||||
|
||||
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
|
||||
|
||||
@@ -33,12 +33,35 @@ def f (x : ℤ) : ℤ := (x + 4)
|
||||
und:
|
||||
"
|
||||
|
||||
open Function
|
||||
|
||||
def f (x : ℤ) : ℤ := (x + 4)
|
||||
|
||||
Statement "" (x : ℤ) : ∃ (g : ℤ → ℤ), (g ∘ f) x = x + 1 := by
|
||||
Hint
|
||||
"**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."
|
||||
Branch
|
||||
use fun (x : ℤ) ↦ x - 3
|
||||
Hint "**Robo**: `((fun (x : ℤ) ↦ x - 3) ∘ f) x` ist per Definition `(fun (x : ℤ) ↦ x - 3) (f x)`, aber mit
|
||||
`rw [comp_apply]` kann man das explizit umschreiben, aber `simp` kennt das
|
||||
Lemma auch."
|
||||
let g := fun (x : ℤ) ↦ x - 3
|
||||
Hint "**Robo**: gute Wahl! Jetzt kannst du diese mit `use g` benützen."
|
||||
use g
|
||||
Hint "**Robo**: `({g} ∘ f) x` ist per Definition `{g} (f x)`, aber mit
|
||||
`rw [comp_apply]` kann man das explizit umschreiben, aber `simp` kennt das
|
||||
Lemma auch."
|
||||
simp
|
||||
Hint "**Robo**: Wie schon gehabt hat `ring` Schwierigkeiten, Definitionen zu öffnen.
|
||||
Du kannst mit `unfold f` oder `rw [f]` nachhelfen."
|
||||
unfold f
|
||||
ring
|
||||
|
||||
@@ -46,38 +69,9 @@ NewTactic «let»
|
||||
NewLemma Function.comp_apply
|
||||
LemmaTab "Function"
|
||||
|
||||
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…
|
||||
**Robo**: Ich hatte ja keine Ahnung ob die generierte Aufgabe beweisbar ist… aber offenbar
|
||||
hatte ich Glück.
|
||||
|
||||
Und damit erreicht ihr den Hügel mit der Bibliothek."
|
||||
|
||||
@@ -25,7 +25,7 @@ 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
|
||||
open Set Function
|
||||
|
||||
namespace LevelFunction4
|
||||
|
||||
@@ -34,62 +34,64 @@ def g : ℚ → ℚ := fun x ↦ if 0 ≤ x then 2*x else 0
|
||||
|
||||
Statement ""
|
||||
: f ∘ g = g ∘ f := by
|
||||
Hint "
|
||||
**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.
|
||||
"
|
||||
funext x
|
||||
simp_rw [Function.comp_apply]
|
||||
Hint "
|
||||
**Du**: Ah und jetzt kann ich erst einmal `(g ∘ f) {x}` zu `g (f {x})` umschreiben?
|
||||
|
||||
**Robo**: Mit `simp` klappt das.
|
||||
"
|
||||
simp
|
||||
Hint "**Robo**: Jetzt würde ich einmal mit `unfold g` die Definition von `g` öffnen."
|
||||
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
|
||||
Hint "**Robo**: Jetzt kannst du nämlich eine 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."
|
||||
by_cases h : 0 ≤ x
|
||||
· Hint "**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₂ : _`?"
|
||||
have h' : 0 ≤ f x
|
||||
· unfold f
|
||||
linarith
|
||||
rw [if_pos h]
|
||||
rw [if_pos h']
|
||||
unfold f
|
||||
ring
|
||||
· have h' : ¬ (0 ≤ f x)
|
||||
unfold f
|
||||
linarith
|
||||
rw [if_neg h]
|
||||
rw [if_neg h']
|
||||
unfold f
|
||||
ring
|
||||
|
||||
NewTactic funext by_cases simp_rw linarith
|
||||
|
||||
NewLemma not_le if_pos if_neg
|
||||
LemmaTab "Logic"
|
||||
|
||||
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?
|
||||
Hint (x : ℚ) : (f ∘ g) x = (g ∘ f) x => ""
|
||||
|
||||
**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) =>
|
||||
|
||||
@@ -19,20 +19,16 @@ Plötzlich begegnet ihr einem älteren Wesen mit Fakel. Auf die Frage antwortet
|
||||
open Set Function
|
||||
|
||||
Statement "" : Injective (fun (n : ℤ) ↦ n + 3) := by
|
||||
Hint "**Robo**: `Injective` ist als `∀ \{a b : U}, f a = f b → a = b`
|
||||
definiert, also kannst du mit `intro` anfangen."
|
||||
intro a b
|
||||
Branch
|
||||
intro h
|
||||
Hint "**Robot**: Jetzt musst du wohl `{h}` vereinfachen."
|
||||
Hint (hidden := true) "**Du**: Kann man das wohl vereinfachen?"
|
||||
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."
|
||||
LemmaTab "Function"
|
||||
|
||||
Conclusion "**Du** Woa das war ja einfach!"
|
||||
|
||||
@@ -22,10 +22,31 @@ example (f : ℤ → ℤ) (h : StrictMono f) : Injective f := by
|
||||
-- Odd.strictMono_pow
|
||||
|
||||
Statement "" : Injective (fun (n : ℤ) ↦ n^3 + (n + 3)) := by
|
||||
Hint "**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."
|
||||
Hint (hidden := true) "**Robo**: `apply` ist wonach du suchst."
|
||||
Branch
|
||||
intro a b
|
||||
Hint "**Robo**: Ich glaube, dieser Weg ist zu steinig. Fang doch nochmals von vorne an!"
|
||||
intro ha
|
||||
Hint "**Robo**: Ich glaube, dieser Weg ist zu steinig. Fang doch nochmals von vorne an!"
|
||||
apply StrictMono.injective
|
||||
Hint "**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!"
|
||||
apply StrictMono.add
|
||||
Hint "**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…"
|
||||
apply Odd.strictMono_pow
|
||||
Hint (hidden := true) "**Du**: Ist das nicht ne Trivialität? Warte mal!"
|
||||
trivial
|
||||
Hint "**Du**: Ha! Und dieser Teil funktioniert sicher gleich wie Injektivität vorhin!"
|
||||
intro a b
|
||||
simp
|
||||
|
||||
@@ -33,47 +54,6 @@ NewDefinition Injective
|
||||
NewLemma StrictMono.injective StrictMono.add Odd.strictMono_pow
|
||||
LemmaTab "Function"
|
||||
|
||||
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."
|
||||
|
||||
@@ -40,31 +40,23 @@ def f : ℕ → ℕ := fun n ↦ if Even n then n^2 else n+1
|
||||
|
||||
Statement "" : ¬ (f + f).Injective := by
|
||||
unfold Injective
|
||||
Hint "**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…"
|
||||
Hint (hidden := true) "**Robo**: Das war `push_neg`."
|
||||
push_neg
|
||||
Hint "**Du** Jetzt muss ich einfach ein Gegenbeispiel nennen, oder?
|
||||
|
||||
**Robo** Genau! Welche beiden Zahlen möchtest du denn verwenden?"
|
||||
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?"
|
||||
LemmaTab "Function"
|
||||
|
||||
Conclusion
|
||||
"
|
||||
|
||||
@@ -20,18 +20,17 @@ Bevor er dieses aushändigt, will er aber folgendes wissen:
|
||||
open Function
|
||||
|
||||
Statement "" : Surjective (fun (n : ℤ) ↦ n + 1) := by
|
||||
Hint "**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!"
|
||||
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!"
|
||||
LemmaTab "Function"
|
||||
|
||||
Conclusion
|
||||
"Der Gelehrte händigt euch schmunzelnd das Buch aus."
|
||||
|
||||
@@ -17,6 +17,10 @@ Introduction
|
||||
open Function
|
||||
|
||||
Statement "" : Bijective (fun (n : ℤ) ↦ n + 1) := by
|
||||
Hint "
|
||||
**Robo** *(flüsternd)*: `Bijectve f` ist als `Injective f ∧ Surjective f` definiert.
|
||||
|
||||
**Du**: Dann ist das ja ganz simpel!"
|
||||
unfold Bijective
|
||||
constructor
|
||||
intro a b
|
||||
@@ -25,14 +29,9 @@ Statement "" : Bijective (fun (n : ℤ) ↦ n + 1) := by
|
||||
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!
|
||||
"
|
||||
NewDefinition Bijective
|
||||
LemmaTab "Function"
|
||||
|
||||
Conclusion
|
||||
"Zufrieden drückt euch der Gelehrte eine neue Fackel in die Hand und
|
||||
zeigt euch den Weg nach draußen."
|
||||
|
||||
NewDefinition Bijective
|
||||
|
||||
@@ -7,6 +7,8 @@ Level 9
|
||||
|
||||
Title "Inverse"
|
||||
|
||||
set_option tactic.hygienic false
|
||||
|
||||
Introduction
|
||||
"
|
||||
Eigentlich hast du nur beiläufig Robo gefragt, ob bijektiv nicht auch bedeute, dass
|
||||
@@ -20,39 +22,86 @@ 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
|
||||
-- bijective_iff_has_inverse
|
||||
Statement "" {A B : Type} (f : A → B) :
|
||||
Statement Function.bijective_iff_has_inverse "" {A B : Type} (f : A → B) :
|
||||
Bijective f ↔ ∃ g, LeftInverse g f ∧ RightInverse g f := by
|
||||
Hint "**Du**: Nah da sagt mir so manches nichts, aber ich kann ja mal mit dem `↔` anfangen,
|
||||
das kenn ich ja schon."
|
||||
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
|
||||
· intro h
|
||||
Hint "**Robo**: Tipp. Teil doch `Bijective` mit `rcases {h} with ⟨hI, hS⟩` in
|
||||
`Injective` und `Surjective` auf!"
|
||||
rcases h with ⟨hI, hS⟩
|
||||
Hint "**Du**: Ja was ist eigentlich die Inverse von `f`…?
|
||||
|
||||
**Robo**: Hast du eine Idee?
|
||||
|
||||
**Du**: Also von der Surjektivität weiss ich, dass für alle `y` ein Urbild existiert
|
||||
und mit der Injektivität könnte ich dann zeigen, dass dieses eindeutig ist.
|
||||
|
||||
**Robo**: Also Schritt für Schritt: Mit `fun y ↦ ({hS} y).choose ` kannst du eine Funktion
|
||||
definieren, die `y` irgendein Urbild zuweist.
|
||||
|
||||
**Du**: Die ist aber nicht wohldefiniert, oder?
|
||||
|
||||
**Robo**: In der Mathe nicht. In Lean geht das ganz gut, aber es ist dann unmöglich etwas
|
||||
darüber zu beweisen, wenn es mehrere Möglichkeiten gäbe."
|
||||
use fun x => (hS x).choose
|
||||
constructor
|
||||
· Hint "**Robo**: fang mal mit `intro` an."
|
||||
intro x
|
||||
Hint "**Du**: kompliziert.
|
||||
|
||||
**Robo**: Aber mit `simp` kannst du es ja etwas vereinfachen."
|
||||
simp
|
||||
Hint "**Du**: Das kann ich jetzt nicht zeigen solange ich nicht weiss, dass nur genau ein
|
||||
Urbild besteht.
|
||||
|
||||
**Robo**: Dann wende doch mit `apply {hI}` die Injektivität an!"
|
||||
apply hI
|
||||
Hint "**Robo**: Dies ist jetzt eine etwas tautologische Aussage. In Lean ist das
|
||||
`Exists.choose_spec`. Konkret `apply Exists.choose_spec (hS (f x))`."
|
||||
apply Exists.choose_spec (hS (f x))
|
||||
· Hint "**Robo**: Gut! Auf zum Rechtsinversen! Fang auch hier wieder mit `intro` an."
|
||||
intro x
|
||||
Hint "**Du**: Kann ich das vereinfachen?"
|
||||
simp
|
||||
Hint "**Du**: Also wieder `Exists.choose_spec`?
|
||||
|
||||
**Robo**: Genau! Diesmal mit dem Argument `(hS x)`."
|
||||
apply Exists.choose_spec (hS x)
|
||||
· Hint "**Robo**: Die eine Richtung ist gezeigt. Jetzt auf zur Rückrichtung!"
|
||||
intro h
|
||||
Hint "**Robo**: Zerlege {h} noch soweit du kannst!"
|
||||
rcases h with ⟨g, h⟩
|
||||
Hint "**Robo**: Das UND auch noch!"
|
||||
rcases h with ⟨hL, hR⟩
|
||||
Hint "**Robo**: Das `Bijective` kannst du auch aufteilen."
|
||||
constructor
|
||||
· Hint "**Robo**: Injektivität ist der schwierige Teil. Fang mal an mit `intro`."
|
||||
intro a b hab
|
||||
Hint "**Robo**: Im nächsten Schritt must du `LeftInverse` brauchen um das Goal
|
||||
zu `g (f a) = g (f b)` zu wechseln: benutze `rw [←{hL} {a}, …]`."
|
||||
rw [← hL a, ← hL b]
|
||||
Hint "**Du**: Wenn die Argumente `f a = f b` gleich sind, ist dann auch `g (f a) = g (f b)`,
|
||||
wie sag ich das?
|
||||
|
||||
**Robo**: Das heisst `apply congrArg`."
|
||||
apply congrArg
|
||||
assumption
|
||||
rw [h₁, h₁] at h
|
||||
assumption
|
||||
· intro x
|
||||
use g x
|
||||
rw [h₂]
|
||||
· Hint "Die Surjektivität sollte einfacher sein."
|
||||
intro x
|
||||
Hint (hidden := true) "**Robo**: Psst, mit `RightInverse g f` weisst du, dass `f (g x) = x`.
|
||||
Hilft das rauszufinden was du hier brauchen musst?"
|
||||
use g x
|
||||
Hint (hidden := true) "**Robo**: Du kannst die `RightInverse`-Annahme einfach mit `rw`
|
||||
benützen."
|
||||
rw [hR]
|
||||
|
||||
NewDefinition LeftInverse RightInverse
|
||||
NewLemma Exists.choose Exists.choose_spec congrArg congrFun
|
||||
DisabledLemma Function.bijective_iff_has_inverse
|
||||
LemmaTab "Logic"
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import Adam.Metadata
|
||||
import Mathlib
|
||||
|
||||
Game "Adam"
|
||||
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
|
||||
|
||||
-- bijective_iff_has_inverse
|
||||
Statement {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