field_theory.splitting_field.constructionMathlib.FieldTheory.SplittingField.Construction

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)

(last sync)

chore(field_theory/splitting_field): refactor splitting_field (#19178)

We refactor the definition of splitting_field. The main motivation is to backport 4#4891 since the is seems very problematic to port the current design.

Zulip discussion relevant to this PR: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/!4.234891.20.20FieldTheory.2ESplittingField

Diff
@@ -19,6 +19,12 @@ In this file we prove the existence and uniqueness of splitting fields.
 * `polynomial.is_splitting_field.alg_equiv`: Every splitting field of a polynomial `f` is isomorphic
   to `splitting_field f` and thus, being a splitting field is unique up to isomorphism.
 
+## Implementation details
+We construct a `splitting_field_aux` without worrying about whether the instances satisfy nice
+definitional equalities. Then the actual `splitting_field` is defined to be a quotient of a
+`mv_polynomial` ring by the kernel of the obvious map into `splitting_field_aux`. Because the
+actual `splitting_field` will be a quotient of a `mv_polynomial`, it has nice instances on it.
+
 -/
 
 noncomputable theory
@@ -86,248 +92,38 @@ by rw [nat_degree_remove_factor, hfn, n.add_sub_cancel]
 /-- Auxiliary construction to a splitting field of a polynomial, which removes
 `n` (arbitrarily-chosen) factors.
 
-Uses recursion on the degree. For better definitional behaviour, structures
-including `splitting_field_aux` (such as instances) should be defined using
-this recursion in each field, rather than defining the whole tuple through
-recursion.
--/
-def splitting_field_aux (n : ℕ) : Π {K : Type u} [field K], by exactI Π (f : K[X]), Type u :=
-nat.rec_on n (λ K _ _, K) $ λ n ih K _ f, by exactI
-ih f.remove_factor
-
-namespace splitting_field_aux
-
-theorem succ (n : ℕ) (f : K[X]) :
-  splitting_field_aux (n+1) f = splitting_field_aux n f.remove_factor := rfl
-
-section lift_instances
+It constructs the type, proves that is a field and algebra over the base field.
 
-/-! ### Instances on `splitting_field_aux`
-
-In order to avoid diamond issues, we have to be careful to define each data field of algebraic
-instances on `splitting_field_aux` by recursion, rather than defining the whole structure by
-recursion at once.
+Uses recursion on the degree.
+-/
+def splitting_field_aux_aux (n : ℕ) : Π {K : Type u} [field K], by exactI Π (f : K[X]),
+  Σ (L : Type u) (inst : field L), by exactI algebra K L :=
+nat.rec_on n (λ K inst f, ⟨K, inst, infer_instance⟩) (λ m ih K inst f,
+  let L := ih (@remove_factor K inst f) in let h₁ := L.2.1 in let h₂ := L.2.2 in
+  ⟨L.1, L.2.1, by
+    { exactI (ring_hom.comp (algebra_map _ _) (adjoin_root.of f.factor)).to_algebra }⟩)
 
-The important detail is that the `smul` instances can be lifted _before_ we create the algebraic
-instances; if we do not do this, this creates a mutual dependence on both on each other, and it
-is impossible to untangle this mess. In order to do this, we need that these `smul` instances
-are distributive in the sense of `distrib_smul`, which is weak enough to be guaranteed at this
-stage. This is sufficient to lift an action to `adjoin_root f` (remember that this is a quotient,
-so these conditions are equivalent to well-definedness), which is all we need.
+/-- Auxiliary construction to a splitting field of a polynomial, which removes
+`n` (arbitrarily-chosen) factors. It is the type constructed in `splitting_field_aux_aux`.
 -/
+def splitting_field_aux (n : ℕ) {K : Type u} [field K] (f : K[X]) : Type u :=
+  (splitting_field_aux_aux n f).1
 
-/-- Splitting fields have a zero. -/
-protected def zero (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, by exactI @has_zero.zero K _) (λ n ih K fK f, ih)
-
-/-- Splitting fields have an addition. -/
-protected def add (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  splitting_field_aux n f → splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, by exactI @has_add.add K _) (λ n ih K fK f, ih)
-
-/-- Splitting fields inherit scalar multiplication. -/
-protected def smul (n : ℕ) : Π (α : Type*) {K : Type u} [field K],
-  by exactI Π [distrib_smul α K],
-  by exactI Π [is_scalar_tower α K K] {f : K[X]},
-  α → splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n
-  (λ α K fK ds ist f, by exactI @has_smul.smul _ K _)
-  (λ n ih α K fK ds ist f, by exactI ih α)
-
-instance has_smul (α : Type*) (n : ℕ) {K : Type u} [field K] [distrib_smul α K]
-  [is_scalar_tower α K K] {f : K[X]} :
-  has_smul α (splitting_field_aux n f) :=
-⟨splitting_field_aux.smul n α⟩
-
-instance is_scalar_tower (n : ℕ) : Π (R₁ R₂ : Type*) {K : Type u}
-  [has_smul R₁ R₂] [field K],
-  by exactI Π [distrib_smul R₂ K] [distrib_smul R₁ K],
-  by exactI Π [is_scalar_tower R₁ K K] [is_scalar_tower R₂ K K] [is_scalar_tower R₁ R₂ K]
-    {f : K[X]}, by exactI is_scalar_tower R₁ R₂ (splitting_field_aux n f) :=
-nat.rec_on n (λ R₁ R₂ K _ _ hs₂ hs₁ _ _ h f,
-begin
-  rcases hs₁ with @⟨@⟨⟨hs₁⟩,_⟩,_⟩,
-  rcases hs₂ with @⟨@⟨⟨hs₂⟩,_⟩,_⟩,
-  exact h,
-end) $ λ n ih R₁ R₂ K _ _ _ _ _ _ _ f, by exactI ih R₁ R₂
-
-/-- Splitting fields have a negation. -/
-protected def neg (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, by exactI @has_neg.neg K _) (λ n ih K fK f, ih)
-
-/-- Splitting fields have subtraction. -/
-protected def sub (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  splitting_field_aux n f → splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, by exactI @has_sub.sub K _) (λ n ih K fK f, ih)
-
-/-- Splitting fields have a one. -/
-protected def one (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, by exactI @has_one.one K _) (λ n ih K fK f, ih)
-
-/-- Splitting fields have a multiplication. -/
-protected def mul (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  splitting_field_aux n f → splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, by exactI @has_mul.mul K _) (λ n ih K fK f, ih)
-
-/-- Splitting fields have a power operation. -/
-protected def npow (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  ℕ → splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f n x, by exactI @has_pow.pow K _ _ x n) (λ n ih K fK f, ih)
-
-/-- Splitting fields have an injection from the base field. -/
-protected def mk (n : ℕ) : Π {K : Type u} [field K],
-  by exactI Π {f : K[X]}, K → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, id) (λ n ih K fK f, by exactI ih ∘ coe)
--- note that `coe` goes from `K → adjoin_root f`, and then `ih` lifts to the full splitting field
--- (as we generalise over all fields in this recursion!)
-
-/-- Splitting fields have an inverse. -/
-protected def inv (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, by exactI @has_inv.inv K _) (λ n ih K fK f, ih)
-
-/-- Splitting fields have a division. -/
-protected def div (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  splitting_field_aux n f → splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f, by exactI @has_div.div K _) (λ n ih K fK f, ih)
-
-/-- Splitting fields have powers by integers. -/
-protected def zpow (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]},
-  ℤ → splitting_field_aux n f → splitting_field_aux n f :=
-nat.rec_on n (λ K fK f n x, by exactI @has_pow.pow K _ _ x n) (λ n ih K fK f, ih)
-
--- I'm not sure why these two lemmas break, but inlining them seems to not work.
-private lemma nsmul_zero (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]}
-  (x : splitting_field_aux n f), (0 : ℕ) • x = splitting_field_aux.zero n :=
-nat.rec_on n (λ K fK f, by exactI zero_nsmul) (λ n ih K fK f, by exactI ih)
-
-private lemma nsmul_succ (n : ℕ) : Π {K : Type u} [field K], by exactI Π {f : K[X]}
-  (k : ℕ) (x : splitting_field_aux n f),
-  (k + 1) • x = splitting_field_aux.add n x (k • x) :=
-nat.rec_on n (λ K fK f n x, by exactI succ_nsmul x n) (λ n ih K fK f, by exactI ih)
-
-instance field (n : ℕ) {K : Type u} [field K] {f : K[X]} :
-  field (splitting_field_aux n f) :=
-begin
-  refine
-  { zero := splitting_field_aux.zero n,
-    one := splitting_field_aux.one n,
-    add := splitting_field_aux.add n,
-    zero_add := have h : _ := @zero_add, _,
-    add_zero := have h : _ := @add_zero, _,
-    add_assoc := have h : _ := @add_assoc, _,
-    add_comm := have h : _ := @add_comm, _,
-    neg := splitting_field_aux.neg n,
-    add_left_neg := have h : _ := @add_left_neg, _,
-    sub := splitting_field_aux.sub n,
-    sub_eq_add_neg := have h : _ := @sub_eq_add_neg, _,
-    mul := splitting_field_aux.mul n,
-    one_mul := have h : _ := @one_mul, _,
-    mul_one := have h : _ := @mul_one, _,
-    mul_assoc := have h : _ := @mul_assoc, _,
-    left_distrib := have h : _ := @left_distrib, _,
-    right_distrib := have h : _ := @right_distrib, _,
-    mul_comm := have h : _ := @mul_comm, _,
-    inv := splitting_field_aux.inv n,
-    inv_zero := have h : _ := @inv_zero, _,
-    div := splitting_field_aux.div n,
-    div_eq_mul_inv := have h : _ := @div_eq_mul_inv, _,
-    mul_inv_cancel := have h : _ := @mul_inv_cancel, _,
-    exists_pair_ne := have h : _ := @exists_pair_ne, _,
-    nat_cast := splitting_field_aux.mk n ∘ (coe : ℕ → K),
-    nat_cast_zero := have h : _ := @comm_ring.nat_cast_zero, _,
-    nat_cast_succ := have h : _ := @comm_ring.nat_cast_succ, _,
-    nsmul := (•),
-    nsmul_zero' := nsmul_zero n,
-    nsmul_succ' := nsmul_succ n,
-    int_cast := splitting_field_aux.mk n ∘ (coe : ℤ → K),
-    int_cast_of_nat := have h : _ := @comm_ring.int_cast_of_nat, _,
-    int_cast_neg_succ_of_nat := have h : _ := @comm_ring.int_cast_neg_succ_of_nat, _,
-    zsmul := (•),
-    zsmul_zero' := have h : _ := @subtraction_comm_monoid.zsmul_zero', _,
-    zsmul_succ' := have h : _ := @subtraction_comm_monoid.zsmul_succ', _,
-    zsmul_neg' := have h : _ := @subtraction_comm_monoid.zsmul_neg', _,
-    rat_cast := splitting_field_aux.mk n ∘ (coe : ℚ → K),
-    rat_cast_mk := have h : _ := @field.rat_cast_mk, _,
-    qsmul := (•),
-    qsmul_eq_mul' := have h : _ := @field.qsmul_eq_mul', _,
-    npow := splitting_field_aux.npow n,
-    npow_zero' := have h : _ := @comm_ring.npow_zero', _,
-    npow_succ' := have h : _ := @comm_ring.npow_succ', _,
-    zpow := splitting_field_aux.zpow n,
-    zpow_zero' := have h : _ := @field.zpow_zero', _,
-    zpow_succ' := have h : _ := @field.zpow_succ', _,
-    zpow_neg' := have h : _ := @field.zpow_neg', _},
-  all_goals {
-    unfreezingI { induction n with n ih generalizing K },
-    { apply @h K },
-    { exact @ih _ _ _ } },
-end
+instance splitting_field_aux.field (n : ℕ) {K : Type u} [field K] (f : K[X]) :
+    field (splitting_field_aux n f) :=
+  (splitting_field_aux_aux n f).2.1
 
-instance inhabited {n : ℕ} {f : K[X]} :
-  inhabited (splitting_field_aux n f) := ⟨37⟩
+instance  (n : ℕ) {K : Type u} [field K] (f : K[X]) : inhabited (splitting_field_aux n f) :=
+⟨0⟩
 
-/-- The injection from the base field as a ring homomorphism. -/
-@[simps] protected def mk_hom (n : ℕ) {K : Type u} [field K] {f : K[X]} :
-  K →+* splitting_field_aux n f :=
-{ to_fun := splitting_field_aux.mk n,
-  map_one' :=
-  begin
-    unfreezingI { induction n with k hk generalizing K },
-    { simp [splitting_field_aux.mk] },
-    exact hk
-  end,
-  map_mul' :=
-  begin
-    unfreezingI { induction n with k hk generalizing K },
-    { simp [splitting_field_aux.mk] },
-    intros x y,
-    change (splitting_field_aux.mk k) ((adjoin_root.of f.factor) _) = _,
-    rw [map_mul],
-    exact hk _ _
-  end,
-  map_zero' :=
-  begin
-    unfreezingI { induction n with k hk generalizing K },
-    { simp [splitting_field_aux.mk] },
-    change (splitting_field_aux.mk k) ((adjoin_root.of f.factor) 0) = _,
-    rw [map_zero, hk],
-  end,
-  map_add' :=
-  begin
-    unfreezingI { induction n with k hk generalizing K },
-    { simp [splitting_field_aux.mk] },
-    intros x y,
-    change (splitting_field_aux.mk k) ((adjoin_root.of f.factor) _) = _,
-    rw [map_add],
-    exact hk _ _
-  end }
-
-instance algebra (n : ℕ) (R : Type*) {K : Type u} [comm_semiring R] [field K]
-  [algebra R K] {f : K[X]} : algebra R (splitting_field_aux n f) :=
-{ to_fun := (splitting_field_aux.mk_hom n).comp (algebra_map R K),
-  smul := (•),
-  smul_def' :=
-  begin
-    unfreezingI { induction n with k hk generalizing K },
-    { exact algebra.smul_def },
-    exact hk
-  end,
-  commutes' := λ a b, mul_comm _ _,
-  .. (splitting_field_aux.mk_hom n).comp (algebra_map R K) }
-
-/-- Because `splitting_field_aux` is defined by recursion, we have to make sure all instances
-on `splitting_field_aux` are defined by recursion within the fields. Otherwise, there will be
-instance diamonds such as the following: -/
-example (n : ℕ) {K : Type u} [field K] {f : K[X]} :
-    (add_comm_monoid.nat_module : module ℕ (splitting_field_aux n f)) =
-  @algebra.to_module _ _ _ _ (splitting_field_aux.algebra n _) :=
-rfl
+instance splitting_field_aux.algebra (n : ℕ) {K : Type u} [field K] (f : K[X]) :
+    algebra K (splitting_field_aux n f) :=
+  (splitting_field_aux_aux n f).2.2
 
-end lift_instances
+namespace splitting_field_aux
+
+theorem succ (n : ℕ) (f : K[X]) :
+  splitting_field_aux (n+1) f = splitting_field_aux n f.remove_factor := rfl
 
 instance algebra''' {n : ℕ} {f : K[X]} :
   algebra (adjoin_root f.factor)
@@ -340,29 +136,19 @@ splitting_field_aux.algebra'''
 
 instance algebra'' {n : ℕ} {f : K[X]} :
   algebra K (splitting_field_aux n f.remove_factor) :=
-splitting_field_aux.algebra n K
+ring_hom.to_algebra (ring_hom.comp (algebra_map _ _) (adjoin_root.of f.factor))
 
 instance scalar_tower' {n : ℕ} {f : K[X]} :
   is_scalar_tower K (adjoin_root f.factor)
     (splitting_field_aux n f.remove_factor) :=
-begin
-  -- finding this instance ourselves makes things faster
-  haveI : is_scalar_tower K (adjoin_root f.factor) (adjoin_root f.factor) :=
-    is_scalar_tower.right,
-  exact
-    splitting_field_aux.is_scalar_tower n K (adjoin_root f.factor),
-end
-
-instance scalar_tower {n : ℕ} {f : K[X]} :
-  is_scalar_tower K (adjoin_root f.factor) (splitting_field_aux (n + 1) f) :=
-splitting_field_aux.scalar_tower'
+is_scalar_tower.of_algebra_map_eq (λ x, rfl)
 
 theorem algebra_map_succ (n : ℕ) (f : K[X]) :
   by exact algebra_map K (splitting_field_aux (n+1) f) =
     (algebra_map (adjoin_root f.factor)
         (splitting_field_aux n f.remove_factor)).comp
       (adjoin_root.of f.factor) :=
-is_scalar_tower.algebra_map_eq _ _ _
+rfl
 
 protected theorem splits (n : ℕ) : ∀ {K : Type u} [field K], by exactI
   ∀ (f : K[X]) (hfn : f.nat_degree = n),
@@ -373,24 +159,6 @@ by { resetI, rw [← splits_id_iff_splits, algebra_map_succ, ← map_map, splits
     ← X_sub_C_mul_remove_factor f (λ h, by { rw h at hf, cases hf })],
 exact splits_mul _ (splits_X_sub_C _) (ih _ (nat_degree_remove_factor' hf)) }
 
-theorem exists_lift (n : ℕ) : ∀ {K : Type u} [field K], by exactI
-  ∀ (f : K[X]) (hfn : f.nat_degree = n) {L : Type*} [field L], by exactI
-    ∀ (j : K →+* L) (hf : splits j f), ∃ k : splitting_field_aux n f →+* L,
-      k.comp (algebra_map _ _) = j :=
-nat.rec_on n (λ K _ _ _ L _ j _, by exactI ⟨j, j.comp_id⟩) $ λ n ih K _ f hf L _ j hj, by exactI
-have hndf : f.nat_degree ≠ 0, by { intro h, rw h at hf, cases hf },
-have hfn0 : f ≠ 0, by { intro h, rw h at hndf, exact hndf rfl },
-let ⟨r, hr⟩ := exists_root_of_splits _ (splits_of_splits_of_dvd j hfn0 hj
-  (factor_dvd_of_nat_degree_ne_zero hndf))
-  (mt is_unit_iff_degree_eq_zero.2 f.irreducible_factor.1) in
-have hmf0 : map (adjoin_root.of f.factor) f ≠ 0, from map_ne_zero hfn0,
-have hsf : splits (adjoin_root.lift j r hr) f.remove_factor,
-by { rw ← X_sub_C_mul_remove_factor _ hndf at hmf0, refine (splits_of_splits_mul _ hmf0 _).2,
-  rwa [X_sub_C_mul_remove_factor _ hndf, ← splits_id_iff_splits, map_map, adjoin_root.lift_comp_of,
-      splits_id_iff_splits] },
-let ⟨k, hk⟩ := ih f.remove_factor (nat_degree_remove_factor' hf) (adjoin_root.lift j r hr) hsf in
-⟨k, by rw [algebra_map_succ, ← ring_hom.comp_assoc, hk, adjoin_root.lift_comp_of]⟩
-
 theorem adjoin_root_set (n : ℕ) : ∀ {K : Type u} [field K], by exactI
   ∀ (f : K[X]) (hfn : f.nat_degree = n),
     algebra.adjoin K (f.root_set (splitting_field_aux n f)) = ⊤ :=
@@ -414,26 +182,108 @@ begin
       ih _ (nat_degree_remove_factor' hfn), subalgebra.restrict_scalars_top]
 end
 
+instance (f : K[X]) : is_splitting_field K (splitting_field_aux f.nat_degree f) f :=
+  ⟨splitting_field_aux.splits _ _ rfl, splitting_field_aux.adjoin_root_set _ _ rfl⟩
+
+/-- The natural map from `mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f))`
+to `splitting_field_aux f.nat_degree f` sendind a variable to the corresponding root. -/
+def of_mv_polynomial (f : K[X]) :
+    mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f)) K →ₐ[K]
+    splitting_field_aux f.nat_degree f :=
+  mv_polynomial.aeval (λ i, i.1)
+
+theorem of_mv_polynomial_surjective (f : K[X]) : function.surjective (of_mv_polynomial f) :=
+begin
+  suffices : alg_hom.range (of_mv_polynomial f) = ⊤,
+  { rw [← set.range_iff_surjective]; rwa [set_like.ext'_iff] at this },
+  rw [of_mv_polynomial, ← algebra.adjoin_range_eq_range_aeval K, eq_top_iff,
+    ← adjoin_root_set _ _ rfl],
+  exact algebra.adjoin_le (λ α hα, algebra.subset_adjoin ⟨⟨α, hα⟩, rfl⟩)
+end
+
+/-- The algebra isomorphism between the quotient of
+`mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f)) K` by the kernel of
+`of_mv_polynomial f` and `splitting_field_aux f.nat_degree f`. It is used to transport all the
+algebraic structures from the latter to `f.splitting_field`, that is defined as the former. -/
+def alg_equiv_quotient_mv_polynomial (f : K[X]) :
+    (mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f)) K ⧸
+      ring_hom.ker (of_mv_polynomial f).to_ring_hom) ≃ₐ[K]
+    splitting_field_aux f.nat_degree f :=
+  (ideal.quotient_ker_alg_equiv_of_surjective (of_mv_polynomial_surjective f) : _)
+
 end splitting_field_aux
 
 /-- A splitting field of a polynomial. -/
 def splitting_field (f : K[X]) :=
-splitting_field_aux f.nat_degree f
+mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f)) K ⧸
+    ring_hom.ker (splitting_field_aux.of_mv_polynomial f).to_ring_hom
 
 namespace splitting_field
 
 variables (f : K[X])
 
-instance : field (splitting_field f) :=
-splitting_field_aux.field _
+instance comm_ring : comm_ring (splitting_field f) :=
+ideal.quotient.comm_ring _
+
+instance inhabited : inhabited (splitting_field f) :=
+  ⟨37⟩
 
-instance inhabited : inhabited (splitting_field f) := ⟨37⟩
+instance {S : Type*} [distrib_smul S K] [is_scalar_tower S K K] :
+  has_smul S (splitting_field f) :=
+  submodule.quotient.has_smul' _
 
-instance algebra' {R} [comm_semiring R] [algebra R K] : algebra R (splitting_field f) :=
-splitting_field_aux.algebra _ _
+instance algebra : algebra K (splitting_field f) :=
+ideal.quotient.algebra _
 
-instance : algebra K (splitting_field f) :=
-splitting_field_aux.algebra _ _
+instance algebra' {R : Type*} [comm_semiring R] [algebra R K] : algebra R (splitting_field f) :=
+ideal.quotient.algebra _
+
+instance is_scalar_tower {R : Type*} [comm_semiring R] [algebra R K] :
+  is_scalar_tower R K (splitting_field f) :=
+ideal.quotient.is_scalar_tower _ _ _
+
+/-- The algebra equivalence with `splitting_field_aux`,
+which we will use to construct the field structure. -/
+def alg_equiv_splitting_field_aux (f : K[X]) :
+    splitting_field f ≃ₐ[K] splitting_field_aux f.nat_degree f :=
+  splitting_field_aux.alg_equiv_quotient_mv_polynomial f
+
+instance : field (splitting_field f) :=
+let e := alg_equiv_splitting_field_aux f in
+{ rat_cast := λ a, algebra_map K _ (a : K),
+  inv := λ a, e.symm (e a)⁻¹,
+  qsmul := (•),
+  qsmul_eq_mul' := λ a x, quotient.induction_on' x (λ p, congr_arg quotient.mk'
+  begin
+    ext,
+    simp only [mv_polynomial.algebra_map_eq, rat.smul_def, mv_polynomial.coeff_smul,
+      mv_polynomial.coeff_C_mul],
+  end),
+  rat_cast_mk := λ a b h1 h2,
+  begin
+    apply e.injective,
+    change e (algebra_map K _ _) = _,
+    simp only [map_rat_cast, map_nat_cast, map_mul, map_int_cast, alg_equiv.commutes],
+    change _ = e ↑a * e (e.symm (e b)⁻¹),
+    rw [alg_equiv.apply_symm_apply],
+    convert field.rat_cast_mk a b h1 h2,
+    all_goals { simp },
+  end,
+  exists_pair_ne := ⟨e.symm 0, e.symm 1, λ w, zero_ne_one ((e.symm).injective w)⟩,
+  mul_inv_cancel := λ a w,
+  begin
+    apply e.injective,
+    rw [map_mul, map_one],
+    change e a * e (e.symm (e a)⁻¹) = 1,
+    rw [alg_equiv.apply_symm_apply, mul_inv_cancel],
+    exact (λ w', w (by simpa only [add_equiv_class.map_eq_zero_iff] using w')),
+  end,
+  inv_zero :=
+  begin
+    change e.symm (e 0)⁻¹ = 0,
+    simp
+  end,
+  ..splitting_field.comm_ring f }
 
 instance [char_zero K] : char_zero (splitting_field f) :=
 char_zero_of_injective_algebra_map ((algebra_map K _).injective)
@@ -451,24 +301,23 @@ rfl
 example [char_zero K] : (splitting_field.algebra' f) = algebra_rat :=
 rfl
 
-example [char_zero K] : (splitting_field.algebra' f) = algebra_rat :=
-rfl
-
 example {q : ℚ[X]} : algebra_int (splitting_field q) = splitting_field.algebra' q := rfl
 
+instance _root_.polynomial.is_splitting_field.splitting_field (f : K[X]) :
+    is_splitting_field K (splitting_field f) f :=
+  is_splitting_field.of_alg_equiv _ f (splitting_field_aux.alg_equiv_quotient_mv_polynomial f).symm
+
 protected theorem splits : splits (algebra_map K (splitting_field f)) f :=
-splitting_field_aux.splits _ _ rfl
+is_splitting_field.splits f.splitting_field f
 
 variables [algebra K L] (hb : splits (algebra_map K L) f)
 
 /-- Embeds the splitting field into any other field that splits the polynomial. -/
 def lift : splitting_field f →ₐ[K] L :=
-{ commutes' := λ r, by { have := classical.some_spec (splitting_field_aux.exists_lift _ _ rfl _ hb),
-    exact ring_hom.ext_iff.1 this r },
-  .. classical.some (splitting_field_aux.exists_lift _ _ _ _ hb) }
+is_splitting_field.lift f.splitting_field f hb
 
 theorem adjoin_root_set : algebra.adjoin K (f.root_set (splitting_field f)) = ⊤ :=
-splitting_field_aux.adjoin_root_set _ _ rfl
+polynomial.is_splitting_field.adjoin_root_set _ f
 
 end splitting_field
 
@@ -479,12 +328,15 @@ namespace is_splitting_field
 variables (K L) [algebra K L]
 
 variables {K}
-instance splitting_field (f : K[X]) : is_splitting_field K (splitting_field f) f :=
-⟨splitting_field.splits f, splitting_field.adjoin_root_set f⟩
 
 instance (f : K[X]) : _root_.finite_dimensional K f.splitting_field :=
 finite_dimensional f.splitting_field f
 
+instance [fintype K] (f : K[X]) : fintype f.splitting_field :=
+finite_dimensional.fintype_of_fintype K _
+
+instance (f : K[X]) : no_zero_smul_divisors K f.splitting_field := infer_instance
+
 /-- Any splitting field is isomorphic to `splitting_field f`. -/
 def alg_equiv (f : K[X]) [is_splitting_field K L f] : L ≃ₐ[K] splitting_field f :=
 begin

(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)

refactor(field_theory/splitting_field/is_splitting_field): use root_set (#19179)

Co-authored-by: Eric Rodriguez <ericrboidi@gmail.com>

Diff
@@ -391,26 +391,28 @@ by { rw ← X_sub_C_mul_remove_factor _ hndf at hmf0, refine (splits_of_splits_m
 let ⟨k, hk⟩ := ih f.remove_factor (nat_degree_remove_factor' hf) (adjoin_root.lift j r hr) hsf in
 ⟨k, by rw [algebra_map_succ, ← ring_hom.comp_assoc, hk, adjoin_root.lift_comp_of]⟩
 
-theorem adjoin_roots (n : ℕ) : ∀ {K : Type u} [field K], by exactI
+theorem adjoin_root_set (n : ℕ) : ∀ {K : Type u} [field K], by exactI
   ∀ (f : K[X]) (hfn : f.nat_degree = n),
-    algebra.adjoin K (↑(f.map $ algebra_map K $ splitting_field_aux n f).roots.to_finset :
-      set (splitting_field_aux n f)) = ⊤ :=
+    algebra.adjoin K (f.root_set (splitting_field_aux n f)) = ⊤ :=
 nat.rec_on n (λ K _ f hf, by exactI algebra.eq_top_iff.2 (λ x, subalgebra.range_le _ ⟨x, rfl⟩)) $
 λ n ih K _ f hfn, by exactI
 have hndf : f.nat_degree ≠ 0, by { intro h, rw h at hfn, cases hfn },
 have hfn0 : f ≠ 0, by { intro h, rw h at hndf, exact hndf rfl },
 have hmf0 : map (algebra_map K (splitting_field_aux n.succ f)) f ≠ 0 := map_ne_zero hfn0,
-by { rw [algebra_map_succ, ← map_map, ← X_sub_C_mul_remove_factor _ hndf,
+begin
+  simp_rw root_set at ⊢ ih,
+  rw [algebra_map_succ, ← map_map, ← X_sub_C_mul_remove_factor _ hndf,
          polynomial.map_mul] at hmf0 ⊢,
-rw [roots_mul hmf0, polynomial.map_sub, map_X, map_C, roots_X_sub_C, multiset.to_finset_add,
-    finset.coe_union, multiset.to_finset_singleton, finset.coe_singleton,
-    algebra.adjoin_union_eq_adjoin_adjoin, ← set.image_singleton,
-    algebra.adjoin_algebra_map K (adjoin_root f.factor)
-      (splitting_field_aux n f.remove_factor),
-    adjoin_root.adjoin_root_eq_top, algebra.map_top,
-    is_scalar_tower.adjoin_range_to_alg_hom K (adjoin_root f.factor)
-      (splitting_field_aux n f.remove_factor),
-    ih _ (nat_degree_remove_factor' hfn), subalgebra.restrict_scalars_top] }
+  rw [roots_mul hmf0, polynomial.map_sub, map_X, map_C, roots_X_sub_C, multiset.to_finset_add,
+      finset.coe_union, multiset.to_finset_singleton, finset.coe_singleton,
+      algebra.adjoin_union_eq_adjoin_adjoin, ← set.image_singleton,
+      algebra.adjoin_algebra_map K (adjoin_root f.factor)
+        (splitting_field_aux n f.remove_factor),
+      adjoin_root.adjoin_root_eq_top, algebra.map_top,
+      is_scalar_tower.adjoin_range_to_alg_hom K (adjoin_root f.factor)
+        (splitting_field_aux n f.remove_factor),
+      ih _ (nat_degree_remove_factor' hfn), subalgebra.restrict_scalars_top]
+end
 
 end splitting_field_aux
 
@@ -465,12 +467,8 @@ def lift : splitting_field f →ₐ[K] L :=
     exact ring_hom.ext_iff.1 this r },
   .. classical.some (splitting_field_aux.exists_lift _ _ _ _ hb) }
 
-theorem adjoin_roots : algebra.adjoin K
-    (↑(f.map (algebra_map K $ splitting_field f)).roots.to_finset : set (splitting_field f)) = ⊤ :=
-splitting_field_aux.adjoin_roots _ _ rfl
-
-theorem adjoin_root_set : algebra.adjoin K (f.root_set f.splitting_field) = ⊤ :=
-adjoin_roots f
+theorem adjoin_root_set : algebra.adjoin K (f.root_set (splitting_field f)) = ⊤ :=
+splitting_field_aux.adjoin_root_set _ _ rfl
 
 end splitting_field
 
@@ -482,7 +480,7 @@ variables (K L) [algebra K L]
 
 variables {K}
 instance splitting_field (f : K[X]) : is_splitting_field K (splitting_field f) f :=
-⟨splitting_field.splits f, splitting_field.adjoin_roots f⟩
+⟨splitting_field.splits f, splitting_field.adjoin_root_set f⟩
 
 instance (f : K[X]) : _root_.finite_dimensional K f.splitting_field :=
 finite_dimensional f.splitting_field f

(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)

(first ported)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -352,7 +352,7 @@ instance : Field (SplittingField f) :=
             ext
             simp only [MvPolynomial.algebraMap_eq, Rat.smul_def, MvPolynomial.coeff_smul,
               MvPolynomial.coeff_C_mul])
-    ratCast_mk := fun a b h1 h2 => by
+    ratCast_def := fun a b h1 h2 => by
       apply e.injective
       change e (algebraMap K _ _) = _
       simp only [map_ratCast, map_natCast, map_mul, map_intCast, AlgEquiv.commutes]
Diff
@@ -220,7 +220,7 @@ protected theorem splits (n : ℕ) :
     fun n ih K _ f hf => by
     skip;
     rw [← splits_id_iff_splits, algebra_map_succ, ← map_map, splits_id_iff_splits, ←
-      X_sub_C_mul_remove_factor f fun h => by rw [h] at hf ; cases hf]
+      X_sub_C_mul_remove_factor f fun h => by rw [h] at hf; cases hf]
     exact splits_mul _ (splits_X_sub_C _) (ih _ (nat_degree_remove_factor' hf))
 #align polynomial.splitting_field_aux.splits Polynomial.SplittingFieldAux.splits
 -/
@@ -233,8 +233,8 @@ theorem adjoin_rootSet (n : ℕ) :
   Nat.recOn n (fun K _ f hf => Algebra.eq_top_iff.2 fun x => Subalgebra.range_le _ ⟨x, rfl⟩)
     fun n ih K _ f hfn =>
     by
-    have hndf : f.nat_degree ≠ 0 := by intro h; rw [h] at hfn ; cases hfn
-    have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf ; exact hndf rfl
+    have hndf : f.nat_degree ≠ 0 := by intro h; rw [h] at hfn; cases hfn
+    have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf; exact hndf rfl
     have hmf0 : map (algebraMap K (splitting_field_aux n.succ f)) f ≠ 0 := map_ne_zero hfn0
     simp_rw [root_set] at ih ⊢
     rw [algebra_map_succ, ← map_map, ← X_sub_C_mul_remove_factor _ hndf, Polynomial.map_mul] at hmf0
@@ -264,7 +264,7 @@ def ofMvPolynomial (f : K[X]) :
 theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomial f) :=
   by
   suffices AlgHom.range (of_mv_polynomial f) = ⊤ by
-    rw [← Set.range_iff_surjective] <;> rwa [SetLike.ext'_iff] at this 
+    rw [← Set.range_iff_surjective] <;> rwa [SetLike.ext'_iff] at this
   rw [of_mv_polynomial, ← Algebra.adjoin_range_eq_range_aeval K, eq_top_iff, ←
     adjoin_root_set _ _ rfl]
   exact Algebra.adjoin_le fun α hα => Algebra.subset_adjoin ⟨⟨α, hα⟩, rfl⟩
Diff
@@ -3,7 +3,7 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
 -/
-import Mathbin.FieldTheory.Normal
+import FieldTheory.Normal
 
 #align_import field_theory.splitting_field.construction from "leanprover-community/mathlib"@"cff8231f04dfa33fd8f2f45792eebd862ef30cad"
 
Diff
@@ -253,7 +253,6 @@ theorem adjoin_rootSet (n : ℕ) :
 instance (f : K[X]) : IsSplittingField K (SplittingFieldAux f.natDegree f) f :=
   ⟨SplittingFieldAux.splits _ _ rfl, SplittingFieldAux.adjoin_rootSet _ _ rfl⟩
 
-#print Polynomial.SplittingFieldAux.ofMvPolynomial /-
 /-- The natural map from `mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f))`
 to `splitting_field_aux f.nat_degree f` sendind a variable to the corresponding root. -/
 def ofMvPolynomial (f : K[X]) :
@@ -261,9 +260,7 @@ def ofMvPolynomial (f : K[X]) :
       SplittingFieldAux f.natDegree f :=
   MvPolynomial.aeval fun i => i.1
 #align polynomial.splitting_field_aux.of_mv_polynomial Polynomial.SplittingFieldAux.ofMvPolynomial
--/
 
-#print Polynomial.SplittingFieldAux.ofMvPolynomial_surjective /-
 theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomial f) :=
   by
   suffices AlgHom.range (of_mv_polynomial f) = ⊤ by
@@ -272,9 +269,7 @@ theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomi
     adjoin_root_set _ _ rfl]
   exact Algebra.adjoin_le fun α hα => Algebra.subset_adjoin ⟨⟨α, hα⟩, rfl⟩
 #align polynomial.splitting_field_aux.of_mv_polynomial_surjective Polynomial.SplittingFieldAux.ofMvPolynomial_surjective
--/
 
-#print Polynomial.SplittingFieldAux.algEquivQuotientMvPolynomial /-
 /-- The algebra isomorphism between the quotient of
 `mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f)) K` by the kernel of
 `of_mv_polynomial f` and `splitting_field_aux f.nat_degree f`. It is used to transport all the
@@ -285,7 +280,6 @@ def algEquivQuotientMvPolynomial (f : K[X]) :
       SplittingFieldAux f.natDegree f :=
   (Ideal.quotientKerAlgEquivOfSurjective (ofMvPolynomial_surjective f) : _)
 #align polynomial.splitting_field_aux.alg_equiv_quotient_mv_polynomial Polynomial.SplittingFieldAux.algEquivQuotientMvPolynomial
--/
 
 end SplittingFieldAux
 
Diff
@@ -314,7 +314,7 @@ instance inhabited : Inhabited (SplittingField f) :=
 -/
 
 instance {S : Type _} [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
-  Submodule.Quotient.hasSmul' _
+  Submodule.Quotient.instSMul' _
 
 #print Polynomial.SplittingField.algebra /-
 instance algebra : Algebra K (SplittingField f) :=
Diff
@@ -2,14 +2,11 @@
 Copyright (c) 2018 Chris Hughes. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
-
-! This file was ported from Lean 3 source module field_theory.splitting_field.construction
-! leanprover-community/mathlib commit cff8231f04dfa33fd8f2f45792eebd862ef30cad
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.FieldTheory.Normal
 
+#align_import field_theory.splitting_field.construction from "leanprover-community/mathlib"@"cff8231f04dfa33fd8f2f45792eebd862ef30cad"
+
 /-!
 # Splitting fields
 
Diff
@@ -52,58 +52,79 @@ open Polynomial
 
 section SplittingField
 
+#print Polynomial.factor /-
 /-- Non-computably choose an irreducible factor from a polynomial. -/
 def factor (f : K[X]) : K[X] :=
   if H : ∃ g, Irreducible g ∧ g ∣ f then Classical.choose H else X
 #align polynomial.factor Polynomial.factor
+-/
 
+#print Polynomial.irreducible_factor /-
 theorem irreducible_factor (f : K[X]) : Irreducible (factor f) := by rw [factor]; split_ifs with H;
   · exact (Classical.choose_spec H).1; · exact irreducible_X
 #align polynomial.irreducible_factor Polynomial.irreducible_factor
+-/
 
+#print Polynomial.fact_irreducible_factor /-
 /-- See note [fact non-instances]. -/
 theorem fact_irreducible_factor (f : K[X]) : Fact (Irreducible (factor f)) :=
   ⟨irreducible_factor f⟩
 #align polynomial.fact_irreducible_factor Polynomial.fact_irreducible_factor
+-/
 
 attribute [local instance] fact_irreducible_factor
 
+#print Polynomial.factor_dvd_of_not_isUnit /-
 theorem factor_dvd_of_not_isUnit {f : K[X]} (hf1 : ¬IsUnit f) : factor f ∣ f :=
   by
   by_cases hf2 : f = 0; · rw [hf2]; exact dvd_zero _
   rw [factor, dif_pos (WfDvdMonoid.exists_irreducible_factor hf1 hf2)]
   exact (Classical.choose_spec <| WfDvdMonoid.exists_irreducible_factor hf1 hf2).2
 #align polynomial.factor_dvd_of_not_is_unit Polynomial.factor_dvd_of_not_isUnit
+-/
 
+#print Polynomial.factor_dvd_of_degree_ne_zero /-
 theorem factor_dvd_of_degree_ne_zero {f : K[X]} (hf : f.degree ≠ 0) : factor f ∣ f :=
   factor_dvd_of_not_isUnit (mt degree_eq_zero_of_isUnit hf)
 #align polynomial.factor_dvd_of_degree_ne_zero Polynomial.factor_dvd_of_degree_ne_zero
+-/
 
+#print Polynomial.factor_dvd_of_natDegree_ne_zero /-
 theorem factor_dvd_of_natDegree_ne_zero {f : K[X]} (hf : f.natDegree ≠ 0) : factor f ∣ f :=
   factor_dvd_of_degree_ne_zero (mt natDegree_eq_of_degree_eq_some hf)
 #align polynomial.factor_dvd_of_nat_degree_ne_zero Polynomial.factor_dvd_of_natDegree_ne_zero
+-/
 
+#print Polynomial.removeFactor /-
 /-- Divide a polynomial f by X - C r where r is a root of f in a bigger field extension. -/
 def removeFactor (f : K[X]) : Polynomial (AdjoinRoot <| factor f) :=
   map (AdjoinRoot.of f.factor) f /ₘ (X - C (AdjoinRoot.root f.factor))
 #align polynomial.remove_factor Polynomial.removeFactor
+-/
 
-theorem x_sub_c_mul_removeFactor (f : K[X]) (hf : f.natDegree ≠ 0) :
+#print Polynomial.X_sub_C_mul_removeFactor /-
+theorem X_sub_C_mul_removeFactor (f : K[X]) (hf : f.natDegree ≠ 0) :
     (X - C (AdjoinRoot.root f.factor)) * f.removeFactor = map (AdjoinRoot.of f.factor) f :=
   let ⟨g, hg⟩ := factor_dvd_of_natDegree_ne_zero hf
   mul_divByMonic_eq_iff_isRoot.2 <| by
     rw [is_root.def, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, MulZeroClass.zero_mul]
-#align polynomial.X_sub_C_mul_remove_factor Polynomial.x_sub_c_mul_removeFactor
+#align polynomial.X_sub_C_mul_remove_factor Polynomial.X_sub_C_mul_removeFactor
+-/
 
+#print Polynomial.natDegree_removeFactor /-
 theorem natDegree_removeFactor (f : K[X]) : f.removeFactor.natDegree = f.natDegree - 1 := by
   rw [remove_factor, nat_degree_div_by_monic _ (monic_X_sub_C _), nat_degree_map,
     nat_degree_X_sub_C]
 #align polynomial.nat_degree_remove_factor Polynomial.natDegree_removeFactor
+-/
 
-theorem natDegree_remove_factor' {f : K[X]} {n : ℕ} (hfn : f.natDegree = n + 1) :
+#print Polynomial.natDegree_removeFactor' /-
+theorem natDegree_removeFactor' {f : K[X]} {n : ℕ} (hfn : f.natDegree = n + 1) :
     f.removeFactor.natDegree = n := by rw [nat_degree_remove_factor, hfn, n.add_sub_cancel]
-#align polynomial.nat_degree_remove_factor' Polynomial.natDegree_remove_factor'
+#align polynomial.nat_degree_remove_factor' Polynomial.natDegree_removeFactor'
+-/
 
+#print Polynomial.SplittingFieldAuxAux /-
 /-- Auxiliary construction to a splitting field of a polynomial, which removes
 `n` (arbitrarily-chosen) factors.
 
@@ -111,67 +132,87 @@ It constructs the type, proves that is a field and algebra over the base field.
 
 Uses recursion on the degree.
 -/
-def splittingFieldAuxAux (n : ℕ) :
+def SplittingFieldAuxAux (n : ℕ) :
     ∀ {K : Type u} [Field K], ∀ f : K[X], Σ (L : Type u) (inst : Field L), Algebra K L :=
   Nat.recOn n (fun K inst f => ⟨K, inst, inferInstance⟩) fun m ih K inst f =>
     let L := ih (@removeFactor K inst f)
     let h₁ := L.2.1
     let h₂ := L.2.2
     ⟨L.1, L.2.1, (RingHom.comp (algebraMap _ _) (AdjoinRoot.of f.factor)).toAlgebra⟩
-#align polynomial.splitting_field_aux_aux Polynomial.splittingFieldAuxAux
+#align polynomial.splitting_field_aux_aux Polynomial.SplittingFieldAuxAux
+-/
 
+#print Polynomial.SplittingFieldAux /-
 /-- Auxiliary construction to a splitting field of a polynomial, which removes
 `n` (arbitrarily-chosen) factors. It is the type constructed in `splitting_field_aux_aux`.
 -/
 def SplittingFieldAux (n : ℕ) {K : Type u} [Field K] (f : K[X]) : Type u :=
-  (splittingFieldAuxAux n f).1
+  (SplittingFieldAuxAux n f).1
 #align polynomial.splitting_field_aux Polynomial.SplittingFieldAux
+-/
 
+#print Polynomial.SplittingFieldAux.field /-
 instance SplittingFieldAux.field (n : ℕ) {K : Type u} [Field K] (f : K[X]) :
     Field (SplittingFieldAux n f) :=
-  (splittingFieldAuxAux n f).2.1
+  (SplittingFieldAuxAux n f).2.1
 #align polynomial.splitting_field_aux.field Polynomial.SplittingFieldAux.field
+-/
 
 instance (n : ℕ) {K : Type u} [Field K] (f : K[X]) : Inhabited (SplittingFieldAux n f) :=
   ⟨0⟩
 
+#print Polynomial.SplittingFieldAux.algebra /-
 instance SplittingFieldAux.algebra (n : ℕ) {K : Type u} [Field K] (f : K[X]) :
     Algebra K (SplittingFieldAux n f) :=
-  (splittingFieldAuxAux n f).2.2
+  (SplittingFieldAuxAux n f).2.2
 #align polynomial.splitting_field_aux.algebra Polynomial.SplittingFieldAux.algebra
+-/
 
 namespace SplittingFieldAux
 
+#print Polynomial.SplittingFieldAux.succ /-
 theorem succ (n : ℕ) (f : K[X]) :
     SplittingFieldAux (n + 1) f = SplittingFieldAux n f.removeFactor :=
   rfl
 #align polynomial.splitting_field_aux.succ Polynomial.SplittingFieldAux.succ
+-/
 
+#print Polynomial.SplittingFieldAux.algebra''' /-
 instance algebra''' {n : ℕ} {f : K[X]} :
     Algebra (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor) :=
   SplittingFieldAux.algebra n _
 #align polynomial.splitting_field_aux.algebra''' Polynomial.SplittingFieldAux.algebra'''
+-/
 
+#print Polynomial.SplittingFieldAux.algebra' /-
 instance algebra' {n : ℕ} {f : K[X]} : Algebra (AdjoinRoot f.factor) (SplittingFieldAux n.succ f) :=
   SplittingFieldAux.algebra'''
 #align polynomial.splitting_field_aux.algebra' Polynomial.SplittingFieldAux.algebra'
+-/
 
+#print Polynomial.SplittingFieldAux.algebra'' /-
 instance algebra'' {n : ℕ} {f : K[X]} : Algebra K (SplittingFieldAux n f.removeFactor) :=
   RingHom.toAlgebra (RingHom.comp (algebraMap _ _) (AdjoinRoot.of f.factor))
 #align polynomial.splitting_field_aux.algebra'' Polynomial.SplittingFieldAux.algebra''
+-/
 
+#print Polynomial.SplittingFieldAux.scalar_tower' /-
 instance scalar_tower' {n : ℕ} {f : K[X]} :
     IsScalarTower K (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor) :=
   IsScalarTower.of_algebraMap_eq fun x => rfl
 #align polynomial.splitting_field_aux.scalar_tower' Polynomial.SplittingFieldAux.scalar_tower'
+-/
 
+#print Polynomial.SplittingFieldAux.algebraMap_succ /-
 theorem algebraMap_succ (n : ℕ) (f : K[X]) :
     algebraMap K (splitting_field_aux (n + 1) f) =
       (algebraMap (AdjoinRoot f.factor) (splitting_field_aux n f.remove_factor)).comp
         (AdjoinRoot.of f.factor) :=
   rfl
 #align polynomial.splitting_field_aux.algebra_map_succ Polynomial.SplittingFieldAux.algebraMap_succ
+-/
 
+#print Polynomial.SplittingFieldAux.splits /-
 protected theorem splits (n : ℕ) :
     ∀ {K : Type u} [Field K],
       ∀ (f : K[X]) (hfn : f.natDegree = n), splits (algebraMap K <| splitting_field_aux n f) f :=
@@ -185,7 +226,9 @@ protected theorem splits (n : ℕ) :
       X_sub_C_mul_remove_factor f fun h => by rw [h] at hf ; cases hf]
     exact splits_mul _ (splits_X_sub_C _) (ih _ (nat_degree_remove_factor' hf))
 #align polynomial.splitting_field_aux.splits Polynomial.SplittingFieldAux.splits
+-/
 
+#print Polynomial.SplittingFieldAux.adjoin_rootSet /-
 theorem adjoin_rootSet (n : ℕ) :
     ∀ {K : Type u} [Field K],
       ∀ (f : K[X]) (hfn : f.natDegree = n),
@@ -208,10 +251,12 @@ theorem adjoin_rootSet (n : ℕ) :
         (splitting_field_aux n f.remove_factor),
       ih _ (nat_degree_remove_factor' hfn), Subalgebra.restrictScalars_top]
 #align polynomial.splitting_field_aux.adjoin_root_set Polynomial.SplittingFieldAux.adjoin_rootSet
+-/
 
 instance (f : K[X]) : IsSplittingField K (SplittingFieldAux f.natDegree f) f :=
   ⟨SplittingFieldAux.splits _ _ rfl, SplittingFieldAux.adjoin_rootSet _ _ rfl⟩
 
+#print Polynomial.SplittingFieldAux.ofMvPolynomial /-
 /-- The natural map from `mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f))`
 to `splitting_field_aux f.nat_degree f` sendind a variable to the corresponding root. -/
 def ofMvPolynomial (f : K[X]) :
@@ -219,7 +264,9 @@ def ofMvPolynomial (f : K[X]) :
       SplittingFieldAux f.natDegree f :=
   MvPolynomial.aeval fun i => i.1
 #align polynomial.splitting_field_aux.of_mv_polynomial Polynomial.SplittingFieldAux.ofMvPolynomial
+-/
 
+#print Polynomial.SplittingFieldAux.ofMvPolynomial_surjective /-
 theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomial f) :=
   by
   suffices AlgHom.range (of_mv_polynomial f) = ⊤ by
@@ -228,7 +275,9 @@ theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomi
     adjoin_root_set _ _ rfl]
   exact Algebra.adjoin_le fun α hα => Algebra.subset_adjoin ⟨⟨α, hα⟩, rfl⟩
 #align polynomial.splitting_field_aux.of_mv_polynomial_surjective Polynomial.SplittingFieldAux.ofMvPolynomial_surjective
+-/
 
+#print Polynomial.SplittingFieldAux.algEquivQuotientMvPolynomial /-
 /-- The algebra isomorphism between the quotient of
 `mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f)) K` by the kernel of
 `of_mv_polynomial f` and `splitting_field_aux f.nat_degree f`. It is used to transport all the
@@ -239,48 +288,63 @@ def algEquivQuotientMvPolynomial (f : K[X]) :
       SplittingFieldAux f.natDegree f :=
   (Ideal.quotientKerAlgEquivOfSurjective (ofMvPolynomial_surjective f) : _)
 #align polynomial.splitting_field_aux.alg_equiv_quotient_mv_polynomial Polynomial.SplittingFieldAux.algEquivQuotientMvPolynomial
+-/
 
 end SplittingFieldAux
 
+#print Polynomial.SplittingField /-
 /-- A splitting field of a polynomial. -/
 def SplittingField (f : K[X]) :=
   MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K ⧸
     RingHom.ker (SplittingFieldAux.ofMvPolynomial f).toRingHom
 #align polynomial.splitting_field Polynomial.SplittingField
+-/
 
 namespace SplittingField
 
 variable (f : K[X])
 
+#print Polynomial.SplittingField.commRing /-
 instance commRing : CommRing (SplittingField f) :=
   Ideal.Quotient.commRing _
 #align polynomial.splitting_field.comm_ring Polynomial.SplittingField.commRing
+-/
 
+#print Polynomial.SplittingField.inhabited /-
 instance inhabited : Inhabited (SplittingField f) :=
   ⟨37⟩
 #align polynomial.splitting_field.inhabited Polynomial.SplittingField.inhabited
+-/
 
 instance {S : Type _} [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
   Submodule.Quotient.hasSmul' _
 
+#print Polynomial.SplittingField.algebra /-
 instance algebra : Algebra K (SplittingField f) :=
   Ideal.Quotient.algebra _
 #align polynomial.splitting_field.algebra Polynomial.SplittingField.algebra
+-/
 
+#print Polynomial.SplittingField.algebra' /-
 instance algebra' {R : Type _} [CommSemiring R] [Algebra R K] : Algebra R (SplittingField f) :=
   Ideal.Quotient.algebra _
 #align polynomial.splitting_field.algebra' Polynomial.SplittingField.algebra'
+-/
 
+#print Polynomial.SplittingField.isScalarTower /-
 instance isScalarTower {R : Type _} [CommSemiring R] [Algebra R K] :
     IsScalarTower R K (SplittingField f) :=
   Ideal.Quotient.isScalarTower _ _ _
 #align polynomial.splitting_field.is_scalar_tower Polynomial.SplittingField.isScalarTower
+-/
 
+#print Polynomial.SplittingField.algEquivSplittingFieldAux /-
 /-- The algebra equivalence with `splitting_field_aux`,
 which we will use to construct the field structure. -/
 def algEquivSplittingFieldAux (f : K[X]) : SplittingField f ≃ₐ[K] SplittingFieldAux f.natDegree f :=
   SplittingFieldAux.algEquivQuotientMvPolynomial f
 #align polynomial.splitting_field.alg_equiv_splitting_field_aux Polynomial.SplittingField.algEquivSplittingFieldAux
+-/
 
 instance : Field (SplittingField f) :=
   let e := algEquivSplittingFieldAux f
@@ -337,25 +401,33 @@ example [CharZero K] : SplittingField.algebra' f = algebraRat :=
 example {q : ℚ[X]} : algebraInt (SplittingField q) = SplittingField.algebra' q :=
   rfl
 
+#print Polynomial.IsSplittingField.splittingField /-
 instance Polynomial.IsSplittingField.splittingField (f : K[X]) :
     IsSplittingField K (SplittingField f) f :=
   IsSplittingField.of_algEquiv _ f (SplittingFieldAux.algEquivQuotientMvPolynomial f).symm
 #align polynomial.is_splitting_field.splitting_field Polynomial.IsSplittingField.splittingField
+-/
 
+#print Polynomial.SplittingField.splits /-
 protected theorem splits : Splits (algebraMap K (SplittingField f)) f :=
   IsSplittingField.splits f.SplittingField f
 #align polynomial.splitting_field.splits Polynomial.SplittingField.splits
+-/
 
 variable [Algebra K L] (hb : Splits (algebraMap K L) f)
 
+#print Polynomial.SplittingField.lift /-
 /-- Embeds the splitting field into any other field that splits the polynomial. -/
 def lift : SplittingField f →ₐ[K] L :=
   IsSplittingField.lift f.SplittingField f hb
 #align polynomial.splitting_field.lift Polynomial.SplittingField.lift
+-/
 
+#print Polynomial.SplittingField.adjoin_rootSet /-
 theorem adjoin_rootSet : Algebra.adjoin K (f.rootSet (SplittingField f)) = ⊤ :=
   Polynomial.IsSplittingField.adjoin_rootSet _ f
 #align polynomial.splitting_field.adjoin_root_set Polynomial.SplittingField.adjoin_rootSet
+-/
 
 end SplittingField
 
@@ -376,6 +448,7 @@ instance [Fintype K] (f : K[X]) : Fintype f.SplittingField :=
 instance (f : K[X]) : NoZeroSMulDivisors K f.SplittingField :=
   inferInstance
 
+#print Polynomial.IsSplittingField.algEquiv /-
 /-- Any splitting field is isomorphic to `splitting_field f`. -/
 def algEquiv (f : K[X]) [IsSplittingField K L f] : L ≃ₐ[K] SplittingField f :=
   by
@@ -396,6 +469,7 @@ def algEquiv (f : K[X]) [IsSplittingField K L f] : L ≃ₐ[K] SplittingField f
   refine' (LinearMap.injective_iff_surjective_of_finrank_eq_finrank this).1 _
   exact RingHom.injective (lift L f <| splits (splitting_field f) f : L →+* f.splitting_field)
 #align polynomial.is_splitting_field.alg_equiv Polynomial.IsSplittingField.algEquiv
+-/
 
 end IsSplittingField
 
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
 
 ! This file was ported from Lean 3 source module field_theory.splitting_field.construction
-! leanprover-community/mathlib commit e3f4be1fcb5376c4948d7f095bec45350bfb9d1a
+! leanprover-community/mathlib commit cff8231f04dfa33fd8f2f45792eebd862ef30cad
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -13,6 +13,9 @@ import Mathbin.FieldTheory.Normal
 /-!
 # Splitting fields
 
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
 In this file we prove the existence and uniqueness of splitting fields.
 
 ## Main definitions
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
 
 ! This file was ported from Lean 3 source module field_theory.splitting_field.construction
-! leanprover-community/mathlib commit 9fb8964792b4237dac6200193a0d533f1b3f7423
+! leanprover-community/mathlib commit e3f4be1fcb5376c4948d7f095bec45350bfb9d1a
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -24,6 +24,12 @@ In this file we prove the existence and uniqueness of splitting fields.
 * `polynomial.is_splitting_field.alg_equiv`: Every splitting field of a polynomial `f` is isomorphic
   to `splitting_field f` and thus, being a splitting field is unique up to isomorphism.
 
+## Implementation details
+We construct a `splitting_field_aux` without worrying about whether the instances satisfy nice
+definitional equalities. Then the actual `splitting_field` is defined to be a quotient of a
+`mv_polynomial` ring by the kernel of the obvious map into `splitting_field_aux`. Because the
+actual `splitting_field` will be a quotient of a `mv_polynomial`, it has nice instances on it.
+
 -/
 
 
@@ -98,322 +104,45 @@ theorem natDegree_remove_factor' {f : K[X]} {n : ℕ} (hfn : f.natDegree = n + 1
 /-- Auxiliary construction to a splitting field of a polynomial, which removes
 `n` (arbitrarily-chosen) factors.
 
-Uses recursion on the degree. For better definitional behaviour, structures
-including `splitting_field_aux` (such as instances) should be defined using
-this recursion in each field, rather than defining the whole tuple through
-recursion.
--/
-def SplittingFieldAux (n : ℕ) : ∀ {K : Type u} [Field K], ∀ f : K[X], Type u :=
-  Nat.recOn n (fun K _ _ => K) fun n ih K _ f => ih f.remove_factor
-#align polynomial.splitting_field_aux Polynomial.SplittingFieldAux
-
-namespace SplittingFieldAux
-
-theorem succ (n : ℕ) (f : K[X]) :
-    SplittingFieldAux (n + 1) f = SplittingFieldAux n f.removeFactor :=
-  rfl
-#align polynomial.splitting_field_aux.succ Polynomial.SplittingFieldAux.succ
-
-section LiftInstances
-
-/-! ### Instances on `splitting_field_aux`
+It constructs the type, proves that is a field and algebra over the base field.
 
-In order to avoid diamond issues, we have to be careful to define each data field of algebraic
-instances on `splitting_field_aux` by recursion, rather than defining the whole structure by
-recursion at once.
-
-The important detail is that the `smul` instances can be lifted _before_ we create the algebraic
-instances; if we do not do this, this creates a mutual dependence on both on each other, and it
-is impossible to untangle this mess. In order to do this, we need that these `smul` instances
-are distributive in the sense of `distrib_smul`, which is weak enough to be guaranteed at this
-stage. This is sufficient to lift an action to `adjoin_root f` (remember that this is a quotient,
-so these conditions are equivalent to well-definedness), which is all we need.
+Uses recursion on the degree.
 -/
+def splittingFieldAuxAux (n : ℕ) :
+    ∀ {K : Type u} [Field K], ∀ f : K[X], Σ (L : Type u) (inst : Field L), Algebra K L :=
+  Nat.recOn n (fun K inst f => ⟨K, inst, inferInstance⟩) fun m ih K inst f =>
+    let L := ih (@removeFactor K inst f)
+    let h₁ := L.2.1
+    let h₂ := L.2.2
+    ⟨L.1, L.2.1, (RingHom.comp (algebraMap _ _) (AdjoinRoot.of f.factor)).toAlgebra⟩
+#align polynomial.splitting_field_aux_aux Polynomial.splittingFieldAuxAux
 
+/-- Auxiliary construction to a splitting field of a polynomial, which removes
+`n` (arbitrarily-chosen) factors. It is the type constructed in `splitting_field_aux_aux`.
+-/
+def SplittingFieldAux (n : ℕ) {K : Type u} [Field K] (f : K[X]) : Type u :=
+  (splittingFieldAuxAux n f).1
+#align polynomial.splitting_field_aux Polynomial.SplittingFieldAux
 
-/-- Splitting fields have a zero. -/
-protected def zero (n : ℕ) : ∀ {K : Type u} [Field K], ∀ {f : K[X]}, splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => @Zero.zero K _) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.zero Polynomial.SplittingFieldAux.zero
-
-/-- Splitting fields have an addition. -/
-protected def add (n : ℕ) :
-    ∀ {K : Type u} [Field K],
-      ∀ {f : K[X]}, splitting_field_aux n f → splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => @Add.add K _) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.add Polynomial.SplittingFieldAux.add
-
-/-- Splitting fields inherit scalar multiplication. -/
-protected def smul (n : ℕ) :
-    ∀ (α : Type _) {K : Type u} [Field K],
-      ∀ [DistribSMul α K],
-        ∀ [IsScalarTower α K K] {f : K[X]}, α → splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun α K fK ds ist f => @SMul.smul _ K _) fun n ih α K fK ds ist f => ih α
-#align polynomial.splitting_field_aux.smul Polynomial.SplittingFieldAux.smul
-
-instance hasSmul (α : Type _) (n : ℕ) {K : Type u} [Field K] [DistribSMul α K] [IsScalarTower α K K]
-    {f : K[X]} : SMul α (SplittingFieldAux n f) :=
-  ⟨SplittingFieldAux.smul n α⟩
-#align polynomial.splitting_field_aux.has_smul Polynomial.SplittingFieldAux.hasSmul
-
-instance isScalarTower (n : ℕ) :
-    ∀ (R₁ R₂ : Type _) {K : Type u} [SMul R₁ R₂] [Field K],
-      ∀ [DistribSMul R₂ K] [DistribSMul R₁ K],
-        ∀ [IsScalarTower R₁ K K] [IsScalarTower R₂ K K] [IsScalarTower R₁ R₂ K] {f : K[X]},
-          IsScalarTower R₁ R₂ (splitting_field_aux n f) :=
-  Nat.recOn n
-    (fun R₁ R₂ K _ _ hs₂ hs₁ _ _ h f =>
-      by
-      rcases hs₁ with @⟨@⟨⟨hs₁⟩, _⟩, _⟩
-      rcases hs₂ with @⟨@⟨⟨hs₂⟩, _⟩, _⟩
-      exact h)
-    fun n ih R₁ R₂ K _ _ _ _ _ _ _ f => ih R₁ R₂
-#align polynomial.splitting_field_aux.is_scalar_tower Polynomial.SplittingFieldAux.isScalarTower
-
-/-- Splitting fields have a negation. -/
-protected def neg (n : ℕ) :
-    ∀ {K : Type u} [Field K], ∀ {f : K[X]}, splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => @Neg.neg K _) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.neg Polynomial.SplittingFieldAux.neg
-
-/-- Splitting fields have subtraction. -/
-protected def sub (n : ℕ) :
-    ∀ {K : Type u} [Field K],
-      ∀ {f : K[X]}, splitting_field_aux n f → splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => @Sub.sub K _) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.sub Polynomial.SplittingFieldAux.sub
-
-/-- Splitting fields have a one. -/
-protected def one (n : ℕ) : ∀ {K : Type u} [Field K], ∀ {f : K[X]}, splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => @One.one K _) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.one Polynomial.SplittingFieldAux.one
-
-/-- Splitting fields have a multiplication. -/
-protected def mul (n : ℕ) :
-    ∀ {K : Type u} [Field K],
-      ∀ {f : K[X]}, splitting_field_aux n f → splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => @Mul.mul K _) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.mul Polynomial.SplittingFieldAux.mul
-
-/-- Splitting fields have a power operation. -/
-protected def npow (n : ℕ) :
-    ∀ {K : Type u} [Field K], ∀ {f : K[X]}, ℕ → splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f n x => @Pow.pow K _ _ x n) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.npow Polynomial.SplittingFieldAux.npow
-
-/-- Splitting fields have an injection from the base field. -/
-protected def mk (n : ℕ) : ∀ {K : Type u} [Field K], ∀ {f : K[X]}, K → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => id) fun n ih K fK f => ih ∘ coe
-#align polynomial.splitting_field_aux.mk Polynomial.SplittingFieldAux.mk
-
--- note that `coe` goes from `K → adjoin_root f`, and then `ih` lifts to the full splitting field
--- (as we generalise over all fields in this recursion!)
-/-- Splitting fields have an inverse. -/
-protected def inv (n : ℕ) :
-    ∀ {K : Type u} [Field K], ∀ {f : K[X]}, splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => @Inv.inv K _) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.inv Polynomial.SplittingFieldAux.inv
-
-/-- Splitting fields have a division. -/
-protected def div (n : ℕ) :
-    ∀ {K : Type u} [Field K],
-      ∀ {f : K[X]}, splitting_field_aux n f → splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f => @Div.div K _) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.div Polynomial.SplittingFieldAux.div
-
-/-- Splitting fields have powers by integers. -/
-protected def zpow (n : ℕ) :
-    ∀ {K : Type u} [Field K], ∀ {f : K[X]}, ℤ → splitting_field_aux n f → splitting_field_aux n f :=
-  Nat.recOn n (fun K fK f n x => @Pow.pow K _ _ x n) fun n ih K fK f => ih
-#align polynomial.splitting_field_aux.zpow Polynomial.SplittingFieldAux.zpow
-
--- I'm not sure why these two lemmas break, but inlining them seems to not work.
-private theorem nsmul_zero (n : ℕ) :
-    ∀ {K : Type u} [Field K],
-      ∀ {f : K[X]} (x : splitting_field_aux n f), (0 : ℕ) • x = splitting_field_aux.zero n :=
-  Nat.recOn n (fun K fK f => zero_nsmul) fun n ih K fK f => ih
-
-private theorem nsmul_succ (n : ℕ) :
-    ∀ {K : Type u} [Field K],
-      ∀ {f : K[X]} (k : ℕ) (x : splitting_field_aux n f),
-        (k + 1) • x = splitting_field_aux.add n x (k • x) :=
-  Nat.recOn n (fun K fK f n x => succ_nsmul x n) fun n ih K fK f => ih
-
-instance field (n : ℕ) {K : Type u} [Field K] {f : K[X]} : Field (SplittingFieldAux n f) :=
-  by
-  refine'
-    { zero := splitting_field_aux.zero n
-      one := splitting_field_aux.one n
-      add := splitting_field_aux.add n
-      zero_add :=
-        have h := @zero_add
-        _
-      add_zero :=
-        have h := @add_zero
-        _
-      add_assoc :=
-        have h := @add_assoc
-        _
-      add_comm :=
-        have h := @add_comm
-        _
-      neg := splitting_field_aux.neg n
-      add_left_neg :=
-        have h := @add_left_neg
-        _
-      sub := splitting_field_aux.sub n
-      sub_eq_add_neg :=
-        have h := @sub_eq_add_neg
-        _
-      mul := splitting_field_aux.mul n
-      one_mul :=
-        have h := @one_mul
-        _
-      mul_one :=
-        have h := @mul_one
-        _
-      mul_assoc :=
-        have h := @mul_assoc
-        _
-      left_distrib :=
-        have h := @left_distrib
-        _
-      right_distrib :=
-        have h := @right_distrib
-        _
-      mul_comm :=
-        have h := @mul_comm
-        _
-      inv := splitting_field_aux.inv n
-      inv_zero :=
-        have h := @inv_zero
-        _
-      div := splitting_field_aux.div n
-      div_eq_mul_inv :=
-        have h := @div_eq_mul_inv
-        _
-      mul_inv_cancel :=
-        have h := @mul_inv_cancel
-        _
-      exists_pair_ne :=
-        have h := @exists_pair_ne
-        _
-      natCast := splitting_field_aux.mk n ∘ (coe : ℕ → K)
-      natCast_zero :=
-        have h := @CommRing.natCast_zero
-        _
-      natCast_succ :=
-        have h := @CommRing.natCast_succ
-        _
-      nsmul := (· • ·)
-      nsmul_zero := nsmul_zero n
-      nsmul_succ := nsmul_succ n
-      intCast := splitting_field_aux.mk n ∘ (coe : ℤ → K)
-      intCast_ofNat :=
-        have h := @CommRing.intCast_ofNat
-        _
-      intCast_negSucc :=
-        have h := @CommRing.intCast_neg_succ_ofNat
-        _
-      zsmul := (· • ·)
-      zsmul_zero' :=
-        have h := @SubtractionCommMonoid.zsmul_zero'
-        _
-      zsmul_succ' :=
-        have h := @SubtractionCommMonoid.zsmul_succ'
-        _
-      zsmul_neg' :=
-        have h := @SubtractionCommMonoid.zsmul_neg'
-        _
-      ratCast := splitting_field_aux.mk n ∘ (coe : ℚ → K)
-      ratCast_mk :=
-        have h := @Field.ratCast_mk
-        _
-      qsmul := (· • ·)
-      qsmul_eq_mul' :=
-        have h := @Field.qsmul_eq_mul'
-        _
-      npow := splitting_field_aux.npow n
-      npow_zero :=
-        have h := @CommRing.npow_zero'
-        _
-      npow_succ :=
-        have h := @CommRing.npow_succ'
-        _
-      zpow := splitting_field_aux.zpow n
-      zpow_zero' :=
-        have h := @Field.zpow_zero'
-        _
-      zpow_succ' :=
-        have h := @Field.zpow_succ'
-        _
-      zpow_neg' :=
-        have h := @Field.zpow_neg'
-        _ }
-  all_goals
-    induction' n with n ih generalizing K
-    · apply @h K
-    · exact @ih _ _ _
+instance SplittingFieldAux.field (n : ℕ) {K : Type u} [Field K] (f : K[X]) :
+    Field (SplittingFieldAux n f) :=
+  (splittingFieldAuxAux n f).2.1
 #align polynomial.splitting_field_aux.field Polynomial.SplittingFieldAux.field
 
-instance inhabited {n : ℕ} {f : K[X]} : Inhabited (SplittingFieldAux n f) :=
-  ⟨37⟩
-#align polynomial.splitting_field_aux.inhabited Polynomial.SplittingFieldAux.inhabited
-
-/-- The injection from the base field as a ring homomorphism. -/
-@[simps]
-protected def mkHom (n : ℕ) {K : Type u} [Field K] {f : K[X]} : K →+* SplittingFieldAux n f
-    where
-  toFun := SplittingFieldAux.mk n
-  map_one' := by
-    induction' n with k hk generalizing K
-    · simp [splitting_field_aux.mk]
-    exact hk
-  map_mul' := by
-    induction' n with k hk generalizing K
-    · simp [splitting_field_aux.mk]
-    intro x y
-    change (splitting_field_aux.mk k) ((AdjoinRoot.of f.factor) _) = _
-    rw [map_mul]
-    exact hk _ _
-  map_zero' := by
-    induction' n with k hk generalizing K
-    · simp [splitting_field_aux.mk]
-    change (splitting_field_aux.mk k) ((AdjoinRoot.of f.factor) 0) = _
-    rw [map_zero, hk]
-  map_add' := by
-    induction' n with k hk generalizing K
-    · simp [splitting_field_aux.mk]
-    intro x y
-    change (splitting_field_aux.mk k) ((AdjoinRoot.of f.factor) _) = _
-    rw [map_add]
-    exact hk _ _
-#align polynomial.splitting_field_aux.mk_hom Polynomial.SplittingFieldAux.mkHom
-
-instance algebra (n : ℕ) (R : Type _) {K : Type u} [CommSemiring R] [Field K] [Algebra R K]
-    {f : K[X]} : Algebra R (SplittingFieldAux n f) :=
-  {
-    (SplittingFieldAux.mkHom n).comp
-      (algebraMap R
-        K) with
-    toFun := (SplittingFieldAux.mkHom n).comp (algebraMap R K)
-    smul := (· • ·)
-    smul_def' := by
-      induction' n with k hk generalizing K
-      · exact Algebra.smul_def
-      exact hk
-    commutes' := fun a b => mul_comm _ _ }
+instance (n : ℕ) {K : Type u} [Field K] (f : K[X]) : Inhabited (SplittingFieldAux n f) :=
+  ⟨0⟩
+
+instance SplittingFieldAux.algebra (n : ℕ) {K : Type u} [Field K] (f : K[X]) :
+    Algebra K (SplittingFieldAux n f) :=
+  (splittingFieldAuxAux n f).2.2
 #align polynomial.splitting_field_aux.algebra Polynomial.SplittingFieldAux.algebra
 
-/-- Because `splitting_field_aux` is defined by recursion, we have to make sure all instances
-on `splitting_field_aux` are defined by recursion within the fields. Otherwise, there will be
-instance diamonds such as the following: -/
-example (n : ℕ) {K : Type u} [Field K] {f : K[X]} :
-    (AddCommMonoid.natModule : Module ℕ (SplittingFieldAux n f)) =
-      @Algebra.toModule _ _ _ _ (SplittingFieldAux.algebra n _) :=
-  rfl
+namespace SplittingFieldAux
 
-end LiftInstances
+theorem succ (n : ℕ) (f : K[X]) :
+    SplittingFieldAux (n + 1) f = SplittingFieldAux n f.removeFactor :=
+  rfl
+#align polynomial.splitting_field_aux.succ Polynomial.SplittingFieldAux.succ
 
 instance algebra''' {n : ℕ} {f : K[X]} :
     Algebra (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor) :=
@@ -425,25 +154,19 @@ instance algebra' {n : ℕ} {f : K[X]} : Algebra (AdjoinRoot f.factor) (Splittin
 #align polynomial.splitting_field_aux.algebra' Polynomial.SplittingFieldAux.algebra'
 
 instance algebra'' {n : ℕ} {f : K[X]} : Algebra K (SplittingFieldAux n f.removeFactor) :=
-  SplittingFieldAux.algebra n K
+  RingHom.toAlgebra (RingHom.comp (algebraMap _ _) (AdjoinRoot.of f.factor))
 #align polynomial.splitting_field_aux.algebra'' Polynomial.SplittingFieldAux.algebra''
 
 instance scalar_tower' {n : ℕ} {f : K[X]} :
     IsScalarTower K (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor) :=
-  haveI : IsScalarTower K (AdjoinRoot f.factor) (AdjoinRoot f.factor) := IsScalarTower.right
-  splitting_field_aux.is_scalar_tower n K (AdjoinRoot f.factor)
+  IsScalarTower.of_algebraMap_eq fun x => rfl
 #align polynomial.splitting_field_aux.scalar_tower' Polynomial.SplittingFieldAux.scalar_tower'
 
-instance scalar_tower {n : ℕ} {f : K[X]} :
-    IsScalarTower K (AdjoinRoot f.factor) (SplittingFieldAux (n + 1) f) :=
-  SplittingFieldAux.scalar_tower'
-#align polynomial.splitting_field_aux.scalar_tower Polynomial.SplittingFieldAux.scalar_tower
-
 theorem algebraMap_succ (n : ℕ) (f : K[X]) :
     algebraMap K (splitting_field_aux (n + 1) f) =
       (algebraMap (AdjoinRoot f.factor) (splitting_field_aux n f.remove_factor)).comp
         (AdjoinRoot.of f.factor) :=
-  IsScalarTower.algebraMap_eq _ _ _
+  rfl
 #align polynomial.splitting_field_aux.algebra_map_succ Polynomial.SplittingFieldAux.algebraMap_succ
 
 protected theorem splits (n : ℕ) :
@@ -460,28 +183,6 @@ protected theorem splits (n : ℕ) :
     exact splits_mul _ (splits_X_sub_C _) (ih _ (nat_degree_remove_factor' hf))
 #align polynomial.splitting_field_aux.splits Polynomial.SplittingFieldAux.splits
 
-theorem exists_lift (n : ℕ) :
-    ∀ {K : Type u} [Field K],
-      ∀ (f : K[X]) (hfn : f.natDegree = n) {L : Type _} [Field L],
-        ∀ (j : K →+* L) (hf : splits j f),
-          ∃ k : splitting_field_aux n f →+* L, k.comp (algebraMap _ _) = j :=
-  Nat.recOn n (fun K _ _ _ L _ j _ => ⟨j, j.comp_id⟩) fun n ih K _ f hf L _ j hj =>
-    have hndf : f.nat_degree ≠ 0 := by intro h; rw [h] at hf ; cases hf
-    have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf ; exact hndf rfl
-    let ⟨r, hr⟩ :=
-      exists_root_of_splits _
-        (splits_of_splits_of_dvd j hfn0 hj (factor_dvd_of_nat_degree_ne_zero hndf))
-        (mt is_unit_iff_degree_eq_zero.2 f.irreducible_factor.1)
-    have hmf0 : map (AdjoinRoot.of f.factor) f ≠ 0 := map_ne_zero hfn0
-    have hsf : splits (AdjoinRoot.lift j r hr) f.remove_factor :=
-      by
-      rw [← X_sub_C_mul_remove_factor _ hndf] at hmf0 ; refine' (splits_of_splits_mul _ hmf0 _).2
-      rwa [X_sub_C_mul_remove_factor _ hndf, ← splits_id_iff_splits, map_map,
-        AdjoinRoot.lift_comp_of, splits_id_iff_splits]
-    let ⟨k, hk⟩ := ih f.remove_factor (nat_degree_remove_factor' hf) (AdjoinRoot.lift j r hr) hsf
-    ⟨k, by rw [algebra_map_succ, ← RingHom.comp_assoc, hk, AdjoinRoot.lift_comp_of]⟩
-#align polynomial.splitting_field_aux.exists_lift Polynomial.SplittingFieldAux.exists_lift
-
 theorem adjoin_rootSet (n : ℕ) :
     ∀ {K : Type u} [Field K],
       ∀ (f : K[X]) (hfn : f.natDegree = n),
@@ -505,30 +206,112 @@ theorem adjoin_rootSet (n : ℕ) :
       ih _ (nat_degree_remove_factor' hfn), Subalgebra.restrictScalars_top]
 #align polynomial.splitting_field_aux.adjoin_root_set Polynomial.SplittingFieldAux.adjoin_rootSet
 
+instance (f : K[X]) : IsSplittingField K (SplittingFieldAux f.natDegree f) f :=
+  ⟨SplittingFieldAux.splits _ _ rfl, SplittingFieldAux.adjoin_rootSet _ _ rfl⟩
+
+/-- The natural map from `mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f))`
+to `splitting_field_aux f.nat_degree f` sendind a variable to the corresponding root. -/
+def ofMvPolynomial (f : K[X]) :
+    MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K →ₐ[K]
+      SplittingFieldAux f.natDegree f :=
+  MvPolynomial.aeval fun i => i.1
+#align polynomial.splitting_field_aux.of_mv_polynomial Polynomial.SplittingFieldAux.ofMvPolynomial
+
+theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomial f) :=
+  by
+  suffices AlgHom.range (of_mv_polynomial f) = ⊤ by
+    rw [← Set.range_iff_surjective] <;> rwa [SetLike.ext'_iff] at this 
+  rw [of_mv_polynomial, ← Algebra.adjoin_range_eq_range_aeval K, eq_top_iff, ←
+    adjoin_root_set _ _ rfl]
+  exact Algebra.adjoin_le fun α hα => Algebra.subset_adjoin ⟨⟨α, hα⟩, rfl⟩
+#align polynomial.splitting_field_aux.of_mv_polynomial_surjective Polynomial.SplittingFieldAux.ofMvPolynomial_surjective
+
+/-- The algebra isomorphism between the quotient of
+`mv_polynomial (f.root_set (splitting_field_aux f.nat_degree f)) K` by the kernel of
+`of_mv_polynomial f` and `splitting_field_aux f.nat_degree f`. It is used to transport all the
+algebraic structures from the latter to `f.splitting_field`, that is defined as the former. -/
+def algEquivQuotientMvPolynomial (f : K[X]) :
+    (MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K ⧸
+        RingHom.ker (ofMvPolynomial f).toRingHom) ≃ₐ[K]
+      SplittingFieldAux f.natDegree f :=
+  (Ideal.quotientKerAlgEquivOfSurjective (ofMvPolynomial_surjective f) : _)
+#align polynomial.splitting_field_aux.alg_equiv_quotient_mv_polynomial Polynomial.SplittingFieldAux.algEquivQuotientMvPolynomial
+
 end SplittingFieldAux
 
 /-- A splitting field of a polynomial. -/
 def SplittingField (f : K[X]) :=
-  SplittingFieldAux f.natDegree f
+  MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K ⧸
+    RingHom.ker (SplittingFieldAux.ofMvPolynomial f).toRingHom
 #align polynomial.splitting_field Polynomial.SplittingField
 
 namespace SplittingField
 
 variable (f : K[X])
 
-instance : Field (SplittingField f) :=
-  SplittingFieldAux.field _
+instance commRing : CommRing (SplittingField f) :=
+  Ideal.Quotient.commRing _
+#align polynomial.splitting_field.comm_ring Polynomial.SplittingField.commRing
 
 instance inhabited : Inhabited (SplittingField f) :=
   ⟨37⟩
 #align polynomial.splitting_field.inhabited Polynomial.SplittingField.inhabited
 
-instance algebra' {R} [CommSemiring R] [Algebra R K] : Algebra R (SplittingField f) :=
-  SplittingFieldAux.algebra _ _
+instance {S : Type _} [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
+  Submodule.Quotient.hasSmul' _
+
+instance algebra : Algebra K (SplittingField f) :=
+  Ideal.Quotient.algebra _
+#align polynomial.splitting_field.algebra Polynomial.SplittingField.algebra
+
+instance algebra' {R : Type _} [CommSemiring R] [Algebra R K] : Algebra R (SplittingField f) :=
+  Ideal.Quotient.algebra _
 #align polynomial.splitting_field.algebra' Polynomial.SplittingField.algebra'
 
-instance : Algebra K (SplittingField f) :=
-  SplittingFieldAux.algebra _ _
+instance isScalarTower {R : Type _} [CommSemiring R] [Algebra R K] :
+    IsScalarTower R K (SplittingField f) :=
+  Ideal.Quotient.isScalarTower _ _ _
+#align polynomial.splitting_field.is_scalar_tower Polynomial.SplittingField.isScalarTower
+
+/-- The algebra equivalence with `splitting_field_aux`,
+which we will use to construct the field structure. -/
+def algEquivSplittingFieldAux (f : K[X]) : SplittingField f ≃ₐ[K] SplittingFieldAux f.natDegree f :=
+  SplittingFieldAux.algEquivQuotientMvPolynomial f
+#align polynomial.splitting_field.alg_equiv_splitting_field_aux Polynomial.SplittingField.algEquivSplittingFieldAux
+
+instance : Field (SplittingField f) :=
+  let e := algEquivSplittingFieldAux f
+  {
+    SplittingField.commRing
+      f with
+    ratCast := fun a => algebraMap K _ (a : K)
+    inv := fun a => e.symm (e a)⁻¹
+    qsmul := (· • ·)
+    qsmul_eq_mul' := fun a x =>
+      Quotient.inductionOn' x fun p =>
+        congr_arg Quotient.mk''
+          (by
+            ext
+            simp only [MvPolynomial.algebraMap_eq, Rat.smul_def, MvPolynomial.coeff_smul,
+              MvPolynomial.coeff_C_mul])
+    ratCast_mk := fun a b h1 h2 => by
+      apply e.injective
+      change e (algebraMap K _ _) = _
+      simp only [map_ratCast, map_natCast, map_mul, map_intCast, AlgEquiv.commutes]
+      change _ = e ↑a * e (e.symm (e b)⁻¹)
+      rw [AlgEquiv.apply_symm_apply]
+      convert Field.ratCast_mk a b h1 h2
+      all_goals simp
+    exists_pair_ne := ⟨e.symm 0, e.symm 1, fun w => zero_ne_one (e.symm.Injective w)⟩
+    mul_inv_cancel := fun a w => by
+      apply e.injective
+      rw [map_mul, map_one]
+      change e a * e (e.symm (e a)⁻¹) = 1
+      rw [AlgEquiv.apply_symm_apply, mul_inv_cancel]
+      exact fun w' => w (by simpa only [AddEquivClass.map_eq_zero_iff] using w')
+    inv_zero := by
+      change e.symm (e 0)⁻¹ = 0
+      simp }
 
 instance [CharZero K] : CharZero (SplittingField f) :=
   charZero_of_injective_algebraMap (algebraMap K _).Injective
@@ -548,28 +331,27 @@ example :
 example [CharZero K] : SplittingField.algebra' f = algebraRat :=
   rfl
 
-example [CharZero K] : SplittingField.algebra' f = algebraRat :=
-  rfl
-
 example {q : ℚ[X]} : algebraInt (SplittingField q) = SplittingField.algebra' q :=
   rfl
 
+instance Polynomial.IsSplittingField.splittingField (f : K[X]) :
+    IsSplittingField K (SplittingField f) f :=
+  IsSplittingField.of_algEquiv _ f (SplittingFieldAux.algEquivQuotientMvPolynomial f).symm
+#align polynomial.is_splitting_field.splitting_field Polynomial.IsSplittingField.splittingField
+
 protected theorem splits : Splits (algebraMap K (SplittingField f)) f :=
-  SplittingFieldAux.splits _ _ rfl
+  IsSplittingField.splits f.SplittingField f
 #align polynomial.splitting_field.splits Polynomial.SplittingField.splits
 
 variable [Algebra K L] (hb : Splits (algebraMap K L) f)
 
 /-- Embeds the splitting field into any other field that splits the polynomial. -/
 def lift : SplittingField f →ₐ[K] L :=
-  { Classical.choose (SplittingFieldAux.exists_lift _ _ _ _ hb) with
-    commutes' := fun r =>
-      haveI := Classical.choose_spec (splitting_field_aux.exists_lift _ _ rfl _ hb)
-      RingHom.ext_iff.1 this r }
+  IsSplittingField.lift f.SplittingField f hb
 #align polynomial.splitting_field.lift Polynomial.SplittingField.lift
 
 theorem adjoin_rootSet : Algebra.adjoin K (f.rootSet (SplittingField f)) = ⊤ :=
-  SplittingFieldAux.adjoin_rootSet _ _ rfl
+  Polynomial.IsSplittingField.adjoin_rootSet _ f
 #align polynomial.splitting_field.adjoin_root_set Polynomial.SplittingField.adjoin_rootSet
 
 end SplittingField
@@ -582,13 +364,15 @@ variable (K L) [Algebra K L]
 
 variable {K}
 
-instance splittingField (f : K[X]) : IsSplittingField K (SplittingField f) f :=
-  ⟨SplittingField.splits f, SplittingField.adjoin_rootSet f⟩
-#align polynomial.is_splitting_field.splitting_field Polynomial.IsSplittingField.splittingField
-
 instance (f : K[X]) : FiniteDimensional K f.SplittingField :=
   finiteDimensional f.SplittingField f
 
+instance [Fintype K] (f : K[X]) : Fintype f.SplittingField :=
+  FiniteDimensional.fintypeOfFintype K _
+
+instance (f : K[X]) : NoZeroSMulDivisors K f.SplittingField :=
+  inferInstance
+
 /-- Any splitting field is isomorphic to `splitting_field f`. -/
 def algEquiv (f : K[X]) [IsSplittingField K L f] : L ≃ₐ[K] SplittingField f :=
   by
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
 
 ! This file was ported from Lean 3 source module field_theory.splitting_field.construction
-! leanprover-community/mathlib commit df76f43357840485b9d04ed5dee5ab115d420e87
+! leanprover-community/mathlib commit 9fb8964792b4237dac6200193a0d533f1b3f7423
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -482,19 +482,17 @@ theorem exists_lift (n : ℕ) :
     ⟨k, by rw [algebra_map_succ, ← RingHom.comp_assoc, hk, AdjoinRoot.lift_comp_of]⟩
 #align polynomial.splitting_field_aux.exists_lift Polynomial.SplittingFieldAux.exists_lift
 
-theorem adjoin_roots (n : ℕ) :
+theorem adjoin_rootSet (n : ℕ) :
     ∀ {K : Type u} [Field K],
       ∀ (f : K[X]) (hfn : f.natDegree = n),
-        Algebra.adjoin K
-            (↑(f.map <| algebraMap K <| splitting_field_aux n f).roots.toFinset :
-              Set (splitting_field_aux n f)) =
-          ⊤ :=
+        Algebra.adjoin K (f.rootSet (splitting_field_aux n f)) = ⊤ :=
   Nat.recOn n (fun K _ f hf => Algebra.eq_top_iff.2 fun x => Subalgebra.range_le _ ⟨x, rfl⟩)
     fun n ih K _ f hfn =>
     by
     have hndf : f.nat_degree ≠ 0 := by intro h; rw [h] at hfn ; cases hfn
     have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf ; exact hndf rfl
     have hmf0 : map (algebraMap K (splitting_field_aux n.succ f)) f ≠ 0 := map_ne_zero hfn0
+    simp_rw [root_set] at ih ⊢
     rw [algebra_map_succ, ← map_map, ← X_sub_C_mul_remove_factor _ hndf, Polynomial.map_mul] at hmf0
       ⊢
     rw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
@@ -505,7 +503,7 @@ theorem adjoin_roots (n : ℕ) :
       IsScalarTower.adjoin_range_toAlgHom K (AdjoinRoot f.factor)
         (splitting_field_aux n f.remove_factor),
       ih _ (nat_degree_remove_factor' hfn), Subalgebra.restrictScalars_top]
-#align polynomial.splitting_field_aux.adjoin_roots Polynomial.SplittingFieldAux.adjoin_roots
+#align polynomial.splitting_field_aux.adjoin_root_set Polynomial.SplittingFieldAux.adjoin_rootSet
 
 end SplittingFieldAux
 
@@ -570,15 +568,8 @@ def lift : SplittingField f →ₐ[K] L :=
       RingHom.ext_iff.1 this r }
 #align polynomial.splitting_field.lift Polynomial.SplittingField.lift
 
-theorem adjoin_roots :
-    Algebra.adjoin K
-        (↑(f.map (algebraMap K <| SplittingField f)).roots.toFinset : Set (SplittingField f)) =
-      ⊤ :=
-  SplittingFieldAux.adjoin_roots _ _ rfl
-#align polynomial.splitting_field.adjoin_roots Polynomial.SplittingField.adjoin_roots
-
-theorem adjoin_rootSet : Algebra.adjoin K (f.rootSet f.SplittingField) = ⊤ :=
-  adjoin_roots f
+theorem adjoin_rootSet : Algebra.adjoin K (f.rootSet (SplittingField f)) = ⊤ :=
+  SplittingFieldAux.adjoin_rootSet _ _ rfl
 #align polynomial.splitting_field.adjoin_root_set Polynomial.SplittingField.adjoin_rootSet
 
 end SplittingField
@@ -592,7 +583,7 @@ variable (K L) [Algebra K L]
 variable {K}
 
 instance splittingField (f : K[X]) : IsSplittingField K (SplittingField f) f :=
-  ⟨SplittingField.splits f, SplittingField.adjoin_roots f⟩
+  ⟨SplittingField.splits f, SplittingField.adjoin_rootSet f⟩
 #align polynomial.is_splitting_field.splitting_field Polynomial.IsSplittingField.splittingField
 
 instance (f : K[X]) : FiniteDimensional K f.SplittingField :=
Diff
@@ -430,8 +430,7 @@ instance algebra'' {n : ℕ} {f : K[X]} : Algebra K (SplittingFieldAux n f.remov
 
 instance scalar_tower' {n : ℕ} {f : K[X]} :
     IsScalarTower K (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor) :=
-  haveI-- finding this instance ourselves makes things faster
-   : IsScalarTower K (AdjoinRoot f.factor) (AdjoinRoot f.factor) := IsScalarTower.right
+  haveI : IsScalarTower K (AdjoinRoot f.factor) (AdjoinRoot f.factor) := IsScalarTower.right
   splitting_field_aux.is_scalar_tower n K (AdjoinRoot f.factor)
 #align polynomial.splitting_field_aux.scalar_tower' Polynomial.SplittingFieldAux.scalar_tower'
 
Diff
@@ -3,34 +3,24 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
 
-! This file was ported from Lean 3 source module field_theory.splitting_field
-! leanprover-community/mathlib commit b353176c24d96c23f0ce1cc63efc3f55019702d9
+! This file was ported from Lean 3 source module field_theory.splitting_field.construction
+! 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.Algebra.CharP.Algebra
-import Mathbin.FieldTheory.IntermediateField
-import Mathbin.RingTheory.Adjoin.Field
+import Mathbin.FieldTheory.Normal
 
 /-!
 # Splitting fields
 
-This file introduces the notion of a splitting field of a polynomial and provides an embedding from
-a splitting field to any field that splits the polynomial. A polynomial `f : K[X]` splits
-over a field extension `L` of `K` if it is zero or all of its irreducible factors over `L` have
-degree `1`. A field extension of `K` of a polynomial `f : K[X]` is called a splitting field
-if it is the smallest field extension of `K` such that `f` splits.
+In this file we prove the existence and uniqueness of splitting fields.
 
 ## Main definitions
 
 * `polynomial.splitting_field f`: A fixed splitting field of the polynomial `f`.
-* `polynomial.is_splitting_field`: A predicate on a field to be a splitting field of a polynomial
-  `f`.
 
 ## Main statements
 
-* `polynomial.is_splitting_field.lift`: An embedding of a splitting field of the polynomial `f` into
-  another field such that `f` splits.
 * `polynomial.is_splitting_field.alg_equiv`: Every splitting field of a polynomial `f` is isomorphic
   to `splitting_field f` and thus, being a splitting field is unique up to isomorphism.
 
@@ -594,109 +584,18 @@ theorem adjoin_rootSet : Algebra.adjoin K (f.rootSet f.SplittingField) = ⊤ :=
 
 end SplittingField
 
-variable (K L) [Algebra K L]
-
-/- ./././Mathport/Syntax/Translate/Command.lean:394:30: infer kinds are unsupported in Lean 4: #[`Splits] [] -/
-/- ./././Mathport/Syntax/Translate/Command.lean:394:30: infer kinds are unsupported in Lean 4: #[`adjoin_roots] [] -/
-/-- Typeclass characterising splitting fields. -/
-class IsSplittingField (f : K[X]) : Prop where
-  Splits : Splits (algebraMap K L) f
-  adjoin_roots : Algebra.adjoin K (↑(f.map (algebraMap K L)).roots.toFinset : Set L) = ⊤
-#align polynomial.is_splitting_field Polynomial.IsSplittingField
+end SplittingField
 
 namespace IsSplittingField
 
+variable (K L) [Algebra K L]
+
 variable {K}
 
 instance splittingField (f : K[X]) : IsSplittingField K (SplittingField f) f :=
   ⟨SplittingField.splits f, SplittingField.adjoin_roots f⟩
 #align polynomial.is_splitting_field.splitting_field Polynomial.IsSplittingField.splittingField
 
-section ScalarTower
-
-variable {K L F} [Algebra F K] [Algebra F L] [IsScalarTower F K L]
-
-variable {K}
-
-instance map (f : F[X]) [IsSplittingField F L f] : IsSplittingField K L (f.map <| algebraMap F K) :=
-  ⟨by rw [splits_map_iff, ← IsScalarTower.algebraMap_eq]; exact splits L f,
-    Subalgebra.restrictScalars_injective F <|
-      by
-      rw [map_map, ← IsScalarTower.algebraMap_eq, Subalgebra.restrictScalars_top, eq_top_iff, ←
-        adjoin_roots L f, Algebra.adjoin_le_iff]
-      exact fun x hx => @Algebra.subset_adjoin K _ _ _ _ _ _ hx⟩
-#align polynomial.is_splitting_field.map Polynomial.IsSplittingField.map
-
-variable {K} (L)
-
-theorem splits_iff (f : K[X]) [IsSplittingField K L f] :
-    Polynomial.Splits (RingHom.id K) f ↔ (⊤ : Subalgebra K L) = ⊥ :=
-  ⟨fun h =>
-    eq_bot_iff.2 <|
-      adjoin_roots L f ▸
-        (roots_map (algebraMap K L) h).symm ▸
-          Algebra.adjoin_le_iff.2 fun y hy =>
-            let ⟨x, hxs, hxy⟩ := Finset.mem_image.1 (by rwa [Multiset.toFinset_map] at hy )
-            hxy ▸ SetLike.mem_coe.2 <| Subalgebra.algebraMap_mem _ _,
-    fun h =>
-    @RingEquiv.toRingHom_refl K _ ▸
-      RingEquiv.self_trans_symm (RingEquiv.ofBijective _ <| Algebra.bijective_algebraMap_iff.2 h) ▸
-        by rw [RingEquiv.toRingHom_trans]; exact splits_comp_of_splits _ _ (splits L f)⟩
-#align polynomial.is_splitting_field.splits_iff Polynomial.IsSplittingField.splits_iff
-
-theorem mul (f g : F[X]) (hf : f ≠ 0) (hg : g ≠ 0) [IsSplittingField F K f]
-    [IsSplittingField K L (g.map <| algebraMap F K)] : IsSplittingField F L (f * g) :=
-  ⟨(IsScalarTower.algebraMap_eq F K L).symm ▸
-      splits_mul _ (splits_comp_of_splits _ _ (splits K f))
-        ((splits_map_iff _ _).1 (splits L <| g.map <| algebraMap F K)),
-    by
-    rw [Polynomial.map_mul,
-      roots_mul (mul_ne_zero (map_ne_zero hf : f.map (algebraMap F L) ≠ 0) (map_ne_zero hg)),
-      Multiset.toFinset_add, Finset.coe_union, Algebra.adjoin_union_eq_adjoin_adjoin,
-      IsScalarTower.algebraMap_eq F K L, ← map_map,
-      roots_map (algebraMap K L) ((splits_id_iff_splits <| algebraMap F K).2 <| splits K f),
-      Multiset.toFinset_map, Finset.coe_image, Algebra.adjoin_algebraMap, adjoin_roots,
-      Algebra.map_top, IsScalarTower.adjoin_range_toAlgHom, ← map_map, adjoin_roots,
-      Subalgebra.restrictScalars_top]⟩
-#align polynomial.is_splitting_field.mul Polynomial.IsSplittingField.mul
-
-end ScalarTower
-
-/-- Splitting field of `f` embeds into any field that splits `f`. -/
-def lift [Algebra K F] (f : K[X]) [IsSplittingField K L f]
-    (hf : Polynomial.Splits (algebraMap K F) f) : L →ₐ[K] F :=
-  if hf0 : f = 0 then
-    (Algebra.ofId K F).comp <|
-      (Algebra.botEquiv K L : (⊥ : Subalgebra K L) →ₐ[K] K).comp <|
-        by
-        rw [← (splits_iff L f).1 (show f.splits (RingHom.id K) from hf0.symm ▸ splits_zero _)]
-        exact Algebra.toTop
-  else
-    AlgHom.comp
-      (by rw [← adjoin_roots L f];
-        exact
-          Classical.choice
-            (lift_of_splits _ fun y hy =>
-              have : aeval y f = 0 :=
-                (eval₂_eq_eval_map _).trans <|
-                  (mem_roots <| map_ne_zero hf0).1 (multiset.mem_to_finset.mp hy)
-              ⟨isAlgebraic_iff_isIntegral.1 ⟨f, hf0, this⟩,
-                splits_of_splits_of_dvd _ hf0 hf <| minpoly.dvd _ _ this⟩))
-      Algebra.toTop
-#align polynomial.is_splitting_field.lift Polynomial.IsSplittingField.lift
-
-theorem finiteDimensional (f : K[X]) [IsSplittingField K L f] : FiniteDimensional K L :=
-  ⟨@Algebra.top_toSubmodule K L _ _ _ ▸
-      adjoin_roots L f ▸
-        FG_adjoin_of_finite (Finset.finite_toSet _) fun y hy =>
-          if hf : f = 0 then by rw [hf, Polynomial.map_zero, roots_zero] at hy ; cases hy
-          else
-            isAlgebraic_iff_isIntegral.1
-              ⟨f, hf,
-                (eval₂_eq_eval_map _).trans <|
-                  (mem_roots <| map_ne_zero hf).1 (Multiset.mem_toFinset.mp hy)⟩⟩
-#align polynomial.is_splitting_field.finite_dimensional Polynomial.IsSplittingField.finiteDimensional
-
 instance (f : K[X]) : FiniteDimensional K f.SplittingField :=
   finiteDimensional f.SplittingField f
 
@@ -721,41 +620,14 @@ def algEquiv (f : K[X]) [IsSplittingField K L f] : L ≃ₐ[K] SplittingField f
   exact RingHom.injective (lift L f <| splits (splitting_field f) f : L →+* f.splitting_field)
 #align polynomial.is_splitting_field.alg_equiv Polynomial.IsSplittingField.algEquiv
 
-theorem of_algEquiv [Algebra K F] (p : K[X]) (f : F ≃ₐ[K] L) [IsSplittingField K F p] :
-    IsSplittingField K L p := by
-  constructor
-  · rw [← f.to_alg_hom.comp_algebra_map]
-    exact splits_comp_of_splits _ _ (splits F p)
-  ·
-    rw [← (Algebra.range_top_iff_surjective f.to_alg_hom).mpr f.surjective, ← root_set,
-      adjoin_root_set_eq_range (splits F p), root_set, adjoin_roots F p]
-#align polynomial.is_splitting_field.of_alg_equiv Polynomial.IsSplittingField.of_algEquiv
-
 end IsSplittingField
 
-end SplittingField
-
 end Polynomial
 
-namespace IntermediateField
+section Normal
 
-open Polynomial
-
-variable [Field K] [Field L] [Algebra K L] {p : K[X]}
-
-theorem splits_of_splits {F : IntermediateField K L} (h : p.Splits (algebraMap K L))
-    (hF : ∀ x ∈ p.rootSet L, x ∈ F) : p.Splits (algebraMap K F) :=
-  by
-  simp_rw [root_set, Finset.mem_coe, Multiset.mem_toFinset] at hF 
-  rw [splits_iff_exists_multiset]
-  refine' ⟨Multiset.pmap Subtype.mk _ hF, map_injective _ (algebraMap F L).Injective _⟩
-  conv_lhs =>
-    rw [Polynomial.map_map, ← IsScalarTower.algebraMap_eq, eq_prod_roots_of_splits h, ←
-      Multiset.pmap_eq_map _ _ _ hF]
-  simp_rw [Polynomial.map_mul, Polynomial.map_multiset_prod, Multiset.map_pmap, Polynomial.map_sub,
-    map_C, map_X]
-  rfl
-#align intermediate_field.splits_of_splits IntermediateField.splits_of_splits
+instance [Field F] (p : F[X]) : Normal F p.SplittingField :=
+  Normal.of_isSplittingField p
 
-end IntermediateField
+end Normal
 

Changes in mathlib4

mathlib3
mathlib4
feat: NNRat.cast (#11203)

Define the canonical coercion from the nonnegative rationals to any division semiring.

From LeanAPAP

Diff
@@ -277,10 +277,15 @@ instance instGroupWithZero : GroupWithZero (SplittingField f) :=
 instance instField : Field (SplittingField f) where
   __ := commRing _
   __ := instGroupWithZero _
+  nnratCast q := algebraMap K _ q
   ratCast q := algebraMap K _ q
+  nnqsmul := (· • ·)
   qsmul := (· • ·)
+  nnratCast_def q := by change algebraMap K _ _ = _; simp_rw [NNRat.cast_def, map_div₀, map_natCast]
   ratCast_def q := by
     change algebraMap K _ _ = _; rw [Rat.cast_def, map_div₀, map_intCast, map_natCast]
+  nnqsmul_def q x := Quotient.inductionOn x fun p ↦ congr_arg Quotient.mk'' $ by
+    ext; simp [MvPolynomial.algebraMap_eq, NNRat.smul_def]
   qsmul_def q x := Quotient.inductionOn x fun p ↦ congr_arg Quotient.mk'' $ by
     ext; simp [MvPolynomial.algebraMap_eq, Rat.smul_def]
 
chore: Final cleanup before NNRat.cast (#12360)

This is the parts of the diff of #11203 which don't mention NNRat.cast.

  • Use more where notation.
  • Write qsmul := _ instead of qsmul := qsmulRec _ to make the instances more robust to definition changes.
  • Delete qsmulRec.
  • Move qsmul before ratCast_def in instance declarations.
  • Name more instances.
  • Rename rat_smul to qsmul.
Diff
@@ -278,9 +278,9 @@ instance instField : Field (SplittingField f) where
   __ := commRing _
   __ := instGroupWithZero _
   ratCast q := algebraMap K _ q
+  qsmul := (· • ·)
   ratCast_def q := by
     change algebraMap K _ _ = _; rw [Rat.cast_def, map_div₀, map_intCast, map_natCast]
-  qsmul := (· • ·)
   qsmul_def q x := Quotient.inductionOn x fun p ↦ congr_arg Quotient.mk'' $ by
     ext; simp [MvPolynomial.algebraMap_eq, Rat.smul_def]
 
chore: rename IsRoot.definition back to IsRoot.def (#11999)

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

Diff
@@ -90,7 +90,7 @@ theorem X_sub_C_mul_removeFactor (f : K[X]) (hf : f.natDegree ≠ 0) :
   let ⟨g, hg⟩ := factor_dvd_of_natDegree_ne_zero hf
   apply (mul_divByMonic_eq_iff_isRoot
     (R := AdjoinRoot f.factor) (a := AdjoinRoot.root f.factor)).mpr
-  rw [IsRoot.definition, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, zero_mul]
+  rw [IsRoot.def, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, zero_mul]
 set_option linter.uppercaseLean3 false in
 #align polynomial.X_sub_C_mul_remove_factor Polynomial.X_sub_C_mul_removeFactor
 
refactor: Avoid Rat internals in the definition of Field (#11639)

Soon, there will be NNRat analogs of the Rat fields in the definition of Field. NNRat is less nicely a structure than Rat, hence there is a need to reduce the dependency of Field on the internals of Rat.

This PR achieves this by restating Field.ratCast_mk' in terms of Rat.num, Rat.den. This requires fixing a few downstream instances.

Reduce the diff of #11203.

Co-authored-by: Floris van Doorn <fpvdoorn@gmail.com>

Diff
@@ -267,34 +267,22 @@ def algEquivSplittingFieldAux (f : K[X]) : SplittingField f ≃ₐ[K] SplittingF
   Ideal.quotientKerAlgEquivOfSurjective fun x => ⟨MvPolynomial.X x, by simp⟩
 #align polynomial.splitting_field.alg_equiv_splitting_field_aux Polynomial.SplittingField.algEquivSplittingFieldAux
 
-instance : Field (SplittingField f) :=
+instance instGroupWithZero : GroupWithZero (SplittingField f) :=
   let e := algEquivSplittingFieldAux f
-  { toCommRing := SplittingField.commRing f
-    ratCast := fun a => algebraMap K _ (a : K)
-    inv := fun a => e.symm (e a)⁻¹
-    qsmul := (· • ·)
-    qsmul_eq_mul' := fun a x =>
-      Quotient.inductionOn x (fun p => congr_arg Quotient.mk''
-        (by ext; simp [MvPolynomial.algebraMap_eq, Rat.smul_def]))
-    ratCast_mk := fun a b h1 h2 => by
-      apply_fun e
-      change e (algebraMap K _ _) = _
-      simp only [map_ratCast, map_natCast, map_mul, map_intCast, AlgEquiv.commutes,
-        AlgEquiv.apply_symm_apply]
-      apply Field.ratCast_mk
-    exists_pair_ne := ⟨e.symm 0, e.symm 1, fun w => zero_ne_one ((e.symm).injective w)⟩
-    mul_inv_cancel := fun a w => by
-      -- This could surely be golfed.
-      apply_fun e
-      have : e a ≠ 0 := fun w' => by
-        apply w
-        simp? at w' says
-          simp only [AddEquivClass.map_eq_zero_iff] at w'
-        exact w'
-      simp only [map_mul, AlgEquiv.apply_symm_apply, ne_eq, AddEquivClass.map_eq_zero_iff, map_one]
-      rw [mul_inv_cancel]
-      assumption
-    inv_zero := by simp }
+  { inv := fun a ↦ e.symm (e a)⁻¹
+    inv_zero := by simp
+    mul_inv_cancel := fun a ha ↦ e.injective $ by simp [(AddEquivClass.map_ne_zero_iff _).2 ha]
+    __ := e.surjective.nontrivial }
+
+instance instField : Field (SplittingField f) where
+  __ := commRing _
+  __ := instGroupWithZero _
+  ratCast q := algebraMap K _ q
+  ratCast_def q := by
+    change algebraMap K _ _ = _; rw [Rat.cast_def, map_div₀, map_intCast, map_natCast]
+  qsmul := (· • ·)
+  qsmul_def q x := Quotient.inductionOn x fun p ↦ congr_arg Quotient.mk'' $ by
+    ext; simp [MvPolynomial.algebraMap_eq, Rat.smul_def]
 
 instance instCharZero [CharZero K] : CharZero (SplittingField f) :=
   charZero_of_injective_algebraMap (algebraMap K _).injective
chore: rename away from 'def' (#11548)

This will become an error in 2024-03-16 nightly, possibly not permanently.

Co-authored-by: Scott Morrison <scott@tqft.net>

Diff
@@ -90,7 +90,7 @@ theorem X_sub_C_mul_removeFactor (f : K[X]) (hf : f.natDegree ≠ 0) :
   let ⟨g, hg⟩ := factor_dvd_of_natDegree_ne_zero hf
   apply (mul_divByMonic_eq_iff_isRoot
     (R := AdjoinRoot f.factor) (a := AdjoinRoot.root f.factor)).mpr
-  rw [IsRoot.def, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, zero_mul]
+  rw [IsRoot.definition, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, zero_mul]
 set_option linter.uppercaseLean3 false in
 #align polynomial.X_sub_C_mul_remove_factor Polynomial.X_sub_C_mul_removeFactor
 
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
@@ -351,7 +351,6 @@ namespace IsSplittingField
 
 variable (K L)
 variable [Algebra K L]
-
 variable {K}
 
 instance (f : K[X]) : FiniteDimensional K f.SplittingField :=
refactor: generalize CharP+Prime to ExpChar in frobenius (#10016)

Consequently, the part about frobenius in Algebra/CharP/Basic is moved to CharP/ExpChar, and imports are adjusted as necessary.

  • Add instances from CharP+Fact(Nat.Prime) and CharZero to ExpChar, to allow lemmas generalized to ExpChar still apply to CharP.

  • Remove lemmas in Algebra/CharP/ExpChar from [#9799](https://github.com/leanprover-community/mathlib4/commit/1e74fcfff8d5ffe5a3a9881864cf10fa39f619e6) because they coincide with the generalized lemmas, and golf the other lemmas (in Algebra/CharP/Basic).

  • Define the RingHom iterateFrobenius and the semilinear map LinearMap.(iterate)Frobenius for an algebra. When the characteristic is zero (ExpChar is 1), these are all equal to the identity map (· ^ 1). Also define iterateFrobeniusEquiv for perfect rings.

  • Fix and/or generalize other files.

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

Diff
@@ -302,6 +302,9 @@ instance instCharZero [CharZero K] : CharZero (SplittingField f) :=
 instance instCharP (p : ℕ) [CharP K p] : CharP (SplittingField f) p :=
   charP_of_injective_algebraMap (algebraMap K _).injective p
 
+instance instExpChar (p : ℕ) [ExpChar K p] : ExpChar (SplittingField f) p :=
+  expChar_of_injective_algebraMap (algebraMap K _).injective p
+
 -- The algebra instance deriving from `K` should be definitionally equal to that
 -- deriving from the field structure on `SplittingField f`.
 example :
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,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
 -/
 import Mathlib.FieldTheory.SplittingField.IsSplittingField
+import Mathlib.Algebra.CharP.Algebra
 
 #align_import field_theory.splitting_field.construction from "leanprover-community/mathlib"@"e3f4be1fcb5376c4948d7f095bec45350bfb9d1a"
 
chore(*): use α → β instead of ∀ _ : α, β (#9529)
Diff
@@ -110,7 +110,7 @@ It constructs the type, proves that is a field and algebra over the base field.
 
 Uses recursion on the degree.
 -/
-def SplittingFieldAuxAux (n : ℕ) : ∀ {K : Type u} [Field K], ∀ _ : K[X],
+def SplittingFieldAuxAux (n : ℕ) : ∀ {K : Type u} [Field K], K[X] →
     Σ (L : Type u) (_ : Field L), Algebra K L :=
   -- Porting note: added motive
   Nat.recOn (motive := fun (_x : ℕ) => ∀ {K : Type u} [_inst_4 : Field K], K[X] →
chore: Remove nonterminal simp at (#7795)

Removes nonterminal uses of simp at. Replaces most of these with instances of simp? ... says.

Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Mario Carneiro <di.gama@gmail.com>

Diff
@@ -287,7 +287,8 @@ instance : Field (SplittingField f) :=
       apply_fun e
       have : e a ≠ 0 := fun w' => by
         apply w
-        simp at w'
+        simp? at w' says
+          simp only [AddEquivClass.map_eq_zero_iff] at w'
         exact w'
       simp only [map_mul, AlgEquiv.apply_symm_apply, ne_eq, AddEquivClass.map_eq_zero_iff, map_one]
       rw [mul_inv_cancel]
chore: space after (#8178)

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -201,7 +201,7 @@ theorem adjoin_rootSet (n : ℕ) :
     have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf; exact hndf rfl
     have hmf0 : map (algebraMap K (SplittingFieldAux n.succ f)) f ≠ 0 := map_ne_zero hfn0
     rw [rootSet_def, aroots_def]
-    rw [algebraMap_succ, ←map_map, ←X_sub_C_mul_removeFactor _ hndf, Polynomial.map_mul] at hmf0 ⊢
+    rw [algebraMap_succ, ← map_map, ← X_sub_C_mul_removeFactor _ hndf, Polynomial.map_mul] at hmf0 ⊢
     -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
     erw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
       Finset.coe_union, Multiset.toFinset_singleton, Finset.coe_singleton,
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
@@ -362,7 +362,7 @@ instance (f : K[X]) : NoZeroSMulDivisors K f.SplittingField :=
 def algEquiv (f : K[X]) [h : IsSplittingField K L f] : L ≃ₐ[K] SplittingField f :=
   AlgEquiv.ofBijective (lift L f <| splits (SplittingField f) f) <|
     have := finiteDimensional L f
-    ((Algebra.isAlgebraic_of_finite K L).algHom_bijective₂ _ <| lift _ f h.1).1
+    ((Algebra.IsAlgebraic.of_finite K L).algHom_bijective₂ _ <| lift _ f h.1).1
 #align polynomial.is_splitting_field.alg_equiv Polynomial.IsSplittingField.algEquiv
 
 end IsSplittingField
chore: golf IsSplittingField.algEquiv (#8142)

Also golfs Normal.of_algEquiv and Algebra.IsIntegral.of_finite and refactors Algebra.IsAlgebraic.bijective_of_isScalarTower.

Diff
@@ -359,23 +359,10 @@ instance (f : K[X]) : NoZeroSMulDivisors K f.SplittingField :=
   inferInstance
 
 /-- Any splitting field is isomorphic to `SplittingFieldAux f`. -/
-def algEquiv (f : K[X]) [IsSplittingField K L f] : L ≃ₐ[K] SplittingField f := by
-  refine'
-    AlgEquiv.ofBijective (lift L f <| splits (SplittingField f) f)
-      ⟨RingHom.injective (lift L f <| splits (SplittingField f) f).toRingHom, _⟩
-  haveI := finiteDimensional (SplittingField f) f
-  haveI := finiteDimensional L f
-  have : FiniteDimensional.finrank K L = FiniteDimensional.finrank K (SplittingField f) :=
-    le_antisymm
-      (LinearMap.finrank_le_finrank_of_injective
-        (show Function.Injective (lift L f <| splits (SplittingField f) f).toLinearMap from
-          RingHom.injective (lift L f <| splits (SplittingField f) f : L →+* f.SplittingField)))
-      (LinearMap.finrank_le_finrank_of_injective
-        (show Function.Injective (lift (SplittingField f) f <| splits L f).toLinearMap from
-          RingHom.injective (lift (SplittingField f) f <| splits L f : f.SplittingField →+* L)))
-  change Function.Surjective (lift L f <| splits (SplittingField f) f).toLinearMap
-  refine' (LinearMap.injective_iff_surjective_of_finrank_eq_finrank this).1 _
-  exact RingHom.injective (lift L f <| splits (SplittingField f) f : L →+* f.SplittingField)
+def algEquiv (f : K[X]) [h : IsSplittingField K L f] : L ≃ₐ[K] SplittingField f :=
+  AlgEquiv.ofBijective (lift L f <| splits (SplittingField f) f) <|
+    have := finiteDimensional L f
+    ((Algebra.isAlgebraic_of_finite K L).algHom_bijective₂ _ <| lift _ f h.1).1
 #align polynomial.is_splitting_field.alg_equiv Polynomial.IsSplittingField.algEquiv
 
 end IsSplittingField
refactor: golf Normal.of_isSplittingField (#8004)

Before: Construction only imports Normal, which transitively imports IsSplittingField Now: Normal imports Construction, Construction only imports IsSplittingField So no extra transitive import is added to any file other than Construction and Normal. As a consequence, Polynomial.SplittingField.instNormal is moved from Construction to Normal.

adjoin_rootSet_eq_range is added to IsSplittingField.

splits_of_comp in Splits is extracted from splits_of_splits in IsSplittingField.

Source of proof: https://math.stackexchange.com/a/2585087/12932

Move Algebra.adjoin.liftSingleton from IsAlgClosed/Basic to Adjoin/Field in order to speed up lift_of_splits (renamed to add namespace Polynomial).

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

Diff
@@ -3,7 +3,7 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
 -/
-import Mathlib.FieldTheory.Normal
+import Mathlib.FieldTheory.SplittingField.IsSplittingField
 
 #align_import field_theory.splitting_field.construction from "leanprover-community/mathlib"@"e3f4be1fcb5376c4948d7f095bec45350bfb9d1a"
 
@@ -381,11 +381,3 @@ def algEquiv (f : K[X]) [IsSplittingField K L f] : L ≃ₐ[K] SplittingField f
 end IsSplittingField
 
 end Polynomial
-
-section Normal
-
-instance Polynomial.SplittingField.instNormal [Field F] (p : F[X]) : Normal F p.SplittingField :=
-  Normal.of_isSplittingField p
-#align polynomial.splitting_field.normal Polynomial.SplittingField.instNormal
-
-end Normal
Revert "chore: revert #7703 (#7710)"

This reverts commit f3695eb2.

Diff
@@ -202,7 +202,8 @@ theorem adjoin_rootSet (n : ℕ) :
     have hmf0 : map (algebraMap K (SplittingFieldAux n.succ f)) f ≠ 0 := map_ne_zero hfn0
     rw [rootSet_def, aroots_def]
     rw [algebraMap_succ, ←map_map, ←X_sub_C_mul_removeFactor _ hndf, Polynomial.map_mul] at hmf0 ⊢
-    rw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
+    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
+    erw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
       Finset.coe_union, Multiset.toFinset_singleton, Finset.coe_singleton,
       Algebra.adjoin_union_eq_adjoin_adjoin, ← Set.image_singleton,
       Algebra.adjoin_algebraMap K (SplittingFieldAux n f.removeFactor),
chore: revert #7703 (#7710)

This reverts commit 26eb2b0a.

Diff
@@ -202,8 +202,7 @@ theorem adjoin_rootSet (n : ℕ) :
     have hmf0 : map (algebraMap K (SplittingFieldAux n.succ f)) f ≠ 0 := map_ne_zero hfn0
     rw [rootSet_def, aroots_def]
     rw [algebraMap_succ, ←map_map, ←X_sub_C_mul_removeFactor _ hndf, Polynomial.map_mul] at hmf0 ⊢
-    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
-    erw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
+    rw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
       Finset.coe_union, Multiset.toFinset_singleton, Finset.coe_singleton,
       Algebra.adjoin_union_eq_adjoin_adjoin, ← Set.image_singleton,
       Algebra.adjoin_algebraMap K (SplittingFieldAux n f.removeFactor),
chore: bump toolchain to v4.2.0-rc2 (#7703)

This includes all the changes from #7606.

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

Diff
@@ -202,7 +202,8 @@ theorem adjoin_rootSet (n : ℕ) :
     have hmf0 : map (algebraMap K (SplittingFieldAux n.succ f)) f ≠ 0 := map_ne_zero hfn0
     rw [rootSet_def, aroots_def]
     rw [algebraMap_succ, ←map_map, ←X_sub_C_mul_removeFactor _ hndf, Polynomial.map_mul] at hmf0 ⊢
-    rw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
+    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
+    erw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
       Finset.coe_union, Multiset.toFinset_singleton, Finset.coe_singleton,
       Algebra.adjoin_union_eq_adjoin_adjoin, ← Set.image_singleton,
       Algebra.adjoin_algebraMap K (SplittingFieldAux n f.removeFactor),
chore: only four spaces for subsequent lines (#7286)

Co-authored-by: Moritz Firsching <firsching@google.com>

Diff
@@ -100,7 +100,7 @@ theorem natDegree_removeFactor (f : K[X]) : f.removeFactor.natDegree = f.natDegr
 #align polynomial.nat_degree_remove_factor Polynomial.natDegree_removeFactor
 
 theorem natDegree_removeFactor' {f : K[X]} {n : ℕ} (hfn : f.natDegree = n + 1) :
-  f.removeFactor.natDegree = n := by rw [natDegree_removeFactor, hfn, n.add_sub_cancel]
+    f.removeFactor.natDegree = n := by rw [natDegree_removeFactor, hfn, n.add_sub_cancel]
 #align polynomial.nat_degree_remove_factor' Polynomial.natDegree_removeFactor'
 
 /-- Auxiliary construction to a splitting field of a polynomial, which removes
feat: roots in an algebra (#6740)

Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com>

Diff
@@ -194,14 +194,13 @@ theorem adjoin_rootSet (n : ℕ) :
   Nat.recOn (motive := fun n =>
     ∀ {K : Type u} [Field K],
       ∀ (f : K[X]) (_hfn : f.natDegree = n),
-        Algebra.adjoin K
-            (↑(f.map <| algebraMap K <| SplittingFieldAux n f).roots.toFinset :
-              Set (SplittingFieldAux n f)) = ⊤)
+        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤)
     n (fun {K} _ f _hf => Algebra.eq_top_iff.2 fun x => Subalgebra.range_le _ ⟨x, rfl⟩)
     fun n ih {K} _ f hfn => by
     have hndf : f.natDegree ≠ 0 := by intro h; rw [h] at hfn; cases hfn
     have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf; exact hndf rfl
     have hmf0 : map (algebraMap K (SplittingFieldAux n.succ f)) f ≠ 0 := map_ne_zero hfn0
+    rw [rootSet_def, aroots_def]
     rw [algebraMap_succ, ←map_map, ←X_sub_C_mul_removeFactor _ hndf, Polynomial.map_mul] at hmf0 ⊢
     rw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
       Finset.coe_union, Multiset.toFinset_singleton, Finset.coe_singleton,
@@ -212,9 +211,7 @@ theorem adjoin_rootSet (n : ℕ) :
         (SplittingFieldAux n f.removeFactor)]` -/
     have := IsScalarTower.adjoin_range_toAlgHom K (AdjoinRoot f.factor)
         (SplittingFieldAux n f.removeFactor)
-        (↑(f.removeFactor.map <| algebraMap (AdjoinRoot f.factor) <|
-          SplittingFieldAux n f.removeFactor).roots.toFinset :
-              Set (SplittingFieldAux n f.removeFactor))
+        (f.removeFactor.rootSet (SplittingFieldAux n f.removeFactor))
     refine this.trans ?_
     rw [ih _ (natDegree_removeFactor' hfn), Subalgebra.restrictScalars_top]
 #align polynomial.splitting_field_aux.adjoin_root_set Polynomial.SplittingFieldAux.adjoin_rootSet
feat(RingTheory/FiniteType): generalize some results to non-commutative rings (#6681)

I was hoping to use this in combination with #6680 to show the TensorAlgebra is finitely generated, where I needed to generalize FiniteType.equiv; but it turns out that the FiniteType instance on MonoidAlgebra also isn't generalized!

The summary here is:

  • Move Algebra.adjoin_algebraMap from Mathlib/RingTheory/Adjoin/Tower.lean to Mathlib/RingTheory/Adjoin/Basic.lean and golf the proof to oblivion
  • Provide an alternative statement of adjoin_union_eq_adjoin_adjoin, adjoin_algebraMap_image_union_eq_adjoin_adjoin, which works in non-commutative rings, and use it along with a new adjoin_top lemma to prove Algebra.fg_trans' more generally.
  • Introduce a new S variable throughout, with the convention that R and S are commutative, A and B remain not-necessarily-commutative, and A/S/R is a tower of algebras.
  • Apply some zero-effort generalizations to semirings.
Diff
@@ -206,7 +206,7 @@ theorem adjoin_rootSet (n : ℕ) :
     rw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
       Finset.coe_union, Multiset.toFinset_singleton, Finset.coe_singleton,
       Algebra.adjoin_union_eq_adjoin_adjoin, ← Set.image_singleton,
-      Algebra.adjoin_algebraMap K (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor),
+      Algebra.adjoin_algebraMap K (SplittingFieldAux n f.removeFactor),
       AdjoinRoot.adjoinRoot_eq_top, Algebra.map_top]
     /- Porting note: was `rw [IsScalarTower.adjoin_range_toAlgHom K (AdjoinRoot f.factor)
         (SplittingFieldAux n f.removeFactor)]` -/
chore: simplify construction of splitting field (#6735)

Co-authored-by: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com>

Diff
@@ -222,41 +222,16 @@ theorem adjoin_rootSet (n : ℕ) :
 instance (f : K[X]) : IsSplittingField K (SplittingFieldAux f.natDegree f) f :=
   ⟨SplittingFieldAux.splits _ _ rfl, SplittingFieldAux.adjoin_rootSet _ _ rfl⟩
 
-/-- The natural map from `MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f))`
-to `SplittingFieldAux f.natDegree f` sendind a variable to the corresponding root. -/
-def ofMvPolynomial (f : K[X]) :
-    MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K →ₐ[K]
-      SplittingFieldAux f.natDegree f :=
-  MvPolynomial.aeval fun i => i.1
-#align polynomial.splitting_field_aux.of_mv_polynomial Polynomial.SplittingFieldAux.ofMvPolynomial
-
-theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomial f) := by
-  suffices AlgHom.range (ofMvPolynomial f) = ⊤ by
-    rw [← Set.range_iff_surjective]; rwa [SetLike.ext'_iff] at this
-  rw [ofMvPolynomial, ← Algebra.adjoin_range_eq_range_aeval K, eq_top_iff, ← adjoin_rootSet _ _ rfl]
-  apply Algebra.adjoin_le
-  intro α hα
-  apply Algebra.subset_adjoin
-  exact ⟨⟨α, hα⟩, rfl⟩
-#align polynomial.splitting_field_aux.of_mv_polynomial_surjective Polynomial.SplittingFieldAux.ofMvPolynomial_surjective
-
-/-- The algebra isomorphism between the quotient of
-`MvPolynomial (f.rootSet (SplittingFieldAuxAux f.natDegree f)) K` by the kernel of
-`ofMvPolynomial f` and `SplittingFieldAux f.natDegree f`. It is used to transport all the
-algebraic structures from the latter to `f.SplittingFieldAux`, that is defined as the former. -/
-def algEquivQuotientMvPolynomial (f : K[X]) :
-    (MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K ⧸
-        RingHom.ker (ofMvPolynomial f).toRingHom) ≃ₐ[K]
-      SplittingFieldAux f.natDegree f :=
-  (Ideal.quotientKerAlgEquivOfSurjective (ofMvPolynomial_surjective f) : _)
-#align polynomial.splitting_field_aux.alg_equiv_quotient_mv_polynomial Polynomial.SplittingFieldAux.algEquivQuotientMvPolynomial
+#noalign polynomial.splitting_field_aux.of_mv_polynomial
+#noalign polynomial.splitting_field_aux.of_mv_polynomial_surjective
+#noalign polynomial.splitting_field_aux.alg_equiv_quotient_mv_polynomial
 
 end SplittingFieldAux
 
 /-- A splitting field of a polynomial. -/
 def SplittingField (f : K[X]) :=
-  MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K ⧸
-    RingHom.ker (SplittingFieldAux.ofMvPolynomial f).toRingHom
+  MvPolynomial (SplittingFieldAux f.natDegree f) K ⧸
+    RingHom.ker (MvPolynomial.aeval (R := K) id).toRingHom
 #align polynomial.splitting_field Polynomial.SplittingField
 
 namespace SplittingField
@@ -290,7 +265,7 @@ instance isScalarTower {R : Type*} [CommSemiring R] [Algebra R K] :
 /-- The algebra equivalence with `SplittingFieldAux`,
 which we will use to construct the field structure. -/
 def algEquivSplittingFieldAux (f : K[X]) : SplittingField f ≃ₐ[K] SplittingFieldAux f.natDegree f :=
-  SplittingFieldAux.algEquivQuotientMvPolynomial f
+  Ideal.quotientKerAlgEquivOfSurjective fun x => ⟨MvPolynomial.X x, by simp⟩
 #align polynomial.splitting_field.alg_equiv_splitting_field_aux Polynomial.SplittingField.algEquivSplittingFieldAux
 
 instance : Field (SplittingField f) :=
@@ -347,7 +322,7 @@ example {q : ℚ[X]} : algebraInt (SplittingField q) = SplittingField.algebra' q
 
 instance _root_.Polynomial.IsSplittingField.splittingField (f : K[X]) :
     IsSplittingField K (SplittingField f) f :=
-  IsSplittingField.of_algEquiv _ f (SplittingFieldAux.algEquivQuotientMvPolynomial f).symm
+  IsSplittingField.of_algEquiv _ f (algEquivSplittingFieldAux f).symm
 #align polynomial.is_splitting_field.splitting_field Polynomial.IsSplittingField.splittingField
 
 protected theorem splits : Splits (algebraMap K (SplittingField f)) f :=
chore: drop MulZeroClass. in mul_zero/zero_mul (#6682)

Search&replace MulZeroClass.mul_zero -> mul_zero, MulZeroClass.zero_mul -> zero_mul.

These were introduced by Mathport, as the full name of mul_zero is actually MulZeroClass.mul_zero (it's exported with the short name).

Diff
@@ -89,7 +89,7 @@ theorem X_sub_C_mul_removeFactor (f : K[X]) (hf : f.natDegree ≠ 0) :
   let ⟨g, hg⟩ := factor_dvd_of_natDegree_ne_zero hf
   apply (mul_divByMonic_eq_iff_isRoot
     (R := AdjoinRoot f.factor) (a := AdjoinRoot.root f.factor)).mpr
-  rw [IsRoot.def, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, MulZeroClass.zero_mul]
+  rw [IsRoot.def, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, zero_mul]
 set_option linter.uppercaseLean3 false in
 #align polynomial.X_sub_C_mul_remove_factor Polynomial.X_sub_C_mul_removeFactor
 
chore: refactor perfect rings / fields (#6182)

The main changes are:

  • we replace the data-bearing PerfectRing typeclass with a Prop-valued (non-constructive) version,
  • we introduce a new typeclass PerfectField,
  • we add a proof that a perfect field of positive characteristic has surjective Frobenius map,
  • we add some basic facts such as perfection of finite rings / fields and products of perfect rings.
Diff
@@ -321,9 +321,12 @@ instance : Field (SplittingField f) :=
       assumption
     inv_zero := by simp }
 
-instance [CharZero K] : CharZero (SplittingField f) :=
+instance instCharZero [CharZero K] : CharZero (SplittingField f) :=
   charZero_of_injective_algebraMap (algebraMap K _).injective
 
+instance instCharP (p : ℕ) [CharP K p] : CharP (SplittingField f) p :=
+  charP_of_injective_algebraMap (algebraMap K _).injective p
+
 -- The algebra instance deriving from `K` should be definitionally equal to that
 -- deriving from the field structure on `SplittingField f`.
 example :
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
@@ -271,18 +271,18 @@ instance inhabited : Inhabited (SplittingField f) :=
   ⟨37⟩
 #align polynomial.splitting_field.inhabited Polynomial.SplittingField.inhabited
 
-instance {S : Type _} [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
+instance {S : Type*} [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
   Submodule.Quotient.instSMul' _
 
 instance algebra : Algebra K (SplittingField f) :=
   Ideal.Quotient.algebra _
 #align polynomial.splitting_field.algebra Polynomial.SplittingField.algebra
 
-instance algebra' {R : Type _} [CommSemiring R] [Algebra R K] : Algebra R (SplittingField f) :=
+instance algebra' {R : Type*} [CommSemiring R] [Algebra R K] : Algebra R (SplittingField f) :=
   Ideal.Quotient.algebra _
 #align polynomial.splitting_field.algebra' Polynomial.SplittingField.algebra'
 
-instance isScalarTower {R : Type _} [CommSemiring R] [Algebra R K] :
+instance isScalarTower {R : Type*} [CommSemiring R] [Algebra R K] :
     IsScalarTower R K (SplittingField f) :=
   Ideal.Quotient.isScalarTower _ _ _
 #align polynomial.splitting_field.is_scalar_tower Polynomial.SplittingField.isScalarTower
chore: tidy various files (#6274)
Diff
@@ -272,7 +272,7 @@ instance inhabited : Inhabited (SplittingField f) :=
 #align polynomial.splitting_field.inhabited Polynomial.SplittingField.inhabited
 
 instance {S : Type _} [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
-  Submodule.Quotient.hasSmul' _
+  Submodule.Quotient.instSMul' _
 
 instance algebra : Algebra K (SplittingField f) :=
   Ideal.Quotient.algebra _
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,14 +2,11 @@
 Copyright (c) 2018 Chris Hughes. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
-
-! This file was ported from Lean 3 source module field_theory.splitting_field.construction
-! leanprover-community/mathlib commit e3f4be1fcb5376c4948d7f095bec45350bfb9d1a
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.FieldTheory.Normal
 
+#align_import field_theory.splitting_field.construction from "leanprover-community/mathlib"@"e3f4be1fcb5376c4948d7f095bec45350bfb9d1a"
+
 /-!
 # Splitting fields
 
chore: remove occurrences of semicolon after space (#5713)

This is the second half of the changes originally in #5699, removing all occurrences of ; after a space and implementing a linter rule to enforce it.

In most cases this 2-character substring has a space after it, so the following command was run first:

find . -type f -name "*.lean" -exec sed -i -E 's/ ; /; /g' {} \;

The remaining cases were few enough in number that they were done manually.

Diff
@@ -186,7 +186,7 @@ protected theorem splits (n : ℕ) :
         (le_trans degree_le_natDegree <| hf.symm ▸ WithBot.coe_le_coe.2 zero_le_one))
     fun n ih {K} _ f hf => by
     rw [← splits_id_iff_splits, algebraMap_succ, ← map_map, splits_id_iff_splits,
-      ← X_sub_C_mul_removeFactor f fun h => by rw [h] at hf ; cases hf]
+      ← X_sub_C_mul_removeFactor f fun h => by rw [h] at hf; cases hf]
     exact splits_mul _ (splits_X_sub_C _) (ih _ (natDegree_removeFactor' hf))
 #align polynomial.splitting_field_aux.splits Polynomial.SplittingFieldAux.splits
 
@@ -202,8 +202,8 @@ theorem adjoin_rootSet (n : ℕ) :
               Set (SplittingFieldAux n f)) = ⊤)
     n (fun {K} _ f _hf => Algebra.eq_top_iff.2 fun x => Subalgebra.range_le _ ⟨x, rfl⟩)
     fun n ih {K} _ f hfn => by
-    have hndf : f.natDegree ≠ 0 := by intro h; rw [h] at hfn ; cases hfn
-    have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf ; exact hndf rfl
+    have hndf : f.natDegree ≠ 0 := by intro h; rw [h] at hfn; cases hfn
+    have hfn0 : f ≠ 0 := by intro h; rw [h] at hndf; exact hndf rfl
     have hmf0 : map (algebraMap K (SplittingFieldAux n.succ f)) f ≠ 0 := map_ne_zero hfn0
     rw [algebraMap_succ, ←map_map, ←X_sub_C_mul_removeFactor _ hndf, Polynomial.map_mul] at hmf0 ⊢
     rw [roots_mul hmf0, Polynomial.map_sub, map_X, map_C, roots_X_sub_C, Multiset.toFinset_add,
feat: port FieldTheory.PolynomialGaloisGroup (#5159)

Co-authored-by: Xavier-François Roblot <46200072+xroblot@users.noreply.github.com> Co-authored-by: Chris Hughes <chrishughes24@gmail.com> Co-authored-by: Xavier Roblot <46200072+xroblot@users.noreply.github.com>

Diff
@@ -411,7 +411,8 @@ end Polynomial
 
 section Normal
 
-instance [Field F] (p : F[X]) : Normal F p.SplittingField :=
+instance Polynomial.SplittingField.instNormal [Field F] (p : F[X]) : Normal F p.SplittingField :=
   Normal.of_isSplittingField p
+#align polynomial.splitting_field.normal Polynomial.SplittingField.instNormal
 
 end Normal
chore: use mathport output in FieldTheory.SplittingField.Construction (#5087)

The mathlib3 version was manually backported from the mathlib4 version. We use here the mathport output.

Diff
@@ -4,13 +4,11 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Chris Hughes
 
 ! This file was ported from Lean 3 source module field_theory.splitting_field.construction
-! leanprover-community/mathlib commit df76f43357840485b9d04ed5dee5ab115d420e87
+! leanprover-community/mathlib commit e3f4be1fcb5376c4948d7f095bec45350bfb9d1a
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
 import Mathlib.FieldTheory.Normal
-import Mathlib.Data.MvPolynomial.Basic
-import Mathlib.RingTheory.Ideal.QuotientOperations
 
 /-!
 # Splitting fields
@@ -26,6 +24,12 @@ In this file we prove the existence and uniqueness of splitting fields.
 * `Polynomial.IsSplittingField.algEquiv`: Every splitting field of a polynomial `f` is isomorphic
   to `SplittingField f` and thus, being a splitting field is unique up to isomorphism.
 
+## Implementation details
+We construct a `SplittingFieldAux` without worrying about whether the instances satisfy nice
+definitional equalities. Then the actual `SplittingField` is defined to be a quotient of a
+`MvPolynomial` ring by the kernel of the obvious map into `SplittingFieldAux`. Because the
+actual `SplittingField` will be a quotient of a `MvPolynomial`, it has nice instances on it.
+
 -/
 
 
@@ -78,7 +82,7 @@ theorem factor_dvd_of_natDegree_ne_zero {f : K[X]} (hf : f.natDegree ≠ 0) : fa
   factor_dvd_of_degree_ne_zero (mt natDegree_eq_of_degree_eq_some hf)
 #align polynomial.factor_dvd_of_nat_degree_ne_zero Polynomial.factor_dvd_of_natDegree_ne_zero
 
-/-- Divide a polynomial f by X - C r where r is a root of f in a bigger field extension. -/
+/-- Divide a polynomial f by `X - C r` where `r` is a root of `f` in a bigger field extension. -/
 def removeFactor (f : K[X]) : Polynomial (AdjoinRoot <| factor f) :=
   map (AdjoinRoot.of f.factor) f /ₘ (X - C (AdjoinRoot.root f.factor))
 #align polynomial.remove_factor Polynomial.removeFactor
@@ -99,16 +103,15 @@ theorem natDegree_removeFactor (f : K[X]) : f.removeFactor.natDegree = f.natDegr
 #align polynomial.nat_degree_remove_factor Polynomial.natDegree_removeFactor
 
 theorem natDegree_removeFactor' {f : K[X]} {n : ℕ} (hfn : f.natDegree = n + 1) :
-    f.removeFactor.natDegree = n := by rw [natDegree_removeFactor, hfn, n.add_sub_cancel]
+  f.removeFactor.natDegree = n := by rw [natDegree_removeFactor, hfn, n.add_sub_cancel]
 #align polynomial.nat_degree_remove_factor' Polynomial.natDegree_removeFactor'
 
 /-- Auxiliary construction to a splitting field of a polynomial, which removes
 `n` (arbitrarily-chosen) factors.
 
-Uses recursion on the degree. For better definitional behaviour, structures
-including `SplittingFieldAux` (such as instances) should be defined using
-this recursion in each field, rather than defining the whole tuple through
-recursion.
+It constructs the type, proves that is a field and algebra over the base field.
+
+Uses recursion on the degree.
 -/
 def SplittingFieldAuxAux (n : ℕ) : ∀ {K : Type u} [Field K], ∀ _ : K[X],
     Σ (L : Type u) (_ : Field L), Algebra K L :=
@@ -119,7 +122,11 @@ def SplittingFieldAuxAux (n : ℕ) : ∀ {K : Type u} [Field K], ∀ _ : K[X],
     fun _ ih _ _ f =>
       let ⟨L, fL, _⟩ := ih f.removeFactor
       ⟨L, fL, (RingHom.comp (algebraMap _ _) (AdjoinRoot.of f.factor)).toAlgebra⟩
+#align polynomial.splitting_field_aux_aux Polynomial.SplittingFieldAuxAux
 
+/-- Auxiliary construction to a splitting field of a polynomial, which removes
+`n` (arbitrarily-chosen) factors. It is the type constructed in `SplittingFieldAuxAux`.
+-/
 def SplittingFieldAux (n : ℕ) {K : Type u} [Field K] (f : K[X]) : Type u :=
   (SplittingFieldAuxAux n f).1
 #align polynomial.splitting_field_aux Polynomial.SplittingFieldAux
@@ -127,10 +134,15 @@ def SplittingFieldAux (n : ℕ) {K : Type u} [Field K] (f : K[X]) : Type u :=
 instance SplittingFieldAux.field (n : ℕ) {K : Type u} [Field K] (f : K[X]) :
     Field (SplittingFieldAux n f) :=
   (SplittingFieldAuxAux n f).2.1
+#align polynomial.splitting_field_aux.field Polynomial.SplittingFieldAux.field
+
+instance (n : ℕ) {K : Type u} [Field K] (f : K[X]) : Inhabited (SplittingFieldAux n f) :=
+  ⟨0⟩
 
 instance SplittingFieldAux.algebra (n : ℕ) {K : Type u} [Field K] (f : K[X]) :
     Algebra K (SplittingFieldAux n f) :=
   (SplittingFieldAuxAux n f).2.2
+#align polynomial.splitting_field_aux.algebra Polynomial.SplittingFieldAux.algebra
 
 namespace SplittingFieldAux
 
@@ -139,28 +151,6 @@ theorem succ (n : ℕ) (f : K[X]) :
   rfl
 #align polynomial.splitting_field_aux.succ Polynomial.SplittingFieldAux.succ
 
-section LiftInstances
-
-#noalign polynomial.splitting_field_aux.zero
-#noalign polynomial.splitting_field_aux.add
-#noalign polynomial.splitting_field_aux.smul
-#noalign polynomial.splitting_field_aux.is_scalar_tower
-#noalign polynomial.splitting_field_aux.neg
-#noalign polynomial.splitting_field_aux.sub
-#noalign polynomial.splitting_field_aux.one
-#noalign polynomial.splitting_field_aux.mul
-#noalign polynomial.splitting_field_aux.npow
-#noalign polynomial.splitting_field_aux.mk
-#noalign polynomial.splitting_field_aux.Inv
-#noalign polynomial.splitting_field_aux.div
-#noalign polynomial.splitting_field_aux.zpow
-#noalign polynomial.splitting_field_aux.Field
-#noalign polynomial.splitting_field_aux.inhabited
-#noalign polynomial.splitting_field_aux.mk_hom
-#noalign polynomial.splitting_field_aux.algebra
-
-end LiftInstances
-
 instance algebra''' {n : ℕ} {f : K[X]} :
     Algebra (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor) :=
   SplittingFieldAux.algebra n _
@@ -179,8 +169,6 @@ instance scalar_tower' {n : ℕ} {f : K[X]} :
   IsScalarTower.of_algebraMap_eq fun _ => rfl
 #align polynomial.splitting_field_aux.scalar_tower' Polynomial.SplittingFieldAux.scalar_tower'
 
-#noalign polynomial.splitting_field_aux.scalar_tower
-
 theorem algebraMap_succ (n : ℕ) (f : K[X]) :
     algebraMap K (SplittingFieldAux (n + 1) f) =
       (algebraMap (AdjoinRoot f.factor) (SplittingFieldAux n f.removeFactor)).comp
@@ -202,8 +190,6 @@ protected theorem splits (n : ℕ) :
     exact splits_mul _ (splits_X_sub_C _) (ih _ (natDegree_removeFactor' hf))
 #align polynomial.splitting_field_aux.splits Polynomial.SplittingFieldAux.splits
 
-#noalign polynomial.splitting_field_aux.exists_lift
-
 theorem adjoin_rootSet (n : ℕ) :
     ∀ {K : Type u} [Field K],
       ∀ (f : K[X]) (_hfn : f.natDegree = n),
@@ -236,13 +222,16 @@ theorem adjoin_rootSet (n : ℕ) :
     rw [ih _ (natDegree_removeFactor' hfn), Subalgebra.restrictScalars_top]
 #align polynomial.splitting_field_aux.adjoin_root_set Polynomial.SplittingFieldAux.adjoin_rootSet
 
-instance : IsSplittingField K (SplittingFieldAux f.natDegree f) f :=
+instance (f : K[X]) : IsSplittingField K (SplittingFieldAux f.natDegree f) f :=
   ⟨SplittingFieldAux.splits _ _ rfl, SplittingFieldAux.adjoin_rootSet _ _ rfl⟩
 
+/-- The natural map from `MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f))`
+to `SplittingFieldAux f.natDegree f` sendind a variable to the corresponding root. -/
 def ofMvPolynomial (f : K[X]) :
     MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K →ₐ[K]
-    SplittingFieldAux f.natDegree f :=
-  MvPolynomial.aeval (fun i => i.1)
+      SplittingFieldAux f.natDegree f :=
+  MvPolynomial.aeval fun i => i.1
+#align polynomial.splitting_field_aux.of_mv_polynomial Polynomial.SplittingFieldAux.ofMvPolynomial
 
 theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomial f) := by
   suffices AlgHom.range (ofMvPolynomial f) = ⊤ by
@@ -252,17 +241,23 @@ theorem ofMvPolynomial_surjective (f : K[X]) : Function.Surjective (ofMvPolynomi
   intro α hα
   apply Algebra.subset_adjoin
   exact ⟨⟨α, hα⟩, rfl⟩
+#align polynomial.splitting_field_aux.of_mv_polynomial_surjective Polynomial.SplittingFieldAux.ofMvPolynomial_surjective
 
+/-- The algebra isomorphism between the quotient of
+`MvPolynomial (f.rootSet (SplittingFieldAuxAux f.natDegree f)) K` by the kernel of
+`ofMvPolynomial f` and `SplittingFieldAux f.natDegree f`. It is used to transport all the
+algebraic structures from the latter to `f.SplittingFieldAux`, that is defined as the former. -/
 def algEquivQuotientMvPolynomial (f : K[X]) :
     (MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K ⧸
-      RingHom.ker (ofMvPolynomial f).toRingHom) ≃ₐ[K]
-    SplittingFieldAux f.natDegree f :=
+        RingHom.ker (ofMvPolynomial f).toRingHom) ≃ₐ[K]
+      SplittingFieldAux f.natDegree f :=
   (Ideal.quotientKerAlgEquivOfSurjective (ofMvPolynomial_surjective f) : _)
+#align polynomial.splitting_field_aux.alg_equiv_quotient_mv_polynomial Polynomial.SplittingFieldAux.algEquivQuotientMvPolynomial
 
 end SplittingFieldAux
 
 /-- A splitting field of a polynomial. -/
-def SplittingField (f : K[X]) : Type v :=
+def SplittingField (f : K[X]) :=
   MvPolynomial (f.rootSet (SplittingFieldAux f.natDegree f)) K ⧸
     RingHom.ker (SplittingFieldAux.ofMvPolynomial f).toRingHom
 #align polynomial.splitting_field Polynomial.SplittingField
@@ -271,26 +266,35 @@ namespace SplittingField
 
 variable (f : K[X])
 
-instance commRing : CommRing (SplittingField f) := by
-  delta SplittingField; infer_instance
+instance commRing : CommRing (SplittingField f) :=
+  Ideal.Quotient.commRing _
+#align polynomial.splitting_field.comm_ring Polynomial.SplittingField.commRing
 
 instance inhabited : Inhabited (SplittingField f) :=
   ⟨37⟩
 #align polynomial.splitting_field.inhabited Polynomial.SplittingField.inhabited
 
--- Porting note: new instance
-instance [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
+instance {S : Type _} [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
   Submodule.Quotient.hasSmul' _
 
-instance algebra' {R} [CommSemiring R] [Algebra R K] : Algebra R (SplittingField f) := by
-  delta SplittingField; infer_instance
+instance algebra : Algebra K (SplittingField f) :=
+  Ideal.Quotient.algebra _
+#align polynomial.splitting_field.algebra Polynomial.SplittingField.algebra
+
+instance algebra' {R : Type _} [CommSemiring R] [Algebra R K] : Algebra R (SplittingField f) :=
+  Ideal.Quotient.algebra _
 #align polynomial.splitting_field.algebra' Polynomial.SplittingField.algebra'
 
+instance isScalarTower {R : Type _} [CommSemiring R] [Algebra R K] :
+    IsScalarTower R K (SplittingField f) :=
+  Ideal.Quotient.isScalarTower _ _ _
+#align polynomial.splitting_field.is_scalar_tower Polynomial.SplittingField.isScalarTower
+
 /-- The algebra equivalence with `SplittingFieldAux`,
 which we will use to construct the field structure. -/
-def algEquivSplittingFieldAux (f : K[X]) :
-    SplittingField f ≃ₐ[K] SplittingFieldAux f.natDegree f :=
+def algEquivSplittingFieldAux (f : K[X]) : SplittingField f ≃ₐ[K] SplittingFieldAux f.natDegree f :=
   SplittingFieldAux.algEquivQuotientMvPolynomial f
+#align polynomial.splitting_field.alg_equiv_splitting_field_aux Polynomial.SplittingField.algEquivSplittingFieldAux
 
 instance : Field (SplittingField f) :=
   let e := algEquivSplittingFieldAux f
@@ -357,13 +361,8 @@ def lift : SplittingField f →ₐ[K] L :=
   IsSplittingField.lift f.SplittingField f hb
 #align polynomial.splitting_field.lift Polynomial.SplittingField.lift
 
-theorem adjoin_roots : Algebra.adjoin K
-    (↑(f.map (algebraMap K <| SplittingField f)).roots.toFinset : Set (SplittingField f)) = ⊤ :=
-  IsSplittingField.adjoin_rootSet f.SplittingField f
-#align polynomial.splitting_field.adjoin_roots Polynomial.SplittingField.adjoin_roots
-
-theorem adjoin_rootSet : Algebra.adjoin K (f.rootSet f.SplittingField) = ⊤ :=
-  adjoin_roots f
+theorem adjoin_rootSet : Algebra.adjoin K (f.rootSet (SplittingField f)) = ⊤ :=
+  Polynomial.IsSplittingField.adjoin_rootSet _ f
 #align polynomial.splitting_field.adjoin_root_set Polynomial.SplittingField.adjoin_rootSet
 
 end SplittingField
@@ -380,7 +379,13 @@ variable {K}
 instance (f : K[X]) : FiniteDimensional K f.SplittingField :=
   finiteDimensional f.SplittingField f
 
-/-- Any splitting field is isomorphic to `SplittingField f`. -/
+instance [Fintype K] (f : K[X]) : Fintype f.SplittingField :=
+  FiniteDimensional.fintypeOfFintype K _
+
+instance (f : K[X]) : NoZeroSMulDivisors K f.SplittingField :=
+  inferInstance
+
+/-- Any splitting field is isomorphic to `SplittingFieldAux f`. -/
 def algEquiv (f : K[X]) [IsSplittingField K L f] : L ≃ₐ[K] SplittingField f := by
   refine'
     AlgEquiv.ofBijective (lift L f <| splits (SplittingField f) f)
chore: forward-port leanprover-community/mathlib#19187 (#5070)

A sloppy version of this was added in #4891. This adds the better version that we wrote in mathlib3.

Diff
@@ -279,7 +279,7 @@ instance inhabited : Inhabited (SplittingField f) :=
 #align polynomial.splitting_field.inhabited Polynomial.SplittingField.inhabited
 
 -- Porting note: new instance
-instance [CommSemiring S] [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
+instance [DistribSMul S K] [IsScalarTower S K K] : SMul S (SplittingField f) :=
   Submodule.Quotient.hasSmul' _
 
 instance algebra' {R} [CommSemiring R] [Algebra R K] : Algebra R (SplittingField f) := by
feat: port FieldTheory.SplittingField.Construction (#4891)

Co-authored-by: Scott Morrison <scott.morrison@anu.edu.au> Co-authored-by: Johan Commelin <johan@commelin.net> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>

Dependencies 10 + 655

656 files ported (98.5%)
273057 lines ported (98.8%)
Show graph

The unported dependencies are