levels and custom induction

pull/68/head
Jon Eugster 3 years ago
parent c8b0ac4e6c
commit 9b25eda668

@ -363,7 +363,7 @@ LemmaDoc add_pow_two as "add_pow_two" in "Nat"
* Mathlib Doc: [#add_pow_two](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Algebra/GroupPower/Ring.html#add_pow_two) * Mathlib Doc: [#add_pow_two](https://leanprover-community.github.io/mathlib4_docs/Mathlib/Algebra/GroupPower/Ring.html#add_pow_two)
" "
LemmaDoc Finset.sum_comm as "Finset.sum_comm" in "Sum" LemmaDoc Finset.sum_comm as "sum_comm" in "Sum"
" "
## Eigenschaften ## Eigenschaften

@ -7,6 +7,8 @@ import Mathlib.Tactic.Ring
import Adam.ToBePorted import Adam.ToBePorted
set_option tactic.hygienic false
Game "Adam" Game "Adam"
World "Contradiction" World "Contradiction"
Level 1 Level 1
@ -49,10 +51,10 @@ Statement (A B : Prop) (h : A → ¬ B) (k : A ∧ B) : False := by
Hint (hidden := true) "**Robo**: `apply` sollte helfen" Hint (hidden := true) "**Robo**: `apply` sollte helfen"
apply h apply h
assumption assumption
· Hint (hidden := true) "**Du**: Und wie war das nochmals wenn zwei Annahmen sich widersprechen? Hint "**Du**: Und wie war das nochmals wenn zwei Annahmen sich widersprechen?
**Robo**: `contradiction`." **Robo**: `contradiction`."
contradiction contradiction
NewTactic «have» NewTactic «have»
DisabledTactic «suffices» DisabledTactic «suffices»

@ -23,7 +23,7 @@ Statement not_imp_not (A B : Prop) : A → B ↔ (¬ B → ¬ A) := by
Hint "**Du**: Ja, das habe ich tatsächlich schon einmal gesehen. Hint "**Du**: Ja, das habe ich tatsächlich schon einmal gesehen.
**Robo**: Ja, klar hast du das schon einmal gesehen. Das benutzen Mathematiker doch ständig. Wenn ihnen zu $A ⇒ B$ nichts einfällt, zeigen sie stattdessen $¬B ⇒ ¬A$. Ich würde das ja statt *Kontraposition* oder `not_imp_not` eher *von_hinten_durch_die_Brust_ins_Auge* nennen. Aber gut, ich will mich nicht einmisschen. **Robo**: Ja, klar hast du das schon einmal gesehen. Das benutzen Mathematiker doch ständig. Wenn ihnen zu $A ⇒ B$ nichts einfällt, zeigen sie stattdessen $¬B ⇒ ¬A$. Ich würde das ja statt *Kontraposition* oder `not_imp_not` eher *von_hinten_durch_die_Brust_ins_Auge* nennen. Aber gut, ich will mich nicht einmisschen.
" "
Hint (hidden := true) "**Robo**: Fang doch mal mit `constructor` an." Hint (hidden := true) "**Robo**: Fang doch mal mit `constructor` an."
constructor constructor
intro h b intro h b
@ -44,5 +44,6 @@ Statement not_imp_not (A B : Prop) : A → B ↔ (¬ B → ¬ A) := by
DisabledTactic rw DisabledTactic rw
DisabledLemma not_not DisabledLemma not_not
LemmaTab "Logic"
Conclusion "" Conclusion ""

@ -14,7 +14,7 @@ Title "Kontraposition"
Introduction Introduction
" "
**Benedictus**: Gut, hier ist die angekündigte Frage. Versucht mal einen *direkten* Beweis, ohne `contrapose`. **Benedictus**: Gut, hier ist die angekündigte Frage. Versucht mal einen *direkten* Beweis, ohne `by_contra`.
" "
-- Ein Beweis durch Kontraposition benützt im Grunde das eben bewiesene Lemma -- Ein Beweis durch Kontraposition benützt im Grunde das eben bewiesene Lemma
@ -44,7 +44,7 @@ Statement (n : ) (h : Odd (n ^ 2)): Odd n := by
**Robo**: Erinner dich an `revert`. Mit `revert {h}` kannst du die Annahme `{h}` als Implikationsannahme ins Beweissziel schieben." **Robo**: Erinner dich an `revert`. Mit `revert {h}` kannst du die Annahme `{h}` als Implikationsannahme ins Beweissziel schieben."
revert h revert h
Hint "**Du**: Und jetzt kann ich dieses Kontrapositionslemma anwenden? Wie hieß das noch einmal? Hint "**Du**: Und jetzt kann ich dieses Kontrapositionslemma anwenden? Wie hieß das noch einmal?
**Robo**: Tatsächlich kannst auch einfach `contrapose` schreiben. **Robo**: Tatsächlich kannst auch einfach `contrapose` schreiben.
" "
@ -52,10 +52,13 @@ Statement (n : ) (h : Odd (n ^ 2)): Odd n := by
Hint (hidden := true) "**Robo**: Vielleicht hilft jetzt `even_iff_not_odd` weiter?" Hint (hidden := true) "**Robo**: Vielleicht hilft jetzt `even_iff_not_odd` weiter?"
rw [← even_iff_not_odd] rw [← even_iff_not_odd]
rw [← even_iff_not_odd] rw [← even_iff_not_odd]
Hint "**Du**: Das sieht schon ganz gut aus. Jetzt kann ich tatsächlich das alte Lemma anwenden!" Hint "**Du**: Das sieht schon ganz gut aus. Jetzt kann ich tatsächlich das alte Lemma
`even_square` anwenden!"
apply even_square apply even_square
NewLemma even_square
NewTactic contrapose NewTactic contrapose
DisabledTactic by_contra DisabledTactic by_contra
LemmaTab "Nat"
Conclusion "**Benedictus**: Hervorragend! Ich glaube, damit seid Ihr jetzt ganz gut gewappnet." Conclusion "**Benedictus**: Hervorragend! Ich glaube, damit seid Ihr jetzt ganz gut gewappnet."

@ -31,11 +31,11 @@ open Nat
Statement (n : ) (h : Odd (n ^ 2)) : Odd n := by Statement (n : ) (h : Odd (n ^ 2)) : Odd n := by
Hint "Sobald Ihr Euch sicher vom Gravitationsfeld des Asteroiden befreit habt, beugt Ihr Euch wieder über die Aufgabe. Hint "Sobald Ihr Euch sicher vom Gravitationsfeld des Asteroiden befreit habt, beugt Ihr Euch wieder über die Aufgabe.
**Robo**: Ok, also diesmal fangen wir mit `by_contra g` an!" **Robo**: Ok, also diesmal fangen wir mit `by_contra g` an!"
by_contra g by_contra g
Hint "**Robo**: Jetzt würde ich einen Widerspruch zu `Odd (n ^ 2)` führen." Hint "**Robo**: Jetzt würde ich einen Widerspruch zu `Odd (n ^ 2)` führen."
Hint "**Robo**: Also `suffices g : ¬ Odd (n ^ 2)`." Hint (hidden := true) "**Robo**: Also `suffices g : ¬ Odd (n ^ 2)`."
suffices d : ¬ Odd (n ^ 2) suffices d : ¬ Odd (n ^ 2)
contradiction contradiction
rw [←even_iff_not_odd] at * rw [←even_iff_not_odd] at *
@ -49,7 +49,7 @@ Conclusion "**Robo**: Bravo! Hier ein Überblick, was uns Benediktus gezeigt hat
| | Taktik | Beispiel | | | Taktik | Beispiel |
|:------|:----------------|:-------------------------------------------------------| |:------|:----------------|:-------------------------------------------------------|
| 177 | `have` | Zwischenresultat annehmen | | 17 | `have` | Zwischenresultat annehmen |
| 18 | `suffices` | Zwischenresultat annehmen | | 18 | `suffices` | Zwischenresultat annehmen |
| 19 | `by_contra` | Widerspruch *(startet einen Widerspruchsbeweis)* | | 19 | `by_contra` | Widerspruch *(startet einen Widerspruchsbeweis)* |
| *3* | `contradiction` | *(schliesst einen Widerspruchsbeweis)* | | *3* | `contradiction` | *(schliesst einen Widerspruchsbeweis)* |

@ -27,7 +27,7 @@ Conclusion
" "
**Operationsleiter**: Ok, das leuchtet mir ein. **Operationsleiter**: Ok, das leuchtet mir ein.
**Robo** *(zu Dir)*: Übrigens, so wie bei `(h : A ∧ B)` die beiden Teile `h.left` und `h.right` heißen, **Robo** *(zu dir)*: Übrigens, so wie bei `(h : A ∧ B)` die beiden Teile `h.left` und `h.right` heißen,
heißen bei `(h : A ↔ B)` die beiden Teile `h.mp` und `h.mpr`. heißen bei `(h : A ↔ B)` die beiden Teile `h.mp` und `h.mpr`.
**Du**: Also `h.mp` ist `A → B`? Wieso `mp`? **Du**: Also `h.mp` ist `A → B`? Wieso `mp`?

@ -33,7 +33,7 @@ Statement (A B C D : Prop) (h₁ : C ↔ D) (h₂ : A ↔ B) (h₃ : A ↔ D) :
sowas wie `A ↔ A` erhältst, kann `rfl` das beweisen. sowas wie `A ↔ A` erhältst, kann `rfl` das beweisen.
**Robo: Da fällt mir ein, `rw` wendet ohnehin auch versuchsweise `rfl` an. **Robo: Da fällt mir ein, `rw` wendet ohnehin auch versuchsweise `rfl` an.
Das heißt, Du musst `rfl` nicht einmal ausschreiben." Das heißt, du musst `rfl` nicht einmal ausschreiben."
rw [h₂] rw [h₂]
rw [←h₂] rw [←h₂]
assumption assumption

@ -8,7 +8,7 @@ Title "Kleinergleich"
Introduction Introduction
" "
*(Gesrpäch)* *(Gespräch)*
**Robo** (*lallend*, oder war's fröhlich proklamierend?): **Robo** (*lallend*, oder war's fröhlich proklamierend?):
…und deshalb sind `≥` und `>` eigentlich nur Notationen für `≤`, …und deshalb sind `≥` und `>` eigentlich nur Notationen für `≤`,

@ -4,6 +4,8 @@ import Mathlib.Tactic.LibrarySearch
set_option tactic.hygienic false set_option tactic.hygienic false
open Nat
Game "Adam" Game "Adam"
World "Inequality" World "Inequality"
Level 2 Level 2
@ -12,12 +14,12 @@ Title "Kleinergleich"
Introduction Introduction
" "
*weitere Person*: …ich sag dir, eine positive Zahl kann man sowohl mit `0 < n` **weitere Person**: …ich sag dir, eine positive Zahl kann man sowohl mit `0 < n`
als auch `n ≠ 0` darstellen. als auch `n ≠ 0` darstellen.
*Robo*: Und da gibts leider keinen Standard dazu. **Robo**: Und da gibts leider keinen Standard dazu.
**weitere Person*: Ja und, da kann man ja einfach mit `Nat.pos_iff_ne_zero` **weitere Person**: Ja und, da kann man ja einfach mit `Nat.pos_iff_ne_zero`
wechseln. Wart mal, wieso galt das nochmals… wechseln. Wart mal, wieso galt das nochmals…
" "
@ -35,7 +37,11 @@ Statement Nat.pos_iff_ne_zero (n : ) : 0 < n ↔ n ≠ 0 := by
**Robo** (*flüsternd*): Zweiter pompöser Auftritt: sag einfach `simp` und lass das alles **Robo** (*flüsternd*): Zweiter pompöser Auftritt: sag einfach `simp` und lass das alles
automatisch geschehen." automatisch geschehen."
simp simp
Hint "**Du**: Und hier fang ich wohl am besten an wie ich das schon kenne." Hint "**Du**: Ah und jetzt falls `n ≠ 0`."
Branch
simp
Hint "**Robo**: Warte! Den Rest geb ich dir als Lemma: `Nat.suc_pos`."
apply Nat.succ_pos
constructor constructor
intro intro
simp simp

@ -35,7 +35,12 @@ Statement
(R : Type u) [CommRing R] (a b : R) : a + b = b + a := by (R : Type u) [CommRing R] (a b : R) : a + b = b + a := by
Hint "**Robo**: Naja, Aufgaben zu Universen sind nicht so natürlich, Hint "**Robo**: Naja, Aufgaben zu Universen sind nicht so natürlich,
aber vorige Aufgabe würde man eigentlich besser so schreiben, da aber vorige Aufgabe würde man eigentlich besser so schreiben, da
kannst du mindestens das Uniersum beobachten." kannst du mindestens das Uniersum beobachten.
**Du**: Ah ich sehe, `(R: Type u)` anstatt `(R : Type)`. Muss mich
das interessieren?
**Robo**: Nicht wirklich…"
ring ring
Conclusion "**Du**: Na dann. Aber gut dass ich's mal gesehen hab." Conclusion "**Du**: Na dann. Aber gut dass ich's mal gesehen hab."

@ -9,6 +9,8 @@ Game "Adam"
World "Lean" World "Lean"
Level 3 Level 3
open Fin
Title "Implizite Argumente" Title "Implizite Argumente"
Introduction Introduction
@ -20,8 +22,10 @@ haben als ich hinschreiben muss.
ein Lemma von vorhin ein Lemma von vorhin
``` ```
lemma Fin.sum_univ_castSucc {β : Type _} [AddCommMonoid β] {n : } (f : Fin (n + 1) → β) : lemma Fin.sum_univ_castSucc {β : Type _} [AddCommMonoid β]
∑ i : Fin (n + 1), f i = ∑ i : Fin n, f (↑Fin.castSucc.toEmbedding i) + f (Fin.last n) := by {n : } (f : Fin (n + 1) → β) :
∑ i : Fin (n + 1), f i =
∑ i : Fin n, f (↑Fin.castSucc.toEmbedding i) + f (Fin.last n) := by
sorry sorry
``` ```
@ -57,9 +61,11 @@ Statement (m : ) : ∑ i : Fin (m + 1), (i : ) + (m + 1) = ∑ i : Fin (Na
nicht mehr geht, aber das war nicht der Punkt…" nicht mehr geht, aber das war nicht der Punkt…"
rfl rfl
rw [Fin.sum_univ_castSucc (n := m + 1)] rw [Fin.sum_univ_castSucc (n := m + 1)]
Hint "**Robo**: Gut der Rest ist easy."
rfl rfl
OnlyTactic rw rfl OnlyTactic rw rfl simp trivial
LemmaTab "Sum"
Conclusion "**Du**: Gibt es auch noch ander Methoden implizite Argumente anzugeben. Conclusion "**Du**: Gibt es auch noch ander Methoden implizite Argumente anzugeben.

@ -35,12 +35,13 @@ open BigOperators
Statement (m : ) : Statement (m : ) :
∑ i : Fin (m + 1), (i : ) + (m + 1) = ∑ i : Fin (Nat.succ m + 1), ↑i := by ∑ i : Fin (m + 1), (i : ) + (m + 1) = ∑ i : Fin (Nat.succ m + 1), ↑i := by
Hint "*Robo*: Schreibe `rw [@Fin.sum_univ_castSucc _ _ (m + 1)]` Hint "**Robo**: Schreibe `rw [@Fin.sum_univ_castSucc _ _ (m + 1)]`
anstatt `rw [Fin.sum_univ_castSucc (n := m + 1)]`!" anstatt `rw [Fin.sum_univ_castSucc (n := m + 1)]`!"
rw [@Fin.sum_univ_castSucc _ _ (m + 1)] rw [@Fin.sum_univ_castSucc _ _ (m + 1)]
rfl rfl
OnlyTactic rw rfl OnlyTactic rw rfl simp trivial
LemmaTab "Sum"
Conclusion " Conclusion "
**Du**: Danke Robo! **Du**: Danke Robo!

@ -12,7 +12,7 @@ Game "Adam"
World "Predicate" World "Predicate"
Title "Quantus" Title "Quantus"
Introduction "Auf dem Schwestermond Quantus erwartet Euch bereits ein großer Ansammlung von Formalosopheninnen. Sie reden alle wild durcheinander und Ihr habt Probleme, Euch überhaupt Gehör zu verschaffen. Robo produziert schließlich ein lautes Gong-Geräusch, das sie kurzzeitig zur Ruhe bringt. Introduction "Auf dem Schwestermond Quantus erwartet Euch bereits ein großer Ansammlung von Formalosopheninnen. Sie reden alle wild durcheinander und Ihr habt Probleme, Euch überhaupt Gehör zu verschaffen. Robo produziert schließlich ein lautes Gong-Geräusch, das sie kurzzeitig zur Ruhe bringt.
**Du**: Wir haben einen Brief für Eure Königin. Könntet Ihr uns zu Eurer Königin führen? **Du**: Wir haben einen Brief für Eure Königin. Könntet Ihr uns zu Eurer Königin führen?
@ -22,23 +22,23 @@ Introduction "Auf dem Schwestermond Quantus erwartet Euch bereits ein großer An
Nun herrscht betretenes Schweigen. Alle zucken mit den Schultern. Nun herrscht betretenes Schweigen. Alle zucken mit den Schultern.
**Du**: Habt Ihr überhaupt eine Königin? **Du**: Habt Ihr überhaupt eine Königin?
**Alle** *(im Chor)*: Ja, ja. Wir haben eine Königen, wir haben eine Königen. **Alle** *(im Chor)*: Ja, ja. Wir haben eine Königen, wir haben eine Königen.
**Robo** *(zu Dir)*: Ich fasse mal zusammen. Es existiert eine Königen, aber keiner weiß, wer sie ist … **Robo** *(zu dir)*: Ich fasse mal zusammen. Es existiert eine Königen, aber keiner weiß, wer sie ist …
**Du**: Ist das nicht ein Widerspruch? **Du**: Ist das nicht ein Widerspruch?
**Robo**: Fragst du, du als Mathematiker? Nein, das ist kein Widerspruch. Das ist einfach eine „reine Existenzaussage“. **Robo**: Fragst du, du als Mathematiker? Nein, das ist kein Widerspruch. Das ist einfach eine „reine Existenzaussage“.
Du bist dir nicht ganz sicher, wie ernst er das meint. Du bist dir nicht ganz sicher, wie ernst er das meint.
**Du**: Dann ich schlage vor, wir übergeben das Päckchen einfach an *alle* Bewohner. Dann haben wir es ja insbesondere der Königin übergeben. **Du**: Dann ich schlage vor, wir übergeben das Päckchen einfach an *alle* Bewohner. Dann haben wir es ja insbesondere der Königin übergeben.
**Du** *(in die Menge*): Wir haben Euch ein Päckchen von Implis gebracht. Hier, das ist für Euch. **Du** *(in die Menge*): Wir haben Euch ein Päckchen von Implis gebracht. Hier, das ist für Euch.
Robo spuckt es aus, wirft es in die Menge, und die Formalosophinnen reißen es auf. Darin befinden sich ein paar loser Seiten, die sie sofort eingehend studieren. Robo spuckt es aus, wirft es in die Menge, und die Formalosophinnen reißen es auf. Darin befinden sich ein paar loser Seiten, die sie sofort eingehend studieren.
Zwei Minuten später liegen die Seiten wieder bei Euch. Es sind wieder mathematische Probleme. Und die Formalosophinnen wollen sehen, wie Ihr sie löst. Zwei Minuten später liegen die Seiten wieder bei Euch. Es sind wieder mathematische Probleme. Und die Formalosophinnen wollen sehen, wie Ihr sie löst.
" "

@ -10,7 +10,7 @@ Level 1
Title "Natürliche Zahlen" Title "Natürliche Zahlen"
Introduction Introduction
"Du schaust Dir die erste Seite an." "Du schaust dir die erste Seite an."
Statement (x y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 := by Statement (x y : ) : (x + y) ^ 2 = x ^ 2 + 2 * x * y + y ^ 2 := by
Hint "**Du**: Das ist doch Schulmathematik! Man rechnet das einfach aus, Hint "**Du**: Das ist doch Schulmathematik! Man rechnet das einfach aus,

@ -39,7 +39,7 @@ Statement even_square (n : ) (h : Even n) : Even (n ^ 2) := by
Dann siehst du besser, was los ist." Dann siehst du besser, was los ist."
Branch Branch
unfold Even unfold Even
Hint "Robo**: Am besten machst Du auch noch `unfold Even at h`, damit Du verstehst, was los ist." Hint "Robo**: Am besten machst du auch noch `unfold Even at h`, damit du verstehst, was los ist."
unfold Even at * unfold Even at *
Hint "**Du**: Also von `{h}` weiß ich jetzt, dass ein `r` existiert, so dass `r + r = n` … Hint "**Du**: Also von `{h}` weiß ich jetzt, dass ein `r` existiert, so dass `r + r = n` …

@ -77,7 +77,7 @@ NewTactic push_neg
NewLemma Nat.even_iff_not_odd Nat.odd_iff_not_even not_exists not_forall NewLemma Nat.even_iff_not_odd Nat.odd_iff_not_even not_exists not_forall
Conclusion "Die Formalosophinnen sind ganz begeistert. Conclusion "Die Formalosophinnen sind ganz begeistert.
Nachdem sich der Beifall gelegt hat, hast Du auch einmal eine Frage. Nachdem sich der Beifall gelegt hat, hast du auch einmal eine Frage.
**Du**: Kann uns hier irgendjemand vielleicht ein bisschen Orientierung im Formaloversum geben? **Du**: Kann uns hier irgendjemand vielleicht ein bisschen Orientierung im Formaloversum geben?
@ -88,7 +88,7 @@ Nachdem sich der Beifall gelegt hat, hast Du auch einmal eine Frage.
Die Frage war wieder zu konkret. Betretenes Schweigen. Die Frage war wieder zu konkret. Betretenes Schweigen.
**Robo**: Lass nur. Ich schlage vor, wir machen als nächstes einen Ausflug auf den Asteroiden da **Robo**: Lass nur. Ich schlage vor, wir machen als nächstes einen Ausflug auf den Asteroiden da
drüben. Und bevor Du fragst hier ist wieder ein Überblick, was Du auf diesem Planeten drüben. Und bevor du fragst hier ist wieder ein Überblick, was du auf diesem Planeten
gelernt hast. gelernt hast.
| | Beschreibung | | | Beschreibung |

@ -25,7 +25,7 @@ Richte dich besser darauf ein, hier bleiben und dich zurechtzufinden zu müssen.
Wie es aussieht, gibt es hier viele nette kleine Planeten. Alle bewohnbar, und bis zu Wie es aussieht, gibt es hier viele nette kleine Planeten. Alle bewohnbar, und bis zu
sieben Sonnenuntergänge täglich inklusive. Nur werden sie allesamt von Formalosophen bewohnt, sieben Sonnenuntergänge täglich inklusive. Nur werden sie allesamt von Formalosophen bewohnt,
seltsamen Wesen mit ausgefallenen mathematischen Obsessionen. Und dummerweise hat sich seltsamen Wesen mit ausgefallenen mathematischen Obsessionen. Und dummerweise hat sich
herumgesprochen, dass du in deinem früheren Universum Mathematiker warst. Du wirst hier herumgesprochen, dass du in deinem früheren Universum Mathematiker warst. du wirst hier
keine Ruhe finden, solange du nicht lernst, ihren unablässigen Wissensdurst zu stillen. keine Ruhe finden, solange du nicht lernst, ihren unablässigen Wissensdurst zu stillen.
Es gibt nur zwei Schwierigkeiten: Erstens haben die Formalosophen allem Anschein nach Es gibt nur zwei Schwierigkeiten: Erstens haben die Formalosophen allem Anschein nach

@ -20,7 +20,7 @@ Statement
(A B : Prop) (hA : A) : A (¬ B) := by (A B : Prop) (hA : A) : A (¬ B) := by
Hint "**Du** Muss ich jetzt wieder das Beweisziel de-konstruieren? Hint "**Du** Muss ich jetzt wieder das Beweisziel de-konstruieren?
**Robo** Nein, viel einfacher. Wenn du eine Oder-Aussage beweisen sollst, musst du Dich **Robo** Nein, viel einfacher. Wenn du eine Oder-Aussage beweisen sollst, musst du dich
einfach entscheiden, ob du die linke oder rechte Seite beweisen willst. einfach entscheiden, ob du die linke oder rechte Seite beweisen willst.
**Du** Und wie erkläre ich meinem Formalosophen, welche Seite ich gern beweisen würde? **Du** Und wie erkläre ich meinem Formalosophen, welche Seite ich gern beweisen würde?

@ -9,8 +9,7 @@ Game "Adam"
World "Sum" World "Sum"
Title "Endliche Summe" Title "Endliche Summe"
Introduction "Mit dem Gefühl, dass sich *Evenine* und *Oddeus* in Zukunft wieder Introduction "Ihr steigt in eurer Raumschiff und setzt eure Reise fort.
besser verstehen werden, steigt ihr in eurer Raumschiff und setzt eure Reise fort.
Bald erreicht ihr einen neuen Planet. Die oberfläche scheint steinig zu sein, aber nicht etwa Bald erreicht ihr einen neuen Planet. Die oberfläche scheint steinig zu sein, aber nicht etwa
geröll oder Chaos. Stattdessen, scheinen unzählige Steinplatten zu bizzaren hohen Türme geröll oder Chaos. Stattdessen, scheinen unzählige Steinplatten zu bizzaren hohen Türme

@ -43,24 +43,25 @@ In diesem Kapitel lernen wir endliche Summen und mehr Übungen zur Induktion.
open BigOperators open BigOperators
Statement (n : ) : (∑ i : Fin n, (0 + 0)) = 0 := by Statement (n : ) : (∑ i : Fin n, (0 + 0)) = 0 := by
Hint "BUG" Hint "
**Du**: Oh das ist ganz schön viel neues… Mal sehen, das sagt wohl
$( \\sum_i 0 + 0 ) = 0$. Dann ist das vielleicht doch nicht so komplex.
-- TODO (Bug): Invalid escape sequence: **Robo**: Genau! Man schreibt `\\sum`. Beachte den Index:
-- "**Du**: Oh das ist ganz schön viel neues… Mal sehen, das sagt wohl $( \\sum_\{i=0}^\{n-1} 0 + 0 ) = 0$, also `Fin n` ist ein Typ mit den Elementen
-- $( \\sum_i 0 + 0 ) = 0$. Dann ist das vielleicht doch nicht so komplex. $(0, \\ldots, n-1)$.
-- **Robo**: Genau! Man schreibt `\\sum`. Beachte den Index: **Du**: Oke, also `Fin n` hat `n` Elemente. Und was mach ich jetzt?
-- $( \\sum_\{i=0}^\{n-1} 0 + 0 ) = 0$, also `Fin n` ist ein Typ mit den Elementen
-- $\\{0, \\ldots, n-1\\}$.
-- **Du**: Oke, also `Fin n` hat `n` Elemente. Und was mach ich jetzt? **Robo**: `simp` ist eine ganz starke Taktik, die viele Terme vereinfacht, wir
fangen besser an, diese zu benützen.
-- **Robo**: `simp` ist eine ganz starke Taktik, die viele Terme vereinfacht, wir Irgendwie hast du das Gefühl ein Déjà-vue zu haben…"
-- fangen besser an, diese zu benützen.
-- Irgendwie hast du das Gefühl ein Déjà-vue zu haben…"
simp simp
OnlyTactic simp OnlyTactic simp
LemmaTab "Sum"
Conclusion "**Unbekannte**: Sehr gut, folgt mir!" Conclusion "**Unbekannte**: Sehr gut, folgt mir!"
-- TODO: Cannot write $\\{0\\}$ inside a hint.

@ -4,6 +4,7 @@ import Adam.ToBePorted
import Mathlib import Mathlib
set_option tactic.hygienic false set_option tactic.hygienic false
open Finset
Game "Adam" Game "Adam"
World "Sum" World "Sum"
@ -22,21 +23,21 @@ open BigOperators
Statement Statement
"$\\sum_{i=0}^{n-1} (i + 1) = n + \\sum_{i=0}^{n-1} i$." "$\\sum_{i=0}^{n-1} (i + 1) = n + \\sum_{i=0}^{n-1} i$."
(n : ) : ∑ i : Fin n, ((i : ) + 1) = n + (∑ i : Fin n, (i : )) := by (n : ) : ∑ i : Fin n, ((i : ) + 1) = n + (∑ i : Fin n, (i : )) := by
-- Hint "**Du**: Hmm, wieder `simp`? Hint "**Du**: Hmm, wieder `simp`?
-- **Robo**: Nicht ganz. `simp` benützt nur Lemmas, die klar eine Vereinfachung darstellen, **Robo**: Nicht ganz. `simp` benützt nur Lemmas, die klar eine Vereinfachung darstellen,
-- und in deiner Bibliothek mit `@[simp]` markiert wird. Hier brauchen wir eine andere und in deiner Bibliothek mit `@[simp]` markiert wird. Hier brauchen wir eine andere
-- Umformung: Umformung:
-- $$ $$
-- \\sum_\{i = 0}^n a_i + b_i = \\sum_\{i = 0}^n a_i + \\sum_\{j = 0}^n b_j \\sum_\{i = 0}^n a_i + b_i = \\sum_\{i = 0}^n a_i + \\sum_\{j = 0}^n b_j
-- $$ $$
-- **Robo*: Da unklar ist, welche Seite \"einfacher\" ist, wird so ein Lemma nicht mit **Robo**: Da unklar ist, welche Seite \"einfacher\" ist, wird so ein Lemma nicht mit
-- `@[simp]` markiert. Das heisst du musst `Finset.sum_add_distrib` mit `rw` `@[simp]` markiert. Das heisst du musst `sum_add_distrib` mit `rw`
-- explizit anwenden. explizit anwenden.
-- " "
rw [Finset.sum_add_distrib] rw [sum_add_distrib]
Hint "**Robo**: Die zweite Summe `∑ x : Fin n, 1` kann jetzt aber mit Hint "**Robo**: Die zweite Summe `∑ x : Fin n, 1` kann jetzt aber mit
`simp` zu `n` vereinfacht werden." `simp` zu `n` vereinfacht werden."
simp simp
@ -49,6 +50,7 @@ Statement
ring ring
NewLemma Finset.sum_add_distrib add_comm NewLemma Finset.sum_add_distrib add_comm
LemmaTab "Sum"
Conclusion "Eure Begleitung scheint mit der Antwort zu frieden zu sein und zeigt Conclusion "Eure Begleitung scheint mit der Antwort zu frieden zu sein und zeigt
freudig an dem Turm empor, den ihr soeben erreicht habt." freudig an dem Turm empor, den ihr soeben erreicht habt."

@ -25,6 +25,8 @@ einmal Daten verarbeitet. Und die antwort auf deine Frage: Vermutlich ein Stein
dem anderen. dem anderen.
" "
open Fin
open BigOperators open BigOperators
Statement arithmetic_sum Statement arithmetic_sum
@ -34,17 +36,18 @@ Statement arithmetic_sum
wie zeige ich denn die arithmetische Summe, die hier gekritzelt steht? wie zeige ich denn die arithmetische Summe, die hier gekritzelt steht?
Ich würde gerne Induktion über $n$ anwenden. Ich würde gerne Induktion über $n$ anwenden.
**Robo**: Ja dann ist's einfach `induction n`, ist doch logisch!" **Robo**: Ja dann ist's einfach `induction n with d hd`! Der `with d hd` teil ist
induction n Optional und hilft dir die Induktionsvariable und -hypothese zu benennen."
induction n with d hd
Hint "**Du**: Zuerst den Induktionsanfang… Hint "**Du**: Zuerst den Induktionsanfang…
**Robo**: Diesen kannst du oft mit `simp` abkürzen!" **Robo**: Diesen kannst du oft mit `simp` abkürzen!"
simp simp
Hint "**Robo**: Jetzt im Induktionsschritt: Bei Induktion über endlichen Summen willst du Hint "**Robo**: Jetzt im Induktionsschritt: Bei Induktion über endlichen Summen willst du
immer mit `rw [Fin.sum_univ_castSucc]` anfangen" -- : immer mit `rw [sum_univ_castSucc]` anfangen" -- :
-- $$\\sum_\{i=0}^n a_i = \\sum_{i=0}^\{n-1} a_i + a_n$$" -- $$\\sum_\{i=0}^n a_i = \\sum_{i=0}^\{n-1} a_i + a_n$$"
rw [Fin.sum_univ_castSucc] rw [sum_univ_castSucc]
-- TODO: Bug. Dieser Hint wird nicht angezeigt. -- TODO: Bug. Dieser Hint wird nicht angezeigt.
Hint "**Du**: Oh das sieht jetz aber kompliziert aus… Hint "**Du**: Oh das sieht jetz aber kompliziert aus…
@ -63,27 +66,31 @@ Statement arithmetic_sum
Hint "**Du**: Und wie wende ich jetzt die Induktionshypothese an? Hint "**Du**: Und wie wende ich jetzt die Induktionshypothese an?
**Robo mit `rw` wie jede andere Annahme auch." **Robo mit `rw` wie jede andere Annahme auch."
rw [n_ih] rw [hd]
Hint "**Robo**: Jetzt musst du noch kurz `rw [Nat.succ_eq_add_one]` anwenden. Hint "**Du**: Der Rest ist einfach Rechnerei.
**Robo**: Dann wir `ring` wohl keine Probleme haben."
-- Hint "**Robo**: Jetzt musst du noch kurz `rw [Nat.succ_eq_add_one]` anwenden.
**Du**: Aber wieso? -- **Du**: Aber wieso?
**Robo**: Naja, `ring` ist jetzt auch noch nicht so stark, und erkennt nicht dass `n.succ` -- **Robo**: Naja, `ring` ist jetzt auch noch nicht so stark, und erkennt nicht dass `n.succ`
und `n + 1` das gleiche sind. -- und `n + 1` das gleiche sind.
**Du**: Aber das könnte man doch ändern, oder? -- **Du**: Aber das könnte man doch ändern, oder?
**Robo**: Vielleicht wenn wir einmal einem Techniker begegnen, der mir ein Update -- **Robo**: Vielleicht wenn wir einmal einem Techniker begegnen, der mir ein Update
einspielen kann…" -- einspielen kann…"
Branch -- Branch
ring_nf -- ring_nf
Hint "**Robo**: Wie gesagt, brauch doch `rw [Nat.succ_eq_add_one]` als Fix für meine -- Hint "**Robo**: Wie gesagt, brauch doch `rw [Nat.succ_eq_add_one]` als Fix für meine
kleinen Maken." -- kleinen Maken."
rw [Nat.succ_eq_add_one] -- rw [Nat.succ_eq_add_one]
ring ring
NewTactic induction NewTactic induction
NewLemma Fin.sum_univ_castSucc Nat.succ_eq_add_one mul_add add_mul Nat.zero_eq NewLemma Fin.sum_univ_castSucc Nat.succ_eq_add_one mul_add add_mul Nat.zero_eq
LemmaTab "Sum"
Conclusion "Du schaust dich um und bewunderst das Tal in dem hunderte, wenn nicht tausende, Conclusion "Du schaust dich um und bewunderst das Tal in dem hunderte, wenn nicht tausende,
Steintürme in allen Formen und Höhen stehen." Steintürme in allen Formen und Höhen stehen."

@ -18,6 +18,8 @@ Du gehst zu einem etwas kleineren Nachbarsturm.
" "
set_option tactic.hygienic false set_option tactic.hygienic false
open Fin
open BigOperators open BigOperators
Statement odd_arithmetic_sum Statement odd_arithmetic_sum
@ -26,8 +28,12 @@ Statement odd_arithmetic_sum
Hint "**Robo**: Das funktioniert genau gleich wie zuvor, viel Glück." Hint "**Robo**: Das funktioniert genau gleich wie zuvor, viel Glück."
induction n induction n
simp simp
rw [Fin.sum_univ_castSucc] Hint (hidden := true) "Den Induktionschritt mit Summen willst du
eigentlich immer mit `rw [sum_univ_castSucc]` beginnen."
rw [sum_univ_castSucc]
simp simp
rw [n_ih] rw [n_ih]
rw [Nat.succ_eq_add_one] --rw [Nat.succ_eq_add_one]
ring ring
LemmaTab "Sum"

@ -9,6 +9,7 @@ import Adam.Options.ArithSum
set_option tactic.hygienic false set_option tactic.hygienic false
open BigOperators open BigOperators
open Finset
Game "Adam" Game "Adam"
World "Sum" World "Sum"
@ -35,10 +36,11 @@ Statement
**Du**: Hast du nicht ein Lemma dafür? **Du**: Hast du nicht ein Lemma dafür?
**Robo**: Doch, probier mal `Finset.sum_comm`." **Robo**: Doch, probier mal `sum_comm`."
rw [Finset.sum_comm] rw [Finset.sum_comm]
NewLemma Finset.sum_comm NewLemma Finset.sum_comm
LemmaTab "Sum"
Conclusion " Conclusion "
Euer Begleiter ist ganz begeistert als er dir das Stück Papier aus den Händen nimmt, Euer Begleiter ist ganz begeistert als er dir das Stück Papier aus den Händen nimmt,

@ -38,6 +38,8 @@ Da löst sich aus der Steinlandschaft plötzlich ein grosser Steingolem. Er scha
bedrohlich an und fragt in tiefer Stimme: bedrohlich an und fragt in tiefer Stimme:
" "
open Fin
open BigOperators open BigOperators
Statement (m : ) : (∑ i : Fin (m + 1), (i : )^3) = (∑ i : Fin (m + 1), (i : ))^2 := by Statement (m : ) : (∑ i : Fin (m + 1), (i : )^3) = (∑ i : Fin (m + 1), (i : ))^2 := by
@ -45,7 +47,7 @@ Statement (m : ) : (∑ i : Fin (m + 1), (i : )^3) = (∑ i : Fin (m + 1),
induction m induction m
Hint "**Du**: Also den Induktionsanfang kann man einfach zeigen…" Hint "**Du**: Also den Induktionsanfang kann man einfach zeigen…"
simp simp
Hint "**Robo**: Und jetzt wieder `rw [Fin.sum_univ_castSucc]` und `simp` um vorwärts zu Hint (hidden := true) "**Robo**: Und jetzt wieder `rw [sum_univ_castSucc]` und `simp` um vorwärts zu
kommen!" kommen!"
rw [Fin.sum_univ_castSucc] rw [Fin.sum_univ_castSucc]
simp simp
@ -56,9 +58,9 @@ Statement (m : ) : (∑ i : Fin (m + 1), (i : )^3) = (∑ i : Fin (m + 1),
Der Golem schaut dich finster an. Der Golem schaut dich finster an.
**Robo**: Du willst `Fin.sum_univ_castSucc` auf der rechten Seite anwenden, aber es **Robo**: Du willst `sum_univ_castSucc` auf der rechten Seite anwenden, aber es
gibt mehrere Orte, wo das Lemma passen würde. gibt mehrere Orte, wo das Lemma passen würde.
Deshalb musst du mit `rw [Fin.sum_univ_castSucc (n := {n} + 1)]` angeben, wo genau. Deshalb musst du mit `rw [sum_univ_castSucc (n := {n} + 1)]` angeben, wo genau.
**Du**: Was bedeutet das? **Du**: Was bedeutet das?
@ -83,9 +85,10 @@ Statement (m : ) : (∑ i : Fin (m + 1), (i : )^3) = (∑ i : Fin (m + 1),
ring ring
NewLemma arithmetic_sum add_pow_two NewLemma arithmetic_sum add_pow_two
LemmaTab "Sum"
Conclusion "Der Golem denkt ganz lange nach, und ihr bekommt das Gefühl, dass er gar nie Conclusion "Der Golem denkt ganz lange nach, und ihr bekommt das Gefühl, dass er gar nie
aggressive war, sondern nur eine sehr tiefe Stimme hat. aggressiv war, sondern nur eine sehr tiefe Stimme hat.
Mit einem kleinen Erdbeben setzt er sich hin und winkt euch dankend zu. Mit einem kleinen Erdbeben setzt er sich hin und winkt euch dankend zu.

@ -3,3 +3,4 @@ import Adam.TacticDocs
import Adam.LemmaDocs import Adam.LemmaDocs
import Adam.DefinitionDocs import Adam.DefinitionDocs
import Mathlib.Init.Data.Nat.Basic -- Imports the notation . import Mathlib.Init.Data.Nat.Basic -- Imports the notation .
import Adam.Modification.Tactic

@ -0,0 +1,83 @@
import Mathlib.Lean.Expr.Basic
import Lean.Elab.Tactic.Basic
import Mathlib.Init.Data.Nat.Notation
open Lean.Meta Lean.Elab.Tactic Lean.Parser.Tactic
/-!
# Modified `induction` tactic
Modify `induction` tactic to use the cases `0` and `n + 1` (isnstead of `zero` and `succ n`)
and support the lean3-style `with` keyword.
This is mainly copied and modified from the mathlib-tactic `induction'`.
-/
/-- Custom induction principle that uses `0` and `n + 1` instead
of `Nat.zero` and `Nat.succ n`. -/
def CustomTactic.rec' {P : → Prop} (zero : P 0)
(succ : (n : ) → (n_ih : P n) → P (n + 1)) (t : ) : P t := by
induction t with
| zero => assumption
| succ n =>
apply succ
assumption
namespace Lean.Parser.Tactic
open Meta Elab Elab.Tactic
open private getAltNumFields in evalCases ElimApp.evalAlts.go in
def _root_.CustomTactic.ElimApp.evalNames (elimInfo : ElimInfo) (alts : Array ElimApp.Alt) (withArg : Syntax)
(numEqs := 0) (numGeneralized := 0) (toClear : Array FVarId := #[]) :
Lean.Elab.Term.TermElabM (Array MVarId) := do
let mut names : List Syntax := withArg[1].getArgs |>.toList
let mut subgoals := #[]
for { name := altName, mvarId := g, .. } in alts do
let numFields ← getAltNumFields elimInfo altName
let (altVarNames, names') := names.splitAtD numFields (Unhygienic.run `(_))
names := names'
let (fvars, g) ← g.introN numFields <| altVarNames.map (getNameOfIdent' ·[0])
let some (g, subst) ← Cases.unifyEqs? numEqs g {} | pure ()
let (_, g) ← g.introNP numGeneralized
let g ← liftM $ toClear.foldlM (·.tryClear) g
for fvar in fvars, stx in altVarNames do
g.withContext <| (subst.apply <| .fvar fvar).addLocalVarInfoForBinderIdent ⟨stx⟩
subgoals := subgoals.push g
pure subgoals
open private getElimNameInfo generalizeTargets generalizeVars in evalInduction in
/--
Modified `induction` tactic for this game.
Usage: `induction n with d hd`.
For this game, `induction n` uses the cases `0` and `n + 1` instead of `Nat.zero` and
`Nat.succ n`. These are defEq, but it's currently annoying that `ring` does not like the
latter forms.
*(The actual `induction` tactic has a more complex `with`-argument that works differently)*
-/
elab (name := _root_.MyNat.induction) "induction " tgts:(casesTarget,+)
withArg:((" with " (colGt binderIdent)+)?)
: tactic => do
let targets ← elabCasesTargets tgts.1.getSepArgs
let g :: gs ← getUnsolvedGoals | throwNoGoalsToBeSolved
g.withContext do
let elimInfo ← getElimInfo `CustomTactic.rec'
let targets ← addImplicitTargets elimInfo targets
evalInduction.checkTargets targets
let targetFVarIds := targets.map (·.fvarId!)
g.withContext do
let forbidden ← mkGeneralizationForbiddenSet targets
let mut s ← getFVarSetToGeneralize targets forbidden
let (fvarIds, g) ← g.revert (← sortFVarIds s.toArray)
let result ← withRef tgts <| ElimApp.mkElimApp elimInfo targets (← g.getTag)
let elimArgs := result.elimApp.getAppArgs
ElimApp.setMotiveArg g elimArgs[elimInfo.motivePos]!.mvarId! targetFVarIds
g.assign result.elimApp
let subgoals ← CustomTactic.ElimApp.evalNames elimInfo result.alts withArg
(numGeneralized := fvarIds.size) (toClear := targetFVarIds)
setGoals <| (subgoals ++ result.others).toList ++ gs
end Lean.Parser.Tactic

@ -231,7 +231,16 @@ Diese Taktik erstellt zwei Goals:
* Induktionsanfang, wo `n = 0` ersetzt wird. * Induktionsanfang, wo `n = 0` ersetzt wird.
* Induktionsschritt, in dem man die Induktionshypothese `n_ih` zur Verfügung hat. * Induktionsschritt, in dem man die Induktionshypothese `n_ih` zur Verfügung hat.
Der volle Syntax mit Option zum umbenennen der Induktionshypothes und -variable ist ## Modifikationen in diesem Spiel
* `induction n with d hd` benennt Induktionsvariable und -hypothese. (das ist Lean3-Syntax)
und funktioniert ausserhalb vom Spiel nicht genau so.
* Ausserhalb des Spiels kriegst du `Nat.zero` und `Nat.succ n` anstatt `0` und `n + 1`
als Fälle. Diese
Terme sind DefEq, aber manchmal benötigt man die lemmas `zero_eq` und `Nat.succ_eq_add_one`
um zwischen den schreibweisen zu wechseln
Der richtige Lean4-Syntax für `with` streckt sich über mehrere Zeilen und ist:
``` ```
induction n with induction n with

Loading…
Cancel
Save