Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 253b120

Browse files
tb65536pglutz
andcommitted
feat(field_theory): prove primitive element theorem (#4153)
Proof of the primitive element theorem. The main proof is in `field_theory/primitive_element.lean`. Some lemmas we used have been added to other files. We have also changed the notation for adjoining an element to a field to be easier to use. Co-authored-by: Patrick Lutz <pglutz@berkeley.edu>
1 parent d0b5947 commit 253b120

File tree

11 files changed

+601
-26
lines changed

11 files changed

+601
-26
lines changed

src/data/polynomial/field_division.lean

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,32 @@ gcd.induction p q (λ x, by simp_rw [map_zero, euclidean_domain.gcd_zero_left])
203203
by rw [gcd_val, ← map_mod, ih, ← gcd_val]
204204
end
205205

206+
lemma eval₂_gcd_eq_zero [comm_semiring k] {ϕ : R →+* k} {f g : polynomial R} {α : k}
207+
(hf : f.eval₂ ϕ α = 0) (hg : g.eval₂ ϕ α = 0) : (euclidean_domain.gcd f g).eval₂ ϕ α = 0 :=
208+
by rw [euclidean_domain.gcd_eq_gcd_ab f g, polynomial.eval₂_add, polynomial.eval₂_mul,
209+
polynomial.eval₂_mul, hf, hg, zero_mul, zero_mul, zero_add]
210+
211+
lemma eval_gcd_eq_zero {f g : polynomial R} {α : R} (hf : f.eval α = 0) (hg : g.eval α = 0) :
212+
(euclidean_domain.gcd f g).eval α = 0 := eval₂_gcd_eq_zero hf hg
213+
214+
lemma root_left_of_root_gcd [comm_semiring k] {ϕ : R →+* k} {f g : polynomial R} {α : k}
215+
(hα : (euclidean_domain.gcd f g).eval₂ ϕ α = 0) : f.eval₂ ϕ α = 0 :=
216+
by { cases euclidean_domain.gcd_dvd_left f g with p hp,
217+
rw [hp, polynomial.eval₂_mul, hα, zero_mul] }
218+
219+
lemma root_right_of_root_gcd [comm_semiring k] {ϕ : R →+* k} {f g : polynomial R} {α : k}
220+
(hα : (euclidean_domain.gcd f g).eval₂ ϕ α = 0) : g.eval₂ ϕ α = 0 :=
221+
by { cases euclidean_domain.gcd_dvd_right f g with p hp,
222+
rw [hp, polynomial.eval₂_mul, hα, zero_mul] }
223+
224+
lemma root_gcd_iff_root_left_right [comm_semiring k] {ϕ : R →+* k} {f g : polynomial R} {α : k} :
225+
(euclidean_domain.gcd f g).eval₂ ϕ α = 0 ↔ (f.eval₂ ϕ α = 0) ∧ (g.eval₂ ϕ α = 0) :=
226+
⟨λ h, ⟨root_left_of_root_gcd h, root_right_of_root_gcd h⟩, λ h, eval₂_gcd_eq_zero h.1 h.2
227+
228+
lemma is_root_gcd_iff_is_root_left_right {f g : polynomial R} {α : R} :
229+
(euclidean_domain.gcd f g).is_root α ↔ f.is_root α ∧ g.is_root α :=
230+
root_gcd_iff_root_left_right
231+
206232
theorem is_coprime_map [field k] (f : R →+* k) :
207233
is_coprime (p.map f) (q.map f) ↔ is_coprime p q :=
208234
by rw [← gcd_is_unit_iff, ← gcd_is_unit_iff, gcd_map, is_unit_map]
@@ -214,6 +240,14 @@ by simp [polynomial.ext_iff, f.map_eq_zero, coeff_map]
214240
lemma map_ne_zero [field k] {f : R →+* k} (hp : p ≠ 0) : p.map f ≠ 0 :=
215241
mt (map_eq_zero f).1 hp
216242

243+
lemma mem_roots_map [field k] {f : R →+* k} {x : k} (hp : p ≠ 0) :
244+
x ∈ (p.map f).roots ↔ p.eval₂ f x = 0 :=
245+
begin
246+
rw mem_roots (show p.map f ≠ 0, by exact map_ne_zero hp),
247+
dsimp only [is_root],
248+
rw polynomial.eval_map,
249+
end
250+
217251
lemma exists_root_of_degree_eq_one (h : degree p = 1) : ∃ x, is_root p x :=
218252
⟨-(p.coeff 0 / p.coeff 1),
219253
have p.coeff 10,

src/deprecated/subfield.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Andreas Swerdlow
55
-/
66
import deprecated.subring
7+
import algebra.group_with_zero_power
78

89
variables {F : Type*} [field F] (S : set F)
910

@@ -18,6 +19,14 @@ instance is_subfield.field [is_subfield S] : field S :=
1819
inv_zero := subtype.ext_iff_val.2 inv_zero,
1920
..show comm_ring S, by apply_instance }
2021

22+
lemma is_subfield.pow_mem {a : F} {n : ℤ} {s : set F} [is_subfield s] (h : a ∈ s) :
23+
a ^ n ∈ s :=
24+
begin
25+
cases n,
26+
{ exact is_submonoid.pow_mem h },
27+
{ exact is_subfield.inv_mem (is_submonoid.pow_mem h) },
28+
end
29+
2130
instance univ.is_subfield : is_subfield (@set.univ F) :=
2231
{ inv_mem := by intros; trivial }
2332

src/field_theory/adjoin.lean

Lines changed: 122 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Authors: Thomas Browning and Patrick Lutz
55
-/
66

77
import deprecated.subfield
8-
import linear_algebra.finite_dimensional
8+
import field_theory.tower
99

1010
/-!
1111
# Adjoining Elements to Fields
@@ -16,21 +16,21 @@ For example, `algebra.adjoin K {x}` might not include `x⁻¹`.
1616
1717
## Main results
1818
19-
(This is just a start; we've got more to add, including a proof of the Primitive Element Theorem.)
20-
2119
- `adjoin_adjoin_left`: adjoining S and then T is the same as adjoining S ∪ T.
20+
- `bot_eq_top_of_dim_adjoin_eq_one`: if `F⟮x⟯` has dimension `1` over `F` for every `x`
21+
in `E` then `F = E`
2222
2323
## Notation
2424
2525
- `F⟮α⟯`: adjoin a single element `α` to `F`.
2626
-/
2727

2828
namespace field
29+
30+
section adjoin_def
2931
variables (F : Type*) [field F] {E : Type*} [field E] [algebra F E] (S : set E)
3032

31-
/--
32-
`adjoin F S` extends a field `F` by adjoining a set `S ⊆ E`.
33-
-/
33+
/-- `adjoin F S` extends a field `F` by adjoining a set `S ⊆ E`. -/
3434
def adjoin : subalgebra F E :=
3535
{ carrier := field.closure (set.range (algebra_map F E) ∪ S),
3636
one_mem' := is_submonoid.one_mem,
@@ -39,6 +39,9 @@ def adjoin : subalgebra F E :=
3939
add_mem' := λ x y, is_add_submonoid.add_mem,
4040
algebra_map_mem' := λ x, field.mem_closure (or.inl (set.mem_range.mpr ⟨x,rfl⟩)) }
4141

42+
lemma adjoin_eq_range_algebra_map_adjoin :
43+
(adjoin F S : set E) = set.range (algebra_map (adjoin F S) E) := (subtype.range_coe).symm
44+
4245
lemma adjoin.algebra_map_mem (x : F) : algebra_map F E x ∈ adjoin F S :=
4346
field.mem_closure (or.inl (set.mem_range_self x))
4447

@@ -64,7 +67,8 @@ instance adjoin.set_coe : has_coe_t S (adjoin F S) :=
6467
{coe := λ x, ⟨x,subset_adjoin F S (subtype.mem x)⟩}
6568

6669
lemma adjoin.mono (T : set E) (h : S ⊆ T) : (adjoin F S : set E) ⊆ adjoin F T :=
67-
field.closure_mono (set.union_subset (set.subset_union_left _ _) (set.subset_union_of_subset_right h _))
70+
field.closure_mono (set.union_subset (set.subset_union_left _ _)
71+
(set.subset_union_of_subset_right h _))
6872

6973
instance adjoin.is_subfield : is_subfield (adjoin F S : set E) := field.closure.is_subfield
7074

@@ -116,33 +120,127 @@ begin
116120
(subset_adjoin _ _) },
117121
end
118122

119-
variables (α : E)
123+
/-- `F[S][T] = F[T][S]` -/
124+
lemma adjoin_adjoin_comm (T : set E) :
125+
(adjoin (adjoin F S : set E) T : set E) = (adjoin (adjoin F T : set E) S : set E) :=
126+
by rw [adjoin_adjoin_left, adjoin_adjoin_left, set.union_comm]
120127

121-
notation K`⟮`:std.prec.max_plus l:(foldr `, ` (h t, set.insert h t) ∅) `⟯` := adjoin K l
128+
/--
129+
Variation on `set.insert` to enable good notation for adjoining elements to fields.
130+
Used to preferentially use `singleton` rather than `insert` when adjoining one element.
131+
-/
132+
--this definition of notation is courtesy of Kyle Miller on zulip
133+
class insert {α : Type*} (s : set α) :=
134+
(insert : α → set α)
122135

123-
--unfortunately this lemma is not definitionally true
124-
lemma adjoin_singleton : F⟮α⟯ = adjoin F {α} :=
125-
begin
126-
change adjoin F (insert α ∅) = adjoin F {α},
127-
rw insert_emptyc_eq α,
128-
exact set.is_lawful_singleton,
129-
end
136+
@[priority 1000]
137+
instance insert_empty {α : Type*} : insert (∅ : set α) :=
138+
{ insert := λ x, @singleton _ _ set.has_singleton x }
139+
140+
@[priority 900]
141+
instance insert_nonempty {α : Type*} (s : set α) : insert s :=
142+
{ insert := λ x, set.insert x s }
143+
144+
notation K`⟮`:std.prec.max_plus l:(foldr `, ` (h t, insert.insert t h) ∅) `⟯` := adjoin K l
145+
146+
section adjoin_simple
147+
variables (α : E)
130148

131149
lemma mem_adjoin_simple_self : α ∈ F⟮α⟯ :=
132-
begin
133-
rw adjoin_singleton,
134-
exact subset_adjoin F {α} (set.mem_singleton α),
135-
end
150+
subset_adjoin F {α} (set.mem_singleton α)
136151

137152
/-- generator of `F⟮α⟯` -/
138153
def adjoin_simple.gen : F⟮α⟯ := ⟨α, mem_adjoin_simple_self F α⟩
139154

140-
lemma adjoin_simple.algebra_map_gen : algebra_map F⟮α⟯ E (adjoin_simple.gen F α) = α := rfl
155+
@[simp] lemma adjoin_simple.algebra_map_gen : algebra_map F⟮α⟯ E (adjoin_simple.gen F α) = α := rfl
156+
157+
lemma adjoin_simple_adjoin_simple (β : E) : (F⟮α⟯⟮β⟯ : set E) = (F⟮α, β⟯ : set E) :=
158+
adjoin_adjoin_left _ _ _
159+
160+
lemma adjoin_simple_comm (β : E) : (F⟮α⟯⟮β⟯ : set E) = (F⟮β⟯⟮α⟯ : set E) :=
161+
adjoin_adjoin_comm _ _ _
162+
163+
end adjoin_simple
164+
end adjoin_def
165+
166+
section adjoin_subalgebra_lattice
167+
variables {F : Type*} [field F] {E : Type*} [field E] [algebra F E] {α : E} {S : set E}
168+
169+
lemma adjoin_eq_bot (h : S ⊆ (⊥ : subalgebra F E)) : adjoin F S = ⊥ :=
170+
begin
171+
rw eq_bot_iff,
172+
intros x,
173+
rw [subalgebra.mem_coe, subalgebra.mem_coe, algebra.mem_bot],
174+
rw algebra.coe_bot at h,
175+
apply adjoin_subset_subfield _ _ set.subset.rfl h,
176+
end
177+
178+
lemma adjoin_simple_eq_bot (hα : α ∈ ((⊥ : subalgebra F E) : set E)) : F⟮α⟯ = (⊥ : subalgebra F E) :=
179+
adjoin_eq_bot (set.singleton_subset_iff.mpr hα)
180+
181+
lemma adjoin_zero : F⟮0⟯ = (⊥ : subalgebra F E) :=
182+
adjoin_simple_eq_bot (algebra.mem_bot.mpr (is_add_submonoid.zero_mem))
183+
184+
lemma adjoin_one : F⟮1⟯ = (⊥ : subalgebra F E) :=
185+
adjoin_simple_eq_bot (algebra.mem_bot.mpr (is_submonoid.one_mem))
186+
187+
lemma sub_bot_of_adjoin_sub_bot (h : adjoin F S = ⊥) : S ⊆ (⊥ : subalgebra F E) :=
188+
calc S ⊆ adjoin F S : subset_adjoin _ _
189+
... = (⊥ : subalgebra F E) : congr_arg coe h
190+
191+
lemma mem_bot_of_adjoin_simple_sub_bot (h : F⟮α⟯ = ⊥) : α ∈ ((⊥ : subalgebra F E) : set E) :=
192+
set.singleton_subset_iff.mp (sub_bot_of_adjoin_sub_bot h)
193+
194+
lemma adjoin_eq_bot_iff : S ⊆ (⊥ : subalgebra F E) ↔ adjoin F S = ⊥ :=
195+
⟨adjoin_eq_bot, sub_bot_of_adjoin_sub_bot⟩
196+
197+
lemma adjoin_simple_eq_bot_iff : α ∈ (⊥ : subalgebra F E) ↔ F⟮α⟯ = ⊥ :=
198+
⟨adjoin_simple_eq_bot, mem_bot_of_adjoin_simple_sub_bot⟩
199+
200+
section adjoin_dim
201+
open finite_dimensional vector_space
202+
203+
lemma sub_bot_of_adjoin_dim_eq_one (h : dim F (adjoin F S) = 1) : S ⊆ (⊥ : subalgebra F E) :=
204+
by rwa [adjoin_eq_bot_iff, ← subalgebra.dim_eq_one_iff]
141205

142-
lemma adjoin_simple_adjoin_simple (β : E) : F⟮α,β⟯ = adjoin F {α,β} :=
206+
lemma mem_bot_of_adjoin_simple_dim_eq_one (h : dim F F⟮α⟯ = 1) : α ∈ ((⊥ : subalgebra F E) : set E) :=
207+
set.singleton_subset_iff.mp (sub_bot_of_adjoin_dim_eq_one h)
208+
209+
lemma adjoin_dim_eq_one_of_sub_bot (h : S ⊆ (⊥ : subalgebra F E)) : dim F (adjoin F S) = 1 :=
210+
by { rw adjoin_eq_bot h, exact subalgebra.dim_bot }
211+
212+
lemma adjoin_simple_dim_eq_one_of_mem_bot (h : α ∈ ((⊥ : subalgebra F E) : set E)) : dim F F⟮α⟯ = 1 :=
213+
adjoin_dim_eq_one_of_sub_bot (set.singleton_subset_iff.mpr h)
214+
215+
lemma adjoin_dim_eq_one_iff : dim F (adjoin F S) = 1 ↔ S ⊆ (⊥ : subalgebra F E) :=
216+
⟨sub_bot_of_adjoin_dim_eq_one, adjoin_dim_eq_one_of_sub_bot⟩
217+
218+
lemma adjoin_simple_dim_eq_one_iff : dim F F⟮α⟯ = 1 ↔ α ∈ (⊥ : subalgebra F E) :=
219+
⟨mem_bot_of_adjoin_simple_dim_eq_one, adjoin_simple_dim_eq_one_of_mem_bot⟩
220+
221+
lemma adjoin_findim_eq_one_iff : findim F (adjoin F S) = 1 ↔ S ⊆ (⊥ : subalgebra F E) :=
222+
by rw [← adjoin_dim_eq_one_iff, subalgebra.dim_eq_one_iff, subalgebra.findim_eq_one_iff]
223+
224+
lemma adjoin_simple_findim_eq_one_iff : findim F F⟮α⟯ = 1 ↔ α ∈ (⊥ : subalgebra F E) :=
225+
by rw [← adjoin_simple_dim_eq_one_iff, subalgebra.dim_eq_one_iff, subalgebra.findim_eq_one_iff]
226+
227+
/-- If `F⟮x⟯` has dimension `1` over `F` for every `x ∈ E` then `F = E`. -/
228+
lemma bot_eq_top_of_dim_adjoin_eq_one (h : ∀ x : E, dim F F⟮x⟯ = 1) : (⊥ : subalgebra F E) = ⊤ :=
229+
by simp [subalgebra.ext_iff, algebra.mem_top, ← adjoin_simple_dim_eq_one_iff, h]
230+
231+
lemma bot_eq_top_of_findim_adjoin_eq_one (h : ∀ x : E, findim F F⟮x⟯ = 1) :
232+
(⊥ : subalgebra F E) = ⊤ :=
233+
by simp [subalgebra.ext_iff, algebra.mem_top, ← adjoin_simple_findim_eq_one_iff, h]
234+
235+
/-- If `F⟮x⟯` has dimension `≤1` over `F` for every `x ∈ E` then `F = E`. -/
236+
lemma bot_eq_top_of_findim_adjoin_le_one [finite_dimensional F E]
237+
(h : ∀ x : E, findim F F⟮x⟯ ≤ 1) : (⊥ : subalgebra F E) = ⊤ :=
143238
begin
144-
change adjoin F (insert α (insert β ∅)) = adjoin F _,
145-
simp only [insert_emptyc_eq],
239+
have : ∀ x : E, findim F F⟮x⟯ = 1 := λ x, by linarith [h x, show 0 < findim F F⟮x⟯, from findim_pos],
240+
exact bot_eq_top_of_findim_adjoin_eq_one this,
146241
end
147242

243+
end adjoin_dim
244+
end adjoin_subalgebra_lattice
245+
148246
end field

src/field_theory/minimal_polynomial.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ begin
107107
simpa using hp }
108108
end
109109

110+
lemma dvd_map_of_is_scalar_tower {α γ : Type*} (β : Type*) [comm_ring α] [field β] [comm_ring γ]
111+
[algebra α β] [algebra α γ] [algebra β γ] [is_scalar_tower α β γ] {x : γ} (hx : is_integral α x) :
112+
minimal_polynomial (is_integral_of_is_scalar_tower x hx) ∣ (minimal_polynomial hx).map (algebra_map α β) :=
113+
by { apply minimal_polynomial.dvd, rw [← is_scalar_tower.aeval_apply, minimal_polynomial.aeval] }
114+
110115
variables [nontrivial β]
111116

112117
/--The degree of a minimal polynomial is nonzero.-/

0 commit comments

Comments
 (0)