pull/68/head
Jon Eugster 2 years ago
parent f636a8d833
commit 68606aab99

@ -61,16 +61,16 @@ Conclusion
"Fertig!"
Path Proposition → Implication → Predicate → Predicate → Contradiction → Sum → Lean
Path Proposition → Implication → Predicate → Predicate → Contradiction → Sum → Lean → Function
Path Predicate → Inequality → Sum
-- Path Inequality → Prime
-- Path Sum → Inequality -- → Induction
-- Path SetTheory2 → Numbers
Path Lean → SetTheory → SetTheory2 → SetFunction → Module
Path Lean → Function → SetFunction
Path Lean → SetTheory → SetTheory2
-- Path SetTheory2 → Numbers
Path SetTheory2 → SetFunction → Module
Path Function → SetFunction
Path Module → Basis → Module2
MakeGame

@ -76,12 +76,37 @@ DefinitionDoc StrictMono as "StrictMono"
"
DefinitionDoc Symbol.Subset as "⊆" "
DefinitionDoc Disjoint as "Disjoint"
"
"
Auf Mengen (`Set`) ist `A ⊆ B` als `∀x, x ∈ A → x ∈ B` implementiert.
DefinitionDoc Set.preimage as "preimage"
"
"
DefinitionDoc Set.Nonempty as "Nonempty" "
`A.Nonemty` ist als `∃ x, x ∈ A` definiert.
"
DefinitionDoc Symbol.Subset as "⊆" "
Auf Mengen (`Set`) ist `A ⊆ B` als `∀x, x ∈ A → x ∈ B` implementiert.
Im goal kann man direkt `intro x hx` machen, in einer Annahme, kann man mit `rcases`
loslegen.
Alternativ kann man mit `rw[Set.subset_def]` die Definition explizit einsetzen.
"
DefinitionDoc Symbol.function as "fun x => _" "
Anonyme funktionen kann man mit `fun (x : ) => 2 * x` definieren und
wie andere Objekte verwenden.
Note: `=>` wird in mathlib oft auch `↦` (`\\maps`) geschrieben.
"

@ -243,17 +243,45 @@ für eine verwandte Version.
* Mathlib Doc: [#Subset.antisymm_iff](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Set/Basic.html#Set.Subset.antisymm_iff)
"
LemmaDoc Set.diff_inter as "union_assoc" in "Set"
""
LemmaDoc Set.diff_inter as "diff_inter" in "Set"
"
`{α : Type u} {s t u : Set α} : s \\ (t ∩ u) = s \\ t s \\ u`
## Eigenschaften
* Namespace: `Set`
* Mathlib Doc: [#Set.diff_inter](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Set/Basic.html#Set.diff_inter)
"
LemmaDoc Set.union_assoc as "union_assoc" in "Set"
""
"
` {α : Type u} (a b c : Set α) : a b c = a (b c)`
## Eigenschaften
* Namespace: `Set`
* Mathlib Doc: [#Set.union_assoc](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Set/Basic.html#Set.union_assoc)
"
LemmaDoc Set.union_diff_distrib as "union_diff_distrib" in "Set"
""
"
`{α : Type u} {s t u : Set α} : (s t) \\ u = s \\ u t \\ u`
## Eigenschaften
* Namespace: `Set`
* Mathlib Doc: [#Set.union_diff_distrib](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Set/Basic.html#Set.union_diff_distrib)
"
LemmaDoc Set.univ_union as "univ_union" in "Set"
""
"
` {α : Type u} {s : Set α} : Set.univ s = Set.univ`
## Eigenschaften
* Namespace: `Set`
* Mathlib Doc: [#Set.univ_union](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Set/Basic.html#Set.univ_union)
"
LemmaDoc Nat.prime_def_lt'' as "prime_def_lt''" in "Nat"
"
@ -315,7 +343,7 @@ LemmaDoc Set.eq_empty_iff_forall_not_mem as "eq_empty_iff_forall_not_mem" in "Su
* Mathlib Doc: [#eq_empty_iff_forall_not_mem](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Set/Basic.html#Set.eq_empty_iff_forall_not_mem)
"
LemmaDoc Nat.zero_eq as "zero_eq" in "Sum"
LemmaDoc Nat.zero_eq as "zero_eq" in "Nat"
"
## Eigenschaften
@ -371,7 +399,7 @@ LemmaDoc Finset.sum_comm as "sum_comm" in "Sum"
* Mathlib Doc: [#sum_comm](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Algebra/BigOperators/Basic.html#Finset.sum_comm)
"
LemmaDoc Function.comp_apply as "Function.comp_apply" in "Function"
LemmaDoc Function.comp_apply as "comp_apply" in "Function"
"
## Eigenschaften
@ -427,7 +455,7 @@ LemmaDoc Odd.strictMono_pow as "Odd.strictMono_pow" in "Function"
* Mathlib Doc: [#Odd.strictMono_pow](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Algebra/Parity.html#Odd.strictMono_pow)
"
LemmaDoc Exists.choose as "Exists.choose" in "Function"
LemmaDoc Exists.choose as "Exists.choose" in "Logic"
"
## Eigenschaften
@ -435,21 +463,21 @@ LemmaDoc Exists.choose as "Exists.choose" in "Function"
* Mathlib Doc: [#Exists.choose](https://leanprover-community.github.io/mathlib4_docs/Std/Logic.html#Exists.choose)
"
LemmaDoc Exists.choose_spec as "Exists.choose_spec" in "Function"
LemmaDoc Exists.choose_spec as "Exists.choose_spec" in "Logic"
"
## Eigenschaften
* Mathlib Doc: [#Exists.choose_spec](https://leanprover-community.github.io/mathlib4_docs/Std/Logic.html#Exists.choose_spec)
"
LemmaDoc congrArg as "congrArg" in "Function"
LemmaDoc congrArg as "congrArg" in "Logic"
"
## Eigenschaften
* Mathlib Doc: [#congrArg](https://leanprover-community.github.io/mathlib4_docs/Init/Prelude.html#congrArg)
"
LemmaDoc congrFun as "congrFun" in "Function"
LemmaDoc congrFun as "congrFun" in "Logic"
"
## Eigenschaften
@ -482,3 +510,127 @@ LemmaDoc Set.nonempty_iff_ne_empty as "nonempty_iff_ne_empty" in "Logic"
* Mathlib Doc: [#nonempty_iff_ne_empty](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Data/Set/Basic.html#Set.nonempty_iff_ne_empty)
"
LemmaDoc Set.subset_univ as "subset_univ" in "Set"
"
`{α : Type u} {s : Set α} : s ⊆ univ`
"
LemmaDoc Set.not_mem_compl_iff as "not_mem_compl_iff" in "Set"
"
` {α : Type u} {s : Set α} {x : α} : ¬x ∈ sᶜ ↔ x ∈ s`
"
LemmaDoc Set.mem_of_subset_of_mem as "mem_of_subset_of_mem" in "Set"
"
`{α : Type u} {s₁ : Set α} {s₂ : Set α} {a : α} (h : s₁ ⊆ s₂) :
a ∈ s₁ → a ∈ s₂`
"
LemmaDoc Set.compl_eq_univ_diff as "compl_eq_univ_diff" in "Set"
"
` {α : Type u} (s : Set α) :
sᶜ = Set.univ \\ s`
"
LemmaDoc Set.compl_union as "compl_union" in "Set"
"
` {α : Type u} (s t : Set α) :
(s t)ᶜ = sᶜ ∩ tᶜ`
"
LemmaDoc Set.diff_diff as "diff_diff" in "Set"
"
` {α : Type u} {s t u : Set α} :
(s \\ t) \\ u = s \\ (t u)`
"
LemmaDoc Set.compl_inter as "compl_inter" in "Set"
"
` {α : Type u} (s t : Set α) :
(s ∩ t)ᶜ = sᶜ tᶜ`
"
LemmaDoc Set.diff_eq_compl_inter as "diff_eq_compl_inter" in "Set"
"
`{α : Type u} {s t : Set α} : s \\ t = tᶜ ∩ s`
"
LemmaDoc Set.inter_comm as "inter_comm" in "Set"
"
`{α : Type u} (a b : Set α) : a ∩ b = b ∩ a`
"
LemmaDoc Set.mem_compl_iff as "mem_compl_iff" in "Set"
"
`{α : Type u} (s : Set α) (x : α) : x ∈ sᶜ ↔ ¬x ∈ s`
"
LemmaDoc Set.subset_def as "subset_def" in "Set"
"
``
"
LemmaDoc Set.ssubset_def as "ssubset_def" in "Set"
"
``
"
LemmaDoc not_imp as "not_imp" in "Logic"
"
`{a : Prop} {b : Prop} : (a → b) ↔ a ∧ ¬b`
"
LemmaDoc Set.mem_diff as "mem_diff" in "Set"
"
``
"
LemmaDoc Set.mem_insert_iff as "mem_insert_iff" in "Logic"
"
``
"
LemmaDoc Set.mem_singleton_iff as "mem_singleton_iff" in "Set"
"
``
"
LemmaDoc Function.bijective_iff_has_inverse as "bijective_iff_has_inverse" in "Function"
"
``
"
LemmaDoc Set.mem_setOf as "mem_setOf" in "Set"
"
``
"
LemmaDoc Set.mem_powerset_iff as "mem_powerset_iff" in "Set"
"
``
"
LemmaDoc Set.subset_union_of_subset_left as "subset_union_of_subset_left" in "Set"
"
``
"
LemmaDoc Set.subset_union_of_subset_right as "subset_union_of_subset_right" in "Set"
"
``
"
LemmaDoc Set.setOf_or as "setOf_or" in "Set"
"
``
"
LemmaDoc Set.setOf_and as "setOf_and" in "Set"
"
``
"
LemmaDoc Set.mem_inter_iff as "mem_inter_iff" in "Set"
"
``
"

@ -573,3 +573,7 @@ mit dem man das Goal beweisen möchte.
`use n` versucht zudem anschliessend `rfl` aufzurufen, und kann das Goal damit manchmal direkt
schließen.
"
TacticDoc ext
"
"

@ -7,7 +7,6 @@ import Adam.Levels.Function.L06_Injective
import Adam.Levels.Function.L07_Surjective
import Adam.Levels.Function.L08_Bijective
import Adam.Levels.Function.L09_Inverse
import Adam.Levels.Function.L11_Inverse
Game "Adam"
World "Function"

@ -15,47 +15,45 @@ 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 : )`.
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?
**Du**: War `→` nicht eben noch eine Implikation?
**Robo**: Doch, die brauchen das gleiche Zeichen für beides.
**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?
**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
**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}
$$
$$
\\begin\{aligned}
f : \\mathbb\{} &\\to \\mathbb\{} \\\\
x &\\mapsto x ^ 2
\\end\{aligned}
$$
**Robo**: PS, `↦` ist `\\mapsto`. Aber man kann auch stattdessen `=>` benützen.
"
**Robo**: PS, `↦` ist `\\mapsto`. Aber man kann auch stattdessen `=>` benützen.
"
Hint (hidden := true)
"
**Du**: Ja aber was mach ich damit?
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?"
**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
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?
**Robo**: Mit `simp_rw` geht das übrigens schneller.
Hint (x : ) : (f ∘ g) x = (g ∘ f) x => ""
**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
push_neg
use 2
use 3
simp
Hint : ¬ (Injective (f + f)) =>
"
**Robo**: Das ist sicher ein Hinweis.
**Du**: Aber `¬ Injective` sagt mir nichts…
Hint "**Robo**: Das ist sicher ein Hinweis.
**Robo**: Könntest du etwas mit `¬ ∀` anfangen? Dann könntest du ja `Injektive` zuerst öffnen.
**Du**: Aber `¬ Injective` sagt mir nichts…
**Du**: Darüber haben wir doch mal was gelernt…
"
**Robo**: Könntest du etwas mit `¬ ∀` anfangen? Dann könntest du ja `Injektive` zuerst öffnen.
HiddenHint : ¬ (Injective (f + f)) =>
"
**Robo**: Das war `push_neg`.
"
**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?
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?"
use 2
use 3
simp
**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?"

@ -9,23 +9,29 @@ Title ""
open Set
set_option tactic.hygienic false
Introduction
"
Wenn man mit Abildungen auf Mengen arbeitet, muss man in Lean etwas aufpassen, um
die Typen (z.B. `(U : Type _)`) und Mengen von diesen Typen (z.B. `(S : Set U)`)
zu unterscheiden.
Das Bild einer Funktion ist eine Menge, die als `f '' S` geschrieben wird.
In der Mathe ist das normalerweise als $f(S)$ geschrieben.
Abbildungen sind prinzipiell immer auf Typen definiert. Wenn eine Funktion nicht
auf dem ganzen Typen definiert ist, hat man prinzipiell zwei Optionen:
Mit `ext i` kann man Gleichheit von Mengen angehen.
"
1. Nach dem Motto \"Chunk in, chunk out\" werden in der Mathlib Funktionen
oft einfach auf irgendwas gesetzt wenn sie nicht definiert sind, so gibt `1 / 0` in ``
einfach `0`. Dies funktioniert, weil dann alle relevanten Theoreme, die von `x / n`
handeln, dann Annahmen der Form `(h : n ≠ 0)` haben.
2. Man kann auch Funktionen auf *Subtypen* definieren, also z.B. auf `+`.
-- Wenn man mit Abildungen auf Mengen arbeitet, muss man in Lean etwas aufpassen, um
-- die Typen (z.B. `(U : Type _)`) und Mengen von diesen Typen (z.B. `(S : Set U)`)
-- zu unterscheiden.
"
-- Abbildungen sind prinzipiell immer auf Typen definiert. Wenn eine Funktion nicht
-- auf dem ganzen Typen definiert ist, hat man prinzipiell zwei Optionen:
-- 1. Nach dem Motto \"Junk in, junk out\" werden in der Mathlib Funktionen
-- oft einfach auf irgendwas gesetzt wenn sie nicht definiert sind, so gibt `1 / 0` in ``
-- einfach `0`. Dies funktioniert, weil dann alle relevanten Theoreme, die von `x / n`
-- handeln, dann Annahmen der Form `(h : n ≠ 0)` haben.
-- 2. Man kann auch Funktionen auf *Subtypen* definieren, also z.B. auf `+`.
-- /- Image of Union -/
@ -34,6 +40,7 @@ handeln, dann Annahmen der Form `(h : n ≠ 0)` haben.
Statement
""
(S T : Set ) (f : ) : (f '' S) (f '' T) = f '' (S T) := by
Hint "Fang mal mit `ext i` an."
ext i
rw [mem_union]
simp_rw [mem_image]
@ -63,3 +70,6 @@ Statement
constructor
assumption
assumption
NewTactic ext
LemmaTab "Set"

@ -7,15 +7,27 @@ Level 2
Title ""
open Set
Introduction
"
Das Urbild einer Menge `U` unter einer Funktion `f` ist mit `f ⁻¹' U` bezeichnet.
Note: `f ⁻¹` ist das abstrakte, gruppentheoretische Inverse von `f`, was generell nicht existieren muss,
deshalb wurde die andere Notation hier gewählt
"
Statement
""
(U : Set ) (f : ) : U ⊆ f ⁻¹' (f '' U) := by
Hint "Fang wieder mal mit `intro` an."
intro x hx
Hint "Mit `rw [preimage]` kannst du sehen, wie das Urbild definiert ist."
rw [preimage]
Hint "Also musst du jetzt ein Element `y` angeben sodass `f y` in `f '' U` liegt."
use x
constructor
assumption
rfl
NewDefinition Set.preimage

@ -9,6 +9,8 @@ Title ""
Introduction
"
Wenn man Aussagen über Familien von Mengen machen will, macht man das mit
`(N : I → Set V)`, also also Funktionen von einer Indexmenge.
"
Statement

@ -14,17 +14,19 @@ import Adam.Levels.SetTheory.L13_Insert
import Adam.Levels.SetTheory.L14_SetOf
import Adam.Levels.SetTheory.L15_Powerset
import Adam.Levels.SetTheory.L16_Disjoint
import Adam.Levels.SetTheory.L17_SetOf
import Adam.Levels.SetTheory.L18_SetOf
import Adam.Levels.SetTheory.L19_Subtype
-- import Adam.Levels.SetTheory.L17_SetOf
-- import Adam.Levels.SetTheory.L18_SetOf
-- import Adam.Levels.SetTheory.L19_Subtype
Game "Adam"
World "SetTheory"
Title "Mengenlehre"
Introduction
"Der größere der beiden Monde sieht dunkelrot und karg aus. Trotzdem sollen dort nomadische
"[Note: von hier an sind die Levels leider noch nicht vollständig. Evt. müsst ihr etwas ausprobieren oder
fragen, wenn ihr nicht weiterkommt.]
Der größere der beiden Monde sieht dunkelrot und karg aus. Trotzdem sollen dort nomadische
Gesellschaften wohnen, die sich in der Einöde zurechtfinden.
Ihr steuert einen der wenigen befestigten Standorte am Fusse eines Berges an.

@ -54,4 +54,6 @@ Statement Set.mem_univ "" {A : Type} (x : A) : x ∈ (univ : Set A) := by
**Du**: Also das ist ja dann `trivial`. Hoffentlich sehen die das hier auch so…"
trivial
LemmaTab "Set"
Conclusion "**Mengea**: Ja das stimmt schon. Dann wünsche ich euch viel Erfolg auf eurer Reise!"

@ -27,6 +27,7 @@ Statement Set.not_mem_empty "" {A : Type} (x : A) :
tauto
NewLemma Set.mem_univ
LemmaTab "Set"
Conclusion "Der Junge rennt weiter.

@ -31,7 +31,7 @@ namespace MySet
open Set
Statement (A : Set ) : A ⊆ univ := by
Statement Set.subset_univ (A : Set ) : A ⊆ univ := by
Hint "**Robo**: `A ⊆ B` ist als `∀ x, x ∈ A → x ∈ B` definiert.
**Du**: Also kann ich mit `intro` anfangen, wie ich das bei einem `∀` funktioniert?
@ -43,6 +43,7 @@ Statement (A : Set ) : A ⊆ univ := by
DisabledTactic tauto simp
NewDefinition Symbol.Subset
LemmaTab "Set"
Conclusion "Damit drehen sich die beiden Mädchen um und folgen dem Jungen."

@ -52,4 +52,5 @@ Statement Set.subset_empty_iff {A : Type _} (s : Set A) :
rw [h]
DisabledTactic tauto
NewLemma Set.Subset.antisymm Set.Subset.antisymm_iff Set.empty_subset
NewLemma Set.Subset.antisymm Set.Subset.antisymm_iff Set.empty_subset Set.subset_univ
LemmaTab "Set"

@ -32,3 +32,4 @@ Statement Set.eq_empty_iff_forall_not_mem
NewTactic constructor intro rw assumption rcases simp tauto trivial
NewLemma Set.subset_empty_iff
LemmaTab "Set"

@ -34,3 +34,4 @@ Statement Set.nonempty_iff_ne_empty
NewLemma ne_eq Set.eq_empty_iff_forall_not_mem
NewDefinition Set.Nonempty
LemmaTab "Set"

@ -27,3 +27,4 @@ Statement
simp
NewTactic constructor intro rw assumption rcases simp tauto trivial
LemmaTab "Set"

@ -12,12 +12,12 @@ Title "Schnittmenge und Vereinigung"
Introduction
"
Ansonsten gibt es jegliche Lemmas in
`import Mathlib.Data.Set.Basic`
Ansonsten gibt es jegliche Lemmas in der Mathlib
die beim Umgang mit diesen Operationen weiterhelfen. Schaue in der Bibliothek auf
der Seite nach Lemmas, die dir hier weiterhelfen!
Denk daran, die lemma Namen sind blockweise aus der Aussage konstruiert. Ein lemma mit
der Aussage `C \\ (A ∩ B) + …` wird vermutlich mit `diff_inter_…` anfangen.
"
open Set
@ -26,9 +26,15 @@ Statement
""
(A B : Set ) : univ \ (A ∩ B) = (univ \ A) (univ \ B) (A \ B) := by
rw [diff_inter]
Hint (hidden := true) "mit `union_assoc` und `union_diff_distrib` kannst du
auf der rechten Seite weiterkommen."
rw [union_assoc]
rw [←union_diff_distrib]
rw [univ_union]
NewTactic constructor intro rw assumption rcases simp tauto trivial
DisabledTactic tauto
NewLemma Set.diff_inter Set.union_assoc Set.union_diff_distrib Set.univ_union
LemmaTab "Set"
Conclusion "Wie du vielleicht bemerkt hast, könnte `tauto` sowas automatisch lösen."

@ -16,18 +16,25 @@ sind `not_mem_compl_iff` und `compl_eq_univ_diff`.
open Set
#check not_mem_compl_iff
#check compl_eq_univ_diff
Statement
""
(A : Set ) (h : Aᶜ ⊆ A) : A = univ := by
Hint "Start doch mit `apply Subset.antisymm`."
apply Subset.antisymm
simp only [subset_univ]
Hint "Da `⊆` als `∀x, x ∈ A → x ∈ B ` definiert ist, fängst du
am besten mit `intro` an."
intros x hx
Hint "Eine Möglichkeit ist, eine Fallunterscheidung zu machen: `by_cases g: {x} ∈ {A}ᶜ`."
by_cases h4 : x ∈ Aᶜ
exact mem_of_subset_of_mem h h4
rw [←not_mem_compl_iff]
exact h4
Hint "Hier könnte `mem_of_subset_of_mem` hilfreich werden."
apply mem_of_subset_of_mem h
assumption
Hint "Diese Richtung geben wir als Lemma: `not_mem_compl_iff`."
rw [not_mem_compl_iff] at h4
assumption
NewTactic constructor intro rw assumption rcases simp tauto trivial
NewLemma Set.not_mem_compl_iff Set.mem_of_subset_of_mem Set.compl_eq_univ_diff
DisabledTactic tauto
LemmaTab "Set"

@ -43,6 +43,9 @@ open Set
Statement
(A B C : Set ) : (A \ B)ᶜ ∩ (C \ B)ᶜ = ((univ \ A) \ C) (univ \ Bᶜ) := by
Hint "Oft kann es auch nützlich sein, mit `rw [← …]` rückwärts umzuschreiben.
Der ganze Level ist mit `rw`/`simp_rw` und den Lemmas in deiner Bibliothek
lösbar."
rw [←compl_union]
rw [←union_diff_distrib]
rw [diff_diff]
@ -51,7 +54,8 @@ Statement
rw [diff_eq_compl_inter]
rw [inter_comm]
NewTactic constructor intro rw assumption rcases simp tauto trivial
-- TODOs
-- Lemmas compl_union compl_inter mem_compl_iff
OnlyTactic rw simp_rw tauto trivial assumption rfl «have» «suffices»
NewTactic simp_rw
LemmaTab "Set"
NewLemma Set.mem_compl_iff Set.compl_union Set.diff_diff Set.compl_inter
Set.diff_eq_compl_inter Set.inter_comm

@ -19,18 +19,20 @@ Zudem kann man mit `rw [ssubset_def]` explizit die Definition einsetzen.
Note: `rw [subset_def]` macht das gleiche für `⊆`.
"
--open Set
open Set
Statement
""
(A B : Set ) (h : A ⊂ B) : ∃ x, x ∈ B \ A := by
cases' h with h₁ h₂
rw [Set.subset_def] at h₂
rw [subset_def] at h₂
rw [not_forall] at h₂
cases' h₂ with x hx
use x
rw [not_imp] at hx
rw [Set.mem_diff]
rw [mem_diff]
exact hx
NewTactic constructor intro rw assumption rcases simp tauto trivial
NewLemma Set.subset_def Set.ssubset_def not_imp Set.mem_diff
LemmaTab "Set"

@ -12,7 +12,7 @@ Introduction
"
Nun schauen wir uns konkrete Mengen an. Man schreibt diese mit
geschweiften Klammern: `{0, 4, 117, 3}`. Meistens muss man
den Typ explizit angeben, weil lein nicht weiss, ob man mit `Set` (Mengen)
den Typ explizit angeben, weil Lean nicht weiss, ob man mit `Set` (Mengen)
oder `Finset` (endliche Mengen) arbeiten möchte: `({4, 9} : Set )`.
`Finset` schauen wir uns später an.
@ -28,8 +28,9 @@ Die folgende Aufgabe ist entsprechend mit `rfl` lösbar.
open Set
Statement
"Die Menge $\\{4, 9\\}}$ ist per Definition \\{4}\\cup\\{9\\}." :
"Die Menge $\\{4, 9\\}$ ist per Definition $\\{4}\\cup\\{9\\}$." :
({4, 9} : Set ) = Set.insert 4 {9} := by
rfl
NewTactic constructor intro rw assumption rcases simp tauto trivial
OnlyTactic rfl
LemmaTab "Set"

@ -18,7 +18,7 @@ einfaches Rezept:
simp_rw [mem_insert_iff, mem_singleton_iff] at *
```
vereinfacht Aussagen der Form `6 ∈ { 0, 6, 1}` zu `(6 = 0) (6 = 6) (6 = 1)`,
vereinfacht Aussagen der Form `6 ∈ {0, 6, 1}` zu `(6 = 0) (6 = 6) (6 = 1)`,
und dann kann `tauto` diese Aussage beweisen.
Bei `⊆` kann man wie schon vorher zuerst mit `intro x hx` die Definition
@ -28,12 +28,12 @@ auseinandernehmen und dann gleich vorgehen.
open Set
Statement
"" :
Statement :
({2, 3, 5} : Set ) ⊆ {4, 2, 5, 7, 3} := by
Hint "Fang wieder mit `rw [subset_def]` oder direkt mit `intro` an."
intro x hx
simp_rw [mem_insert_iff, mem_singleton_iff] at *
tauto
NewTactic simp_rw intro tauto rw
--Lemmas Subset.antisymm_iff empty_subset
NewLemma Set.mem_insert_iff Set.mem_singleton_iff
LemmaTab "Set"

@ -25,11 +25,14 @@ dieses Element erfüllt ist.
open Set
Statement
"" :
3 ∈ {n : | Odd n} := by
Statement : 3 ∈ {n : | Odd n} := by
rw [mem_setOf]
Hint (hidden := true) "**Robo**: Zur Erinnerung, wenn du nicht mehr weisst, wie `Odd` definiert
ist, benutze `rw [Odd]`."
Branch
rw [Odd]
use 1
ring
NewTactic constructor intro rw assumption rcases simp tauto trivial
NewLemma Set.mem_setOf
LemmaTab "Set"

@ -27,14 +27,24 @@ open Set
Statement
"" (X Y : Set ):
𝒫 X 𝒫 Y ⊆ 𝒫 (X Y) := by
Hint "**Robo**: Fang mal mit `intro` an, wie das bei `⊆` fast immer der Fall ist."
intro A hA
Hint "**Robo**: Als nächstes must du noch die Annahme `{A} ∈ 𝒫 X 𝒫 Y` zu
`{A} ∈ (𝒫 X) {A} ∈ (𝒫 Y)` wechseln. Dafür kennst du schon ein Lemma."
rw [mem_union] at hA
Hint "**Robo**: Jetzt wär der Zeitpunkt um `mem_powerset_iff` mal überall anzuwenden."
simp_rw [mem_powerset_iff] at *
rcases hA with hA | hA
apply subset_union_of_subset_left
assumption
apply subset_union_of_subset_right
assumption
NewTactic constructor intro rw assumption rcases simp tauto trivial
Hint "**Robo**: Jetzt kann `tauto` den rest übernehmen, vielleicht solltest du diese
Hilfe annehmen.
Wenn nicht, brauchst du vermutlich die Lemmas `Set.subset_union_of_subset_left`
und `Set.subset_union_of_subset_right`"
Branch
rcases hA with hA | hA
apply subset_union_of_subset_left
assumption
apply subset_union_of_subset_right
assumption
tauto
NewLemma Set.mem_powerset_iff Set.subset_union_of_subset_left Set.subset_union_of_subset_right
LemmaTab "Set"

@ -25,15 +25,23 @@ das gleiche.
open Set
Statement
"" :
Statement :
¬Disjoint ({n : | ∃ k, n = 2 * k} : Set ) ({3, 5, 6, 9, 11} : Set ) := by
unfold Disjoint
rw [not_forall] -- why not `push_neg`?
Hint "**Robo**: Öffne als erstes mal `Disjoint`."
rw [Disjoint]
Branch
rw [not_forall] -- why not `push_neg`?
push_neg
Hint "**Robo**: Das sieht jetzt ein bisschen gefürchig aus, aber das ist einfach ein `∃`.
Was du jetzt angeben musst, ist eine Menge, die Teilmenge beider Mengen
`\{n : | ∃ k, n = 2 * k}` und `\{3, 5, 6, 9, 11}` ist.
"
Hint (hidden := true) "**Robo**: Versuch einmal `use \{6}`."
use {6}
Hint "**Robo**: Schau mal wie weit `simp` kommt."
simp
use 3
ring
NewTactic constructor intro rw assumption rcases simp tauto trivial
NewDefinition Disjoint
LemmaTab "Set"

@ -33,5 +33,5 @@ Statement
rw [hx]
ring
NewTactic constructor intro rw assumption rcases simp tauto trivial
NewLemma Set.setOf_or Set.setOf_and Set.mem_inter_iff
LemmaTab "Set"

@ -26,6 +26,6 @@ open Set
Statement
"" (S : Set ) :
{ x ∈ (S : Set ) | 0 ≤ x} ⊆ S := by
library_search
simp
NewTactic constructor intro rw assumption rcases simp tauto trivial
LemmaTab "Set"

@ -24,3 +24,4 @@ Statement
ring
NewTactic constructor intro rw assumption rcases simp tauto trivial
LemmaTab "Set"

@ -23,3 +23,4 @@ Statement
"" : True := sorry
NewTactic constructor intro rw assumption rcases simp tauto trivial
LemmaTab "Set"

@ -24,3 +24,4 @@ Statement
ring
NewTactic constructor intro rw assumption rcases simp tauto trivial
LemmaTab "Set"

@ -1,6 +1,6 @@
import GameServer.Commands
import Adam.TacticDocs
import Adam.LemmaDocs
import Adam.DefinitionDocs
import Adam.Doc.Tactics
import Adam.Doc.Lemmas
import Adam.Doc.Definitions
import Mathlib.Init.Data.Nat.Basic -- Imports the notation .
import Adam.Modification.Tactic

Loading…
Cancel
Save