field_theory.splitting_field.construction
⟷
Mathlib.FieldTheory.SplittingField.Construction
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.
(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)
splitting_field
(#19178)
We refactor the definition of splitting_field
. The main motivation is to backport 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
@@ -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)
@@ -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)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -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]
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -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⟩
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -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"
mathlib commit https://github.com/leanprover-community/mathlib/commit/32a7e535287f9c73f2e4d2aef306a39190f0b504
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/63721b2c3eba6c325ecf8ae8cca27155a4f6306f
@@ -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) :=
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/2a0ce625dbb0ffbc7d1316597de0b25c1ec75303
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/893964fc28cefbcffc7cb784ed00a2895b4e65cf
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/bf9bbbcf0c1c1ead18280b0d010e417b10abb1b6
@@ -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
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -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 :=
mathlib commit https://github.com/leanprover-community/mathlib/commit/7e5137f579de09a059a5ce98f364a04e221aabf0
@@ -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'
mathlib commit https://github.com/leanprover-community/mathlib/commit/a3209ddf94136d36e5e5c624b10b2a347cc9d090
@@ -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
NNRat.cast
(#11203)
Define the canonical coercion from the nonnegative rationals to any division semiring.
From LeanAPAP
@@ -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]
NNRat.cast
(#12360)
This is the parts of the diff of #11203 which don't mention NNRat.cast
.
where
notation.qsmul := _
instead of qsmul := qsmulRec _
to make the instances more robust to definition changes.qsmulRec
.qsmul
before ratCast_def
in instance declarations.rat_smul
to qsmul
.@@ -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]
@@ -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
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>
@@ -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
@@ -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
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)
@@ -351,7 +351,6 @@ namespace IsSplittingField
variable (K L)
variable [Algebra K L]
-
variable {K}
instance (f : K[X]) : FiniteDimensional K f.SplittingField :=
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>
@@ -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 :
@@ -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"
@@ -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] →
@@ -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]
@@ -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,
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_map
→ RingHom.isIntegralElem_map
RingHom.is_integral_of_mem_closure
→ RingHom.IsIntegralElem.of_mem_closure
RingHom.is_integral_zero/one
→ RingHom.isIntegralElem_zero/one
RingHom.is_integral_add/neg/sub/mul/of_mul_unit
→ RingHom.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_trans
→ RingHom.IsIntegral.trans
RingHom.isIntegral_quotient/tower_bot/top_of_isIntegral
→ RingHom.IsIntegral.quotient/tower_bot/top
isIntegral_of_mem_closure'
→ IsIntegral.of_mem_closure'
(and the '' version)
isIntegral_of_surjective
→ Algebra.isIntegral_of_surjective
The next changed file is RingTheory/Algebraic:
Rename:
of_larger_base
→ tower_top
(for consistency with IsIntegral
)
Algebra.isAlgebraic_of_finite
→ Algebra.IsAlgebraic.of_finite
Algebra.isAlgebraic_trans
→ Algebra.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>
@@ -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
Also golfs Normal.of_algEquiv
and Algebra.IsIntegral.of_finite
and refactors Algebra.IsAlgebraic.bijective_of_isScalarTower
.
@@ -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
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>
@@ -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
@@ -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),
@@ -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),
@@ -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),
@@ -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
@@ -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
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:
Algebra.adjoin_algebraMap
from Mathlib/RingTheory/Adjoin/Tower.lean
to Mathlib/RingTheory/Adjoin/Basic.lean
and golf the proof to oblivionadjoin_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.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.@@ -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)]` -/
@@ -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 :=
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).
@@ -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
The main changes are:
PerfectRing
typeclass with a Prop
-valued (non-constructive) version,PerfectField
,@@ -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 :
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -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
@@ -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 _
@@ -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
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.
@@ -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,
@@ -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
The mathlib3 version was manually backported from the mathlib4 version. We use here the mathport output.
@@ -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)
A sloppy version of this was added in #4891. This adds the better version that we wrote in mathlib3.
@@ -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
The unported dependencies are