|
|
|
@ -1,300 +1,524 @@
|
|
|
|
|
import GameServer.Commands
|
|
|
|
|
|
|
|
|
|
import TestGame.Tactics
|
|
|
|
|
|
|
|
|
|
TacticDoc rfl
|
|
|
|
|
TacticDoc assumption
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`assumption` sucht nach einer Annahme, die genau dem Goal entspricht.
|
|
|
|
|
|
|
|
|
|
`rfl` beweist ein Goal der Form `X = X`.
|
|
|
|
|
## Beispiel
|
|
|
|
|
|
|
|
|
|
## Detail
|
|
|
|
|
`assumption` sucht durch die Annahmen und merkt dass `h` genau mit dem Goal übereinstimmt.
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Objekte
|
|
|
|
|
a b c d : ℕ
|
|
|
|
|
h : a + b = c
|
|
|
|
|
g : a * b = 16
|
|
|
|
|
t : c = 12
|
|
|
|
|
Goal
|
|
|
|
|
a + b = c
|
|
|
|
|
```
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc apply
|
|
|
|
|
"
|
|
|
|
|
`apply my_lemma` Versucht das Goal mit der Aussage des Lemmas zu unifizieren
|
|
|
|
|
und erstellt ein neues Goal pro Annahme des Lemmas, die noch zu zeigen ist.
|
|
|
|
|
|
|
|
|
|
`rfl` beweist jedes Goal `A = B` wenn `A` und `B` genau das gleiche sind.
|
|
|
|
|
Wichtig ist nicht, ob diese im Infoview gleich aussehen, sondern ob sie in
|
|
|
|
|
Lean gleich definiert sind.
|
|
|
|
|
## Details
|
|
|
|
|
`apply` funktioniert gleichermassen für Lemmas wie für Implikationen
|
|
|
|
|
wie z.B. `(h : A → B)`.
|
|
|
|
|
|
|
|
|
|
## Beispiel
|
|
|
|
|
`rfl` kann folgenes Goal beweisen:
|
|
|
|
|
|
|
|
|
|
Gegeben folgendes Lemma:
|
|
|
|
|
```
|
|
|
|
|
Objects
|
|
|
|
|
a b c : ℕ
|
|
|
|
|
Prove:
|
|
|
|
|
(a + b) * c = (a + b) * c
|
|
|
|
|
lemma Nat.eq_zero_of_le_zero {n : ℕ} (h : n ≤ 0) : n = 0 := by sorry
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`rfl` kann auch folgendes beweisen:
|
|
|
|
|
Und folgendes Problem:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Objects
|
|
|
|
|
|
|
|
|
|
Objekte
|
|
|
|
|
n : ℕ
|
|
|
|
|
Prove:
|
|
|
|
|
1 + 1 = 2
|
|
|
|
|
...
|
|
|
|
|
Goal
|
|
|
|
|
n = 0
|
|
|
|
|
```
|
|
|
|
|
denn Lean liest dies intern als `0.succ.succ = 0.succ.succ`.
|
|
|
|
|
|
|
|
|
|
Hier ändert `apply Nat.eq_zero_of_le_zero` das Goal zu `n ≤ 0` durch Anwendung
|
|
|
|
|
des Lemmas.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc assumption
|
|
|
|
|
TacticDoc by_cases
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`by_cases h : P` macht eine Fallunterscheidung. Im ersten Goal wird eine Annahme
|
|
|
|
|
`(h : P)` hinzugefügt, im zweiten `(h : ¬P)`.
|
|
|
|
|
|
|
|
|
|
`assumption` sucht nach einer Annahme, die genau dem Goal entspricht.
|
|
|
|
|
## Details
|
|
|
|
|
|
|
|
|
|
`P` kann eine beliegige Aussage sein, die als entweder wahr oder falsch angenommen wird.
|
|
|
|
|
|
|
|
|
|
## Beispiel
|
|
|
|
|
Wenn das Goal wie folgt aussieht:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Objects
|
|
|
|
|
a b c d : ℕ
|
|
|
|
|
h : a + b = c
|
|
|
|
|
g : a * b = 16
|
|
|
|
|
t : c = 12
|
|
|
|
|
Prove:
|
|
|
|
|
a + b = c
|
|
|
|
|
example (A : Prop) : A ∨ ¬ A := by
|
|
|
|
|
by_cases h : A
|
|
|
|
|
· left
|
|
|
|
|
assumption
|
|
|
|
|
· right
|
|
|
|
|
assumption
|
|
|
|
|
```
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
dann findet `assumption` die Annahme `h`und schliesst den Beweis.
|
|
|
|
|
TacticDoc by_contra
|
|
|
|
|
"
|
|
|
|
|
`by_contra h` startet einen Widerspruchsbeweis.
|
|
|
|
|
|
|
|
|
|
## Details
|
|
|
|
|
Sei `P` das aktuelle Goal. `by_contra h` fügt eine neue Annahme `(h : ¬P)` hinzu
|
|
|
|
|
und setzt das Goal auf `False`.
|
|
|
|
|
|
|
|
|
|
TacticDoc rewrite
|
|
|
|
|
Oft will man `by_contra` nutzen wenn das Goal von der Form `¬ P` ist.
|
|
|
|
|
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* `contradiction` schliesst den Widerspruchsbeweis wenn sich (zwei) Annahmen
|
|
|
|
|
widersprechen.
|
|
|
|
|
* `contrapose` führt einen Beweis durch Kontraposition und ist entsprechend
|
|
|
|
|
in ähnlichen Situationen nutzbar wie `by_contra`
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
|
|
|
|
|
Wie `rw` aber ruft `rfl` am Schluss nicht automatisch auf.
|
|
|
|
|
TacticDoc constructor
|
|
|
|
|
"
|
|
|
|
|
`constructor` teilt ein Goal auf, wenn das Goal eine Struktur ist
|
|
|
|
|
|
|
|
|
|
TacticDoc induction
|
|
|
|
|
## Detail
|
|
|
|
|
Wenn das Goal eine Struktur ist, wie z.B. `A ∧ B` welches zwei Felder hat `⟨A, B⟩`, dann
|
|
|
|
|
erzeugt `constructor` ein Goal pro Feld der Struktur.
|
|
|
|
|
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* Das Gegenteil von `constructor` ist `⟨_, _⟩` (`\\<>`), der *anonyme Konstructor*.
|
|
|
|
|
Dieser enspricht ungefähr der Tupel-Notation in
|
|
|
|
|
\"eine Gruppe ist ein Tupel $(G, 0, +)$, sodass …\".
|
|
|
|
|
|
|
|
|
|
## Beispiel
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
example {A B : Prop} (h : A) (g : B) : A ∧ B := by
|
|
|
|
|
constructor
|
|
|
|
|
· assumption
|
|
|
|
|
· assumption
|
|
|
|
|
```
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
|
|
|
|
|
Wie `rw` aber ruft `rfl` am Schluss nicht automatisch auf.
|
|
|
|
|
TacticDoc contradiction
|
|
|
|
|
"
|
|
|
|
|
`contradiction` schliesst den Beweis wenn es einen Widerspruch in den Annahmen findet.
|
|
|
|
|
|
|
|
|
|
## Details
|
|
|
|
|
Ein Widerspruch in den Annahmen kann unter anderem folgendermassen aussehen:
|
|
|
|
|
|
|
|
|
|
TacticDoc linarith
|
|
|
|
|
* `(h : n ≠ n)`
|
|
|
|
|
* `(h : A)` und `(h' : ¬A)`
|
|
|
|
|
* `(h : False)` (i.e. ein Beweis von `False`)
|
|
|
|
|
|
|
|
|
|
## Beispiel
|
|
|
|
|
|
|
|
|
|
Folgenes Goal wird von `contradiction` bewiesen
|
|
|
|
|
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* Normalerweise wird `contradiction` gebraucht um einen Widerspruchsbeweis zu
|
|
|
|
|
schliessen, der mit `by_contra` eröffnet wurde.
|
|
|
|
|
* Ein Beweis von `False` representiert in Lean einen Widerspruch.
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Objekte:
|
|
|
|
|
(n m : ℕ)
|
|
|
|
|
(h : n = m)
|
|
|
|
|
(g : n ≠ m)
|
|
|
|
|
Goal
|
|
|
|
|
37 = 60
|
|
|
|
|
```
|
|
|
|
|
nach dem Motto \"ein Widerspruch beweist alles.\"
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
|
|
|
|
|
TacticDoc contrapose
|
|
|
|
|
"
|
|
|
|
|
`contrapose` ändert ein Goal der Form `A → B` zu `¬B → ¬A` und führt damit
|
|
|
|
|
eine Beweis durch Kontraposition.
|
|
|
|
|
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* `revert h` kann nützlich sein um eine Annahme als Implikationsprämisse zu schreiben bevor man
|
|
|
|
|
`contrapose` verwendet.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc fin_cases
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`fin_cases i` führt eine Fallunterscheidung wenn `i` ein endlicher Typ ist.
|
|
|
|
|
|
|
|
|
|
## Details
|
|
|
|
|
`fin_cases i` ist insbesondere nützlich für `(i : Fin n)`, zum Beispiel als Index in
|
|
|
|
|
endlich dimensionalen Vektorräumen.
|
|
|
|
|
|
|
|
|
|
In diesem Fall bewirkt `fin_cases i` dass man Komponentenweise arbeitet.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc funext
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`funext x` wird bei Gleichungen von Funktionen `f = g` gebraucht. Das Goal wird zu
|
|
|
|
|
`f x = g x`.
|
|
|
|
|
|
|
|
|
|
## Details
|
|
|
|
|
Nach dem Motto `f = g ↔ ∀ x, f x = g x` sind zwei Funktionen dann identisch, wenn sie
|
|
|
|
|
angewendet auf jedes Element identisch sind. `funext x` benützt dieses Argument.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc «have»
|
|
|
|
|
"
|
|
|
|
|
`have h : P` führt ein Zwischenresultat ein.
|
|
|
|
|
|
|
|
|
|
## Details
|
|
|
|
|
Anschliessend muss man zuerst dieses Zwischenresultat beweisen bevor man mit dem Beweis
|
|
|
|
|
weitermachen und das Zwischenresultat verwenden kann.
|
|
|
|
|
|
|
|
|
|
TacticDoc rw
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* `suffices h : P` funktioniert genau gleich, aussert das die beiden entstehenden Beweise
|
|
|
|
|
vertauscht sind.
|
|
|
|
|
* `let h : Prop := A ∧ B` ist verwandt mit `have`, mit Unterschied, dass man mit `let`
|
|
|
|
|
eine temporäre Definition einführt.
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
|
|
|
|
|
Wenn man eine Annahme `(h : X = Y)` hat, kann man mit
|
|
|
|
|
`rw [h]` alle `X` im Goal durch `Y` ersetzen.
|
|
|
|
|
TacticDoc induction
|
|
|
|
|
"
|
|
|
|
|
`induction n` führt einen Induktionsbeweis über `n`.
|
|
|
|
|
|
|
|
|
|
## Detail
|
|
|
|
|
- `rw [←h]` wendet `h` rückwärts an und ersetzt alle `Y` durch `X`.
|
|
|
|
|
- `rw [h, g, ←f]`: Man kann auch mehrere `rw` zusammenfassen.
|
|
|
|
|
- `rw [h] at h₂` ersetzt alle `X` in `h₂` zu `Y` (anstatt im Goal).
|
|
|
|
|
|
|
|
|
|
`rw` funktioniert gleichermassen mit Annahmen `(h : X = Y)` also auch
|
|
|
|
|
mit Theoremen/Lemmas der Form `X = Y`
|
|
|
|
|
Diese Taktik erstellt zwei Goals:
|
|
|
|
|
* Induktionsanfang, wo `n = 0` ersetzt wird.
|
|
|
|
|
* Induktionsschritt, in dem man die Induktionshypothese `n_ih` zur Verfügung hat.
|
|
|
|
|
|
|
|
|
|
Der volle Syntax mit Option zum umbenennen der Induktionshypothes und -variable ist
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
induction n with
|
|
|
|
|
| zero =>
|
|
|
|
|
sorry
|
|
|
|
|
| succ m m_ih =>
|
|
|
|
|
sorry
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
da dieser sich über mehrere Zeilen erstreckt wird er im Spiel nicht eingeführt.
|
|
|
|
|
|
|
|
|
|
## Hifreiche Resultate
|
|
|
|
|
|
|
|
|
|
* `Nat.succ_eq_add_one`: schreibt `n.succ = n + 1` um.
|
|
|
|
|
* `Nat.zero_eq`: schreibt `Nat.zero = 0` um.
|
|
|
|
|
|
|
|
|
|
Beide sind DefEq, aber manche Taktiken können nicht damit umgehen
|
|
|
|
|
|
|
|
|
|
* Siehe Definition `∑` für Hilfe mit Induktion über Summen.
|
|
|
|
|
* `rcases n` ist sehr ähnlich zu `induction n`. Der Unterschied ist, dass bei
|
|
|
|
|
`rcases` keine Induktionshypothese im Fall `n + 1` zur Verfügung steht.
|
|
|
|
|
|
|
|
|
|
## Beispiel
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
```
|
|
|
|
|
example (n : ℕ) : 4 ∣ 5^n + 7 := by
|
|
|
|
|
induction n
|
|
|
|
|
sorry -- Fall `n = 0`
|
|
|
|
|
sorry -- Fall `n + 1`
|
|
|
|
|
```
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc simp_rw
|
|
|
|
|
TacticDoc intro
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`intro x` wird für Goals der Form `A → B` oder `∀ x, P x` verwendet.
|
|
|
|
|
Dadurch wird die Implikationsprämisse (oder das Objekt `x`) den Annahmen hinzugefügt.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* `revert h` macht das Gegenteil von `intro`.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc by_cases
|
|
|
|
|
TacticDoc left
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
Wenn das Goal von der Form `A ∨ B` ist, enscheidet man mit `left` die linke Seite zu zeigen.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* `right` entscheidet sich für die linke Seite.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc apply
|
|
|
|
|
TacticDoc «let»
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`let x : ℕ := 5 ^ 2` führt eine neue temporäre Definition ein.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* `have x : ℕ := 5 ^ 2` führt ebenfalls eine neue natürliche Zahle `x` ein, aber
|
|
|
|
|
Lean vergisst sofort, wie die Zahl definiert war. D.h. `x = 25` wäre dann nicht
|
|
|
|
|
beweisbar. Mit `let x : ℕ := 5 ^ 2` ist `x = 25` durch `rfl` beweisbar.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc constructor
|
|
|
|
|
TacticDoc linarith
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`linarith` löst Systeme linearer (Un-)Gleichungen.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
## Detail
|
|
|
|
|
`linarith` kann lineare Gleichungen und Ungleichungen beweisen indem
|
|
|
|
|
es das Gegenteil vom Goal annimmt und versucht einen Widerspruch in den
|
|
|
|
|
Annahmen zu erzeugen (Widerspruchsbeweis). Es braucht ein `≤` definiert um
|
|
|
|
|
zu funktionieren.
|
|
|
|
|
|
|
|
|
|
## Beispiel
|
|
|
|
|
|
|
|
|
|
Folgendes kann `linarith` beweisen.
|
|
|
|
|
```
|
|
|
|
|
Objekte
|
|
|
|
|
x y : ℤ
|
|
|
|
|
h₁ : 5 * y ≤ 35 - 2 * x
|
|
|
|
|
h₂ : 2 * y ≤ x + 3
|
|
|
|
|
Goal
|
|
|
|
|
y ≤ 5
|
|
|
|
|
```
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc tauto
|
|
|
|
|
TacticDoc push_neg
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`push_neg` schreibt `¬∀ x, _` zu `∃ x, ¬ _` und `¬∃ x, _` zu `∀x, ¬ _` um.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
## Details
|
|
|
|
|
|
|
|
|
|
`psuh_neg` schiebt das `¬` soweit nach innen wie möglich.
|
|
|
|
|
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* Die beiden Lemmas heissen `not_forall` und `not_exists` und können mit `rw` einzeln angewendet
|
|
|
|
|
werden.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc rcases
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`rcases h` teilt eine Annahme `h` in ihre Einzelteile auf.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
"
|
|
|
|
|
## Details
|
|
|
|
|
Für Annahmen die Strukturen sind, wie z.B. `h : A ∧ B` (oder `∃x, P x`) kann man die
|
|
|
|
|
Einzelteile mit `rcases h with ⟨a, b⟩` (oder `rcases h with ⟨x, hx⟩`) benennen.
|
|
|
|
|
|
|
|
|
|
TacticDoc left
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
Für eine Annahme der Form `h : A ∨ B` kann man mit `rcases h with ha | hb` zwei Goals
|
|
|
|
|
erzeugen, einmal unter Annahme der linken Seite, einmal unter Annahme der Rechten.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
"
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
TacticDoc right
|
|
|
|
|
* Für `n : ℕ` hat `rcases n` einen ähnlichen Effekt wie `induction n` mit dem Unterschied,
|
|
|
|
|
dass im Fall `n + 1` keine Induktionshypothese zur Verfügung steht.
|
|
|
|
|
* In Lean gibt es auch die Taktik `cases`, die gleich funktioniert wie `rcases` aber
|
|
|
|
|
einen mehrzeiligen Syntax hat:
|
|
|
|
|
```
|
|
|
|
|
cases h with
|
|
|
|
|
| inl ha =>
|
|
|
|
|
sorry
|
|
|
|
|
| inr hb =>
|
|
|
|
|
sorry
|
|
|
|
|
```
|
|
|
|
|
Hier sind `inl`/`inr` die Namen der Fälle und `ha`/`hb` sind frei gewählte Namen für die
|
|
|
|
|
freien Variablen
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
TacticDoc revert
|
|
|
|
|
"
|
|
|
|
|
`revert h` fügt die Annahme `h` als Implikationsprämisse vorne ans Goal an.
|
|
|
|
|
|
|
|
|
|
TacticDoc simp
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
"
|
|
|
|
|
* `revert` ist das Gegenteil von `intro`.
|
|
|
|
|
* `revert` kann insbesondere nützlich sein, um anschliessend `contrapose` zu verwenden.
|
|
|
|
|
|
|
|
|
|
TacticDoc trivial
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
## Beispiel
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
"
|
|
|
|
|
```
|
|
|
|
|
Objekte
|
|
|
|
|
A P : Prop
|
|
|
|
|
h : P
|
|
|
|
|
Goal
|
|
|
|
|
A
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
TacticDoc contradiction
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
hier ändert `revert h` den Status zu
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
```
|
|
|
|
|
Objekte
|
|
|
|
|
A P : Prop
|
|
|
|
|
Goal
|
|
|
|
|
P → A
|
|
|
|
|
```
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc push_neg
|
|
|
|
|
TacticDoc rfl
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`rfl` beweist ein Goal der Form `X = X`.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
"
|
|
|
|
|
## Detail
|
|
|
|
|
|
|
|
|
|
`rfl` beweist jedes Goal `A = B` wenn `A` und `B` per Definition das gleiche sind (DefEq).
|
|
|
|
|
Andere Taktiken rufen `rfl` oft am Ende versteckt
|
|
|
|
|
automatisch auf um zu versuchen, den Beweis zu schliessen.
|
|
|
|
|
|
|
|
|
|
TacticDoc contrapose
|
|
|
|
|
|
|
|
|
|
## Beispiel
|
|
|
|
|
`rfl` kann folgende Goals beweisen:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Objekte
|
|
|
|
|
a b c : ℕ
|
|
|
|
|
Goal:
|
|
|
|
|
(a + b) * c = (a + b) * c
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Objekte
|
|
|
|
|
n : ℕ
|
|
|
|
|
Goal
|
|
|
|
|
1 + 1 = 2
|
|
|
|
|
```
|
|
|
|
|
denn Lean liest dies intern als `0.succ.succ = 0.succ.succ`.
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
TacticDoc right
|
|
|
|
|
"
|
|
|
|
|
Wenn das Goal von der Form `A ∨ B` ist, enscheidet man mit `right` die rechte Seite zu zeigen.
|
|
|
|
|
|
|
|
|
|
TacticDoc revert
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
* `left` entscheidet sich für die linke Seite.
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
TacticDoc ring
|
|
|
|
|
"
|
|
|
|
|
Löst Gleichungen mit den Operationen `+, -, *, ^`.
|
|
|
|
|
|
|
|
|
|
## Details
|
|
|
|
|
Insbesondere funktioniert `ring` in Ringen/Semiringen wie z.B. `ℕ, ℤ, ℚ, …`
|
|
|
|
|
(i.e. Typen `R` mit Instanzen `Ring R` oder `Semiring R`).
|
|
|
|
|
Die Taktik ist besonders auf kommutative Ringe (`CommRing R`) ausgelegt.
|
|
|
|
|
|
|
|
|
|
TacticDoc by_contra
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
* `ring` kann nicht wirklich mit Division (`/`) oder Inversen (`⁻¹`) umgehen. Dafür ist die
|
|
|
|
|
Taktik `field_simp` gedacht, und die typische Sequenz ist
|
|
|
|
|
```
|
|
|
|
|
field_simp
|
|
|
|
|
ring
|
|
|
|
|
```
|
|
|
|
|
* Wenn `ring` nicht abschliesst, sagt es man solle `ring_nf` verwenden. Normalerweise heisst
|
|
|
|
|
das aber, dass man was falsch gemacht hat und die Seiten der Gleichung noch nicht gleich sind.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc ring
|
|
|
|
|
TacticDoc rw
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
Wenn man eine Annahme `(h : X = Y)` hat, kann man mit
|
|
|
|
|
`rw [h]` alle `X` im Goal durch `Y` ersetzen.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
## Details
|
|
|
|
|
|
|
|
|
|
* `rw [←h]` wendet `h` rückwärts an und ersetzt alle `Y` durch `X`.
|
|
|
|
|
* `rw [h, g, ←f]`: Man kann auch mehrere `rw` zusammenfassen.
|
|
|
|
|
* `rw [h] at h₂` ersetzt alle `X` in `h₂` zu `Y` (anstatt im Goal).
|
|
|
|
|
|
|
|
|
|
`rw` funktioniert gleichermassen mit Annahmen `(h : X = Y)` also auch
|
|
|
|
|
mit Theoremen/Lemmas der Form `X = Y`
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc unfold
|
|
|
|
|
TacticDoc simp
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`simp` versucht alle Vereinfachungslemmas anzuwenden, die in der `mathlib` mit `@[simp]`
|
|
|
|
|
gekennzeichnet sind.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
## Details
|
|
|
|
|
|
|
|
|
|
* `simp?` zeigt welche Lemmas verwendet wurden.
|
|
|
|
|
* `simp [my_lemma]` fügt zudem `my_lemma` temporär zur Menge der `simp`-Lemmas hinzu.
|
|
|
|
|
* ein `simp`, das nicht am Ende des Beweis steht sollte durch eine entsprechende
|
|
|
|
|
`simp only [...]` Aussage ersetzt werden, um den Beweis stabiler zu machen.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc use
|
|
|
|
|
TacticDoc simp_rw
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`simp_rw [h₁, h₂, h₃]` versucht wie `rw` jedes Lemma der Reihe nach zu Umschreiben zu verwenden,
|
|
|
|
|
verwendet aber jedes Lemma so oft es kann.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
## Details
|
|
|
|
|
|
|
|
|
|
Es bestehen aber drei grosse Unterschiede zu `rw`:
|
|
|
|
|
|
|
|
|
|
* `simp_rw` wendet jedes Lemma so oft an wie es nur kann.
|
|
|
|
|
* `simp_rw` kann besser unter Quantifiern umschreiben als `rw`.
|
|
|
|
|
* `simp_rw` führt nach jedem Schritt ein `simp only []` aus und vereinfacht dadurch grundlegenste
|
|
|
|
|
Sachen.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc «suffices»
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
`suffices h : P` führt ein neues Zwischenresultat ein, aus dem das Goal direkt folgen soll.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
"
|
|
|
|
|
## Details
|
|
|
|
|
|
|
|
|
|
TacticDoc «have»
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
Der einzige Unterschied zu `have h : P` ist, dass die beiden resultierenden Goals vertauscht sind.
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
Mathematisch braucht man diese in ein bisschen unterschiedlichen Fällen:
|
|
|
|
|
|
|
|
|
|
* `suffices h : P` : \"Es genügt zu zeigen, dass …\". Als erstes folgt die Erklärung wieso
|
|
|
|
|
das genügt, danach muss man nur noch `P` beweisen.
|
|
|
|
|
* `have h : P` : Ein (kleines) Zwischenresultat. Als erstes folgt dann der Beweis dieses
|
|
|
|
|
Resultats, anschliessend setzt man den Beweis mit Hilfe des Zwischenresultats fort.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc «let»
|
|
|
|
|
TacticDoc tauto
|
|
|
|
|
"
|
|
|
|
|
## Beschreibung
|
|
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc induction_on
|
|
|
|
|
TacticDoc trivial
|
|
|
|
|
"
|
|
|
|
|
## Summary
|
|
|
|
|
`trivial` versucht durch Kombination von wenigen simplen Taktiken das Goal zu schliessen.
|
|
|
|
|
|
|
|
|
|
If `n : ℕ` is in our objects list, then `induction_on n`
|
|
|
|
|
attempts to prove the current goal by induction on `n`, with the inductive
|
|
|
|
|
assumption in the `succ` case being `ind_hyp`.
|
|
|
|
|
## Details
|
|
|
|
|
Die Taktiken, die verwendet werden sind:
|
|
|
|
|
|
|
|
|
|
### Example:
|
|
|
|
|
If your current goal is:
|
|
|
|
|
```
|
|
|
|
|
Objects
|
|
|
|
|
n : ℕ
|
|
|
|
|
Prove:
|
|
|
|
|
2 * n = n + n
|
|
|
|
|
```
|
|
|
|
|
* `assumption`
|
|
|
|
|
* `rfl`
|
|
|
|
|
* `contradiction`
|
|
|
|
|
* und noch 3 andere, die hier nicht behandelt werden
|
|
|
|
|
(`decide`, `apply True.intro`, `apply And.intro`).
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
then
|
|
|
|
|
TacticDoc unfold
|
|
|
|
|
"
|
|
|
|
|
`unfold myDef` öffnet eine Definition im Goal.
|
|
|
|
|
|
|
|
|
|
`induction_on n`
|
|
|
|
|
## Details
|
|
|
|
|
Bis auf DefEq (definitinal equality) ändert `unfold` nichts, manche Taktiken
|
|
|
|
|
(z.B. `push_neg`, `rw`) brauchen aber manchmal die Hilfe.
|
|
|
|
|
|
|
|
|
|
will give us two goals:
|
|
|
|
|
`unfold myDef at h` kann auch Definitionen in Annahmen öffnen
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Prove:
|
|
|
|
|
2 * 0 = 0 + 0
|
|
|
|
|
```
|
|
|
|
|
## Hilfreiche Resultate
|
|
|
|
|
|
|
|
|
|
and
|
|
|
|
|
```
|
|
|
|
|
Objects
|
|
|
|
|
n : ℕ,
|
|
|
|
|
Assumptions
|
|
|
|
|
ind_hyp : 2 * n = n + n
|
|
|
|
|
Prove:
|
|
|
|
|
2 * succ n = succ n + succ n
|
|
|
|
|
```
|
|
|
|
|
* `change P` ist eine andere Taktik, die das aktuelle Goal in einen DefEq-Ausdruck umschreibt.
|
|
|
|
|
Diese Taktik braucht man auch manchmal um zu hacken, wenn Lean Mühe hat etwas zu verstehen.
|
|
|
|
|
"
|
|
|
|
|
|
|
|
|
|
TacticDoc intro
|
|
|
|
|
"Useful to introduce stuff"
|
|
|
|
|
TacticDoc use
|
|
|
|
|
"
|
|
|
|
|
Wenn das Goal von der Form `∃x, P x` ist, kann man mit `use n` ein konkretes Element angeben
|
|
|
|
|
mit dem man das Goal beweisen möchte.
|
|
|
|
|
"
|
|
|
|
|