field_theory.primitive_elementMathlib.FieldTheory.PrimitiveElement

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -141,7 +141,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮
     apply le_antisymm
     · rw [adjoin_le_iff]
       have α_in_Fγ : α ∈ F⟮⟯ := by
-        rw [← add_sub_cancel α (c • β)]
+        rw [← add_sub_cancel_right α (c • β)]
         exact F⟮⟯.sub_mem (mem_adjoin_simple_self F γ) (F⟮⟯.toSubalgebra.smul_mem β_in_Fγ c)
       exact fun x hx => by cases hx <;> cases hx <;> cases hx <;> assumption
     · rw [adjoin_simple_le_iff]
@@ -159,7 +159,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮
   · have finale : β = algebraMap F⟮⟯ E (-p.coeff 0 / p.coeff 1) :=
       by
       rw [map_div₀, RingHom.map_neg, ← coeff_map, ← coeff_map, p_linear]
-      simp [mul_sub, coeff_C, mul_div_cancel_left β (mt leading_coeff_eq_zero.mp h_ne_zero)]
+      simp [mul_sub, coeff_C, mul_div_cancel_left₀ β (mt leading_coeff_eq_zero.mp h_ne_zero)]
     rw [finale]
     exact Subtype.mem (-p.coeff 0 / p.coeff 1)
   have h_sep : h.separable := separable_gcd_right _ (IsSeparable.separable F β).map
@@ -167,7 +167,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮
     apply eval_gcd_eq_zero
     ·
       rw [eval_comp, eval_sub, eval_mul, eval_C, eval_C, eval_X, eval_map, ← aeval_def, ←
-        Algebra.smul_def, add_sub_cancel, minpoly.aeval]
+        Algebra.smul_def, add_sub_cancel_right, minpoly.aeval]
     · rw [eval_map, ← aeval_def, minpoly.aeval]
   have h_splits : splits ιEE' h :=
     splits_of_splits_gcd_right ιEE' map_g_ne_zero (splitting_field.splits _)
Diff
@@ -100,8 +100,8 @@ theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
   let s := (sf.bind fun α' => sg.map fun β' => -(α' - α) / (β' - β)).toFinset
   let s' := s.preimage ϕ fun x hx y hy h => ϕ.injective h
   obtain ⟨c, hc⟩ := Infinite.exists_not_mem_finset s'
-  simp_rw [Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map] at hc 
-  push_neg at hc 
+  simp_rw [Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map] at hc
+  push_neg at hc
   exact ⟨c, hc⟩
 #align field.primitive_element_inf_aux_exists_c Field.primitive_element_inf_aux_exists_c
 -/
@@ -174,12 +174,12 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮
   have h_roots : ∀ x ∈ (h.map ιEE').roots, x = ιEE' β :=
     by
     intro x hx
-    rw [mem_roots_map h_ne_zero] at hx 
+    rw [mem_roots_map h_ne_zero] at hx
     specialize
       hc (ιEE' γ - ιEE' (ιFE c) * x)
         (by
           have f_root := root_left_of_root_gcd hx
-          rw [eval₂_comp, eval₂_sub, eval₂_mul, eval₂_C, eval₂_C, eval₂_X, eval₂_map] at f_root 
+          rw [eval₂_comp, eval₂_sub, eval₂_mul, eval₂_C, eval₂_C, eval₂_X, eval₂_map] at f_root
           exact (mem_roots_map (minpoly.ne_zero hα)).mpr f_root)
     specialize
       hc x
Diff
@@ -3,10 +3,10 @@ Copyright (c) 2020 Thomas Browning, Patrick Lutz. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Thomas Browning, Patrick Lutz
 -/
-import Mathbin.FieldTheory.SplittingField.Construction
-import Mathbin.FieldTheory.IsAlgClosed.Basic
-import Mathbin.FieldTheory.Separable
-import Mathbin.RingTheory.IntegralDomain
+import FieldTheory.SplittingField.Construction
+import FieldTheory.IsAlgClosed.Basic
+import FieldTheory.Separable
+import RingTheory.IntegralDomain
 
 #align_import field_theory.primitive_element from "leanprover-community/mathlib"@"2a0ce625dbb0ffbc7d1316597de0b25c1ec75303"
 
Diff
@@ -2,17 +2,14 @@
 Copyright (c) 2020 Thomas Browning, Patrick Lutz. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Thomas Browning, Patrick Lutz
-
-! This file was ported from Lean 3 source module field_theory.primitive_element
-! leanprover-community/mathlib commit 2a0ce625dbb0ffbc7d1316597de0b25c1ec75303
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.FieldTheory.SplittingField.Construction
 import Mathbin.FieldTheory.IsAlgClosed.Basic
 import Mathbin.FieldTheory.Separable
 import Mathbin.RingTheory.IntegralDomain
 
+#align_import field_theory.primitive_element from "leanprover-community/mathlib"@"2a0ce625dbb0ffbc7d1316597de0b25c1ec75303"
+
 /-!
 # Primitive Element Theorem
 
Diff
@@ -222,7 +222,7 @@ theorem exists_primitive_element : ∃ α : E, F⟮⟯ = ⊤ :=
   by
   rcases isEmpty_or_nonempty (Fintype F) with (F_inf | ⟨⟨F_finite⟩⟩)
   · let P : IntermediateField F E → Prop := fun K => ∃ α : E, F⟮⟯ = K
-    have base : P ⊥ := ⟨0, adjoin_zero⟩
+    have base : P ⊥ := ⟨0, adjoinZero⟩
     have ih : ∀ (K : IntermediateField F E) (x : E), P K → P (K⟮⟯.restrictScalars F) :=
       by
       intro K β hK
Diff
@@ -58,6 +58,7 @@ variable (F : Type _) [Field F] (E : Type _) [Field E] [Algebra F E]
 
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
+#print Field.exists_primitive_element_of_finite_top /-
 /-- **Primitive element theorem** assuming E is finite. -/
 theorem exists_primitive_element_of_finite_top [Finite E] : ∃ α : E, F⟮⟯ = ⊤ :=
   by
@@ -72,14 +73,17 @@ theorem exists_primitive_element_of_finite_top [Finite E] : ∃ α : E, F⟮⟯
     rw [show x = α ^ n by norm_cast; rw [hn, Units.val_mk0]]
     exact zpow_mem (mem_adjoin_simple_self F ↑α) n
 #align field.exists_primitive_element_of_finite_top Field.exists_primitive_element_of_finite_top
+-/
 
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
+#print Field.exists_primitive_element_of_finite_bot /-
 /-- Primitive element theorem for finite dimensional extension of a finite field. -/
 theorem exists_primitive_element_of_finite_bot [Finite F] [FiniteDimensional F E] :
     ∃ α : E, F⟮⟯ = ⊤ :=
   haveI : Finite E := finite_of_finite F E
   exists_primitive_element_of_finite_top F E
 #align field.exists_primitive_element_of_finite_bot Field.exists_primitive_element_of_finite_bot
+-/
 
 end PrimitiveElementFinite
 
@@ -90,6 +94,7 @@ section PrimitiveElementInf
 
 variable {F : Type _} [Field F] [Infinite F] {E : Type _} [Field E] (ϕ : F →+* E) (α β : E)
 
+#print Field.primitive_element_inf_aux_exists_c /-
 theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
     ∃ c : F, ∀ α' ∈ (f.map ϕ).roots, ∀ β' ∈ (g.map ϕ).roots, -(α' - α) / (β' - β) ≠ ϕ c :=
   by
@@ -102,6 +107,7 @@ theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
   push_neg at hc 
   exact ⟨c, hc⟩
 #align field.primitive_element_inf_aux_exists_c Field.primitive_element_inf_aux_exists_c
+-/
 
 variable (F) [Algebra F E]
 
@@ -120,6 +126,7 @@ variable (F) [Algebra F E]
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
+#print Field.primitive_element_inf_aux /-
 -- This is the heart of the proof of the primitive element theorem. It shows that if `F` is
 -- infinite and `α` and `β` are separable over `F` then `F⟮α, β⟯` is generated by a single element.
 theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮⟯ :=
@@ -193,6 +200,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮
     convert (gcd_map (algebraMap F⟮⟯ E)).symm
   · simpa [map_comp, Polynomial.map_map, ← IsScalarTower.algebraMap_eq, h]
 #align field.primitive_element_inf_aux Field.primitive_element_inf_aux
+-/
 
 end PrimitiveElementInf
 
@@ -207,6 +215,7 @@ variable [IsSeparable F E]
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
+#print Field.exists_primitive_element /-
 /-- Primitive element theorem: a finite separable field extension `E` of `F` has a
   primitive element, i.e. there is an `α ∈ E` such that `F⟮α⟯ = (⊤ : subalgebra F E)`.-/
 theorem exists_primitive_element : ∃ α : E, F⟮⟯ = ⊤ :=
@@ -225,8 +234,10 @@ theorem exists_primitive_element : ∃ α : E, F⟮⟯ = ⊤ :=
     exact induction_on_adjoin P base ih ⊤
   · exact exists_primitive_element_of_finite_bot F E
 #align field.exists_primitive_element Field.exists_primitive_element
+-/
 
 /- ./././Mathport/Syntax/Translate/Expr.lean:192:11: unsupported (impossible) -/
+#print Field.powerBasisOfFiniteOfSeparable /-
 /-- Alternative phrasing of primitive element theorem:
 a finite separable field extension has a basis `1, α, α^2, ..., α^n`.
 
@@ -237,11 +248,13 @@ noncomputable def powerBasisOfFiniteOfSeparable : PowerBasis F E :=
   have e : F⟮⟯ = ⊤ := (exists_primitive_element F E).choose_spec
   pb.map ((IntermediateField.equivOfEq e).trans IntermediateField.topEquiv)
 #align field.power_basis_of_finite_of_separable Field.powerBasisOfFiniteOfSeparable
+-/
 
 end SeparableAssumption
 
 end Field
 
+#print AlgHom.card /-
 @[simp]
 theorem AlgHom.card (F E K : Type _) [Field F] [Field E] [Field K] [IsAlgClosed K] [Algebra F E]
     [FiniteDimensional F E] [IsSeparable F E] [Algebra F K] :
@@ -253,4 +266,5 @@ theorem AlgHom.card (F E K : Type _) [Field F] [Field E] [Field K] [IsAlgClosed
       (PowerBasis.finrank _).symm
   infer_instance
 #align alg_hom.card AlgHom.card
+-/
 
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Thomas Browning, Patrick Lutz
 
 ! This file was ported from Lean 3 source module field_theory.primitive_element
-! leanprover-community/mathlib commit df76f43357840485b9d04ed5dee5ab115d420e87
+! leanprover-community/mathlib commit 2a0ce625dbb0ffbc7d1316597de0b25c1ec75303
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -16,6 +16,9 @@ import Mathbin.RingTheory.IntegralDomain
 /-!
 # Primitive Element Theorem
 
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
 In this file we prove the primitive element theorem.
 
 ## Main results
Diff
@@ -4,11 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Thomas Browning, Patrick Lutz
 
 ! This file was ported from Lean 3 source module field_theory.primitive_element
-! leanprover-community/mathlib commit 70fd9563a21e7b963887c9360bd29b2393e6225a
+! leanprover-community/mathlib commit df76f43357840485b9d04ed5dee5ab115d420e87
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
-import Mathbin.FieldTheory.Adjoin
+import Mathbin.FieldTheory.SplittingField.Construction
 import Mathbin.FieldTheory.IsAlgClosed.Basic
 import Mathbin.FieldTheory.Separable
 import Mathbin.RingTheory.IntegralDomain
Diff
@@ -96,7 +96,7 @@ theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
   let s' := s.preimage ϕ fun x hx y hy h => ϕ.injective h
   obtain ⟨c, hc⟩ := Infinite.exists_not_mem_finset s'
   simp_rw [Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map] at hc 
-  push_neg  at hc 
+  push_neg at hc 
   exact ⟨c, hc⟩
 #align field.primitive_element_inf_aux_exists_c Field.primitive_element_inf_aux_exists_c
 
@@ -187,7 +187,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮
   rw [← eq_X_sub_C_of_separable_of_root_eq h_sep h_root h_splits h_roots]
   trans EuclideanDomain.gcd (_ : E[X]) (_ : E[X])
   · dsimp only [p]
-    convert(gcd_map (algebraMap F⟮⟯ E)).symm
+    convert (gcd_map (algebraMap F⟮⟯ E)).symm
   · simpa [map_comp, Polynomial.map_map, ← IsScalarTower.algebraMap_eq, h]
 #align field.primitive_element_inf_aux Field.primitive_element_inf_aux
 
@@ -244,8 +244,9 @@ theorem AlgHom.card (F E K : Type _) [Field F] [Field E] [Field K] [IsAlgClosed
     [FiniteDimensional F E] [IsSeparable F E] [Algebra F K] :
     Fintype.card (E →ₐ[F] K) = finrank F E :=
   by
-  convert(AlgHom.card_of_powerBasis (Field.powerBasisOfFiniteOfSeparable F E)
-          (IsSeparable.separable _ _) (IsAlgClosed.splits_codomain _)).trans
+  convert
+    (AlgHom.card_of_powerBasis (Field.powerBasisOfFiniteOfSeparable F E) (IsSeparable.separable _ _)
+          (IsAlgClosed.splits_codomain _)).trans
       (PowerBasis.finrank _).symm
   infer_instance
 #align alg_hom.card AlgHom.card
Diff
@@ -95,8 +95,8 @@ theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
   let s := (sf.bind fun α' => sg.map fun β' => -(α' - α) / (β' - β)).toFinset
   let s' := s.preimage ϕ fun x hx y hy h => ϕ.injective h
   obtain ⟨c, hc⟩ := Infinite.exists_not_mem_finset s'
-  simp_rw [Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map] at hc
-  push_neg  at hc
+  simp_rw [Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map] at hc 
+  push_neg  at hc 
   exact ⟨c, hc⟩
 #align field.primitive_element_inf_aux_exists_c Field.primitive_element_inf_aux_exists_c
 
@@ -167,12 +167,12 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮
   have h_roots : ∀ x ∈ (h.map ιEE').roots, x = ιEE' β :=
     by
     intro x hx
-    rw [mem_roots_map h_ne_zero] at hx
+    rw [mem_roots_map h_ne_zero] at hx 
     specialize
       hc (ιEE' γ - ιEE' (ιFE c) * x)
         (by
           have f_root := root_left_of_root_gcd hx
-          rw [eval₂_comp, eval₂_sub, eval₂_mul, eval₂_C, eval₂_C, eval₂_X, eval₂_map] at f_root
+          rw [eval₂_comp, eval₂_sub, eval₂_mul, eval₂_C, eval₂_C, eval₂_X, eval₂_map] at f_root 
           exact (mem_roots_map (minpoly.ne_zero hα)).mpr f_root)
     specialize
       hc x
Diff
@@ -40,7 +40,7 @@ exists_adjoin_simple_eq_top
 
 noncomputable section
 
-open Classical Polynomial
+open scoped Classical Polynomial
 
 open FiniteDimensional Polynomial IntermediateField
 
Diff
@@ -66,9 +66,7 @@ theorem exists_primitive_element_of_finite_top [Finite E] : ∃ α : E, F⟮⟯
   · rw [hx]
     exact F⟮⟯.zero_mem
   · obtain ⟨n, hn⟩ := set.mem_range.mp (hα (Units.mk0 x hx))
-    rw [show x = α ^ n by
-        norm_cast
-        rw [hn, Units.val_mk0]]
+    rw [show x = α ^ n by norm_cast; rw [hn, Units.val_mk0]]
     exact zpow_mem (mem_adjoin_simple_self F ↑α) n
 #align field.exists_primitive_element_of_finite_top Field.exists_primitive_element_of_finite_top
 
Diff
@@ -189,7 +189,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮⟯ = F⟮
   rw [← eq_X_sub_C_of_separable_of_root_eq h_sep h_root h_splits h_roots]
   trans EuclideanDomain.gcd (_ : E[X]) (_ : E[X])
   · dsimp only [p]
-    convert (gcd_map (algebraMap F⟮⟯ E)).symm
+    convert(gcd_map (algebraMap F⟮⟯ E)).symm
   · simpa [map_comp, Polynomial.map_map, ← IsScalarTower.algebraMap_eq, h]
 #align field.primitive_element_inf_aux Field.primitive_element_inf_aux
 
@@ -246,9 +246,8 @@ theorem AlgHom.card (F E K : Type _) [Field F] [Field E] [Field K] [IsAlgClosed
     [FiniteDimensional F E] [IsSeparable F E] [Algebra F K] :
     Fintype.card (E →ₐ[F] K) = finrank F E :=
   by
-  convert
-    (AlgHom.card_of_powerBasis (Field.powerBasisOfFiniteOfSeparable F E) (IsSeparable.separable _ _)
-          (IsAlgClosed.splits_codomain _)).trans
+  convert(AlgHom.card_of_powerBasis (Field.powerBasisOfFiniteOfSeparable F E)
+          (IsSeparable.separable _ _) (IsAlgClosed.splits_codomain _)).trans
       (PowerBasis.finrank _).symm
   infer_instance
 #align alg_hom.card AlgHom.card

Changes in mathlib4

mathlib3
mathlib4
chore: unify date formatting in lemma deprecations (#12334)
  • consistently use the YYYY-MM-DD format
  • when easily possible, put the date on the same line as the deprecated attribute
  • when easily possible, format the entire declaration on the same line

Why these changes?

  • consistency makes it easier for tools to parse this information
  • compactness: I don't see a good reason for these declarations taking up more space than needed; as I understand it, deprecated lemmas are not supposed to be used in mathlib anyway
  • putting the date on the same line as the attribute makes it easier to discover un-dated deprecations; they also ease writing a tool to replace these by a machine-readable version using leanprover/lean4#3968
Diff
@@ -290,7 +290,7 @@ theorem FiniteDimensional.of_finite_intermediateField
   rw [htop] at hfin
   exact topEquiv.toLinearEquiv.finiteDimensional
 
-@[deprecated] -- Since 2024/02/02
+@[deprecated] -- Since 2024-02-02
 alias finiteDimensional_of_finite_intermediateField := FiniteDimensional.of_finite_intermediateField
 
 theorem exists_primitive_element_of_finite_intermediateField
@@ -311,7 +311,7 @@ theorem FiniteDimensional.of_exists_primitive_element (halg : Algebra.IsAlgebrai
   rw [hprim] at hfin
   exact topEquiv.toLinearEquiv.finiteDimensional
 
-@[deprecated] -- Since 2024/02/02
+@[deprecated] -- Since 2024-02-02
 alias finiteDimensional_of_exists_primitive_element := FiniteDimensional.of_exists_primitive_element
 
 -- A finite simple extension has only finitely many intermediate fields
chore: Rename mul-div cancellation lemmas (#11530)

Lemma names around cancellation of multiplication and division are a mess.

This PR renames a handful of them according to the following table (each big row contains the multiplicative statement, then the three rows contain the GroupWithZero lemma name, the Group lemma, the AddGroup lemma name).

| Statement | New name | Old name | |

Diff
@@ -115,7 +115,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
     apply le_antisymm
     · rw [adjoin_le_iff]
       have α_in_Fγ : α ∈ F⟮γ⟯ := by
-        rw [← add_sub_cancel α (c • β)]
+        rw [← add_sub_cancel_right α (c • β)]
         exact F⟮γ⟯.sub_mem (mem_adjoin_simple_self F γ) (F⟮γ⟯.toSubalgebra.smul_mem β_in_Fγ c)
       rintro x (rfl | rfl) <;> assumption
     · rw [adjoin_simple_le_iff]
@@ -132,7 +132,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
     have finale : β = algebraMap F⟮γ⟯ E (-p.coeff 0 / p.coeff 1) := by
       rw [map_div₀, RingHom.map_neg, ← coeff_map, ← coeff_map, p_linear]
       -- Porting note: had to add `-map_add` to avoid going in the wrong direction.
-      simp [mul_sub, coeff_C, mul_div_cancel_left β (mt leadingCoeff_eq_zero.mp h_ne_zero),
+      simp [mul_sub, coeff_C, mul_div_cancel_left₀ β (mt leadingCoeff_eq_zero.mp h_ne_zero),
         -map_add]
       -- Porting note: an alternative solution is:
       -- simp_rw [Polynomial.coeff_C_mul, Polynomial.coeff_sub, mul_sub,
@@ -145,7 +145,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
   have h_root : h.eval β = 0 := by
     apply eval_gcd_eq_zero
     · rw [eval_comp, eval_sub, eval_mul, eval_C, eval_C, eval_X, eval_map, ← aeval_def, ←
-        Algebra.smul_def, add_sub_cancel, minpoly.aeval]
+        Algebra.smul_def, add_sub_cancel_right, minpoly.aeval]
     · rw [eval_map, ← aeval_def, minpoly.aeval]
   have h_splits : Splits ιEE' h :=
     splits_of_splits_gcd_right ιEE' map_g_ne_zero (SplittingField.splits _)
@@ -194,7 +194,7 @@ private theorem primitive_element_inf_aux_of_finite_intermediateField
     rw [smul_smul, inv_mul_eq_div, div_self (sub_ne_zero.2 hneq), one_smul] at β_in_K
     have α_in_K : α ∈ F⟮α + x • β⟯ := by
       convert ← sub_mem αxβ_in_K (smul_mem _ β_in_K)
-      apply add_sub_cancel
+      apply add_sub_cancel_right
     rintro x (rfl | rfl) <;> assumption
   · rw [adjoin_simple_le_iff]
     have α_in_Fαβ : α ∈ F⟮α, β⟯ := subset_adjoin F {α, β} (Set.mem_insert α {β})
golf: replace some apply foo.mpr by rw [foo] (#11515)

Sometimes, that line can be golfed into the next line. Inspired by a comment of @loefflerd; any decisions are my own.

Diff
@@ -56,7 +56,7 @@ variable (F : Type*) [Field F] (E : Type*) [Field E] [Algebra F E]
 theorem exists_primitive_element_of_finite_top [Finite E] : ∃ α : E, F⟮α⟯ = ⊤ := by
   obtain ⟨α, hα⟩ := @IsCyclic.exists_generator Eˣ _ _
   use α
-  apply eq_top_iff.mpr
+  rw [eq_top_iff]
   rintro x -
   by_cases hx : x = 0
   · rw [hx]
chore(*): remove empty lines between variable statements (#11418)

Empty lines were removed by executing the following Python script twice

import os
import re


# Loop through each file in the repository
for dir_path, dirs, files in os.walk('.'):
  for filename in files:
    if filename.endswith('.lean'):
      file_path = os.path.join(dir_path, filename)

      # Open the file and read its contents
      with open(file_path, 'r') as file:
        content = file.read()

      # Use a regular expression to replace sequences of "variable" lines separated by empty lines
      # with sequences without empty lines
      modified_content = re.sub(r'(variable.*\n)\n(variable(?! .* in))', r'\1\2', content)

      # Write the modified content back to the file
      with open(file_path, 'w') as file:
        file.write(modified_content)
Diff
@@ -97,7 +97,6 @@ theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
 #align field.primitive_element_inf_aux_exists_c Field.primitive_element_inf_aux_exists_c
 
 variable (F)
-
 variable [Algebra F E]
 
 /-- This is the heart of the proof of the primitive element theorem. It shows that if `F` is
@@ -205,7 +204,6 @@ private theorem primitive_element_inf_aux_of_finite_intermediateField
 end PrimitiveElementInf
 
 variable (F E : Type*) [Field F] [Field E]
-
 variable [Algebra F E]
 
 section SeparableAssumption
chore: move Mathlib to v4.7.0-rc1 (#11162)

This is a very large PR, but it has been reviewed piecemeal already in PRs to the bump/v4.7.0 branch as we update to intermediate nightlies.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Kyle Miller <kmill31415@gmail.com> Co-authored-by: damiano <adomani@gmail.com>

Diff
@@ -90,7 +90,7 @@ theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
   let s := (sf.bind fun α' => sg.map fun β' => -(α' - α) / (β' - β)).toFinset
   let s' := s.preimage ϕ fun x _ y _ h => ϕ.injective h
   obtain ⟨c, hc⟩ := Infinite.exists_not_mem_finset s'
-  simp_rw [s, Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map]
+  simp_rw [s', s, Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map]
     at hc
   push_neg at hc
   exact ⟨c, hc⟩
chore: prepare Lean version bump with explicit simp (#10999)

Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -90,7 +90,8 @@ theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
   let s := (sf.bind fun α' => sg.map fun β' => -(α' - α) / (β' - β)).toFinset
   let s' := s.preimage ϕ fun x _ y _ h => ϕ.injective h
   obtain ⟨c, hc⟩ := Infinite.exists_not_mem_finset s'
-  simp_rw [Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map] at hc
+  simp_rw [s, Finset.mem_preimage, Multiset.mem_toFinset, Multiset.mem_bind, Multiset.mem_map]
+    at hc
   push_neg at hc
   exact ⟨c, hc⟩
 #align field.primitive_element_inf_aux_exists_c Field.primitive_element_inf_aux_exists_c
@@ -162,11 +163,11 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
     by_contra a
     apply hc
     apply (div_eq_iff (sub_ne_zero.mpr a)).mpr
-    simp only [Algebra.smul_def, RingHom.map_add, RingHom.map_mul, RingHom.comp_apply]
+    simp only [γ, Algebra.smul_def, RingHom.map_add, RingHom.map_mul, RingHom.comp_apply]
     ring
   rw [← eq_X_sub_C_of_separable_of_root_eq h_sep h_root h_splits h_roots]
   trans EuclideanDomain.gcd (?_ : E[X]) (?_ : E[X])
-  · dsimp only
+  · dsimp only [γ]
     convert (gcd_map (algebraMap F⟮γ⟯ E)).symm
   · simp only [map_comp, Polynomial.map_map, ← IsScalarTower.algebraMap_eq, Polynomial.map_sub,
       map_C, AdjoinSimple.algebraMap_gen, map_add, Polynomial.map_mul, map_X]
@@ -186,6 +187,7 @@ private theorem primitive_element_inf_aux_of_finite_intermediateField
   · rw [adjoin_le_iff]
     have αxβ_in_K : α + x • β ∈ F⟮α + x • β⟯ := mem_adjoin_simple_self F _
     have αyβ_in_K : α + y • β ∈ F⟮α + y • β⟯ := mem_adjoin_simple_self F _
+    dsimp [f] at *
     simp only [← heq] at αyβ_in_K
     have β_in_K := sub_mem αxβ_in_K αyβ_in_K
     rw [show (α + x • β) - (α + y • β) = (x - y) • β by rw [sub_smul]; abel1] at β_in_K
@@ -267,12 +269,12 @@ theorem isAlgebraic_of_adjoin_eq_adjoin {α : E} {m n : ℕ} (hneq : m ≠ n)
       have hndvd : ¬ n ∣ n * s.natDegree + m := by
         rw [← Nat.dvd_add_iff_right (n.dvd_mul_right s.natDegree)]
         exact Nat.not_dvd_of_pos_of_lt hm hmn
-      simp only [coeff_sub, coeff_X_pow_mul, s.coeff_expand_mul' hn, coeff_natDegree,
+      simp only [f, coeff_sub, coeff_X_pow_mul, s.coeff_expand_mul' hn, coeff_natDegree,
         coeff_expand hn r, hndvd, ite_false, sub_zero]
       exact leadingCoeff_ne_zero.2 hzero
     intro h
     simp only [h, coeff_zero, ne_eq, not_true_eq_false] at this
-  · simp only [map_sub, map_mul, map_pow, aeval_X, expand_aeval, h]
+  · simp only [f, map_sub, map_mul, map_pow, aeval_X, expand_aeval, h]
 
 theorem isAlgebraic_of_finite_intermediateField
     [Finite (IntermediateField F E)] : Algebra.IsAlgebraic F E := fun α ↦
chore: remove stream-of-consciousness uses of have, replace and suffices (#10640)

No changes to tactic file, it's just boring fixes throughout the library.

This follows on from #6964.

Co-authored-by: sgouezel <sebastien.gouezel@univ-rennes1.fr> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Diff
@@ -110,8 +110,8 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
   let ιEE' := algebraMap E (SplittingField (g.map ιFE))
   obtain ⟨c, hc⟩ := primitive_element_inf_aux_exists_c (ιEE'.comp ιFE) (ιEE' α) (ιEE' β) f g
   let γ := α + c • β
-  suffices β_in_Fγ : β ∈ F⟮γ⟯
-  · use γ
+  suffices β_in_Fγ : β ∈ F⟮γ⟯ by
+    use γ
     apply le_antisymm
     · rw [adjoin_le_iff]
       have α_in_Fγ : α ∈ F⟮γ⟯ := by
@@ -128,8 +128,8 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
   have map_g_ne_zero : g.map ιFE ≠ 0 := map_ne_zero (minpoly.ne_zero hβ)
   have h_ne_zero : h ≠ 0 :=
     mt EuclideanDomain.gcd_eq_zero_iff.mp (not_and.mpr fun _ => map_g_ne_zero)
-  suffices p_linear : p.map (algebraMap F⟮γ⟯ E) = C h.leadingCoeff * (X - C β)
-  · have finale : β = algebraMap F⟮γ⟯ E (-p.coeff 0 / p.coeff 1) := by
+  suffices p_linear : p.map (algebraMap F⟮γ⟯ E) = C h.leadingCoeff * (X - C β) by
+    have finale : β = algebraMap F⟮γ⟯ E (-p.coeff 0 / p.coeff 1) := by
       rw [map_div₀, RingHom.map_neg, ← coeff_map, ← coeff_map, p_linear]
       -- Porting note: had to add `-map_add` to avoid going in the wrong direction.
       simp [mul_sub, coeff_C, mul_div_cancel_left β (mt leadingCoeff_eq_zero.mp h_ne_zero),
chore(FiniteDimensional): rename lemmas (#10188)

Rename lemmas to enable new-style dot notation or drop repeating FiniteDimensional.finiteDimensional_*. Restore old names as deprecated aliases.

Diff
@@ -279,7 +279,7 @@ theorem isAlgebraic_of_finite_intermediateField
   have ⟨_m, _n, hneq, heq⟩ := Finite.exists_ne_map_eq_of_infinite fun n ↦ F⟮α ^ n⟯
   isAlgebraic_of_adjoin_eq_adjoin F E hneq heq
 
-theorem finiteDimensional_of_finite_intermediateField
+theorem FiniteDimensional.of_finite_intermediateField
     [Finite (IntermediateField F E)] : FiniteDimensional F E := by
   let IF := { K : IntermediateField F E // ∃ x, K = F⟮x⟯ }
   haveI : ∀ K : IF, FiniteDimensional F K.1 := fun ⟨_, x, rfl⟩ ↦ adjoin.finiteDimensional
@@ -290,9 +290,12 @@ theorem finiteDimensional_of_finite_intermediateField
   rw [htop] at hfin
   exact topEquiv.toLinearEquiv.finiteDimensional
 
+@[deprecated] -- Since 2024/02/02
+alias finiteDimensional_of_finite_intermediateField := FiniteDimensional.of_finite_intermediateField
+
 theorem exists_primitive_element_of_finite_intermediateField
     [Finite (IntermediateField F E)] (K : IntermediateField F E) : ∃ α : E, F⟮α⟯ = K := by
-  haveI := finiteDimensional_of_finite_intermediateField F E
+  haveI := FiniteDimensional.of_finite_intermediateField F E
   rcases finite_or_infinite F with (_ | _)
   · obtain ⟨α, h⟩ := exists_primitive_element_of_finite_bot F K
     exact ⟨α, by simpa only [lift_adjoin_simple, lift_top] using congr_arg lift h⟩
@@ -301,17 +304,20 @@ theorem exists_primitive_element_of_finite_intermediateField
     simp_rw [adjoin_simple_adjoin_simple, eq_comm]
     exact primitive_element_inf_aux_of_finite_intermediateField F α β
 
-theorem finiteDimensional_of_exists_primitive_element (halg : Algebra.IsAlgebraic F E)
+theorem FiniteDimensional.of_exists_primitive_element (halg : Algebra.IsAlgebraic F E)
     (h : ∃ α : E, F⟮α⟯ = ⊤) : FiniteDimensional F E := by
   obtain ⟨α, hprim⟩ := h
   have hfin := adjoin.finiteDimensional (halg α).isIntegral
   rw [hprim] at hfin
   exact topEquiv.toLinearEquiv.finiteDimensional
 
+@[deprecated] -- Since 2024/02/02
+alias finiteDimensional_of_exists_primitive_element := FiniteDimensional.of_exists_primitive_element
+
 -- A finite simple extension has only finitely many intermediate fields
 theorem finite_intermediateField_of_exists_primitive_element (halg : Algebra.IsAlgebraic F E)
     (h : ∃ α : E, F⟮α⟯ = ⊤) : Finite (IntermediateField F E) := by
-  haveI := finiteDimensional_of_exists_primitive_element F E halg h
+  haveI := FiniteDimensional.of_exists_primitive_element F E halg h
   obtain ⟨α, hprim⟩ := h
   -- Let `f` be the minimal polynomial of `α ∈ E` over `F`
   let f : F[X] := minpoly F α
feat: The support of f ^ n (#9617)

This involves moving lemmas from Algebra.GroupPower.Ring to Algebra.GroupWithZero.Basic and changing some 0 < n assumptions to n ≠ 0.

From LeanAPAP

Diff
@@ -253,26 +253,26 @@ theorem isAlgebraic_of_adjoin_eq_adjoin {α : E} {m n : ℕ} (hneq : m ≠ n)
     obtain ⟨y, h⟩ := mem_bot.1 (heq.symm ▸ mem_adjoin_simple_self F (α ^ n))
     refine ⟨X ^ n - C y, X_pow_sub_C_ne_zero hmn y, ?_⟩
     simp only [map_sub, map_pow, aeval_X, aeval_C, h, sub_self]
-  replace hm : 0 < m := Nat.pos_of_ne_zero hm
   obtain ⟨r, s, h⟩ := (mem_adjoin_simple_iff F _).1 (heq ▸ mem_adjoin_simple_self F (α ^ m))
   by_cases hzero : aeval (α ^ n) s = 0
   · simp only [hzero, div_zero, pow_eq_zero_iff hm] at h
     exact h.symm ▸ isAlgebraic_zero
-  · rw [eq_div_iff hzero, ← sub_eq_zero] at h
-    replace hzero : s ≠ 0 := by rintro rfl; simp only [map_zero, not_true_eq_false] at hzero
-    let f : F[X] := X ^ m * expand F n s - expand F n r
-    refine ⟨f, ?_, ?_⟩
-    · have : f.coeff (n * s.natDegree + m) ≠ 0 := by
-        have hn : 0 < n := by linarith only [hm, hmn]
-        have hndvd : ¬ n ∣ n * s.natDegree + m := by
-          rw [← Nat.dvd_add_iff_right (n.dvd_mul_right s.natDegree)]
-          exact Nat.not_dvd_of_pos_of_lt hm hmn
-        simp only [coeff_sub, coeff_X_pow_mul, s.coeff_expand_mul' hn, coeff_natDegree,
-          coeff_expand hn r, hndvd, ite_false, sub_zero]
-        exact leadingCoeff_ne_zero.2 hzero
-      intro h
-      simp only [h, coeff_zero, ne_eq, not_true_eq_false] at this
-    · simp only [map_sub, map_mul, map_pow, aeval_X, expand_aeval, h]
+  replace hm : 0 < m := Nat.pos_of_ne_zero hm
+  rw [eq_div_iff hzero, ← sub_eq_zero] at h
+  replace hzero : s ≠ 0 := by rintro rfl; simp only [map_zero, not_true_eq_false] at hzero
+  let f : F[X] := X ^ m * expand F n s - expand F n r
+  refine ⟨f, ?_, ?_⟩
+  · have : f.coeff (n * s.natDegree + m) ≠ 0 := by
+      have hn : 0 < n := by linarith only [hm, hmn]
+      have hndvd : ¬ n ∣ n * s.natDegree + m := by
+        rw [← Nat.dvd_add_iff_right (n.dvd_mul_right s.natDegree)]
+        exact Nat.not_dvd_of_pos_of_lt hm hmn
+      simp only [coeff_sub, coeff_X_pow_mul, s.coeff_expand_mul' hn, coeff_natDegree,
+        coeff_expand hn r, hndvd, ite_false, sub_zero]
+      exact leadingCoeff_ne_zero.2 hzero
+    intro h
+    simp only [h, coeff_zero, ne_eq, not_true_eq_false] at this
+  · simp only [map_sub, map_mul, map_pow, aeval_X, expand_aeval, h]
 
 theorem isAlgebraic_of_finite_intermediateField
     [Finite (IntermediateField F E)] : Algebra.IsAlgebraic F E := fun α ↦
chore: reduce imports (#9830)

This uses the improved shake script from #9772 to reduce imports across mathlib. The corresponding noshake.json file has been added to #9772.

Co-authored-by: Mario Carneiro <di.gama@gmail.com>

Diff
@@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Thomas Browning, Patrick Lutz
 -/
 import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure
-import Mathlib.FieldTheory.NormalClosure
 import Mathlib.RingTheory.IntegralDomain
 
 #align_import field_theory.primitive_element from "leanprover-community/mathlib"@"df76f43357840485b9d04ed5dee5ab115d420e87"
chore: cleanups following #8609 and #8714 (#8962)
  • generalize image_rootSet, adjoin_rootSet_eq_range and splits_comp_of_splits in Data/Polynomial/Splits and use the last one to golf splits_of_algHom, splits_of_isScalarTower (introduced in # 8609).

  • add three new lemmas mem_range_x_of_minpoly_splits to simplify the construction of IntermediateField.algHomEquivAlgHomOfIsAlgClosed and Algebra.IsAlgebraic.algHomEquivAlgHomOfIsAlgClosed, remove the IsAlgClosed condition and rename. They could be moved to an earlier file but I refrain from doing that. (#find_home says it's already in the right place)

  • golf primitive_element_iff_algHom_eq_of_eval from # 8609, using a new lemma IsIntegral.minpoly_splits_tower_top for the last step.

  • make integralClosure_algEquiv_restrict (from # 8714) computable and rename to AlgEquiv.mapIntegralClosure to follow camelCase naming convention and enable dot notation.

Co-authored-by: Xavier-François Roblot <46200072+xroblot@users.noreply.github.com> Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>

Diff
@@ -360,7 +360,7 @@ theorem AlgHom.card (K : Type*) [Field K] [IsAlgClosed K] [Algebra F K] :
 theorem AlgHom.card_of_splits (L : Type*) [Field L] [Algebra F L]
     (hL : ∀ x : E, (minpoly F x).Splits (algebraMap F L)) :
     Fintype.card (E →ₐ[F] L) = finrank F E := by
-  rw [← Fintype.ofEquiv_card <| Algebra.IsAlgebraic.algHomEquivAlgHomOfIsAlgClosed
+  rw [← Fintype.ofEquiv_card <| Algebra.IsAlgebraic.algHomEquivAlgHomOfSplits
     (AlgebraicClosure L) (Algebra.IsAlgebraic.of_finite F E) _ hL]
   convert AlgHom.card F E (AlgebraicClosure L)
 
@@ -397,34 +397,14 @@ theorem primitive_element_iff_algHom_eq_of_eval' (α : E) :
 
 theorem primitive_element_iff_algHom_eq_of_eval (α : E)
     (φ : E →ₐ[F] A) : F⟮α⟯ = ⊤ ↔ ∀ ψ : E →ₐ[F] A, φ α = ψ α → φ = ψ := by
-  rw [Field.primitive_element_iff_algHom_eq_of_eval' F A hA]
-  refine ⟨fun h _ eq => h eq, fun h φ₀ ψ₀ h' => ?_⟩
-  let K := normalClosure F E A
-  have : IsNormalClosure F E K := by
-    refine Algebra.IsAlgebraic.isNormalClosure_normalClosure ?_ hA
-    exact Algebra.IsAlgebraic.of_finite F E
-  have hK_mem : ∀ (ψ : E →ₐ[F] A) (x : E), ψ x ∈ K :=
-    fun ψ x => AlgHom.fieldRange_le_normalClosure ψ ⟨x, rfl⟩
-  let res : (E →ₐ[F] A) → (E →ₐ[F] K) := fun ψ => AlgHom.codRestrict ψ K.toSubalgebra (hK_mem ψ)
-  rsuffices ⟨σ, hσ⟩ : ∃ σ : K →ₐ[F] A, σ (⟨φ₀ α, hK_mem _ _⟩) = φ α
-  · suffices res φ₀ = res ψ₀ by
-      ext x
-      exact Subtype.mk_eq_mk.mp (AlgHom.congr_fun this x)
-    have eq₁ : φ = AlgHom.comp σ (res φ₀) := h (AlgHom.comp σ (res φ₀)) hσ.symm
-    have eq₂ : φ = AlgHom.comp σ (res ψ₀) := by
-      refine h (AlgHom.comp σ (res ψ₀)) ?_
-      simp_rw [← hσ, h']
-      rfl
-    ext1 x
-    exact (RingHom.injective σ.toRingHom) <| AlgHom.congr_fun (eq₁.symm.trans eq₂) x
-  refine IntermediateField.exists_algHom_of_splits_of_aeval ?_ ?_
-  · refine fun x => ⟨IsAlgebraic.isIntegral (IsAlgebraic.of_finite F x), ?_⟩
-    refine Polynomial.splits_of_algHom ?_ K.toSubalgebra.val
-    exact Normal.splits (IsNormalClosure.normal (K := E)) x
-  · rw [aeval_algHom_apply, _root_.map_eq_zero]
-    convert minpoly.aeval F α
-    letI : Algebra E K := (res φ₀).toAlgebra
-    exact minpoly.algebraMap_eq (algebraMap E K).injective α
+  refine ⟨fun h ψ hψ ↦ (Field.primitive_element_iff_algHom_eq_of_eval' F A hA α).mp h hψ,
+    fun h ↦ eq_of_le_of_finrank_eq' le_top ?_⟩
+  letI : Algebra F⟮α⟯ A := (φ.comp F⟮α⟯.val).toAlgebra
+  haveI := isSeparable_tower_top_of_isSeparable F F⟮α⟯ E
+  rw [IntermediateField.finrank_top, ← AlgHom.card_of_splits _ _ A, Fintype.card_eq_one_iff]
+  · exact ⟨{ __ := φ, commutes' := fun _ ↦ rfl }, fun ψ ↦ AlgHom.restrictScalars_injective F <|
+      Eq.symm <| h _ (ψ.commutes <| AdjoinSimple.gen F α).symm⟩
+  · exact fun x ↦ (IsIntegral.of_finite F x).minpoly_splits_tower_top (hA x)
 
 end Field
 
feat: Add some equivalent characterisations of primitive elements in finite extensions of fields (#8609)

See the Zulip thread

Diff
@@ -3,9 +3,8 @@ Copyright (c) 2020 Thomas Browning, Patrick Lutz. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Thomas Browning, Patrick Lutz
 -/
-import Mathlib.FieldTheory.SplittingField.Construction
-import Mathlib.FieldTheory.IsAlgClosed.Basic
-import Mathlib.FieldTheory.Separable
+import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure
+import Mathlib.FieldTheory.NormalClosure
 import Mathlib.RingTheory.IntegralDomain
 
 #align_import field_theory.primitive_element from "leanprover-community/mathlib"@"df76f43357840485b9d04ed5dee5ab115d420e87"
@@ -348,10 +347,85 @@ end FiniteIntermediateField
 
 end Field
 
+variable (F E : Type*) [Field F] [Field E] [Algebra F E] [FiniteDimensional F E] [IsSeparable F E]
+
 @[simp]
-theorem AlgHom.card (F E K : Type*) [Field F] [Field E] [Field K] [IsAlgClosed K] [Algebra F E]
-    [FiniteDimensional F E] [IsSeparable F E] [Algebra F K] :
+theorem AlgHom.card (K : Type*) [Field K] [IsAlgClosed K] [Algebra F K] :
     Fintype.card (E →ₐ[F] K) = finrank F E := by
   convert (AlgHom.card_of_powerBasis (L := K) (Field.powerBasisOfFiniteOfSeparable F E)
     (IsSeparable.separable _ _) (IsAlgClosed.splits_codomain _)).trans (PowerBasis.finrank _).symm
 #align alg_hom.card AlgHom.card
+
+@[simp]
+theorem AlgHom.card_of_splits (L : Type*) [Field L] [Algebra F L]
+    (hL : ∀ x : E, (minpoly F x).Splits (algebraMap F L)) :
+    Fintype.card (E →ₐ[F] L) = finrank F E := by
+  rw [← Fintype.ofEquiv_card <| Algebra.IsAlgebraic.algHomEquivAlgHomOfIsAlgClosed
+    (AlgebraicClosure L) (Algebra.IsAlgebraic.of_finite F E) _ hL]
+  convert AlgHom.card F E (AlgebraicClosure L)
+
+section iff
+
+namespace Field
+
+open FiniteDimensional IntermediateField Polynomial Algebra Set
+
+variable (F : Type*) {E : Type*} [Field F] [Field E] [Algebra F E] [FiniteDimensional F E]
+
+theorem primitive_element_iff_minpoly_natDegree_eq (α : E) :
+    F⟮α⟯ = ⊤ ↔ (minpoly F α).natDegree = finrank F E := by
+  rw [← adjoin.finrank (IsIntegral.of_finite F α), ← finrank_top F E]
+  refine ⟨fun h => ?_, fun h => eq_of_le_of_finrank_eq le_top h⟩
+  exact congr_arg (fun K : IntermediateField F E => finrank F K) h
+
+theorem primitive_element_iff_minpoly_degree_eq (α : E) :
+    F⟮α⟯ = ⊤ ↔ (minpoly F α).degree = finrank F E := by
+  rw [degree_eq_iff_natDegree_eq, primitive_element_iff_minpoly_natDegree_eq]
+  exact minpoly.ne_zero_of_finite F α
+
+variable [IsSeparable F E] (A : Type*) [Field A] [Algebra F A]
+  (hA : ∀ x : E, (minpoly F x).Splits (algebraMap F A))
+
+theorem primitive_element_iff_algHom_eq_of_eval' (α : E) :
+    F⟮α⟯ = ⊤ ↔ Function.Injective fun φ : E →ₐ[F] A ↦ φ α := by
+  classical
+  simp_rw [primitive_element_iff_minpoly_natDegree_eq, ← card_rootSet_eq_natDegree (K := A)
+    (IsSeparable.separable F α) (hA _), ← toFinset_card,
+    ← (Algebra.IsAlgebraic.of_finite F E).range_eval_eq_rootSet_minpoly_of_splits _ hA α,
+    ← AlgHom.card_of_splits F E A hA, Fintype.card, toFinset_range, Finset.card_image_iff,
+    Finset.coe_univ, ← injective_iff_injOn_univ]
+
+theorem primitive_element_iff_algHom_eq_of_eval (α : E)
+    (φ : E →ₐ[F] A) : F⟮α⟯ = ⊤ ↔ ∀ ψ : E →ₐ[F] A, φ α = ψ α → φ = ψ := by
+  rw [Field.primitive_element_iff_algHom_eq_of_eval' F A hA]
+  refine ⟨fun h _ eq => h eq, fun h φ₀ ψ₀ h' => ?_⟩
+  let K := normalClosure F E A
+  have : IsNormalClosure F E K := by
+    refine Algebra.IsAlgebraic.isNormalClosure_normalClosure ?_ hA
+    exact Algebra.IsAlgebraic.of_finite F E
+  have hK_mem : ∀ (ψ : E →ₐ[F] A) (x : E), ψ x ∈ K :=
+    fun ψ x => AlgHom.fieldRange_le_normalClosure ψ ⟨x, rfl⟩
+  let res : (E →ₐ[F] A) → (E →ₐ[F] K) := fun ψ => AlgHom.codRestrict ψ K.toSubalgebra (hK_mem ψ)
+  rsuffices ⟨σ, hσ⟩ : ∃ σ : K →ₐ[F] A, σ (⟨φ₀ α, hK_mem _ _⟩) = φ α
+  · suffices res φ₀ = res ψ₀ by
+      ext x
+      exact Subtype.mk_eq_mk.mp (AlgHom.congr_fun this x)
+    have eq₁ : φ = AlgHom.comp σ (res φ₀) := h (AlgHom.comp σ (res φ₀)) hσ.symm
+    have eq₂ : φ = AlgHom.comp σ (res ψ₀) := by
+      refine h (AlgHom.comp σ (res ψ₀)) ?_
+      simp_rw [← hσ, h']
+      rfl
+    ext1 x
+    exact (RingHom.injective σ.toRingHom) <| AlgHom.congr_fun (eq₁.symm.trans eq₂) x
+  refine IntermediateField.exists_algHom_of_splits_of_aeval ?_ ?_
+  · refine fun x => ⟨IsAlgebraic.isIntegral (IsAlgebraic.of_finite F x), ?_⟩
+    refine Polynomial.splits_of_algHom ?_ K.toSubalgebra.val
+    exact Normal.splits (IsNormalClosure.normal (K := E)) x
+  · rw [aeval_algHom_apply, _root_.map_eq_zero]
+    convert minpoly.aeval F α
+    letI : Algebra E K := (res φ₀).toAlgebra
+    exact minpoly.algebraMap_eq (algebraMap E K).injective α
+
+end Field
+
+end iff
chore(IntegralClosure): noncommutative generalizations and golfs (#8406)

Zulip

Initially I just wanted to add more dot notations for IsIntegral and IsAlgebraic (done in #8437); then I noticed near-duplicates Algebra.isIntegral_of_finite [Field R] [Ring A] and RingHom.IsIntegral.of_finite [CommRing R] [CommRing A] so I went on to generalize the latter to cover the former, and generalized everything in the IntegralClosure file to the noncommutative case whenever possible.

In the process I noticed more golfs, which result in this PR. Most notably, isIntegral_of_mem_of_FG is now proven using Cayley-Hamilton and doesn't depend on the Noetherian case isIntegral_of_noetherian; the latter is now proven using the former. In total the golfs makes mathlib 227 lines leaner (+487 -714).

The main changes are in the single file RingTheory/IntegralClosure:

  • Change the definition of Algebra.IsIntegral which makes it unfold to IsIntegral rather than RingHom.IsIntegralElem because the former has much more APIs.

  • Fix lemma names involving is_integral which are actually about IsIntegralElem: RingHom.is_integral_mapRingHom.isIntegralElem_map RingHom.is_integral_of_mem_closureRingHom.IsIntegralElem.of_mem_closure RingHom.is_integral_zero/oneRingHom.isIntegralElem_zero/one RingHom.is_integral_add/neg/sub/mul/of_mul_unitRingHom.IsIntegralElem.add/neg/sub/mul/of_mul_unit

  • Add a lemma Algebra.IsIntegral.of_injective.

  • Move isIntegral_of_(submodule_)noetherian down and golf them.

  • Remove (Algebra.)isIntegral_of_finite that work only over fields, in favor of the more general (Algebra.)isIntegral.of_finite.

  • Merge duplicate lemmas isIntegral_of_isScalarTower and isIntegral_tower_top_of_isIntegral into IsIntegral.tower_top.

  • Golf IsIntegral.of_mem_of_fg by first proving IsIntegral.of_finite using Cayley-Hamilton.

  • Add a docstring mentioning the Kurosh problem at Algebra.IsIntegral.finite. The negative solution to the problem means the theorem doesn't generalize to noncommutative algebras.

  • Golf IsIntegral.tmul and isField_of_isIntegral_of_isField(').

  • Combine isIntegral_trans_aux into isIntegral_trans and golf.

  • Add Algebra namespace to isIntegral_sup.

  • rename lemmas for dot notation: RingHom.isIntegral_transRingHom.IsIntegral.trans RingHom.isIntegral_quotient/tower_bot/top_of_isIntegralRingHom.IsIntegral.quotient/tower_bot/top isIntegral_of_mem_closure'IsIntegral.of_mem_closure' (and the '' version) isIntegral_of_surjectiveAlgebra.isIntegral_of_surjective

The next changed file is RingTheory/Algebraic:

  • Rename: of_larger_basetower_top (for consistency with IsIntegral) Algebra.isAlgebraic_of_finiteAlgebra.IsAlgebraic.of_finite Algebra.isAlgebraic_transAlgebra.IsAlgebraic.trans

  • Add new lemmasAlgebra.IsIntegral.isAlgebraic, isAlgebraic_algHom_iff, and Algebra.IsAlgebraic.of_injective to streamline some proofs.

The generalization from CommRing to Ring requires an additional lemma scaleRoots_eval₂_mul_of_commute in Polynomial/ScaleRoots.

A lemma Algebra.lmul_injective is added to Algebra/Bilinear (in order to golf the proof of IsIntegral.of_mem_of_fg).

In all other files, I merely fix the changed names, or use newly available dot notations.

Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>

Diff
@@ -284,8 +284,8 @@ theorem isAlgebraic_of_finite_intermediateField
 theorem finiteDimensional_of_finite_intermediateField
     [Finite (IntermediateField F E)] : FiniteDimensional F E := by
   let IF := { K : IntermediateField F E // ∃ x, K = F⟮x⟯ }
-  haveI : ∀ K : IF, FiniteDimensional F K.1 := fun ⟨_, x, rfl⟩ ↦ adjoin.finiteDimensional <|
-    isAlgebraic_iff_isIntegral.1 (isAlgebraic_of_finite_intermediateField F E x)
+  haveI : ∀ K : IF, FiniteDimensional F K.1 := fun ⟨_, x, rfl⟩ ↦ adjoin.finiteDimensional
+    (isAlgebraic_of_finite_intermediateField F E x).isIntegral
   have hfin := finiteDimensional_iSup_of_finite (t := fun K : IF ↦ K.1)
   have htop : ⨆ K : IF, K.1 = ⊤ := le_top.antisymm fun x _ ↦
     le_iSup (fun K : IF ↦ K.1) ⟨F⟮x⟯, x, rfl⟩ <| mem_adjoin_simple_self F x
@@ -306,7 +306,7 @@ theorem exists_primitive_element_of_finite_intermediateField
 theorem finiteDimensional_of_exists_primitive_element (halg : Algebra.IsAlgebraic F E)
     (h : ∃ α : E, F⟮α⟯ = ⊤) : FiniteDimensional F E := by
   obtain ⟨α, hprim⟩ := h
-  have hfin := adjoin.finiteDimensional <| isAlgebraic_iff_isIntegral.1 (halg α)
+  have hfin := adjoin.finiteDimensional (halg α).isIntegral
   rw [hprim] at hfin
   exact topEquiv.toLinearEquiv.finiteDimensional
 
@@ -324,7 +324,7 @@ theorem finite_intermediateField_of_exists_primitive_element (halg : Algebra.IsA
   -- If `K` is an intermediate field of `E/F`, let `g` be the minimal polynomial of `α` over `K`
   -- which is a monic factor of `f`
   let g : IntermediateField F E → G := fun K ↦
-    ⟨(minpoly K α).map (algebraMap K E), (minpoly.monic <| IsIntegral.of_finite K α).map _, by
+    ⟨(minpoly K α).map (algebraMap K E), (minpoly.monic <| .of_finite K α).map _, by
       convert Polynomial.map_dvd (algebraMap K E) (minpoly.dvd_map_of_isScalarTower F K α)
       rw [Polynomial.map_map]; rfl⟩
   -- The map `K ↦ g` is injective
chore: bump to v4.3.0-rc2 (#8366)

PR contents

This is the supremum of

along with some minor fixes from failures on nightly-testing as Mathlib master is merged into it.

Note that some PRs for changes that are already compatible with the current toolchain and will be necessary have already been split out: #8380.

I am hopeful that in future we will be able to progressively merge adaptation PRs into a bump/v4.X.0 branch, so we never end up with a "big merge" like this. However one of these adaptation PRs (#8056) predates my new scheme for combined CI, and it wasn't possible to keep that PR viable in the meantime.

Lean PRs involved in this bump

In particular this includes adjustments for the Lean PRs

leanprover/lean4#2778

We can get rid of all the

local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue [lean4#2220](https://github.com/leanprover/lean4/pull/2220)

macros across Mathlib (and in any projects that want to write natural number powers of reals).

leanprover/lean4#2722

Changes the default behaviour of simp to (config := {decide := false}). This makes simp (and consequentially norm_num) less powerful, but also more consistent, and less likely to blow up in long failures. This requires a variety of changes: changing some previously by simp or norm_num to decide or rfl, or adding (config := {decide := true}).

leanprover/lean4#2783

This changed the behaviour of simp so that simp [f] will only unfold "fully applied" occurrences of f. The old behaviour can be recovered with simp (config := { unfoldPartialApp := true }). We may in future add a syntax for this, e.g. simp [!f]; please provide feedback! In the meantime, we have made the following changes:

  • switching to using explicit lemmas that have the intended level of application
  • (config := { unfoldPartialApp := true }) in some places, to recover the old behaviour
  • Using @[eqns] to manually adjust the equation lemmas for a particular definition, recovering the old behaviour just for that definition. See #8371, where we do this for Function.comp and Function.flip.

This change in Lean may require further changes down the line (e.g. adding the !f syntax, and/or upstreaming the special treatment for Function.comp and Function.flip, and/or removing this special treatment). Please keep an open and skeptical mind about these changes!

Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>

Diff
@@ -65,7 +65,7 @@ theorem exists_primitive_element_of_finite_top [Finite E] : ∃ α : E, F⟮α
     exact F⟮α.val⟯.zero_mem
   · obtain ⟨n, hn⟩ := Set.mem_range.mp (hα (Units.mk0 x hx))
     simp only at hn
-    rw [show x = α ^ n by norm_cast; rw [hn, Units.val_mk0], Units.val_zpow_eq_zpow_val]
+    rw [show x = α ^ n by norm_cast; rw [hn, Units.val_mk0]]
     exact zpow_mem (mem_adjoin_simple_self F (E := E) ↑α) n
 #align field.exists_primitive_element_of_finite_top Field.exists_primitive_element_of_finite_top
 
@@ -261,7 +261,7 @@ theorem isAlgebraic_of_adjoin_eq_adjoin {α : E} {m n : ℕ} (hneq : m ≠ n)
   · simp only [hzero, div_zero, pow_eq_zero_iff hm] at h
     exact h.symm ▸ isAlgebraic_zero
   · rw [eq_div_iff hzero, ← sub_eq_zero] at h
-    replace hzero : s ≠ 0 := by rintro rfl; simp only [map_zero] at hzero
+    replace hzero : s ≠ 0 := by rintro rfl; simp only [map_zero, not_true_eq_false] at hzero
     let f : F[X] := X ^ m * expand F n s - expand F n r
     refine ⟨f, ?_, ?_⟩
     · have : f.coeff (n * s.natDegree + m) ≠ 0 := by
@@ -273,7 +273,7 @@ theorem isAlgebraic_of_adjoin_eq_adjoin {α : E} {m n : ℕ} (hneq : m ≠ n)
           coeff_expand hn r, hndvd, ite_false, sub_zero]
         exact leadingCoeff_ne_zero.2 hzero
       intro h
-      simp only [h, coeff_zero, ne_eq] at this
+      simp only [h, coeff_zero, ne_eq, not_true_eq_false] at this
     · simp only [map_sub, map_mul, map_pow, aeval_X, expand_aeval, h]
 
 theorem isAlgebraic_of_finite_intermediateField
chore(RingTheory/{Algebraic, Localization/Integral}): rename decls to use dot notation (#8437)

This PR tests a string-based tool for renaming declarations.

Inspired by this Zulip thread, I am trying to reduce the diff of #8406.

This PR makes the following renames:

| From | To |

Diff
@@ -324,7 +324,7 @@ theorem finite_intermediateField_of_exists_primitive_element (halg : Algebra.IsA
   -- If `K` is an intermediate field of `E/F`, let `g` be the minimal polynomial of `α` over `K`
   -- which is a monic factor of `f`
   let g : IntermediateField F E → G := fun K ↦
-    ⟨(minpoly K α).map (algebraMap K E), (minpoly.monic <| isIntegral_of_finite K α).map _, by
+    ⟨(minpoly K α).map (algebraMap K E), (minpoly.monic <| IsIntegral.of_finite K α).map _, by
       convert Polynomial.map_dvd (algebraMap K E) (minpoly.dvd_map_of_isScalarTower F K α)
       rw [Polynomial.map_map]; rfl⟩
   -- The map `K ↦ g` is injective
feat(FieldTheory/PrimitiveElement): Steinitz Theorem (#7788)

Added Field.exists_primitive_element_iff_finite_intermediateField: a finite extension E / F has a primitive element if and only if the intermediate fields between E / F are finitely many. Also known as Steinitz Theorem https://en.wikipedia.org/wiki/Primitive_element_theorem#The_theorems.

Co-authored-by: Junyan Xu <junyanxu.math@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Junyan Xu <junyanxumath@gmail.com> Co-authored-by: Mario Carneiro <di.gama@gmail.com>

Diff
@@ -20,6 +20,10 @@ In this file we prove the primitive element theorem.
 - `exists_primitive_element`: a finite separable extension `E / F` has a primitive element, i.e.
   there is an `α : E` such that `F⟮α⟯ = (⊤ : Subalgebra F E)`.
 
+- `exists_primitive_element_iff_finite_intermediateField`: a finite extension `E / F` has a
+  primitive element if and only if there exist only finitely many intermediate fields between `E`
+  and `F`.
+
 ## Implementation notes
 
 In declaration names, `primitive_element` abbreviates `adjoin_simple_eq_top`:
@@ -52,7 +56,7 @@ variable (F : Type*) [Field F] (E : Type*) [Field E] [Algebra F E]
 
 /-- **Primitive element theorem** assuming E is finite. -/
 theorem exists_primitive_element_of_finite_top [Finite E] : ∃ α : E, F⟮α⟯ = ⊤ := by
-  obtain ⟨α, hα⟩ := @IsCyclic.exists_generator (Units E) _ _
+  obtain ⟨α, hα⟩ := @IsCyclic.exists_generator Eˣ _ _
   use α
   apply eq_top_iff.mpr
   rintro x -
@@ -97,8 +101,8 @@ variable (F)
 
 variable [Algebra F E]
 
--- This is the heart of the proof of the primitive element theorem. It shows that if `F` is
--- infinite and `α` and `β` are separable over `F` then `F⟮α, β⟯` is generated by a single element.
+/-- This is the heart of the proof of the primitive element theorem. It shows that if `F` is
+infinite and `α` and `β` are separable over `F` then `F⟮α, β⟯` is generated by a single element. -/
 theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯ = F⟮γ⟯ := by
   have hα := IsSeparable.isIntegral F α
   have hβ := IsSeparable.isIntegral F β
@@ -115,11 +119,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
       have α_in_Fγ : α ∈ F⟮γ⟯ := by
         rw [← add_sub_cancel α (c • β)]
         exact F⟮γ⟯.sub_mem (mem_adjoin_simple_self F γ) (F⟮γ⟯.toSubalgebra.smul_mem β_in_Fγ c)
-      exact fun x hx => by
-        -- Porting note: was `by cases hx <;> cases hx <;> cases hx <;> assumption`
-        cases' hx with hx hx
-        · rwa [← hx] at α_in_Fγ
-        · cases hx; norm_cast
+      rintro x (rfl | rfl) <;> assumption
     · rw [adjoin_simple_le_iff]
       have α_in_Fαβ : α ∈ F⟮α, β⟯ := subset_adjoin F {α, β} (Set.mem_insert α {β})
       have β_in_Fαβ : β ∈ F⟮α, β⟯ := subset_adjoin F {α, β} (Set.mem_insert_of_mem α rfl)
@@ -170,22 +170,50 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
   trans EuclideanDomain.gcd (?_ : E[X]) (?_ : E[X])
   · dsimp only
     convert (gcd_map (algebraMap F⟮γ⟯ E)).symm
-  · simp [map_comp, Polynomial.map_map, ← IsScalarTower.algebraMap_eq]
+  · simp only [map_comp, Polynomial.map_map, ← IsScalarTower.algebraMap_eq, Polynomial.map_sub,
+      map_C, AdjoinSimple.algebraMap_gen, map_add, Polynomial.map_mul, map_X]
     congr
 #align field.primitive_element_inf_aux Field.primitive_element_inf_aux
 
+-- If `F` is infinite and `E/F` has only finitely many intermediate fields, then for any
+-- `α` and `β` in `E`, `F⟮α, β⟯` is generated by a single element.
+-- Marked as private since it's a special case of
+-- `exists_primitive_element_of_finite_intermediateField`.
+private theorem primitive_element_inf_aux_of_finite_intermediateField
+    [Finite (IntermediateField F E)] : ∃ γ : E, F⟮α, β⟯ = F⟮γ⟯ := by
+  let f : F → IntermediateField F E := fun x ↦ F⟮α + x • β⟯
+  obtain ⟨x, y, hneq, heq⟩ := Finite.exists_ne_map_eq_of_infinite f
+  use α + x • β
+  apply le_antisymm
+  · rw [adjoin_le_iff]
+    have αxβ_in_K : α + x • β ∈ F⟮α + x • β⟯ := mem_adjoin_simple_self F _
+    have αyβ_in_K : α + y • β ∈ F⟮α + y • β⟯ := mem_adjoin_simple_self F _
+    simp only [← heq] at αyβ_in_K
+    have β_in_K := sub_mem αxβ_in_K αyβ_in_K
+    rw [show (α + x • β) - (α + y • β) = (x - y) • β by rw [sub_smul]; abel1] at β_in_K
+    replace β_in_K := smul_mem _ β_in_K (x := (x - y)⁻¹)
+    rw [smul_smul, inv_mul_eq_div, div_self (sub_ne_zero.2 hneq), one_smul] at β_in_K
+    have α_in_K : α ∈ F⟮α + x • β⟯ := by
+      convert ← sub_mem αxβ_in_K (smul_mem _ β_in_K)
+      apply add_sub_cancel
+    rintro x (rfl | rfl) <;> assumption
+  · rw [adjoin_simple_le_iff]
+    have α_in_Fαβ : α ∈ F⟮α, β⟯ := subset_adjoin F {α, β} (Set.mem_insert α {β})
+    have β_in_Fαβ : β ∈ F⟮α, β⟯ := subset_adjoin F {α, β} (Set.mem_insert_of_mem α rfl)
+    exact F⟮α, β⟯.add_mem α_in_Fαβ (F⟮α, β⟯.smul_mem β_in_Fαβ)
+
 end PrimitiveElementInf
 
 variable (F E : Type*) [Field F] [Field E]
 
-variable [Algebra F E] [FiniteDimensional F E]
+variable [Algebra F E]
 
 section SeparableAssumption
 
-variable [IsSeparable F E]
+variable [FiniteDimensional F E] [IsSeparable F E]
 
-/-- Primitive element theorem: a finite separable field extension `E` of `F` has a
-  primitive element, i.e. there is an `α ∈ E` such that `F⟮α⟯ = (⊤ : Subalgebra F E)`.-/
+/-- **Primitive element theorem**: a finite separable field extension `E` of `F` has a
+  primitive element, i.e. there is an `α ∈ E` such that `F⟮α⟯ = (⊤ : Subalgebra F E)`. -/
 theorem exists_primitive_element : ∃ α : E, F⟮α⟯ = ⊤ := by
   rcases isEmpty_or_nonempty (Fintype F) with (F_inf | ⟨⟨F_finite⟩⟩)
   · let P : IntermediateField F E → Prop := fun K => ∃ α : E, F⟮α⟯ = K
@@ -214,6 +242,110 @@ noncomputable def powerBasisOfFiniteOfSeparable : PowerBasis F E :=
 
 end SeparableAssumption
 
+section FiniteIntermediateField
+
+-- TODO: show a more generalized result: [F⟮α⟯ : F⟮α ^ m⟯] = m if m > 0 and α transcendental.
+theorem isAlgebraic_of_adjoin_eq_adjoin {α : E} {m n : ℕ} (hneq : m ≠ n)
+    (heq : F⟮α ^ m⟯ = F⟮α ^ n⟯) : IsAlgebraic F α := by
+  wlog hmn : m < n
+  · exact this F E hneq.symm heq.symm (hneq.lt_or_lt.resolve_left hmn)
+  by_cases hm : m = 0
+  · rw [hm] at heq hmn
+    simp only [pow_zero, adjoin_one] at heq
+    obtain ⟨y, h⟩ := mem_bot.1 (heq.symm ▸ mem_adjoin_simple_self F (α ^ n))
+    refine ⟨X ^ n - C y, X_pow_sub_C_ne_zero hmn y, ?_⟩
+    simp only [map_sub, map_pow, aeval_X, aeval_C, h, sub_self]
+  replace hm : 0 < m := Nat.pos_of_ne_zero hm
+  obtain ⟨r, s, h⟩ := (mem_adjoin_simple_iff F _).1 (heq ▸ mem_adjoin_simple_self F (α ^ m))
+  by_cases hzero : aeval (α ^ n) s = 0
+  · simp only [hzero, div_zero, pow_eq_zero_iff hm] at h
+    exact h.symm ▸ isAlgebraic_zero
+  · rw [eq_div_iff hzero, ← sub_eq_zero] at h
+    replace hzero : s ≠ 0 := by rintro rfl; simp only [map_zero] at hzero
+    let f : F[X] := X ^ m * expand F n s - expand F n r
+    refine ⟨f, ?_, ?_⟩
+    · have : f.coeff (n * s.natDegree + m) ≠ 0 := by
+        have hn : 0 < n := by linarith only [hm, hmn]
+        have hndvd : ¬ n ∣ n * s.natDegree + m := by
+          rw [← Nat.dvd_add_iff_right (n.dvd_mul_right s.natDegree)]
+          exact Nat.not_dvd_of_pos_of_lt hm hmn
+        simp only [coeff_sub, coeff_X_pow_mul, s.coeff_expand_mul' hn, coeff_natDegree,
+          coeff_expand hn r, hndvd, ite_false, sub_zero]
+        exact leadingCoeff_ne_zero.2 hzero
+      intro h
+      simp only [h, coeff_zero, ne_eq] at this
+    · simp only [map_sub, map_mul, map_pow, aeval_X, expand_aeval, h]
+
+theorem isAlgebraic_of_finite_intermediateField
+    [Finite (IntermediateField F E)] : Algebra.IsAlgebraic F E := fun α ↦
+  have ⟨_m, _n, hneq, heq⟩ := Finite.exists_ne_map_eq_of_infinite fun n ↦ F⟮α ^ n⟯
+  isAlgebraic_of_adjoin_eq_adjoin F E hneq heq
+
+theorem finiteDimensional_of_finite_intermediateField
+    [Finite (IntermediateField F E)] : FiniteDimensional F E := by
+  let IF := { K : IntermediateField F E // ∃ x, K = F⟮x⟯ }
+  haveI : ∀ K : IF, FiniteDimensional F K.1 := fun ⟨_, x, rfl⟩ ↦ adjoin.finiteDimensional <|
+    isAlgebraic_iff_isIntegral.1 (isAlgebraic_of_finite_intermediateField F E x)
+  have hfin := finiteDimensional_iSup_of_finite (t := fun K : IF ↦ K.1)
+  have htop : ⨆ K : IF, K.1 = ⊤ := le_top.antisymm fun x _ ↦
+    le_iSup (fun K : IF ↦ K.1) ⟨F⟮x⟯, x, rfl⟩ <| mem_adjoin_simple_self F x
+  rw [htop] at hfin
+  exact topEquiv.toLinearEquiv.finiteDimensional
+
+theorem exists_primitive_element_of_finite_intermediateField
+    [Finite (IntermediateField F E)] (K : IntermediateField F E) : ∃ α : E, F⟮α⟯ = K := by
+  haveI := finiteDimensional_of_finite_intermediateField F E
+  rcases finite_or_infinite F with (_ | _)
+  · obtain ⟨α, h⟩ := exists_primitive_element_of_finite_bot F K
+    exact ⟨α, by simpa only [lift_adjoin_simple, lift_top] using congr_arg lift h⟩
+  · apply induction_on_adjoin (fun K ↦ ∃ α : E, F⟮α⟯ = K) ⟨0, adjoin_zero⟩
+    rintro K β ⟨α, rfl⟩
+    simp_rw [adjoin_simple_adjoin_simple, eq_comm]
+    exact primitive_element_inf_aux_of_finite_intermediateField F α β
+
+theorem finiteDimensional_of_exists_primitive_element (halg : Algebra.IsAlgebraic F E)
+    (h : ∃ α : E, F⟮α⟯ = ⊤) : FiniteDimensional F E := by
+  obtain ⟨α, hprim⟩ := h
+  have hfin := adjoin.finiteDimensional <| isAlgebraic_iff_isIntegral.1 (halg α)
+  rw [hprim] at hfin
+  exact topEquiv.toLinearEquiv.finiteDimensional
+
+-- A finite simple extension has only finitely many intermediate fields
+theorem finite_intermediateField_of_exists_primitive_element (halg : Algebra.IsAlgebraic F E)
+    (h : ∃ α : E, F⟮α⟯ = ⊤) : Finite (IntermediateField F E) := by
+  haveI := finiteDimensional_of_exists_primitive_element F E halg h
+  obtain ⟨α, hprim⟩ := h
+  -- Let `f` be the minimal polynomial of `α ∈ E` over `F`
+  let f : F[X] := minpoly F α
+  let G := { g : E[X] // g.Monic ∧ g ∣ f.map (algebraMap F E) }
+  -- Then `f` has only finitely many monic factors
+  have hfin : Finite G := @Finite.of_fintype _ <| fintypeSubtypeMonicDvd
+    (f.map (algebraMap F E)) <| map_ne_zero (minpoly.ne_zero_of_finite F α)
+  -- If `K` is an intermediate field of `E/F`, let `g` be the minimal polynomial of `α` over `K`
+  -- which is a monic factor of `f`
+  let g : IntermediateField F E → G := fun K ↦
+    ⟨(minpoly K α).map (algebraMap K E), (minpoly.monic <| isIntegral_of_finite K α).map _, by
+      convert Polynomial.map_dvd (algebraMap K E) (minpoly.dvd_map_of_isScalarTower F K α)
+      rw [Polynomial.map_map]; rfl⟩
+  -- The map `K ↦ g` is injective
+  have hinj : Function.Injective g := fun K K' heq ↦ by
+    rw [Subtype.mk.injEq] at heq
+    apply_fun fun f : E[X] ↦ adjoin F (f.frange : Set E) at heq
+    simpa only [adjoin_minpoly_coeff_of_exists_primitive_element F hprim] using heq
+  -- Therefore there are only finitely many intermediate fields
+  exact Finite.of_injective g hinj
+
+/-- **Steinitz theorem**: an algebraic extension `E` of `F` has a
+  primitive element (i.e. there is an `α ∈ E` such that `F⟮α⟯ = (⊤ : Subalgebra F E)`)
+  if and only if there exist only finitely many intermediate fields between `E` and `F`. -/
+theorem exists_primitive_element_iff_finite_intermediateField :
+    (Algebra.IsAlgebraic F E ∧ ∃ α : E, F⟮α⟯ = ⊤) ↔ Finite (IntermediateField F E) :=
+  ⟨fun ⟨halg, h⟩ ↦ finite_intermediateField_of_exists_primitive_element F E halg h,
+    fun _ ↦ ⟨isAlgebraic_of_finite_intermediateField F E,
+      exists_primitive_element_of_finite_intermediateField F E _⟩⟩
+
+end FiniteIntermediateField
+
 end Field
 
 @[simp]
chore: banish Type _ and Sort _ (#6499)

We remove all possible occurences of Type _ and Sort _ in favor of Type* and Sort*.

This has nice performance benefits.

Diff
@@ -45,7 +45,7 @@ namespace Field
 
 section PrimitiveElementFinite
 
-variable (F : Type _) [Field F] (E : Type _) [Field E] [Algebra F E]
+variable (F : Type*) [Field F] (E : Type*) [Field E] [Algebra F E]
 
 /-! ### Primitive element theorem for finite fields -/
 
@@ -79,7 +79,7 @@ end PrimitiveElementFinite
 
 section PrimitiveElementInf
 
-variable {F : Type _} [Field F] [Infinite F] {E : Type _} [Field E] (ϕ : F →+* E) (α β : E)
+variable {F : Type*} [Field F] [Infinite F] {E : Type*} [Field E] (ϕ : F →+* E) (α β : E)
 
 theorem primitive_element_inf_aux_exists_c (f g : F[X]) :
     ∃ c : F, ∀ α' ∈ (f.map ϕ).roots, ∀ β' ∈ (g.map ϕ).roots, -(α' - α) / (β' - β) ≠ ϕ c := by
@@ -176,7 +176,7 @@ theorem primitive_element_inf_aux [IsSeparable F E] : ∃ γ : E, F⟮α, β⟯
 
 end PrimitiveElementInf
 
-variable (F E : Type _) [Field F] [Field E]
+variable (F E : Type*) [Field F] [Field E]
 
 variable [Algebra F E] [FiniteDimensional F E]
 
@@ -217,7 +217,7 @@ end SeparableAssumption
 end Field
 
 @[simp]
-theorem AlgHom.card (F E K : Type _) [Field F] [Field E] [Field K] [IsAlgClosed K] [Algebra F E]
+theorem AlgHom.card (F E K : Type*) [Field F] [Field E] [Field K] [IsAlgClosed K] [Algebra F E]
     [FiniteDimensional F E] [IsSeparable F E] [Algebra F K] :
     Fintype.card (E →ₐ[F] K) = finrank F E := by
   convert (AlgHom.card_of_powerBasis (L := K) (Field.powerBasisOfFiniteOfSeparable F E)
chore: tidy various files (#6291)
Diff
@@ -194,7 +194,7 @@ theorem exists_primitive_element : ∃ α : E, F⟮α⟯ = ⊤ := by
       intro K β hK
       cases' hK with α hK
       rw [← hK, adjoin_simple_adjoin_simple]
-      haveI : Infinite F := is_empty_fintype.mp F_inf
+      haveI : Infinite F := isEmpty_fintype.mp F_inf
       cases' primitive_element_inf_aux F α β with γ hγ
       exact ⟨γ, hγ.symm⟩
     exact induction_on_adjoin P base ih ⊤
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,17 +2,14 @@
 Copyright (c) 2020 Thomas Browning, Patrick Lutz. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Thomas Browning, Patrick Lutz
-
-! This file was ported from Lean 3 source module field_theory.primitive_element
-! leanprover-community/mathlib commit df76f43357840485b9d04ed5dee5ab115d420e87
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.FieldTheory.SplittingField.Construction
 import Mathlib.FieldTheory.IsAlgClosed.Basic
 import Mathlib.FieldTheory.Separable
 import Mathlib.RingTheory.IntegralDomain
 
+#align_import field_theory.primitive_element from "leanprover-community/mathlib"@"df76f43357840485b9d04ed5dee5ab115d420e87"
+
 /-!
 # Primitive Element Theorem
 
feat: port FieldTheory.PrimitiveElement (#5071)

Co-authored-by: Riccardo Brasca <riccardo.brasca@gmail.com>

Dependencies 10 + 683

684 files ported (98.6%)
282957 lines ported (98.8%)
Show graph

The unported dependencies are