Files
AlgebraInLean/Book/Elements.lean
T
2026-08-13 06:38:24 +02:00

500 lines
19 KiB
Lean4
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import VersoManual
import Manual.Meta
-- Minimal-Imports statt `import Mathlib`, ermittelt mit
-- `#min_imports`.
import Mathlib.FieldTheory.IntermediateField.Adjoin.Basic
import Mathlib.RingTheory.Henselian
import Mathlib.RingTheory.RegularLocalRing.Defs
import Mathlib.RingTheory.SimpleRing.Principal
open Verso.Genre
open Verso.Genre.Manual.InlineLean
set_option pp.rawOnError true
set_option verso.docstring.allowMissing true
#doc (Manual) "Der Grad eines Elements" =>
%%%
htmlSplit := .never
tag := "elemente"
file := "elemente"
%%%
Dieses Kapitel übersetzt Satz 3.5.4 des Skripts nach Lean: Für
ein algebraisches Element $`a` stimmt der Grad $`[a:K]` des
Minimalpolynoms mit dem Grad $`[K(a):K]` der erzeugten
Körpererweiterung überein. Zusammen mit der Gradformel aus dem
letzten Kapitel ist das das Arbeitspferd für das nächste
Kapitel, die Transitivität der Algebraizität.
# Das Mathlib-Wörterbuch
* „$`a` ist algebraisch über $`K`“ heißt `IsAlgebraic K a`. Über
Körpern ist das gleichbedeutend damit, dass $`a` Nullstelle
eines _normierten_ Polynoms ist in Mathlib `IsIntegral K a`
(„$`a` ist ganz über $`K`“). Die Umrechnungen heißen
`IsAlgebraic.isIntegral` und `IsIntegral.isAlgebraic`; die
meisten Mathlib-Lemmata sind für `IsIntegral` formuliert.
* Das Minimalpolynom heißt `minpoly K a`; der Grad $`[a:K]` des
Skripts ist sein Grad `(minpoly K a).natDegree`. Für
transzendentes $`a` setzt Mathlib `minpoly K a = 0`, und das
Nullpolynom hat `natDegree` 0 wir treffen also wieder die
0-Konvention für $`\infty` aus dem letzten Kapitel.
* Der Zwischenkörper $`K(a)` heißt `Ka⟯`, kurz für
`IntermediateField.adjoin K {a}`. Die Klammer-Notation wird
durch `open IntermediateField` verfügbar; Vorsicht, `⟮…⟯` sind
eigene Unicode-Zeichen, keine gewöhnlichen Klammern.
* Die Erweiterung $`L/K` ist algebraisch jedes Element von
$`L` ist algebraisch über $`K` ist die Typklasse
`Algebra.IsAlgebraic K L`. Das elementweise Ausbuchstabieren
übernimmt `Algebra.IsAlgebraic.isAlgebraic`.
# Satz 3.5.4
Der Satz verbindet den Grad eines Elements mit dem Grad der von
ihm erzeugten Körpererweiterung:
> *Satz 3.5.4 (Grad von Körpererweiterungen und Grad von
Elementen).* Es sei $`L/K` eine Körpererweiterung und es sei
$`a L`. Dann gilt die Gleichheit $`[a:K] = [K(a):K]`.
Der Beweis im algebraischen Fall:
> _Beweis von Satz 3.5.4, falls $`a` algebraisch ist._ Setze
$`m := [a:K]` und schreibe das Minimalpolynom von $`a` über
$`K` als $`f(x) = λ_0 + λ_1 x + + λ_{m-1} x^{m-1} + x^m`.
Die Menge $`\{1, a, a^2, , a^{m-1}\} K(a)` ist linear
unabhängig über $`K` Betrachte deshalb den
$`m`-dimensionalen Untervektorraum
$`V := \langle 1, a, a^2, , a^{m-1} \rangle_K K(a)`.
Ich behaupte, dass $`V = K(a)` ist; damit ist dann
$`[K(a):K] = \dim_K V = m` und der Satz ist bewiesen.
Die Behauptung mit den beiden Beweisschritten
Abgeschlossenheit unter Multiplikation und Abgeschlossenheit
unter Inversenbildung ist in Mathlib die Konstruktion
`IntermediateField.adjoin.powerBasis`: Für ganzes $`a` baut sie
aus den Potenzen $`1, a, , a^{m-1}` eine Basis von `Ka⟯`, eine
sogenannte _Potenzbasis_. Wie bei der Gradformel bleibt für uns
das Abzählen der Basis und wie dort holen wir den vollständigen
Beweis am Ende des Kapitels nach.
```lean
open IntermediateField
theorem grad_element {K L : Type*} [Field K] [Field L]
[Algebra K L] {a : L} (ha : IsIntegral K a) :
Module.finrank K Ka = (minpoly K a).natDegree := by
-- „Betrachte deshalb den m-dimensionalen Untervektorraum
-- V := ⟨1, a, a², …, a^{m-1}⟩ ⊆ K(a). Ich behaupte,
-- dass V = K(a) ist …“ — die Potenzbasis von K⟮a⟯:
let pb := IntermediateField.adjoin.powerBasis ha
-- „… damit ist dann [K(a):K] = dim_K V = m und der Satz
-- ist bewiesen.“
rw [Module.finrank_eq_card_basis pb.basis,
Fintype.card_fin]
rfl
```
Den transzendenten Fall $`[a:K] = = [K(a):K]` behandelt
das Skript mit den unendlichen Potenzen $`1, a, a^2, …`; in
Mathlibs 0-Konvention steht auf beiden Seiten schlicht 0. Als
fertiges Zitat heißt unser Satz übrigens
`IntermediateField.adjoin.finrank`.
# Übungsaufgabe
Das erste Korollar des Skripts zu Satz 3.5.4:
> Es sei $`L/K` eine Körpererweiterung und es sei $`a L`.
Falls $`[a:K] < ∞` ist, dann ist $`K(a)` algebraisch
über $`K`.
Die beiden Zutaten kennt Mathlib als
`IntermediateField.adjoin.finiteDimensional` (der Grad ist
endlich) und `Algebra.IsAlgebraic.of_finite` (endliche
Erweiterungen sind algebraisch). Beachten Sie, dass die
Endlichkeit mit `have := …` in den Kontext geholt werden muss,
damit die Instanzsuche sie sieht. Öffnen Sie
`AlgebraInLean/Elements.lean` und ersetzen Sie das `sorry`
durch einen Beweis.
```lean
theorem einfach_algebraisch {K L : Type*} [Field K]
[Field L] [Algebra K L] {a : L}
(ha : IsIntegral K a) :
Algebra.IsAlgebraic K Ka := by
sorry
```
# Der vollständige Beweis
Oben haben wir die eigentliche Arbeit die Potenzen bilden eine
Basis von $`K(a)` bei `IntermediateField.adjoin.powerBasis`
eingekauft. Jetzt führen wir den Skript-Beweis Satz für Satz
selbst aus. Er ist deutlich länger als der vollständige Beweis
der Gradformel, denn das Skript zeigt hier wirklich etwas
Substantielles: dass ein endlichdimensionaler Untervektorraum,
der unter Multiplikation abgeschlossen ist, automatisch auch
Inverse enthält.
Die Hauptfigur ist der Untervektorraum aus dem Skript:
> Betrachte deshalb den $`m`-dimensionalen Untervektorraum
$`V := \langle 1, a, a^2, , a^{m-1} \rangle_K K(a)`.
```lean
open Polynomial
variable {K L : Type*} [Field K] [Field L] [Algebra K L]
-- Der Untervektorraum V = ⟨1, a, …, a^{m-1}⟩ des Skripts.
noncomputable def potenzraum (K : Type*) {L : Type*}
[Field K] [Field L] [Algebra K L] (a : L) :
Submodule K L :=
Submodule.span K (Set.range
fun i : Fin (minpoly K a).natDegree => a ^ (i : ))
```
Ein Argument benutzt das Skript zweimal einmal für $`a`, später
noch einmal für ein Element $`y V`:
> Falls nicht, dann gäbe es eine Zahl $`m ` und Elemente
$`λ_0, , λ_m K`, die nicht alle gleich Null sind, sodass
$`0 = \sum_{i} λ_i \cdot a^i` ist. Dann wäre $`a` aber eine
Nullstelle des Polynoms $`f(x) = \sum_i λ_i \cdot x^i K[x]`,
welches nicht das Nullpolynom ist.
Wir formulieren es deshalb als eigenes Hilfslemma: Eine
nichttriviale lineare Relation unter den Potenzen liefert ein
Polynom.
```lean
theorem polynom_aus_relation {k : } (y : L) (μ : Fin k K)
(hrel : i, μ i y ^ (i : ) = 0) (i₀ : Fin k)
( : μ i₀ 0) :
g : K[X],
g 0 g.degree < (k : ) aeval y g = 0 := by
-- Das Polynom g = ∑ μᵢ·xⁱ …
refine ⟨∑ i : Fin k, C (μ i) * X ^ (i : ), ?_, ?_, ?_⟩
-- „… welches nicht das Nullpolynom ist“: sein i₀-ter
-- Koeffizient ist μᵢ₀ ≠ 0.
· intro h0
apply
have hc := congrArg (fun g => coeff g (i₀ : )) h0
simpa [finsetSum_coeff, coeff_C_mul, coeff_X_pow,
Fin.val_inj] using hc
-- … hat Grad < k …
· refine lt_of_le_of_lt (degree_sum_le _ _) ?_
rw [Finset.sup_lt_iff
(by exact_mod_cast WithBot.bot_lt_coe k)]
intro i _
exact lt_of_le_of_lt (degree_C_mul_X_pow_le _ _)
(by exact_mod_cast i.isLt)
-- … und „y wäre eine Nullstelle des Polynoms“.
· rw [map_sum]
simp_rw [map_mul, aeval_C, map_pow, aeval_X,
Algebra.smul_def]
exact hrel
```
Damit folgt die lineare Unabhängigkeit wie im Skript:
> Die Menge $`\{1, a, a^2, , a^{m-1}\} K(a)` ist linear
unabhängig über $`K`: Jede nicht-triviale Linearkombination
der Null lieferte nämlich ein Polynom vom Grad kleiner $`m`,
welches nicht das Nullpolynom ist und $`a` als Nullstelle
hat im Widerspruch zur Minimalität des Grades des
Minimalpolynoms.
Die Minimalität des Grades heißt in Mathlib
`minpoly.degree_le_of_ne_zero`.
```lean
theorem potenzen_unabhaengig {a : L} (ha : IsIntegral K a) :
LinearIndependent K
(fun i : Fin (minpoly K a).natDegree =>
a ^ (i : )) := by
rw [Fintype.linearIndependent_iff]
intro μ hrel i₀
by_contra
-- „Jede nicht-triviale Linearkombination der Null
-- lieferte ein Polynom vom Grad kleiner m … mit a als
-- Nullstelle“
obtain g, hg0, hdeg, hroot :=
polynom_aus_relation a μ hrel i₀
-- „im Widerspruch zur Minimalität des Grades des
-- Minimalpolynoms.“
have hle := minpoly.degree_le_of_ne_zero K a hg0 hroot
rw [degree_eq_natDegree (minpoly.ne_zero ha)] at hle
exact absurd (hle.trans_lt hdeg) (lt_irrefl _)
```
Nun der erste Schritt des Skripts:
> _Schritt 1: Abgeschlossenheit unter Multiplikation._ Weil
$`a` eine Nullstelle des Minimalpolynoms $`f` ist, gilt die
Gleichung $`a^m = -\sum_{i=0}^{m-1} λ_i \cdot a^i V`.
Durch wiederholte Anwendung dieser Gleichung folgt induktiv,
dass $`a^n V` ist, für alle Zahlen $`n `. Jedes Produkt
von Elementen aus $`V` ist eine $`K`-Linearkombination von
Potenzen von $`a`, also gilt für alle $`v_1, v_2 V`, dass
$`v_1 \cdot v_2 V` ist.
```lean
-- „Weil a eine Nullstelle des Minimalpolynoms f ist, gilt
-- die Gleichung a^m = -∑ λᵢ·aⁱ.“
theorem hoechste_potenz {a : L} (ha : IsIntegral K a) :
a ^ (minpoly K a).natDegree =
-∑ i Finset.range (minpoly K a).natDegree,
(minpoly K a).coeff i a ^ i := by
have h := minpoly.aeval K a
rw [aeval_eq_sum_range, Finset.sum_range_succ,
(minpoly.monic ha).coeff_natDegree, one_smul] at h
exact eq_neg_of_add_eq_zero_right h
-- „Durch wiederholte Anwendung dieser Gleichung folgt
-- induktiv, dass aⁿ ∈ V ist, für alle Zahlen n ∈ .“
theorem potenz_mem {a : L} (ha : IsIntegral K a) (n : ) :
a ^ n potenzraum K a := by
induction n using Nat.strong_induction_on with
| _ n IH =>
by_cases hn : n < (minpoly K a).natDegree
· exact Submodule.subset_span ⟨⟨n, hn, rfl
· rw [not_lt] at hn
have hm0 : 0 < (minpoly K a).natDegree :=
minpoly.natDegree_pos ha
have hsplit : a ^ n =
a ^ (n - (minpoly K a).natDegree)
* a ^ (minpoly K a).natDegree := by
rw [ pow_add]
congr 1
omega
rw [hsplit, hoechste_potenz ha, mul_neg,
Finset.mul_sum]
refine Submodule.neg_mem _
(Submodule.sum_mem _ fun i hi => ?_)
rw [mul_smul_comm, pow_add]
refine Submodule.smul_mem _ _ (IH _ ?_)
have := Finset.mem_range.mp hi
omega
-- „Jedes Produkt von Elementen aus V ist eine
-- K-Linearkombination von Potenzen von a, also gilt für
-- alle v₁, v₂ ∈ V, dass v₁·v₂ ∈ V ist.“
theorem produkt_mem {a : L} (ha : IsIntegral K a) {x y : L}
(hx : x potenzraum K a) (hy : y potenzraum K a) :
x * y potenzraum K a := by
induction hx, hy using Submodule.span_induction₂ with
| mem_mem u v hu hv =>
obtain i, rfl := hu
obtain j, rfl := hv
simpa [pow_add] using potenz_mem ha ((i : ) + (j : ))
| zero_left v hv => simp
| zero_right u hu => simp
| add_left u v w _ _ hw h1 h2 =>
rw [add_mul]
exact Submodule.add_mem _ h1 h2
| add_right u v w hu _ _ h1 h2 =>
rw [mul_add]
exact Submodule.add_mem _ h1 h2
| smul_left r u v _ _ h =>
rw [smul_mul_assoc]
exact Submodule.smul_mem _ _ h
| smul_right r u v _ _ h =>
rw [mul_smul_comm]
exact Submodule.smul_mem _ _ h
```
Das Jedes Produkt ist eine $`K`-Linearkombination erledigt
`Submodule.span_induction₂`: Es genügt, die Behauptung für die
erzeugenden Potenzen zu prüfen (der Fall `mem_mem`, dort ist
$`a^i \cdot a^j = a^{i+j}`); Summen und Vielfache vererben sich.
Der zweite Schritt ist das Herzstück:
> _Schritt 2: Abgeschlossenheit unter Inversenbildung._ Es sei
$`y V` mit $`y 0` gegeben. Weil $`V` abgeschlossen unter
der Multiplikation ist, liegen alle Potenzen
$`1, y, y^2, , y^m` in $`V`. Das sind $`m+1` Elemente in
einem Vektorraum der Dimension $`m`, also sind diese Elemente
linear abhängig über $`K`. Insbesondere ist $`y` algebraisch
über $`K`. Es sei $`g(x) = c_0 + c_1 x + + x^n` das
Minimalpolynom von $`y` über $`K`. Dann ist $`c_0 0`:
Andernfalls könnte ich nämlich in $`g` einmal $`x`
ausklammern, also $`g = x \cdot h` schreiben. Weil $`K(a)`
ein Körper und $`y 0` ist, folgte aus
$`0 = g(y) = y \cdot h(y)` schon $`h(y) = 0` im Widerspruch
zur Minimalität des Grades von $`g`. Aus der Gleichung
$`0 = g(y) = y \cdot (y^{n-1} + c_{n-1} y^{n-2} + + c_1) + c_0`
folgt jetzt $`1/y = (y^{n-1} + + c_1)/(-c_0) V`, denn der
Zähler ist eine $`K`-Linearkombination von Potenzen von $`y`,
liegt also in $`V`, und der Nenner $`-c_0` liegt in $`K`.
Das Zählargument „$`m+1` Elemente in Dimension $`m`“ ist
`LinearIndependent.fintype_card_le_finrank`; die Dimension von
$`V` kennen wir aus der linearen Unabhängigkeit
(`finrank_span_eq_card`).
```lean
theorem invers_mem {a : L} (ha : IsIntegral K a) {y : L}
(hy : y potenzraum K a) (hy0 : y 0) :
y⁻¹ potenzraum K a := by
-- „Weil V abgeschlossen unter der Multiplikation ist,
-- liegen alle Potenzen 1, y, y², … in V.“
have hyn : j : , y ^ j potenzraum K a := by
intro j
induction j with
| zero => simpa using potenz_mem ha 0
| succ j IH =>
rw [pow_succ]
exact produkt_mem ha IH hy
-- „Das sind m+1 Elemente in einem Vektorraum der
-- Dimension m, also sind diese Elemente linear abhängig
-- über K.“
have hfin : FiniteDimensional K (potenzraum K a) := by
unfold potenzraum
exact FiniteDimensional.span_of_finite K
(Set.finite_range _)
have hdim : Module.finrank K (potenzraum K a)
= (minpoly K a).natDegree := by
unfold potenzraum
rw [finrank_span_eq_card (potenzen_unabhaengig ha),
Fintype.card_fin]
have habh : ¬ LinearIndependent K
(fun i : Fin ((minpoly K a).natDegree + 1) =>
(y ^ (i : ), hyn i : potenzraum K a)) := by
intro h
have hcard := h.fintype_card_le_finrank
rw [Fintype.card_fin, hdim] at hcard
omega
-- „Insbesondere ist y algebraisch über K.“
rw [Fintype.not_linearIndependent_iff] at habh
obtain μ, hrel, i₀, hμ0 := habh
have hrelL : i : Fin ((minpoly K a).natDegree + 1),
μ i y ^ (i : ) = 0 := by
simpa using congrArg
(Submodule.subtype (potenzraum K a)) hrel
obtain g, hg0, _, hgroot :=
polynom_aus_relation y μ hrelL i₀ hμ0
have hyint : IsIntegral K y :=
(IsAlgebraic.isIntegral g, hg0, hgroot)
-- „Es sei g das Minimalpolynom von y über K. Dann ist
-- c₀ ≠ 0: Andernfalls könnte ich nämlich in g einmal x
-- ausklammern, also g = x·h schreiben. Weil K(a) ein
-- Körper und y ≠ 0 ist, folgte aus 0 = g(y) = y·h(y)
-- schon h(y) = 0 — im Widerspruch zur Minimalität des
-- Grades von g.“
have hc0 : (minpoly K y).coeff 0 0 := by
intro h0
obtain h, hh := X_dvd_iff.mpr h0
have hhy : aeval y h = 0 := by
have haev := minpoly.aeval K y
rw [hh, map_mul, aeval_X] at haev
rcases mul_eq_zero.mp haev with h1 | h1
· exact absurd h1 hy0
· exact h1
have hhne : h 0 := by
rintro rfl
rw [mul_zero] at hh
exact minpoly.ne_zero hyint hh
have hle := minpoly.degree_le_of_ne_zero K y hhne hhy
rw [hh, mul_comm] at hle
exact absurd hle
(not_le.mpr (degree_lt_degree_mul_X hhne))
-- „Aus der Gleichung 0 = g(y) = y·(y^{n-1} + ⋯ + c₁) + c₀
-- folgt jetzt 1/y = (y^{n-1} + ⋯ + c₁)/(-c₀) ∈ V …“
have expand := minpoly.aeval K y
rw [aeval_eq_sum_range, Finset.sum_range_succ'] at expand
simp_rw [pow_succ, smul_mul_assoc, pow_zero] at expand
rw [ Finset.sum_mul] at expand
have hwy : ( i Finset.range (minpoly K y).natDegree,
(minpoly K y).coeff (i + 1) y ^ i) * y
= -((minpoly K y).coeff 0 1) :=
eq_neg_of_add_eq_zero_left expand
have hone : y * ((-(minpoly K y).coeff 0)⁻¹
i Finset.range (minpoly K y).natDegree,
(minpoly K y).coeff (i + 1) y ^ i) = 1 := by
rw [mul_smul_comm, mul_comm y, hwy, neg_smul,
smul_smul, inv_mul_cancel₀ (neg_ne_zero.mpr hc0),
one_smul]
rw [inv_eq_of_mul_eq_one_right hone]
-- „… denn der Zähler ist eine K-Linearkombination von
-- Potenzen von y, liegt also in V, und der Nenner -c₀
-- liegt in K.“
exact Submodule.smul_mem _ _
(Submodule.sum_mem _ fun i _ =>
Submodule.smul_mem _ _ (hyn i))
```
Bleibt der Zusammenbau:
> Ich behaupte, dass $`V = K(a)` ist; damit ist dann
$`[K(a):K] = \dim_K V = m` und der Satz ist bewiesen. Um die
Behauptung zu zeigen, genügt es zu zeigen, dass $`V` ein
Unterkörper von $`K(a)` ist. Denn $`V` enthält $`K` und das
Element $`a`, und $`K(a)` ist per Definition der kleinste
Unterkörper, der $`K` und $`a` enthält. Weil $`V` ein
Untervektorraum ist, ist $`V` abgeschlossen unter der
Addition.
Das Bündeln von $`V` mit den bewiesenen Abgeschlossenheiten zu
einem Unterkörper ist in Lean das Ausfüllen der Strukturfelder
von `Subalgebra` und `IntermediateField`; das per Definition
der kleinste Unterkörper ist `adjoin_simple_le_iff`.
```lean
theorem grad_element_vollstaendig {a : L}
(ha : IsIntegral K a) :
Module.finrank K Ka = (minpoly K a).natDegree := by
-- „… genügt es zu zeigen, dass V ein Unterkörper von K(a)
-- ist.“ — wir bündeln V zu einem Zwischenkörper F:
let A : Subalgebra K L :=
{ carrier := potenzraum K a
mul_mem' := fun hx hy => produkt_mem ha hx hy
one_mem' := by simpa using potenz_mem ha 0
add_mem' := fun hx hy => Submodule.add_mem _ hx hy
zero_mem' := Submodule.zero_mem _
algebraMap_mem' := fun c => by
rw [Algebra.algebraMap_eq_smul_one]
exact Submodule.smul_mem _ _
(by simpa using potenz_mem ha 0) }
let F : IntermediateField K L :=
{ A with
inv_mem' := fun x hx => by
by_cases hx0 : x = 0
· rw [hx0, inv_zero]
exact Submodule.zero_mem _
· exact invers_mem ha hx hx0 }
-- „Denn V enthält K und das Element a, und K(a) ist per
-- Definition der kleinste Unterkörper, der K und a
-- enthält.“
have haF : a F := by
show a potenzraum K a
simpa using potenz_mem ha 1
have oben : Ka F := adjoin_simple_le_iff.mpr haF
have unten : F Ka := by
intro x hx
have hVsub : potenzraum K a
Subalgebra.toSubmodule Ka⟯.toSubalgebra := by
unfold potenzraum
rw [Submodule.span_le]
rintro _ i, rfl
exact pow_mem (mem_adjoin_simple_self K a) _
exact hVsub hx
have hFK : F = Ka := le_antisymm unten oben
-- „… damit ist dann [K(a):K] = dim_K V = m und der Satz
-- ist bewiesen.“
rw [ hFK]
have h1 : Module.finrank K F
= Module.finrank K (potenzraum K a) :=
(Subalgebra.finrank_toSubmodule A).symm
rw [h1]
unfold potenzraum
rw [finrank_span_eq_card (potenzen_unabhaengig ha),
Fintype.card_fin]
```