field_theory.normal
⟷
Mathlib.FieldTheory.Normal
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)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
@@ -138,9 +138,8 @@ local attribute [-instance] adjoin_root.has_smul
lemma normal.of_is_splitting_field (p : F[X]) [hFEp : is_splitting_field F E p] : normal F E :=
begin
unfreezingI { rcases eq_or_ne p 0 with rfl | hp },
- { have := hFEp.adjoin_roots,
- simp only [polynomial.map_zero, roots_zero, multiset.to_finset_zero, finset.coe_empty,
- algebra.adjoin_empty] at this,
+ { have := hFEp.adjoin_root_set,
+ simp only [root_set_zero, algebra.adjoin_empty] at this,
exact normal.of_alg_equiv (alg_equiv.of_bijective (algebra.of_id F E)
(algebra.bijective_algebra_map_iff.2 this.symm)) },
refine normal_iff.2 (λ x, _),
@@ -197,7 +196,7 @@ begin
dsimp only [S],
rw [←finset.image_to_finset, finset.coe_image],
apply eq.trans (algebra.adjoin_res_eq_adjoin_res F E C D
- hFEp.adjoin_roots adjoin_root.adjoin_root_eq_top),
+ hFEp.adjoin_root_set adjoin_root.adjoin_root_eq_top),
rw [set.image_singleton, ring_hom.algebra_map_to_algebra, adjoin_root.lift_root]
end
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(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
@@ -121,7 +121,7 @@ variable (E : Type _) [Field E] [Algebra F E] [Algebra K E] [IsScalarTower F K E
theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E :=
normal_iff.2 fun x => by
cases' h.out x with hx hhx
- rw [algebra_map_eq F K E] at hhx
+ rw [algebra_map_eq F K E] at hhx
exact
⟨IsIntegral.tower_top hx,
Polynomial.splits_of_splits_of_dvd (algebraMap K E)
@@ -159,7 +159,7 @@ theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :
normal_iff.2 fun x => by
cases' h.out (f.symm x) with hx hhx
have H := IsIntegral.map f.to_alg_hom hx
- rw [AlgEquiv.toAlgHom_eq_coe, AlgEquiv.coe_algHom, AlgEquiv.apply_symm_apply] at H
+ rw [AlgEquiv.toAlgHom_eq_coe, AlgEquiv.coe_algHom, AlgEquiv.apply_symm_apply] at H
use H
apply Polynomial.splits_of_splits_of_dvd (algebraMap F E') (minpoly.ne_zero hx)
· rw [← AlgHom.comp_algebraMap f.to_alg_hom]
@@ -191,7 +191,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
by
rcases eq_or_ne p 0 with (rfl | hp)
· have := hFEp.adjoin_root_set
- simp only [root_set_zero, Algebra.adjoin_empty] at this
+ simp only [root_set_zero, Algebra.adjoin_empty] at this
exact
Normal.of_algEquiv
(AlgEquiv.ofBijective (Algebra.ofId F E) (Algebra.bijective_algebraMap_iff.2 this.symm))
@@ -203,7 +203,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
let D := AdjoinRoot q
haveI := Fact.mk q_irred
let pbED := AdjoinRoot.powerBasis q_irred.ne_zero
- haveI : FiniteDimensional E D := PowerBasis.finiteDimensional pbED
+ haveI : FiniteDimensional E D := PowerBasis.finite pbED
have finrankED : FiniteDimensional.finrank E D = q.nat_degree := by
rw [PowerBasis.finrank pbED, AdjoinRoot.powerBasis_dim]
haveI : FiniteDimensional F D := FiniteDimensional.trans F E D
@@ -251,7 +251,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
(Algebra.adjoin E {AdjoinRoot.root q}).restrictScalars F
by
rw [AdjoinRoot.adjoinRoot_eq_top, Subalgebra.restrictScalars_top, ←
- @Subalgebra.restrictScalars_top F C] at this
+ @Subalgebra.restrictScalars_top F C] at this
exact top_le_iff.mpr (Subalgebra.restrictScalars_injective F this)
dsimp only [S]
rw [← Finset.image_toFinset, Finset.coe_image]
@@ -286,7 +286,7 @@ instance normal_iSup {ι : Type _} (t : ι → IntermediateField F K) [h : ∀ i
rw [adjoin_le_iff, ← image_root_set ((h i.1).Splits i.2) (t i.1).val]
exact fun _ ⟨a, _, h⟩ => h ▸ a.2
have := hF.splits ⟨x, hx⟩
- rw [minpoly_eq, Subtype.coe_mk, ← minpoly_eq] at this
+ rw [minpoly_eq, Subtype.coe_mk, ← minpoly_eq] at this
exact Polynomial.splits_comp_of_splits _ (inclusion hE).toRingHom this
#align intermediate_field.normal_supr IntermediateField.normal_iSup
-/
@@ -561,7 +561,7 @@ theorem normalClosure_eq_iSup_adjoin [h : Normal F L] :
minpoly.ne_zero
((isIntegral_algebraMap_iff (algebraMap K L).Injective).mp
(h.is_integral (algebraMap K L x)))
- · rw [Polynomial.rootSet, Finset.mem_coe, Multiset.mem_toFinset] at hy
+ · rw [Polynomial.rootSet, Finset.mem_coe, Multiset.mem_toFinset] at hy
let g :=
(alg_hom_adjoin_integral_equiv F
((isIntegral_algebraMap_iff (algebraMap K L).Injective).mp
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -123,7 +123,7 @@ theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E :=
cases' h.out x with hx hhx
rw [algebra_map_eq F K E] at hhx
exact
- ⟨isIntegral_of_isScalarTower hx,
+ ⟨IsIntegral.tower_top hx,
Polynomial.splits_of_splits_of_dvd (algebraMap K E)
(Polynomial.map_ne_zero (minpoly.ne_zero hx))
((Polynomial.splits_map_iff (algebraMap F K) (algebraMap K E)).mpr hhx)
@@ -141,8 +141,7 @@ theorem AlgHom.normal_bijective [h : Normal F E] (ϕ : E →ₐ[F] K) : Function
minpoly.mem_range_of_degree_eq_one E x
(h2.def.resolve_left (minpoly.ne_zero h1)
(minpoly.irreducible
- (isIntegral_of_isScalarTower
- ((isIntegral_algebraMap_iff (algebraMap K E).Injective).mp h1)))
+ (IsIntegral.tower_top ((isIntegral_algebraMap_iff (algebraMap K E).Injective).mp h1)))
(minpoly.dvd E x
((algebraMap K E).Injective
(by
@@ -159,7 +158,7 @@ variable {F} {E} {E' : Type _} [Field E'] [Algebra F E']
theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :=
normal_iff.2 fun x => by
cases' h.out (f.symm x) with hx hhx
- have H := map_isIntegral f.to_alg_hom hx
+ have H := IsIntegral.map f.to_alg_hom hx
rw [AlgEquiv.toAlgHom_eq_coe, AlgEquiv.coe_algHom, AlgEquiv.apply_symm_apply] at H
use H
apply Polynomial.splits_of_splits_of_dvd (algebraMap F E') (minpoly.ne_zero hx)
@@ -327,8 +326,8 @@ def AlgHom.restrictNormalAux [h : Normal F E] :
Or.resolve_left (h.splits z).def (minpoly.ne_zero (h.is_integral z)) (minpoly.irreducible _)
(minpoly.dvd E _ (by simp [aeval_alg_hom_apply]))
simp only [AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom]
- suffices IsIntegral F _ by exact isIntegral_of_isScalarTower this
- exact map_isIntegral ϕ (map_isIntegral (to_alg_hom F E K₁) (h.is_integral z))⟩
+ suffices IsIntegral F _ by exact IsIntegral.tower_top this
+ exact IsIntegral.map ϕ (IsIntegral.map (to_alg_hom F E K₁) (h.is_integral z))⟩
map_zero' := Subtype.ext ϕ.map_zero
map_one' := Subtype.ext ϕ.map_one
map_add' x y := Subtype.ext (ϕ.map_add x y)
@@ -451,7 +450,7 @@ noncomputable def AlgHom.liftNormal [h : Normal F E] : E →ₐ[F] E :=
@IntermediateField.nonempty_algHom_of_adjoin_splits _ _ _ _ _ _ _
((IsScalarTower.toAlgHom F K₂ E).comp ϕ).toRingHom.toAlgebra _
(IntermediateField.adjoin_univ _ _) fun x hx =>
- ⟨isIntegral_of_isScalarTower (h.out x).1,
+ ⟨IsIntegral.tower_top (h.out x).1,
splits_of_splits_of_dvd _ (map_ne_zero (minpoly.ne_zero (h.out x).1))
(by rw [splits_map_iff, ← IsScalarTower.algebraMap_eq]; exact (h.out x).2)
(minpoly.dvd_map_of_isScalarTower F K₁ x)⟩
@@ -547,8 +546,8 @@ noncomputable def normalClosure : IntermediateField K L :=
namespace normalClosure
-#print normalClosure.restrictScalars_eq_iSup_adjoin /-
-theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
+#print normalClosure_eq_iSup_adjoin /-
+theorem normalClosure_eq_iSup_adjoin [h : Normal F L] :
(normalClosure F K L).restrictScalars F = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) :=
by
refine' le_antisymm (iSup_le _) (iSup_le fun x => adjoin_le_iff.mpr fun y hy => _)
@@ -574,7 +573,7 @@ theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
⟨x, (g.lift_normal_commutes L (adjoin_simple.gen F x)).trans _⟩
rw [Algebra.id.map_eq_id, RingHom.id_apply]
apply PowerBasis.lift_gen
-#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure.restrictScalars_eq_iSup_adjoin
+#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure_eq_iSup_adjoin
-/
#print normalClosure.normal /-
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -232,7 +232,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
let S : Set D := ((p.map (algebraMap F E)).roots.map (algebraMap E D)).toFinset
suffices ⊤ ≤ IntermediateField.adjoin C S
by
- refine' IntermediateField.algHom_mk_adjoin_splits' (top_le_iff.mp this) fun y hy => _
+ refine' IntermediateField.nonempty_algHom_of_adjoin_splits (top_le_iff.mp this) fun y hy => _
rcases multiset.mem_map.mp (multiset.mem_to_finset.mp hy) with ⟨z, hz1, hz2⟩
have Hz : IsIntegral F z := isIntegral_of_noetherian (IsNoetherian.iff_fg.2 hFE) z
use show IsIntegral C y from
@@ -448,7 +448,7 @@ noncomputable def AlgHom.liftNormal [h : Normal F E] : E →ₐ[F] E :=
@AlgHom.restrictScalars F K₁ E E _ _ _ _ _ _
((IsScalarTower.toAlgHom F K₂ E).comp ϕ).toRingHom.toAlgebra _ _ _ _ <|
Nonempty.some <|
- @IntermediateField.algHom_mk_adjoin_splits' _ _ _ _ _ _ _
+ @IntermediateField.nonempty_algHom_of_adjoin_splits _ _ _ _ _ _ _
((IsScalarTower.toAlgHom F K₂ E).comp ϕ).toRingHom.toAlgebra _
(IntermediateField.adjoin_univ _ _) fun x hx =>
⟨isIntegral_of_isScalarTower (h.out x).1,
mathlib commit https://github.com/leanprover-community/mathlib/commit/3365b20c2ffa7c35e47e5209b89ba9abdddf3ffe
@@ -377,8 +377,7 @@ theorem AlgHom.fieldRange_of_normal {E : IntermediateField F K} [Normal F E] (f
haveI : IsScalarTower F E E := by infer_instance
let g := f.restrict_normal' E
rw [← show E.val.comp ↑g = f from fun_like.ext_iff.mpr (f.restrict_normal_commutes E), ←
- IntermediateField.AlgHom.map_fieldRange, g.field_range_eq_top, ← E.val.field_range_eq_map,
- E.field_range_val]
+ AlgHom.map_fieldRange, g.field_range_eq_top, ← E.val.field_range_eq_map, E.field_range_val]
#align alg_hom.field_range_of_normal AlgHom.fieldRange_of_normal
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,10 +3,10 @@ Copyright (c) 2020 Kenny Lau. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
-/
-import Mathbin.FieldTheory.Adjoin
-import Mathbin.FieldTheory.Tower
-import Mathbin.GroupTheory.Solvable
-import Mathbin.RingTheory.PowerBasis
+import FieldTheory.Adjoin
+import FieldTheory.Tower
+import GroupTheory.Solvable
+import RingTheory.PowerBasis
#align_import field_theory.normal from "leanprover-community/mathlib"@"9fb8964792b4237dac6200193a0d533f1b3f7423"
mathlib commit https://github.com/leanprover-community/mathlib/commit/442a83d738cb208d3600056c489be16900ba701d
@@ -603,11 +603,9 @@ instance is_finiteDimensional [FiniteDimensional F K] : FiniteDimensional F (nor
#align normal_closure.is_finite_dimensional normalClosure.is_finiteDimensional
-/
-#print normalClosure.isScalarTower /-
instance isScalarTower : IsScalarTower F (normalClosure F K L) L :=
IsScalarTower.subalgebra' F L L _
#align normal_closure.is_scalar_tower normalClosure.isScalarTower
--/
end normalClosure
mathlib commit https://github.com/leanprover-community/mathlib/commit/32a7e535287f9c73f2e4d2aef306a39190f0b504
@@ -332,7 +332,7 @@ def AlgHom.restrictNormalAux [h : Normal F E] :
map_zero' := Subtype.ext ϕ.map_zero
map_one' := Subtype.ext ϕ.map_one
map_add' x y := Subtype.ext (ϕ.map_add x y)
- map_mul' x y := Subtype.ext (ϕ.map_mul x y)
+ map_mul' x y := Subtype.ext (ϕ.map_hMul x y)
commutes' x := Subtype.ext (ϕ.commutes x)
#align alg_hom.restrict_normal_aux AlgHom.restrictNormalAux
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/63721b2c3eba6c325ecf8ae8cca27155a4f6306f
@@ -235,8 +235,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
refine' IntermediateField.algHom_mk_adjoin_splits' (top_le_iff.mp this) fun y hy => _
rcases multiset.mem_map.mp (multiset.mem_to_finset.mp hy) with ⟨z, hz1, hz2⟩
have Hz : IsIntegral F z := isIntegral_of_noetherian (IsNoetherian.iff_fg.2 hFE) z
- use
- show IsIntegral C y from
+ use show IsIntegral C y from
isIntegral_of_noetherian (IsNoetherian.iff_fg.2 (FiniteDimensional.right F C D)) y
apply splits_of_splits_of_dvd (algebraMap C E) (map_ne_zero (minpoly.ne_zero Hz))
· rw [splits_map_iff, ← algebra_map_eq F C E]
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,17 +2,14 @@
Copyright (c) 2020 Kenny Lau. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
-
-! This file was ported from Lean 3 source module field_theory.normal
-! leanprover-community/mathlib commit 9fb8964792b4237dac6200193a0d533f1b3f7423
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.FieldTheory.Adjoin
import Mathbin.FieldTheory.Tower
import Mathbin.GroupTheory.Solvable
import Mathbin.RingTheory.PowerBasis
+#align_import field_theory.normal from "leanprover-community/mathlib"@"9fb8964792b4237dac6200193a0d533f1b3f7423"
+
/-!
# Normal field extensions
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -50,26 +50,36 @@ class Normal : Prop where
variable {F K}
+#print Normal.isAlgebraic /-
theorem Normal.isAlgebraic (h : Normal F K) (x : K) : IsAlgebraic F x :=
Normal.is_algebraic' x
#align normal.is_algebraic Normal.isAlgebraic
+-/
+#print Normal.isIntegral /-
theorem Normal.isIntegral (h : Normal F K) (x : K) : IsIntegral F x :=
isAlgebraic_iff_isIntegral.mp (h.IsAlgebraic x)
#align normal.is_integral Normal.isIntegral
+-/
+#print Normal.splits /-
theorem Normal.splits (h : Normal F K) (x : K) : Splits (algebraMap F K) (minpoly F x) :=
Normal.splits' x
#align normal.splits Normal.splits
+-/
+#print normal_iff /-
theorem normal_iff : Normal F K ↔ ∀ x : K, IsIntegral F x ∧ Splits (algebraMap F K) (minpoly F x) :=
⟨fun h x => ⟨h.IsIntegral x, h.Splits x⟩, fun h =>
⟨fun x => (h x).1.IsAlgebraic F, fun x => (h x).2⟩⟩
#align normal_iff normal_iff
+-/
+#print Normal.out /-
theorem Normal.out : Normal F K → ∀ x : K, IsIntegral F x ∧ Splits (algebraMap F K) (minpoly F x) :=
normal_iff.1
#align normal.out Normal.out
+-/
variable (F K)
@@ -84,6 +94,7 @@ variable {K}
variable (K)
+#print Normal.exists_isSplittingField /-
theorem Normal.exists_isSplittingField [h : Normal F K] [FiniteDimensional F K] :
∃ p : F[X], IsSplittingField F K p :=
by
@@ -103,11 +114,13 @@ theorem Normal.exists_isSplittingField [h : Normal F K] [FiniteDimensional F K]
rw [is_root.def, eval_map, ← aeval_def, AlgHom.map_prod]
exact Finset.prod_eq_zero (Finset.mem_univ _) (minpoly.aeval _ _)
#align normal.exists_is_splitting_field Normal.exists_isSplittingField
+-/
section NormalTower
variable (E : Type _) [Field E] [Algebra F E] [Algebra K E] [IsScalarTower F K E]
+#print Normal.tower_top_of_normal /-
theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E :=
normal_iff.2 fun x => by
cases' h.out x with hx hhx
@@ -119,7 +132,9 @@ theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E :=
((Polynomial.splits_map_iff (algebraMap F K) (algebraMap K E)).mpr hhx)
(minpoly.dvd_map_of_isScalarTower F K x)⟩
#align normal.tower_top_of_normal Normal.tower_top_of_normal
+-/
+#print AlgHom.normal_bijective /-
theorem AlgHom.normal_bijective [h : Normal F E] (ϕ : E →ₐ[F] K) : Function.Bijective ϕ :=
⟨ϕ.toRingHom.Injective, fun x =>
by
@@ -139,9 +154,11 @@ theorem AlgHom.normal_bijective [h : Normal F E] (ϕ : E →ₐ[F] K) : Function
y hy
exact ⟨y, hy⟩⟩
#align alg_hom.normal_bijective AlgHom.normal_bijective
+-/
variable {F} {E} {E' : Type _} [Field E'] [Algebra F E']
+#print Normal.of_algEquiv /-
theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :=
normal_iff.2 fun x => by
cases' h.out (f.symm x) with hx hhx
@@ -157,10 +174,13 @@ theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :
Eq.trans (Polynomial.aeval_algHom_apply f.symm.to_alg_hom x (minpoly F (f.symm x))).symm
(minpoly.aeval _ _)
#align normal.of_alg_equiv Normal.of_algEquiv
+-/
+#print AlgEquiv.transfer_normal /-
theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F E' :=
⟨fun h => Normal.of_algEquiv f, fun h => Normal.of_algEquiv f.symm⟩
#align alg_equiv.transfer_normal AlgEquiv.transfer_normal
+-/
-- seems to be causing a diamond in the below proof
-- however, this may be a fluke and the proof below uses non-canonical `algebra` instances:
@@ -170,6 +190,7 @@ theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F
-- salient in the future, or at least taking a closer look at the algebra instances it uses.
attribute [-instance] AdjoinRoot.hasSmul
+#print Normal.of_isSplittingField /-
theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] : Normal F E :=
by
rcases eq_or_ne p 0 with (rfl | hp)
@@ -244,11 +265,13 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
(Algebra.adjoin_res_eq_adjoin_res F E C D hFEp.adjoin_root_set AdjoinRoot.adjoinRoot_eq_top)
rw [Set.image_singleton, RingHom.algebraMap_toAlgebra, AdjoinRoot.lift_root]
#align normal.of_is_splitting_field Normal.of_isSplittingField
+-/
end NormalTower
namespace IntermediateField
+#print IntermediateField.normal_iSup /-
/-- A compositum of normal extensions is normal -/
instance normal_iSup {ι : Type _} (t : ι → IntermediateField F K) [h : ∀ i, Normal F (t i)] :
Normal F (⨆ i, t i : IntermediateField F K) :=
@@ -271,14 +294,17 @@ instance normal_iSup {ι : Type _} (t : ι → IntermediateField F K) [h : ∀ i
rw [minpoly_eq, Subtype.coe_mk, ← minpoly_eq] at this
exact Polynomial.splits_comp_of_splits _ (inclusion hE).toRingHom this
#align intermediate_field.normal_supr IntermediateField.normal_iSup
+-/
variable {F K} {L : Type _} [Field L] [Algebra F L] [Algebra K L] [IsScalarTower F K L]
+#print IntermediateField.restrictScalars_normal /-
@[simp]
theorem restrictScalars_normal {E : IntermediateField K L} :
Normal F (E.restrictScalars F) ↔ Normal F E :=
Iff.rfl
#align intermediate_field.restrict_scalars_normal IntermediateField.restrictScalars_normal
+-/
end IntermediateField
@@ -290,6 +316,7 @@ section Restrict
variable (E : Type _) [Field E] [Algebra F E] [Algebra E K₁] [Algebra E K₂] [Algebra E K₃]
[IsScalarTower F E K₁] [IsScalarTower F E K₂] [IsScalarTower F E K₃]
+#print AlgHom.restrictNormalAux /-
/-- Restrict algebra homomorphism to image of normal subfield -/
def AlgHom.restrictNormalAux [h : Normal F E] :
(toAlgHom F E K₁).range →ₐ[F] (toAlgHom F E K₂).range
@@ -312,19 +339,25 @@ def AlgHom.restrictNormalAux [h : Normal F E] :
map_mul' x y := Subtype.ext (ϕ.map_mul x y)
commutes' x := Subtype.ext (ϕ.commutes x)
#align alg_hom.restrict_normal_aux AlgHom.restrictNormalAux
+-/
+#print AlgHom.restrictNormal /-
/-- Restrict algebra homomorphism to normal subfield -/
def AlgHom.restrictNormal [Normal F E] : E →ₐ[F] E :=
((AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₂)).symm.toAlgHom.comp
(ϕ.restrictNormalAux E)).comp
(AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₁)).toAlgHom
#align alg_hom.restrict_normal AlgHom.restrictNormal
+-/
+#print AlgHom.restrictNormal' /-
/-- Restrict algebra homomorphism to normal subfield (`alg_equiv` version) -/
def AlgHom.restrictNormal' [Normal F E] : E ≃ₐ[F] E :=
AlgEquiv.ofBijective (AlgHom.restrictNormal ϕ E) (AlgHom.normal_bijective F E E _)
#align alg_hom.restrict_normal' AlgHom.restrictNormal'
+-/
+#print AlgHom.restrictNormal_commutes /-
@[simp]
theorem AlgHom.restrictNormal_commutes [Normal F E] (x : E) :
algebraMap E K₂ (ϕ.restrictNormal E x) = ϕ (algebraMap E K₁ x) :=
@@ -332,13 +365,17 @@ theorem AlgHom.restrictNormal_commutes [Normal F E] (x : E) :
(AlgEquiv.apply_symm_apply (AlgEquiv.ofInjectiveField (IsScalarTower.toAlgHom F E K₂))
(ϕ.restrictNormalAux E ⟨IsScalarTower.toAlgHom F E K₁ x, x, rfl⟩))
#align alg_hom.restrict_normal_commutes AlgHom.restrictNormal_commutes
+-/
+#print AlgHom.restrictNormal_comp /-
theorem AlgHom.restrictNormal_comp [Normal F E] :
(ψ.restrictNormal E).comp (ϕ.restrictNormal E) = (ψ.comp ϕ).restrictNormal E :=
AlgHom.ext fun _ =>
(algebraMap E K₃).Injective (by simp only [AlgHom.comp_apply, AlgHom.restrictNormal_commutes])
#align alg_hom.restrict_normal_comp AlgHom.restrictNormal_comp
+-/
+#print AlgHom.fieldRange_of_normal /-
theorem AlgHom.fieldRange_of_normal {E : IntermediateField F K} [Normal F E] (f : E →ₐ[F] K) :
f.fieldRange = E := by
haveI : IsScalarTower F E E := by infer_instance
@@ -347,32 +384,42 @@ theorem AlgHom.fieldRange_of_normal {E : IntermediateField F K} [Normal F E] (f
IntermediateField.AlgHom.map_fieldRange, g.field_range_eq_top, ← E.val.field_range_eq_map,
E.field_range_val]
#align alg_hom.field_range_of_normal AlgHom.fieldRange_of_normal
+-/
+#print AlgEquiv.restrictNormal /-
/-- Restrict algebra isomorphism to a normal subfield -/
def AlgEquiv.restrictNormal [h : Normal F E] : E ≃ₐ[F] E :=
AlgHom.restrictNormal' χ.toAlgHom E
#align alg_equiv.restrict_normal AlgEquiv.restrictNormal
+-/
+#print AlgEquiv.restrictNormal_commutes /-
@[simp]
theorem AlgEquiv.restrictNormal_commutes [Normal F E] (x : E) :
algebraMap E K₂ (χ.restrictNormal E x) = χ (algebraMap E K₁ x) :=
χ.toAlgHom.restrictNormal_commutes E x
#align alg_equiv.restrict_normal_commutes AlgEquiv.restrictNormal_commutes
+-/
+#print AlgEquiv.restrictNormal_trans /-
theorem AlgEquiv.restrictNormal_trans [Normal F E] :
(χ.trans ω).restrictNormal E = (χ.restrictNormal E).trans (ω.restrictNormal E) :=
AlgEquiv.ext fun _ =>
(algebraMap E K₃).Injective
(by simp only [AlgEquiv.trans_apply, AlgEquiv.restrictNormal_commutes])
#align alg_equiv.restrict_normal_trans AlgEquiv.restrictNormal_trans
+-/
+#print AlgEquiv.restrictNormalHom /-
/-- Restriction to an normal subfield as a group homomorphism -/
def AlgEquiv.restrictNormalHom [Normal F E] : (K₁ ≃ₐ[F] K₁) →* E ≃ₐ[F] E :=
MonoidHom.mk' (fun χ => χ.restrictNormal E) fun ω χ => χ.restrictNormal_trans ω E
#align alg_equiv.restrict_normal_hom AlgEquiv.restrictNormalHom
+-/
variable (F K₁ E)
+#print Normal.algHomEquivAut /-
/-- If `K₁/E/F` is a tower of fields with `E/F` normal then `normal.alg_hom_equiv_aut` is an
equivalence. -/
@[simps]
@@ -390,6 +437,7 @@ def Normal.algHomEquivAut [Normal F E] : (E →ₐ[F] K₁) ≃ E ≃ₐ[F] E
rw [AlgHom.restrictNormal_commutes]
simp
#align normal.alg_hom_equiv_aut Normal.algHomEquivAut
+-/
end Restrict
@@ -398,6 +446,7 @@ section lift
variable {F} {K₁ K₂} (E : Type _) [Field E] [Algebra F E] [Algebra K₁ E] [Algebra K₂ E]
[IsScalarTower F K₁ E] [IsScalarTower F K₂ E]
+#print AlgHom.liftNormal /-
/-- If `E/Kᵢ/F` are towers of fields with `E/F` normal then we can lift
an algebra homomorphism `ϕ : K₁ →ₐ[F] K₂` to `ϕ.lift_normal E : E →ₐ[F] E`. -/
noncomputable def AlgHom.liftNormal [h : Normal F E] : E →ₐ[F] E :=
@@ -412,13 +461,17 @@ noncomputable def AlgHom.liftNormal [h : Normal F E] : E →ₐ[F] E :=
(by rw [splits_map_iff, ← IsScalarTower.algebraMap_eq]; exact (h.out x).2)
(minpoly.dvd_map_of_isScalarTower F K₁ x)⟩
#align alg_hom.lift_normal AlgHom.liftNormal
+-/
+#print AlgHom.liftNormal_commutes /-
@[simp]
theorem AlgHom.liftNormal_commutes [Normal F E] (x : K₁) :
ϕ.liftNormal E (algebraMap K₁ E x) = algebraMap K₂ E (ϕ x) := by
apply @AlgHom.commutes K₁ E E _ _ _ _
#align alg_hom.lift_normal_commutes AlgHom.liftNormal_commutes
+-/
+#print AlgHom.restrict_liftNormal /-
@[simp]
theorem AlgHom.restrict_liftNormal (ϕ : K₁ →ₐ[F] K₁) [Normal F K₁] [Normal F E] :
(ϕ.liftNormal E).restrictNormal K₁ = ϕ :=
@@ -426,19 +479,25 @@ theorem AlgHom.restrict_liftNormal (ϕ : K₁ →ₐ[F] K₁) [Normal F K₁] [N
(algebraMap K₁ E).Injective
(Eq.trans (AlgHom.restrictNormal_commutes _ K₁ x) (ϕ.liftNormal_commutes E x))
#align alg_hom.restrict_lift_normal AlgHom.restrict_liftNormal
+-/
+#print AlgEquiv.liftNormal /-
/-- If `E/Kᵢ/F` are towers of fields with `E/F` normal then we can lift
an algebra isomorphism `ϕ : K₁ ≃ₐ[F] K₂` to `ϕ.lift_normal E : E ≃ₐ[F] E`. -/
noncomputable def AlgEquiv.liftNormal [Normal F E] : E ≃ₐ[F] E :=
AlgEquiv.ofBijective (χ.toAlgHom.liftNormal E) (AlgHom.normal_bijective F E E _)
#align alg_equiv.lift_normal AlgEquiv.liftNormal
+-/
+#print AlgEquiv.liftNormal_commutes /-
@[simp]
theorem AlgEquiv.liftNormal_commutes [Normal F E] (x : K₁) :
χ.liftNormal E (algebraMap K₁ E x) = algebraMap K₂ E (χ x) :=
χ.toAlgHom.liftNormal_commutes E x
#align alg_equiv.lift_normal_commutes AlgEquiv.liftNormal_commutes
+-/
+#print AlgEquiv.restrict_liftNormal /-
@[simp]
theorem AlgEquiv.restrict_liftNormal (χ : K₁ ≃ₐ[F] K₁) [Normal F K₁] [Normal F E] :
(χ.liftNormal E).restrictNormal K₁ = χ :=
@@ -446,14 +505,18 @@ theorem AlgEquiv.restrict_liftNormal (χ : K₁ ≃ₐ[F] K₁) [Normal F K₁]
(algebraMap K₁ E).Injective
(Eq.trans (AlgEquiv.restrictNormal_commutes _ K₁ x) (χ.liftNormal_commutes E x))
#align alg_equiv.restrict_lift_normal AlgEquiv.restrict_liftNormal
+-/
+#print AlgEquiv.restrictNormalHom_surjective /-
theorem AlgEquiv.restrictNormalHom_surjective [Normal F K₁] [Normal F E] :
Function.Surjective (AlgEquiv.restrictNormalHom K₁ : (E ≃ₐ[F] E) → K₁ ≃ₐ[F] K₁) := fun χ =>
⟨χ.liftNormal E, χ.restrict_liftNormal E⟩
#align alg_equiv.restrict_normal_hom_surjective AlgEquiv.restrictNormalHom_surjective
+-/
variable (F) (K₁) (E)
+#print isSolvable_of_isScalarTower /-
theorem isSolvable_of_isScalarTower [Normal F K₁] [h1 : IsSolvable (K₁ ≃ₐ[F] K₁)]
[h2 : IsSolvable (E ≃ₐ[K₁] E)] : IsSolvable (E ≃ₐ[F] E) :=
by
@@ -468,6 +531,7 @@ theorem isSolvable_of_isScalarTower [Normal F K₁] [h1 : IsSolvable (K₁ ≃
⟨{ ϕ with commutes' := fun x => _ }, AlgEquiv.ext fun _ => rfl⟩
exact Eq.trans (ϕ.restrict_normal_commutes K₁ x).symm (congr_arg _ (alg_equiv.ext_iff.mp hϕ x))
#align is_solvable_of_is_scalar_tower isSolvable_of_isScalarTower
+-/
end lift
@@ -477,15 +541,18 @@ open IntermediateField
variable (F K) (L : Type _) [Field L] [Algebra F L] [Algebra K L] [IsScalarTower F K L]
+#print normalClosure /-
/-- The normal closure of `K` in `L`. -/
noncomputable def normalClosure : IntermediateField K L :=
{ (⨆ f : K →ₐ[F] L, f.fieldRange).toSubfield with
algebraMap_mem' := fun r =>
le_iSup (fun f : K →ₐ[F] L => f.fieldRange) (IsScalarTower.toAlgHom F K L) ⟨r, rfl⟩ }
#align normal_closure normalClosure
+-/
namespace normalClosure
+#print normalClosure.restrictScalars_eq_iSup_adjoin /-
theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
(normalClosure F K L).restrictScalars F = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) :=
by
@@ -513,7 +580,9 @@ theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
rw [Algebra.id.map_eq_id, RingHom.id_apply]
apply PowerBasis.lift_gen
#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure.restrictScalars_eq_iSup_adjoin
+-/
+#print normalClosure.normal /-
instance normal [h : Normal F L] : Normal F (normalClosure F K L) :=
by
let ϕ := algebraMap K L
@@ -527,17 +596,22 @@ instance normal [h : Normal F L] : Normal F (normalClosure F K L) :=
((isIntegral_algebraMap_iff ϕ.injective).mp (h.is_integral (ϕ x))) rfl).symm ▸
h.splits _)
#align normal_closure.normal normalClosure.normal
+-/
+#print normalClosure.is_finiteDimensional /-
instance is_finiteDimensional [FiniteDimensional F K] : FiniteDimensional F (normalClosure F K L) :=
by
haveI : ∀ f : K →ₐ[F] L, FiniteDimensional F f.fieldRange := fun f =>
f.to_linear_map.finite_dimensional_range
apply IntermediateField.finiteDimensional_iSup_of_finite
#align normal_closure.is_finite_dimensional normalClosure.is_finiteDimensional
+-/
+#print normalClosure.isScalarTower /-
instance isScalarTower : IsScalarTower F (normalClosure F K L) L :=
IsScalarTower.subalgebra' F L L _
#align normal_closure.is_scalar_tower normalClosure.isScalarTower
+-/
end normalClosure
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: Kenny Lau, Thomas Browning, Patrick Lutz
! This file was ported from Lean 3 source module field_theory.normal
-! leanprover-community/mathlib commit fd4551cfe4b7484b81c2c9ba3405edae27659676
+! leanprover-community/mathlib commit 9fb8964792b4237dac6200193a0d533f1b3f7423
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -173,9 +173,8 @@ attribute [-instance] AdjoinRoot.hasSmul
theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] : Normal F E :=
by
rcases eq_or_ne p 0 with (rfl | hp)
- · have := hFEp.adjoin_roots
- simp only [Polynomial.map_zero, roots_zero, Multiset.toFinset_zero, Finset.coe_empty,
- Algebra.adjoin_empty] at this
+ · have := hFEp.adjoin_root_set
+ simp only [root_set_zero, Algebra.adjoin_empty] at this
exact
Normal.of_algEquiv
(AlgEquiv.ofBijective (Algebra.ofId F E) (Algebra.bijective_algebraMap_iff.2 this.symm))
@@ -242,7 +241,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
rw [← Finset.image_toFinset, Finset.coe_image]
apply
Eq.trans
- (Algebra.adjoin_res_eq_adjoin_res F E C D hFEp.adjoin_roots AdjoinRoot.adjoinRoot_eq_top)
+ (Algebra.adjoin_res_eq_adjoin_res F E C D hFEp.adjoin_root_set AdjoinRoot.adjoinRoot_eq_top)
rw [Set.image_singleton, RingHom.algebraMap_toAlgebra, AdjoinRoot.lift_root]
#align normal.of_is_splitting_field Normal.of_isSplittingField
mathlib commit https://github.com/leanprover-community/mathlib/commit/c471da714c044131b90c133701e51b877c246677
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
! This file was ported from Lean 3 source module field_theory.normal
-! leanprover-community/mathlib commit df76f43357840485b9d04ed5dee5ab115d420e87
+! leanprover-community/mathlib commit fd4551cfe4b7484b81c2c9ba3405edae27659676
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -16,6 +16,9 @@ import Mathbin.RingTheory.PowerBasis
/-!
# Normal field extensions
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
In this file we define normal field extensions and prove that for a finite extension, being normal
is the same as being a splitting field (`normal.of_is_splitting_field` and
`normal.exists_is_splitting_field`).
mathlib commit https://github.com/leanprover-community/mathlib/commit/7e5137f579de09a059a5ce98f364a04e221aabf0
@@ -36,12 +36,14 @@ open Polynomial IsScalarTower
variable (F K : Type _) [Field F] [Field K] [Algebra F K]
+#print Normal /-
/-- Typeclass for normal field extension: `K` is a normal extension of `F` iff the minimal
polynomial of every element `x` in `K` splits in `K`, i.e. every conjugate of `x` is in `K`. -/
class Normal : Prop where
is_algebraic' : Algebra.IsAlgebraic F K
splits' (x : K) : Splits (algebraMap F K) (minpoly F x)
#align normal Normal
+-/
variable {F K}
@@ -68,10 +70,12 @@ theorem Normal.out : Normal F K → ∀ x : K, IsIntegral F x ∧ Splits (algebr
variable (F K)
+#print normal_self /-
instance normal_self : Normal F F :=
⟨fun x => isIntegral_algebraMap.IsAlgebraic F, fun x =>
(minpoly.eq_X_sub_C' x).symm ▸ splits_X_sub_C _⟩
#align normal_self normal_self
+-/
variable {K}
mathlib commit https://github.com/leanprover-community/mathlib/commit/31c24aa72e7b3e5ed97a8412470e904f82b81004
@@ -338,7 +338,8 @@ theorem AlgHom.fieldRange_of_normal {E : IntermediateField F K} [Normal F E] (f
haveI : IsScalarTower F E E := by infer_instance
let g := f.restrict_normal' E
rw [← show E.val.comp ↑g = f from fun_like.ext_iff.mpr (f.restrict_normal_commutes E), ←
- AlgHom.map_fieldRange, g.field_range_eq_top, ← E.val.field_range_eq_map, E.field_range_val]
+ IntermediateField.AlgHom.map_fieldRange, g.field_range_eq_top, ← E.val.field_range_eq_map,
+ E.field_range_val]
#align alg_hom.field_range_of_normal AlgHom.fieldRange_of_normal
/-- Restrict algebra isomorphism to a normal subfield -/
mathlib commit https://github.com/leanprover-community/mathlib/commit/a3209ddf94136d36e5e5c624b10b2a347cc9d090
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
! This file was ported from Lean 3 source module field_theory.normal
-! leanprover-community/mathlib commit 949dc57e616a621462062668c9f39e4e17b64b69
+! leanprover-community/mathlib commit df76f43357840485b9d04ed5dee5ab115d420e87
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -166,11 +166,12 @@ attribute [-instance] AdjoinRoot.hasSmul
theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] : Normal F E :=
by
rcases eq_or_ne p 0 with (rfl | hp)
- · haveI : is_splitting_field F F 0 := ⟨splits_zero _, Subsingleton.elim _ _⟩
+ · have := hFEp.adjoin_roots
+ simp only [Polynomial.map_zero, roots_zero, Multiset.toFinset_zero, Finset.coe_empty,
+ Algebra.adjoin_empty] at this
exact
- (AlgEquiv.transfer_normal
- ((is_splitting_field.alg_equiv F 0).trans (is_splitting_field.alg_equiv E 0).symm)).mp
- (normal_self F)
+ Normal.of_algEquiv
+ (AlgEquiv.ofBijective (Algebra.ofId F E) (Algebra.bijective_algebraMap_iff.2 this.symm))
refine' normal_iff.2 fun x => _
have hFE : FiniteDimensional F E := is_splitting_field.finite_dimensional E p
have Hx : IsIntegral F x := isIntegral_of_noetherian (IsNoetherian.iff_fg.2 hFE) x
@@ -238,9 +239,6 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
rw [Set.image_singleton, RingHom.algebraMap_toAlgebra, AdjoinRoot.lift_root]
#align normal.of_is_splitting_field Normal.of_isSplittingField
-instance (p : F[X]) : Normal F p.SplittingField :=
- Normal.of_isSplittingField p
-
end NormalTower
namespace IntermediateField
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -104,7 +104,7 @@ variable (E : Type _) [Field E] [Algebra F E] [Algebra K E] [IsScalarTower F K E
theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E :=
normal_iff.2 fun x => by
cases' h.out x with hx hhx
- rw [algebra_map_eq F K E] at hhx
+ rw [algebra_map_eq F K E] at hhx
exact
⟨isIntegral_of_isScalarTower hx,
Polynomial.splits_of_splits_of_dvd (algebraMap K E)
@@ -139,7 +139,7 @@ theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :
normal_iff.2 fun x => by
cases' h.out (f.symm x) with hx hhx
have H := map_isIntegral f.to_alg_hom hx
- rw [AlgEquiv.toAlgHom_eq_coe, AlgEquiv.coe_algHom, AlgEquiv.apply_symm_apply] at H
+ rw [AlgEquiv.toAlgHom_eq_coe, AlgEquiv.coe_algHom, AlgEquiv.apply_symm_apply] at H
use H
apply Polynomial.splits_of_splits_of_dvd (algebraMap F E') (minpoly.ne_zero hx)
· rw [← AlgHom.comp_algebraMap f.to_alg_hom]
@@ -228,7 +228,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
(Algebra.adjoin E {AdjoinRoot.root q}).restrictScalars F
by
rw [AdjoinRoot.adjoinRoot_eq_top, Subalgebra.restrictScalars_top, ←
- @Subalgebra.restrictScalars_top F C] at this
+ @Subalgebra.restrictScalars_top F C] at this
exact top_le_iff.mpr (Subalgebra.restrictScalars_injective F this)
dsimp only [S]
rw [← Finset.image_toFinset, Finset.coe_image]
@@ -264,7 +264,7 @@ instance normal_iSup {ι : Type _} (t : ι → IntermediateField F K) [h : ∀ i
rw [adjoin_le_iff, ← image_root_set ((h i.1).Splits i.2) (t i.1).val]
exact fun _ ⟨a, _, h⟩ => h ▸ a.2
have := hF.splits ⟨x, hx⟩
- rw [minpoly_eq, Subtype.coe_mk, ← minpoly_eq] at this
+ rw [minpoly_eq, Subtype.coe_mk, ← minpoly_eq] at this
exact Polynomial.splits_comp_of_splits _ (inclusion hE).toRingHom this
#align intermediate_field.normal_supr IntermediateField.normal_iSup
@@ -495,7 +495,7 @@ theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
minpoly.ne_zero
((isIntegral_algebraMap_iff (algebraMap K L).Injective).mp
(h.is_integral (algebraMap K L x)))
- · rw [Polynomial.rootSet, Finset.mem_coe, Multiset.mem_toFinset] at hy
+ · rw [Polynomial.rootSet, Finset.mem_coe, Multiset.mem_toFinset] at hy
let g :=
(alg_hom_adjoin_integral_equiv F
((isIntegral_algebraMap_iff (algebraMap K L).Injective).mp
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -28,9 +28,9 @@ is the same as being a splitting field (`normal.of_is_splitting_field` and
noncomputable section
-open BigOperators
+open scoped BigOperators
-open Classical Polynomial
+open scoped Classical Polynomial
open Polynomial IsScalarTower
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -185,9 +185,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
haveI : FiniteDimensional F D := FiniteDimensional.trans F E D
rsuffices ⟨ϕ⟩ : Nonempty (D →ₐ[F] E)
· rw [← WithBot.coe_one, degree_eq_iff_nat_degree_eq q_irred.ne_zero, ← finrankED]
- have nat_lemma : ∀ a b c : ℕ, a * b = c → c ≤ a → 0 < c → b = 1 :=
- by
- intro a b c h1 h2 h3
+ have nat_lemma : ∀ a b c : ℕ, a * b = c → c ≤ a → 0 < c → b = 1 := by intro a b c h1 h2 h3;
nlinarith
exact
nat_lemma _ _ _ (FiniteDimensional.finrank_mul_finrank F E D)
@@ -406,9 +404,7 @@ noncomputable def AlgHom.liftNormal [h : Normal F E] : E →ₐ[F] E :=
(IntermediateField.adjoin_univ _ _) fun x hx =>
⟨isIntegral_of_isScalarTower (h.out x).1,
splits_of_splits_of_dvd _ (map_ne_zero (minpoly.ne_zero (h.out x).1))
- (by
- rw [splits_map_iff, ← IsScalarTower.algebraMap_eq]
- exact (h.out x).2)
+ (by rw [splits_map_iff, ← IsScalarTower.algebraMap_eq]; exact (h.out x).2)
(minpoly.dvd_map_of_isScalarTower F K₁ x)⟩
#align alg_hom.lift_normal AlgHom.liftNormal
mathlib commit https://github.com/leanprover-community/mathlib/commit/75e7fca56381d056096ce5d05e938f63a6567828
@@ -70,7 +70,7 @@ variable (F K)
instance normal_self : Normal F F :=
⟨fun x => isIntegral_algebraMap.IsAlgebraic F, fun x =>
- (minpoly.eq_x_sub_C' x).symm ▸ splits_X_sub_C _⟩
+ (minpoly.eq_X_sub_C' x).symm ▸ splits_X_sub_C _⟩
#align normal_self normal_self
variable {K}
mathlib commit https://github.com/leanprover-community/mathlib/commit/e3fb84046afd187b710170887195d50bada934ee
@@ -248,7 +248,7 @@ end NormalTower
namespace IntermediateField
/-- A compositum of normal extensions is normal -/
-instance normal_supᵢ {ι : Type _} (t : ι → IntermediateField F K) [h : ∀ i, Normal F (t i)] :
+instance normal_iSup {ι : Type _} (t : ι → IntermediateField F K) [h : ∀ i, Normal F (t i)] :
Normal F (⨆ i, t i : IntermediateField F K) :=
by
refine' ⟨is_algebraic_supr fun i => (h i).1, fun x => _⟩
@@ -262,13 +262,13 @@ instance normal_supᵢ {ι : Type _} (t : ι → IntermediateField F K) [h : ∀
· exact Polynomial.splits_comp_of_splits _ (algebraMap (t i.1) K) ((h i.1).Splits i.2)
have hE : E ≤ ⨆ i, t i :=
by
- refine' supᵢ_le fun i => supᵢ_le fun hi => le_supᵢ_of_le i.1 _
+ refine' iSup_le fun i => iSup_le fun hi => le_iSup_of_le i.1 _
rw [adjoin_le_iff, ← image_root_set ((h i.1).Splits i.2) (t i.1).val]
exact fun _ ⟨a, _, h⟩ => h ▸ a.2
have := hF.splits ⟨x, hx⟩
rw [minpoly_eq, Subtype.coe_mk, ← minpoly_eq] at this
exact Polynomial.splits_comp_of_splits _ (inclusion hE).toRingHom this
-#align intermediate_field.normal_supr IntermediateField.normal_supᵢ
+#align intermediate_field.normal_supr IntermediateField.normal_iSup
variable {F K} {L : Type _} [Field L] [Algebra F L] [Algebra K L] [IsScalarTower F K L]
@@ -480,18 +480,18 @@ variable (F K) (L : Type _) [Field L] [Algebra F L] [Algebra K L] [IsScalarTower
noncomputable def normalClosure : IntermediateField K L :=
{ (⨆ f : K →ₐ[F] L, f.fieldRange).toSubfield with
algebraMap_mem' := fun r =>
- le_supᵢ (fun f : K →ₐ[F] L => f.fieldRange) (IsScalarTower.toAlgHom F K L) ⟨r, rfl⟩ }
+ le_iSup (fun f : K →ₐ[F] L => f.fieldRange) (IsScalarTower.toAlgHom F K L) ⟨r, rfl⟩ }
#align normal_closure normalClosure
namespace normalClosure
-theorem restrictScalars_eq_supᵢ_adjoin [h : Normal F L] :
+theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
(normalClosure F K L).restrictScalars F = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) :=
by
- refine' le_antisymm (supᵢ_le _) (supᵢ_le fun x => adjoin_le_iff.mpr fun y hy => _)
+ refine' le_antisymm (iSup_le _) (iSup_le fun x => adjoin_le_iff.mpr fun y hy => _)
· rintro f _ ⟨x, rfl⟩
refine'
- le_supᵢ (fun x => adjoin F ((minpoly F x).rootSet L)) x
+ le_iSup (fun x => adjoin F ((minpoly F x).rootSet L)) x
(subset_adjoin F ((minpoly F x).rootSet L) _)
rw [mem_root_set_of_ne, AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom,
Polynomial.aeval_algHom_apply, minpoly.aeval, map_zero]
@@ -506,18 +506,18 @@ theorem restrictScalars_eq_supᵢ_adjoin [h : Normal F L] :
(h.is_integral (algebraMap K L x)))).symm
⟨y, hy⟩
refine'
- le_supᵢ (fun f : K →ₐ[F] L => f.fieldRange)
+ le_iSup (fun f : K →ₐ[F] L => f.fieldRange)
((g.lift_normal L).comp (IsScalarTower.toAlgHom F K L))
⟨x, (g.lift_normal_commutes L (adjoin_simple.gen F x)).trans _⟩
rw [Algebra.id.map_eq_id, RingHom.id_apply]
apply PowerBasis.lift_gen
-#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure.restrictScalars_eq_supᵢ_adjoin
+#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure.restrictScalars_eq_iSup_adjoin
instance normal [h : Normal F L] : Normal F (normalClosure F K L) :=
by
let ϕ := algebraMap K L
rw [← IntermediateField.restrictScalars_normal, restrict_scalars_eq_supr_adjoin]
- apply IntermediateField.normal_supᵢ F L _
+ apply IntermediateField.normal_iSup F L _
intro x
apply Normal.of_isSplittingField (minpoly F x)
exact
@@ -531,7 +531,7 @@ instance is_finiteDimensional [FiniteDimensional F K] : FiniteDimensional F (nor
by
haveI : ∀ f : K →ₐ[F] L, FiniteDimensional F f.fieldRange := fun f =>
f.to_linear_map.finite_dimensional_range
- apply IntermediateField.finiteDimensional_supᵢ_of_finite
+ apply IntermediateField.finiteDimensional_iSup_of_finite
#align normal_closure.is_finite_dimensional normalClosure.is_finiteDimensional
instance isScalarTower : IsScalarTower F (normalClosure F K L) L :=
mathlib commit https://github.com/leanprover-community/mathlib/commit/cc5dd6244981976cc9da7afc4eee5682b037a013
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
! This file was ported from Lean 3 source module field_theory.normal
-! leanprover-community/mathlib commit d4437c68c8d350fc9d4e95e1e174409db35e30d7
+! leanprover-community/mathlib commit 949dc57e616a621462062668c9f39e4e17b64b69
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -155,18 +155,24 @@ theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F
⟨fun h => Normal.of_algEquiv f, fun h => Normal.of_algEquiv f.symm⟩
#align alg_equiv.transfer_normal AlgEquiv.transfer_normal
+-- seems to be causing a diamond in the below proof
+-- however, this may be a fluke and the proof below uses non-canonical `algebra` instances:
+-- when I replaced all the instances inside the proof with the "canonical" instances we have,
+-- I had the (unprovable) goal (of the form) `adjoin_root.mk f (C x) = adjoin_root.mk f X`
+-- for some `x, f`. So maybe this is indeed the correct approach and rewriting this proof is
+-- salient in the future, or at least taking a closer look at the algebra instances it uses.
+attribute [-instance] AdjoinRoot.hasSmul
+
theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] : Normal F E :=
by
- by_cases hp : p = 0
- · have : is_splitting_field F F p := by
- rw [hp]
- exact ⟨splits_zero _, Subsingleton.elim _ _⟩
+ rcases eq_or_ne p 0 with (rfl | hp)
+ · haveI : is_splitting_field F F 0 := ⟨splits_zero _, Subsingleton.elim _ _⟩
exact
(AlgEquiv.transfer_normal
- ((is_splitting_field.alg_equiv F p).trans (is_splitting_field.alg_equiv E p).symm)).mp
+ ((is_splitting_field.alg_equiv F 0).trans (is_splitting_field.alg_equiv E 0).symm)).mp
(normal_self F)
refine' normal_iff.2 fun x => _
- haveI hFE : FiniteDimensional F E := is_splitting_field.finite_dimensional E p
+ have hFE : FiniteDimensional F E := is_splitting_field.finite_dimensional E p
have Hx : IsIntegral F x := isIntegral_of_noetherian (IsNoetherian.iff_fg.2 hFE) x
refine' ⟨Hx, Or.inr _⟩
rintro q q_irred ⟨r, hr⟩
@@ -174,13 +180,11 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
haveI := Fact.mk q_irred
let pbED := AdjoinRoot.powerBasis q_irred.ne_zero
haveI : FiniteDimensional E D := PowerBasis.finiteDimensional pbED
- have finrankED : FiniteDimensional.finrank E D = q.nat_degree := PowerBasis.finrank pbED
- letI : Algebra F D := RingHom.toAlgebra ((algebraMap E D).comp (algebraMap F E))
- haveI : IsScalarTower F E D := of_algebra_map_eq fun _ => rfl
+ have finrankED : FiniteDimensional.finrank E D = q.nat_degree := by
+ rw [PowerBasis.finrank pbED, AdjoinRoot.powerBasis_dim]
haveI : FiniteDimensional F D := FiniteDimensional.trans F E D
- suffices Nonempty (D →ₐ[F] E) by
- cases' this with ϕ
- rw [← WithBot.coe_one, degree_eq_iff_nat_degree_eq q_irred.ne_zero, ← finrankED]
+ rsuffices ⟨ϕ⟩ : Nonempty (D →ₐ[F] E)
+ · rw [← WithBot.coe_one, degree_eq_iff_nat_degree_eq q_irred.ne_zero, ← finrankED]
have nat_lemma : ∀ a b c : ℕ, a * b = c → c ≤ a → 0 < c → b = 1 :=
by
intro a b c h1 h2 h3
mathlib commit https://github.com/leanprover-community/mathlib/commit/d4437c68c8d350fc9d4e95e1e174409db35e30d7
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
! This file was ported from Lean 3 source module field_theory.normal
-! leanprover-community/mathlib commit 00f91228655eecdcd3ac97a7fd8dbcb139fe990a
+! leanprover-community/mathlib commit d4437c68c8d350fc9d4e95e1e174409db35e30d7
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -333,6 +333,14 @@ theorem AlgHom.restrictNormal_comp [Normal F E] :
(algebraMap E K₃).Injective (by simp only [AlgHom.comp_apply, AlgHom.restrictNormal_commutes])
#align alg_hom.restrict_normal_comp AlgHom.restrictNormal_comp
+theorem AlgHom.fieldRange_of_normal {E : IntermediateField F K} [Normal F E] (f : E →ₐ[F] K) :
+ f.fieldRange = E := by
+ haveI : IsScalarTower F E E := by infer_instance
+ let g := f.restrict_normal' E
+ rw [← show E.val.comp ↑g = f from fun_like.ext_iff.mpr (f.restrict_normal_commutes E), ←
+ AlgHom.map_fieldRange, g.field_range_eq_top, ← E.val.field_range_eq_map, E.field_range_val]
+#align alg_hom.field_range_of_normal AlgHom.fieldRange_of_normal
+
/-- Restrict algebra isomorphism to a normal subfield -/
def AlgEquiv.restrictNormal [h : Normal F E] : E ≃ₐ[F] E :=
AlgHom.restrictNormal' χ.toAlgHom E
mathlib commit https://github.com/leanprover-community/mathlib/commit/3905fa80e62c0898131285baab35559fbc4e5cda
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
! This file was ported from Lean 3 source module field_theory.normal
-! leanprover-community/mathlib commit 3d32bf9cef95940e3fe1ca0dd2412e0f21579f46
+! leanprover-community/mathlib commit 00f91228655eecdcd3ac97a7fd8dbcb139fe990a
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -522,6 +522,10 @@ instance is_finiteDimensional [FiniteDimensional F K] : FiniteDimensional F (nor
apply IntermediateField.finiteDimensional_supᵢ_of_finite
#align normal_closure.is_finite_dimensional normalClosure.is_finiteDimensional
+instance isScalarTower : IsScalarTower F (normalClosure F K L) L :=
+ IsScalarTower.subalgebra' F L L _
+#align normal_closure.is_scalar_tower normalClosure.isScalarTower
+
end normalClosure
end normalClosure
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce86f4e05e9a9b8da5e316b22c76ce76440c56a1
@@ -70,7 +70,7 @@ variable (F K)
instance normal_self : Normal F F :=
⟨fun x => isIntegral_algebraMap.IsAlgebraic F, fun x =>
- (minpoly.eq_x_sub_C' x).symm ▸ splits_x_sub_c _⟩
+ (minpoly.eq_x_sub_C' x).symm ▸ splits_X_sub_C _⟩
#align normal_self normal_self
variable {K}
mathlib commit https://github.com/leanprover-community/mathlib/commit/3180fab693e2cee3bff62675571264cb8778b212
@@ -197,7 +197,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
(AdjoinRoot.lift (algebraMap F D) (AdjoinRoot.root q)
(by
rw [algebra_map_eq F E D, ← eval₂_map, hr, AdjoinRoot.algebraMap_eq, eval₂_mul,
- AdjoinRoot.eval₂_root, zero_mul]))
+ AdjoinRoot.eval₂_root, MulZeroClass.zero_mul]))
letI : Algebra C E := RingHom.toAlgebra (AdjoinRoot.lift (algebraMap F E) x (minpoly.aeval F x))
haveI : IsScalarTower F C D := of_algebra_map_eq fun x => (AdjoinRoot.lift_of _).symm
haveI : IsScalarTower F C E := of_algebra_map_eq fun x => (AdjoinRoot.lift_of _).symm
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
@@ -213,11 +213,11 @@ noncomputable def Algebra.IsAlgebraic.algHomEmbeddingOfSplits (alg : IsAlgebraic
· exact splits_of_splits_of_dvd _ (minpoly.ne_zero iy)
(h y) (minpoly.dvd F x (mem_rootSet.mp hx).2)
· simp [minpoly.eq_zero iy] at hx
- { toFun := (φ.comp <| inclusion <| normalClosure_le_iSup_adjoin alg).comp ∘
- (normalClosure.algHomEquiv F K L').symm
+ let φ' := (φ.comp <| inclusion <| normalClosure_le_iSup_adjoin alg)
+ { toFun := φ'.comp ∘ (normalClosure.algHomEquiv F K L').symm
inj' := fun _ _ h ↦ (normalClosure.algHomEquiv F K L').symm.injective <| by
rw [DFunLike.ext'_iff] at h ⊢
- exact (φ.comp _).injective.comp_left h }
+ exact φ'.injective.comp_left h }
namespace IntermediateField
@@ -83,7 +83,7 @@ theorem Normal.exists_isSplittingField [h : Normal F K] [FiniteDimensional F K]
mt (Polynomial.map_eq_zero <| algebraMap F K).1 <|
Finset.prod_ne_zero_iff.2 fun x _ => _).2 _)
· exact minpoly.ne_zero (h.isIntegral (s x))
- rw [IsRoot.definition, eval_map, ← aeval_def, AlgHom.map_prod]
+ rw [IsRoot.def, eval_map, ← aeval_def, AlgHom.map_prod]
exact Finset.prod_eq_zero (Finset.mem_univ _) (minpoly.aeval _ _)
#align normal.exists_is_splitting_field Normal.exists_isSplittingField
@@ -229,7 +229,7 @@ def AlgHom.restrictNormalAux [h : Normal F E] :
rw [← hx, ← hy]
apply minpoly.mem_range_of_degree_eq_one E
refine'
- Or.resolve_left (h.splits z).def' (minpoly.ne_zero (h.isIntegral z)) (minpoly.irreducible _)
+ Or.resolve_left (h.splits z).def (minpoly.ne_zero (h.isIntegral z)) (minpoly.irreducible _)
(minpoly.dvd E _ (by simp [aeval_algHom_apply]))
simp only [AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom]
suffices IsIntegral F _ by exact this.tower_top
Purely automatic replacement. If this is in any way controversial; I'm happy to just close this PR.
@@ -82,7 +82,7 @@ lemma normalClosure_eq_iSup_adjoin_of_splits :
le_iSup AlgHom.fieldRange φ ⟨x, hφ⟩
/-- If `K/F` is algebraic, the "generated by roots" condition in IsNormalClosure can be replaced
- by "generated by images of embeddings".-/
+ by "generated by images of embeddings". -/
lemma isNormalClosure_iff : IsNormalClosure F K L ↔
(∀ x : K, (minpoly F x).Splits (algebraMap F L)) ∧ normalClosure F K L = ⊤ := by
refine ⟨fun ⟨splits, h⟩ ↦ ⟨splits, ?_⟩, fun ⟨splits, h⟩ ↦ ⟨splits, ?_⟩⟩ <;>
I removed some redundant instance arguments throughout Mathlib. To do this, I used VS Code's regex search. See https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/repeating.20instances.20from.20variable.20command I closed the previous PR for this and reopened it.
@@ -148,7 +148,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
exact ⟨hp, minpoly.ne_zero hx⟩
#align normal.of_is_splitting_field Normal.of_isSplittingField
-instance Polynomial.SplittingField.instNormal [Field F] (p : F[X]) : Normal F p.SplittingField :=
+instance Polynomial.SplittingField.instNormal (p : F[X]) : Normal F p.SplittingField :=
Normal.of_isSplittingField p
#align polynomial.splitting_field.normal Polynomial.SplittingField.instNormal
@@ -83,7 +83,7 @@ theorem Normal.exists_isSplittingField [h : Normal F K] [FiniteDimensional F K]
mt (Polynomial.map_eq_zero <| algebraMap F K).1 <|
Finset.prod_ne_zero_iff.2 fun x _ => _).2 _)
· exact minpoly.ne_zero (h.isIntegral (s x))
- rw [IsRoot.def, eval_map, ← aeval_def, AlgHom.map_prod]
+ rw [IsRoot.definition, eval_map, ← aeval_def, AlgHom.map_prod]
exact Finset.prod_eq_zero (Finset.mem_univ _) (minpoly.aeval _ _)
#align normal.exists_is_splitting_field Normal.exists_isSplittingField
@@ -229,7 +229,7 @@ def AlgHom.restrictNormalAux [h : Normal F E] :
rw [← hx, ← hy]
apply minpoly.mem_range_of_degree_eq_one E
refine'
- Or.resolve_left (h.splits z).def (minpoly.ne_zero (h.isIntegral z)) (minpoly.irreducible _)
+ Or.resolve_left (h.splits z).def' (minpoly.ne_zero (h.isIntegral z)) (minpoly.irreducible _)
(minpoly.dvd E _ (by simp [aeval_algHom_apply]))
simp only [AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom]
suffices IsIntegral F _ by exact this.tower_top
FunLike
to DFunLike
(#9785)
This prepares for the introduction of a non-dependent synonym of FunLike, which helps a lot with keeping #8386 readable.
This is entirely search-and-replace in 680197f combined with manual fixes in 4145626, e900597 and b8428f8. The commands that generated this change:
sed -i 's/\bFunLike\b/DFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\btoFunLike\b/toDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/import Mathlib.Data.DFunLike/import Mathlib.Data.FunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\bHom_FunLike\b/Hom_DFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\binstFunLike\b/instDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\bfunLike\b/instDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\btoo many metavariables to apply `fun_like.has_coe_to_fun`/too many metavariables to apply `DFunLike.hasCoeToFun`/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>
@@ -216,7 +216,7 @@ noncomputable def Algebra.IsAlgebraic.algHomEmbeddingOfSplits (alg : IsAlgebraic
{ toFun := (φ.comp <| inclusion <| normalClosure_le_iSup_adjoin alg).comp ∘
(normalClosure.algHomEquiv F K L').symm
inj' := fun _ _ h ↦ (normalClosure.algHomEquiv F K L').symm.injective <| by
- rw [FunLike.ext'_iff] at h ⊢
+ rw [DFunLike.ext'_iff] at h ⊢
exact (φ.comp _).injective.comp_left h }
namespace IntermediateField
FunLike
to DFunLike
(#9785)
This prepares for the introduction of a non-dependent synonym of FunLike, which helps a lot with keeping #8386 readable.
This is entirely search-and-replace in 680197f combined with manual fixes in 4145626, e900597 and b8428f8. The commands that generated this change:
sed -i 's/\bFunLike\b/DFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\btoFunLike\b/toDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/import Mathlib.Data.DFunLike/import Mathlib.Data.FunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\bHom_FunLike\b/Hom_DFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\binstFunLike\b/instDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\bfunLike\b/instDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\btoo many metavariables to apply `fun_like.has_coe_to_fun`/too many metavariables to apply `DFunLike.hasCoeToFun`/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>
@@ -273,7 +273,7 @@ theorem AlgHom.fieldRange_of_normal [Algebra F K] {E : IntermediateField F K} [N
-- Porting note: this was `IsScalarTower F E E := by infer_instance`.
letI : Algebra E E := Algebra.id E
let g := f.restrictNormal' E
- rw [← show E.val.comp ↑g = f from FunLike.ext_iff.mpr (f.restrictNormal_commutes E),
+ rw [← show E.val.comp ↑g = f from DFunLike.ext_iff.mpr (f.restrictNormal_commutes E),
← AlgHom.map_fieldRange, AlgEquiv.fieldRange_eq_top g, ← AlgHom.fieldRange_eq_map,
IntermediateField.fieldRange_val]
#align alg_hom.field_range_of_normal AlgHom.fieldRange_of_normal
@@ -3,7 +3,7 @@ Copyright (c) 2020 Kenny Lau. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
-/
-import Mathlib.FieldTheory.Adjoin
+import Mathlib.FieldTheory.Extension
import Mathlib.FieldTheory.SplittingField.Construction
import Mathlib.GroupTheory.Solvable
@@ -102,7 +102,7 @@ lemma isNormalClosure_normalClosure : IsNormalClosure F K (normalClosure F K L)
rw [IntermediateField.map_iSup]
refine (iSup_le fun f ↦ ?_ : normalClosure F K L ≤ _) x.2
refine le_iSup_of_le (f.codRestrict _ fun x ↦ f.fieldRange_le_normalClosure ⟨x, rfl⟩) ?_
- erw [AlgHom.map_fieldRange, AlgHom.val_comp_codRestrict]
+ rw [AlgHom.map_fieldRange, val, AlgHom.val_comp_codRestrict]
end Algebra.IsAlgebraic
@@ -190,8 +190,7 @@ theorem splits_of_mem_adjoin {L} [Field L] [Algebra F L] {S : Set K}
(splits x hx).2 fun y hy ↦ (le_iSup _ ⟨x, hx⟩ : _ ≤ E) (subset_adjoin F _ <| by exact hy)
obtain ⟨φ⟩ := nonempty_algHom_adjoin_of_splits fun x hx ↦ ⟨(splits x hx).1, this x hx⟩
convert splits_comp_of_splits _ E.val.toRingHom (normal.splits <| φ ⟨x, hx⟩)
- rw [minpoly.algHom_eq _ φ.injective, ← minpoly.algHom_eq _ (adjoin F S).val.injective]
- rfl
+ rw [minpoly.algHom_eq _ φ.injective, ← minpoly.algHom_eq _ (adjoin F S).val.injective, val_mk]
instance normal_sup
(E E' : IntermediateField F K) [Normal F E] [Normal F E'] :
Main changes are to the file NormalClosure:
Introduce predicate IsNormalClosure
to characterize normal closures L/F of a field extension K/F by the conditions that every minimal polynomial of an element of K over F splits in L, and that L is generated by roots of such polynomials. (When K/F is not necessarily algebraic, the conditions actually says L/F is a normal closure of the algebraic closure of F in K over F.
IsNormalClosure.normal
: a normal closure is always normal.
isNormalClosure_iff
: if K/F is algebraic, the "generated by roots" condition in IsNormalClosure can be replaced by "generated by images of embeddings". To prove it, we split out the two inclusions in restrictScalars_eq_iSup_adjoin
and golf its proof. restrictScalars_eq_iSup_adjoin
is renamed to normalClosure_eq_iSup_adjoin
as it has nothing to do with restrictScalars
.
IsNormalClosure.lift
: a normal closure of K/F embeds into any L/F such that the minpolys of K/F splits in L/F.
IsNormalClosure.equiv
: normal closures are unique up to F-algebra isomorphisms.
isNormalClosure_normalClosure
: normalClosure F K L
is a valid normal closure if K/F is algebraic and all minpolys of K/F splits in L/F; in particular, if there is at least one F-embedding of K into L, and L/F is normal.
Algebra.IsAlgebraic.cardinal_mk_algHom_le_of_splits
: if every minpoly of K/F
splits in L/F
, then L
is maximal w.r.t. F
-embeddings of K
, in the sense that K →ₐ[F] L
achieves maximal cardinality.
In the file Normal:
splits_of_mem_adjoin
: If a set of algebraic elements in a field extension K/F
have minimal polynomials that split in another extension L/F
, then all minimal polynomials in the intermediate field generated by the set also split in L/F
. This is in preparation for connecting IsNormalClosure
and IsSplittingField
.In the file IntermediateField:
comap
and show it forms a Galois connection with map
.In the file FieldTheory/Adjoin:
map_sup/iSup
lemmas that follow from the Galois connection, plus an additional convenience lemma.In the file RingTheory/Algebraic: add a lemma AlgHom.isAlgebraic_of_injective
.
Co-authored-by: Jz Pan <acme_pjz@hotmail.com>
Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
@@ -10,19 +10,37 @@ import Mathlib.Order.Closure
#align_import field_theory.normal from "leanprover-community/mathlib"@"9fb8964792b4237dac6200193a0d533f1b3f7423"
/-!
# Normal closures
-The normal closure of a tower of fields `L/K/F` is the smallest intermediate field of `L/K` that
-contains the image of every `F`-algebra embedding `K →ₐ[F] L`.
-## Main Definitions
-- `normalClosure F K L` a tower of fields `L/K/F`.
+## Main definitions
+
+Given field extensions `K/F` and `L/F`, the predicate `IsNormalClosure F K L` says that the
+minimal polynomial of every element of `K` over `F` splits in `L`, and that `L` is generated
+by the roots of such minimal polynomials. These conditions uniquely characterize `L/F` up to
+`F`-algebra isomorphisms (`IsNormalClosure.equiv`).
+
+The explicit construction `normalClosure F K L` of a field extension `K/F` inside another
+field extension `L/F` is the smallest intermediate field of `L/F` that contains the image
+of every `F`-algebra embedding `K →ₐ[F] L`. It satisfies the `IsNormalClosure` predicate
+if `L/F` satisfies the abovementioned splitting condition, in particular if `L/K/F` form
+a tower and `L/F` is normal.
-/
open BigOperators IntermediateField IsScalarTower Polynomial
-variable (F K L : Type*) [Field F] [Field K] [Field L] [Algebra F K] [Algebra F L] [Algebra K L]
- [IsScalarTower F K L]
+variable (F K L : Type*) [Field F] [Field K] [Field L] [Algebra F K] [Algebra F L]
-/-- The normal closure of `K` in `L`. -/
+/-- `L/F` is a normal closure of `K/F` if the minimal polynomial of every element of `K` over `F`
+ splits in `L`, and `L` is generated by roots of such minimal polynomials over `F`.
+ (Since the minimal polynomial of a transcendental element is 0,
+ the normal closure of `K/F` is the same as the normal closure over `F`
+ of the algebraic closure of `F` in `K`.) -/
+class IsNormalClosure : Prop where
+ splits (x : K) : (minpoly F x).Splits (algebraMap F L)
+ adjoin_rootSet : ⨆ x : K, adjoin F ((minpoly F x).rootSet L) = ⊤
+/- TODO: show `IsNormalClosure F K L ↔ IsNormalClosure F (integralClosure F K) L`; we can't state
+ this yet because `integralClosure F K` needs to have a `Field` instance. -/
+
+/-- The normal closure of `K/F` in `L/F`. -/
noncomputable def normalClosure : IntermediateField F L :=
⨆ f : K →ₐ[F] L, f.fieldRange
@@ -31,62 +49,135 @@ lemma normalClosure_def : normalClosure F K L = ⨆ f : K →ₐ[F] L, f.fieldRa
variable {F K L}
+/-- A normal closure is always normal. -/
+lemma IsNormalClosure.normal [h : IsNormalClosure F K L] : Normal F L :=
+ Normal.of_algEquiv topEquiv (h := h.adjoin_rootSet ▸ IntermediateField.normal_iSup (h :=
+ fun _ ↦ Normal.of_isSplittingField (hFEp := adjoin_rootSet_isSplittingField <| h.splits _)))
+
lemma normalClosure_le_iff {K' : IntermediateField F L} :
normalClosure F K L ≤ K' ↔ ∀ f : K →ₐ[F] L, f.fieldRange ≤ K' :=
iSup_le_iff
-lemma AlgHom.fieldRange_le_normalClosure (f : K →ₐ[F] L) : f.fieldRange ≤ normalClosure F K L :=
+lemma AlgHom.fieldRange_le_normalClosure (f : K →ₐ[F] L) : f.fieldRange ≤ normalClosure F K L :=
le_iSup AlgHom.fieldRange f
+namespace Algebra.IsAlgebraic
+variable (alg : Algebra.IsAlgebraic F K)
+
+lemma normalClosure_le_iSup_adjoin :
+ normalClosure F K L ≤ ⨆ x : K, IntermediateField.adjoin F ((minpoly F x).rootSet L) :=
+ iSup_le fun f _ ⟨x, hx⟩ ↦ le_iSup (α := IntermediateField F L) _ x <|
+ IntermediateField.subset_adjoin F _ <| by
+ rw [mem_rootSet_of_ne (minpoly.ne_zero <| isAlgebraic_iff_isIntegral.mp <| alg x), ← hx,
+ AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom, aeval_algHom_apply, minpoly.aeval, map_zero]
+
+variable (splits : ∀ x : K, (minpoly F x).Splits (algebraMap F L))
+
+lemma normalClosure_eq_iSup_adjoin_of_splits :
+ normalClosure F K L = ⨆ x : K, IntermediateField.adjoin F ((minpoly F x).rootSet L) :=
+ (alg.normalClosure_le_iSup_adjoin).antisymm <|
+ iSup_le fun x ↦ IntermediateField.adjoin_le_iff.mpr fun _ hy ↦
+ let ⟨φ, hφ⟩ := IntermediateField.exists_algHom_of_splits_of_aeval
+ (fun x ↦ ⟨isAlgebraic_iff_isIntegral.mp (alg x), splits x⟩) (mem_rootSet.mp hy).2
+ le_iSup AlgHom.fieldRange φ ⟨x, hφ⟩
+
+/-- If `K/F` is algebraic, the "generated by roots" condition in IsNormalClosure can be replaced
+ by "generated by images of embeddings".-/
+lemma isNormalClosure_iff : IsNormalClosure F K L ↔
+ (∀ x : K, (minpoly F x).Splits (algebraMap F L)) ∧ normalClosure F K L = ⊤ := by
+ refine ⟨fun ⟨splits, h⟩ ↦ ⟨splits, ?_⟩, fun ⟨splits, h⟩ ↦ ⟨splits, ?_⟩⟩ <;>
+ simpa only [alg.normalClosure_eq_iSup_adjoin_of_splits splits] using h
+-- TODO: IntermediateField.isNormalClosure_iff similar to IntermediateField.isSplittingField_iff
+
+/-- `normalClosure F K L` is a valid normal closure if `K/F` is algebraic
+ and all minimal polynomials of `K/F` splits in `L/F`. -/
+lemma isNormalClosure_normalClosure : IsNormalClosure F K (normalClosure F K L) := by
+ rw [alg.isNormalClosure_iff]; constructor
+ · rw [alg.normalClosure_eq_iSup_adjoin_of_splits splits]
+ exact fun x ↦ splits_of_splits (splits x) ((IntermediateField.subset_adjoin F _).trans <|
+ SetLike.coe_subset_coe.mpr <| by apply le_iSup _ x)
+ simp_rw [normalClosure, ← top_le_iff]
+ refine fun x _ ↦ (IntermediateField.val _).injective.mem_set_image.mp ?_
+ change x.val ∈ IntermediateField.map (IntermediateField.val _) _
+ rw [IntermediateField.map_iSup]
+ refine (iSup_le fun f ↦ ?_ : normalClosure F K L ≤ _) x.2
+ refine le_iSup_of_le (f.codRestrict _ fun x ↦ f.fieldRange_le_normalClosure ⟨x, rfl⟩) ?_
+ erw [AlgHom.map_fieldRange, AlgHom.val_comp_codRestrict]
+
+end Algebra.IsAlgebraic
+
+/-- A normal closure of `K/F` embeds into any `L/F`
+ where the minimal polynomials of `K/F` splits. -/
+noncomputable def IsNormalClosure.lift [h : IsNormalClosure F K L] {L'} [Field L'] [Algebra F L']
+ (splits : ∀ x : K, (minpoly F x).Splits (algebraMap F L')) : L →ₐ[F] L' := by
+ have := h.adjoin_rootSet; rw [← gc.l_iSup] at this
+ refine Nonempty.some <| nonempty_algHom_of_adjoin_splits
+ (fun x hx ↦ ⟨isAlgebraic_iff_isIntegral.mp (Normal.isAlgebraic h.normal x), ?_⟩) this
+ obtain ⟨y, hx⟩ := Set.mem_iUnion.mp hx
+ by_cases iy : IsIntegral F y
+ · exact splits_of_splits_of_dvd _ (minpoly.ne_zero iy)
+ (splits y) (minpoly.dvd F x (mem_rootSet.mp hx).2)
+ · simp [minpoly.eq_zero iy] at hx
+
+/-- Normal closures of `K/F` are unique up to F-algebra isomorphisms. -/
+noncomputable def IsNormalClosure.equiv {L'} [Field L'] [Algebra F L']
+ [h : IsNormalClosure F K L] [h' : IsNormalClosure F K L'] : L ≃ₐ[F] L' :=
+ have := h.normal
+ AlgEquiv.ofBijective _ <| And.left <|
+ Normal.isAlgebraic'.algHom_bijective₂
+ (IsNormalClosure.lift fun _ : K ↦ h'.splits _)
+ (IsNormalClosure.lift fun _ : K ↦ h.splits _)
+
variable (F K L)
-namespace normalClosure
+instance isNormalClosure_normalClosure [ne : Nonempty (K →ₐ[F] L)] [h : Normal F L] :
+ IsNormalClosure F K (normalClosure F K L) := by
+ have ⟨φ⟩ := ne
+ apply (h.isAlgebraic'.of_injective φ φ.injective).isNormalClosure_normalClosure
+ simp_rw [← minpoly.algHom_eq _ φ.injective]
+ exact fun _ ↦ h.splits _
-theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
+theorem normalClosure_eq_iSup_adjoin' [ne : Nonempty (K →ₐ[F] L)] [h : Normal F L] :
normalClosure F K L = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) := by
- classical
- have hi : ∀ x : K, IsIntegral F x :=
- fun x ↦ (isIntegral_algebraMap_iff (algebraMap K L).injective).mp (h.isIntegral _)
- refine' le_antisymm (iSup_le _) (iSup_le fun x => adjoin_le_iff.mpr fun y hy => _)
- · rintro f _ ⟨x, rfl⟩
- refine' le_iSup (fun x => adjoin F ((minpoly F x).rootSet L)) x
- (subset_adjoin F ((minpoly F x).rootSet L) _)
- rw [mem_rootSet_of_ne (minpoly.ne_zero (hi x)), AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom,
- Polynomial.aeval_algHom_apply, minpoly.aeval, map_zero]
- · rw [Polynomial.rootSet, Finset.mem_coe, Multiset.mem_toFinset] at hy
- let g := (algHomAdjoinIntegralEquiv F (hi x)).symm ⟨y, hy⟩
- refine' le_iSup (fun f : K →ₐ[F] L => f.fieldRange) ((g.liftNormal L).comp (toAlgHom F K L))
- ⟨x, (g.liftNormal_commutes L (AdjoinSimple.gen F x)).trans _⟩
- rw [Algebra.id.map_eq_id, RingHom.id_apply]
- -- Porting note: in mathlib3 this next `apply` closed the goal.
- -- Now it can't find a proof by unification, so we have to do it ourselves.
- apply PowerBasis.lift_gen
- change aeval y (minpoly F (AdjoinSimple.gen F x)) = 0
- exact minpoly_gen F x ▸ aeval_eq_zero_of_mem_rootSet (Multiset.mem_toFinset.mpr hy)
-
-#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure.restrictScalars_eq_iSup_adjoin
+ have ⟨φ⟩ := ne
+ refine h.isAlgebraic'.of_injective φ φ.injective
+ |>.normalClosure_eq_iSup_adjoin_of_splits fun x ↦ ?_
+ rw [← minpoly.algHom_eq _ φ.injective]
+ apply h.splits
+
+theorem normalClosure_eq_iSup_adjoin [Algebra K L] [IsScalarTower F K L] [Normal F L] :
+ normalClosure F K L = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) :=
+ normalClosure_eq_iSup_adjoin' (ne := ⟨IsScalarTower.toAlgHom F K L⟩)
+#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure_eq_iSup_adjoin
+
+namespace normalClosure
+
+/-- All `F`-`AlgHom`s from `K` to `L` factor through the normal closure of `K/F` in `L/F`. -/
+noncomputable def algHomEquiv : (K →ₐ[F] normalClosure F K L) ≃ (K →ₐ[F] L) where
+ toFun := (normalClosure F K L).val.comp
+ invFun f := f.codRestrict _ fun x ↦ f.fieldRange_le_normalClosure ⟨x, rfl⟩
+ left_inv _ := rfl
+ right_inv _ := rfl
instance normal [h : Normal F L] : Normal F (normalClosure F K L) := by
- let ϕ := algebraMap K L
- rw [← IntermediateField.restrictScalars_normal, restrictScalars_eq_iSup_adjoin]
- -- Porting note: use the `(_)` trick to obtain an instance by unification.
- apply IntermediateField.normal_iSup (h := _)
- intro x
- -- Porting note: use the `(_)` trick to obtain an instance by unification.
- apply Normal.of_isSplittingField (p := minpoly F x) (hFEp := _)
- exact adjoin_rootSet_isSplittingField (minpoly.algebraMap_eq ϕ.injective (A := F) x ▸ h.splits _)
+ obtain _ | φ := isEmpty_or_nonempty (K →ₐ[F] L)
+ · rw [normalClosure, iSup_of_empty]; exact Normal.of_algEquiv (botEquiv F L).symm
+ · exact (isNormalClosure_normalClosure F K L).normal
#align normal_closure.normal normalClosure.normal
instance is_finiteDimensional [FiniteDimensional F K] :
FiniteDimensional F (normalClosure F K L) := by
- haveI : ∀ f : K →ₐ[F] L, FiniteDimensional F f.fieldRange := fun f =>
+ haveI : ∀ f : K →ₐ[F] L, FiniteDimensional F f.fieldRange := fun f ↦
f.toLinearMap.finiteDimensional_range
apply IntermediateField.finiteDimensional_iSup_of_finite
-noncomputable instance algebra : Algebra K (normalClosure F K L) :=
+variable [Algebra K L] [IsScalarTower F K L]
+
+noncomputable instance algebra :
+ Algebra K (normalClosure F K L) :=
IntermediateField.algebra
{ ⨆ f : K →ₐ[F] L, f.fieldRange with
- algebraMap_mem' := fun r => (toAlgHom F K L).fieldRange_le_normalClosure ⟨r, rfl⟩ }
+ algebraMap_mem' := fun r ↦ (toAlgHom F K L).fieldRange_le_normalClosure ⟨r, rfl⟩ }
instance : IsScalarTower F K (normalClosure F K L) := by
apply of_algebraMap_eq'
@@ -102,13 +193,38 @@ lemma restrictScalars_eq :
end normalClosure
+variable {F K L}
+
+open Cardinal in
+/-- An extension `L/F` in which every minimal polynomial of `K/F` splits is maximal with respect
+ to `F`-embeddings of `K`, in the sense that `K →ₐ[F] L` achieves maximal cardinality.
+ We construct an explicit injective function from an arbitrary `K →ₐ[F] L'` into `K →ₐ[F] L`,
+ using an embedding of `normalClosure F K L'` into `L`. -/
+noncomputable def Algebra.IsAlgebraic.algHomEmbeddingOfSplits (alg : IsAlgebraic F K)
+ (h : ∀ x : K, (minpoly F x).Splits (algebraMap F L)) (L' : Type*) [Field L'] [Algebra F L'] :
+ (K →ₐ[F] L') ↪ (K →ₐ[F] L) :=
+ let φ : ↑(⨆ x : K, IntermediateField.adjoin F ((minpoly F x).rootSet L')) →ₐ[F] L :=
+ Nonempty.some <| by
+ rw [← gc.l_iSup]
+ refine nonempty_algHom_adjoin_of_splits fun x hx ↦ ?_
+ obtain ⟨y, hx⟩ := Set.mem_iUnion.mp hx
+ refine ⟨isAlgebraic_iff_isIntegral.mp (isAlgebraic_of_mem_rootSet hx), ?_⟩
+ by_cases iy : IsIntegral F y
+ · exact splits_of_splits_of_dvd _ (minpoly.ne_zero iy)
+ (h y) (minpoly.dvd F x (mem_rootSet.mp hx).2)
+ · simp [minpoly.eq_zero iy] at hx
+ { toFun := (φ.comp <| inclusion <| normalClosure_le_iSup_adjoin alg).comp ∘
+ (normalClosure.algHomEquiv F K L').symm
+ inj' := fun _ _ h ↦ (normalClosure.algHomEquiv F K L').symm.injective <| by
+ rw [FunLike.ext'_iff] at h ⊢
+ exact (φ.comp _).injective.comp_left h }
+
namespace IntermediateField
-variable {F L}
variable (K K' : IntermediateField F L)
lemma le_normalClosure : K ≤ normalClosure F K L :=
-K.fieldRange_val.symm.trans_le K.val.fieldRange_le_normalClosure
+ K.fieldRange_val.symm.trans_le K.val.fieldRange_le_normalClosure
lemma normalClosure_of_normal [Normal F K] : normalClosure F K L = K :=
by simp only [normalClosure_def, AlgHom.fieldRange_of_normal, iSup_const]
Main changes are to the file NormalClosure:
Introduce predicate IsNormalClosure
to characterize normal closures L/F of a field extension K/F by the conditions that every minimal polynomial of an element of K over F splits in L, and that L is generated by roots of such polynomials. (When K/F is not necessarily algebraic, the conditions actually says L/F is a normal closure of the algebraic closure of F in K over F.
IsNormalClosure.normal
: a normal closure is always normal.
isNormalClosure_iff
: if K/F is algebraic, the "generated by roots" condition in IsNormalClosure can be replaced by "generated by images of embeddings". To prove it, we split out the two inclusions in restrictScalars_eq_iSup_adjoin
and golf its proof. restrictScalars_eq_iSup_adjoin
is renamed to normalClosure_eq_iSup_adjoin
as it has nothing to do with restrictScalars
.
IsNormalClosure.lift
: a normal closure of K/F embeds into any L/F such that the minpolys of K/F splits in L/F.
IsNormalClosure.equiv
: normal closures are unique up to F-algebra isomorphisms.
isNormalClosure_normalClosure
: normalClosure F K L
is a valid normal closure if K/F is algebraic and all minpolys of K/F splits in L/F; in particular, if there is at least one F-embedding of K into L, and L/F is normal.
Algebra.IsAlgebraic.cardinal_mk_algHom_le_of_splits
: if every minpoly of K/F
splits in L/F
, then L
is maximal w.r.t. F
-embeddings of K
, in the sense that K →ₐ[F] L
achieves maximal cardinality.
In the file Normal:
splits_of_mem_adjoin
: If a set of algebraic elements in a field extension K/F
have minimal polynomials that split in another extension L/F
, then all minimal polynomials in the intermediate field generated by the set also split in L/F
. This is in preparation for connecting IsNormalClosure
and IsSplittingField
.In the file IntermediateField:
comap
and show it forms a Galois connection with map
.In the file FieldTheory/Adjoin:
map_sup/iSup
lemmas that follow from the Galois connection, plus an additional convenience lemma.In the file RingTheory/Algebraic: add a lemma AlgHom.isAlgebraic_of_injective
.
Co-authored-by: Jz Pan <acme_pjz@hotmail.com>
Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
@@ -177,6 +177,22 @@ instance normal_iSup {ι : Type*} (t : ι → IntermediateField F K) [h : ∀ i,
exact Polynomial.splits_comp_of_splits _ (inclusion hE).toRingHom this
#align intermediate_field.normal_supr IntermediateField.normal_iSup
+/-- If a set of algebraic elements in a field extension `K/F` have minimal polynomials that
+ split in another extension `L/F`, then all minimal polynomials in the intermediate field
+ generated by the set also split in `L/F`. -/
+theorem splits_of_mem_adjoin {L} [Field L] [Algebra F L] {S : Set K}
+ (splits : ∀ x ∈ S, IsIntegral F x ∧ (minpoly F x).Splits (algebraMap F L)) {x : K}
+ (hx : x ∈ adjoin F S) : (minpoly F x).Splits (algebraMap F L) := by
+ let E : IntermediateField F L := ⨆ x : S, adjoin F ((minpoly F x.val).rootSet L)
+ have normal : Normal F E := normal_iSup (h := fun x ↦
+ Normal.of_isSplittingField (hFEp := adjoin_rootSet_isSplittingField (splits x x.2).2))
+ have : ∀ x ∈ S, (minpoly F x).Splits (algebraMap F E) := fun x hx ↦ splits_of_splits
+ (splits x hx).2 fun y hy ↦ (le_iSup _ ⟨x, hx⟩ : _ ≤ E) (subset_adjoin F _ <| by exact hy)
+ obtain ⟨φ⟩ := nonempty_algHom_adjoin_of_splits fun x hx ↦ ⟨(splits x hx).1, this x hx⟩
+ convert splits_comp_of_splits _ E.val.toRingHom (normal.splits <| φ ⟨x, hx⟩)
+ rw [minpoly.algHom_eq _ φ.injective, ← minpoly.algHom_eq _ (adjoin F S).val.injective]
+ rfl
+
instance normal_sup
(E E' : IntermediateField F K) [Normal F E] [Normal F E'] :
Normal F (E ⊔ E' : IntermediateField F K) :=
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>
@@ -46,7 +46,7 @@ theorem Normal.isAlgebraic (_ : Normal F K) (x : K) : IsAlgebraic F x :=
#align normal.is_algebraic Normal.isAlgebraic
theorem Normal.isIntegral (h : Normal F K) (x : K) : IsIntegral F x :=
- isAlgebraic_iff_isIntegral.mp (h.isAlgebraic' x)
+ (h.isAlgebraic' x).isIntegral
#align normal.is_integral Normal.isIntegral
theorem Normal.splits (_ : Normal F K) (x : K) : Splits (algebraMap F K) (minpoly F x) :=
@@ -55,7 +55,7 @@ theorem Normal.splits (_ : Normal F K) (x : K) : Splits (algebraMap F K) (minpol
theorem normal_iff : Normal F K ↔ ∀ x : K, IsIntegral F x ∧ Splits (algebraMap F K) (minpoly F x) :=
⟨fun h x => ⟨h.isIntegral x, h.splits x⟩, fun h =>
- ⟨fun x => (h x).1.isAlgebraic F, fun x => (h x).2⟩⟩
+ ⟨fun x => (h x).1.isAlgebraic, fun x => (h x).2⟩⟩
#align normal_iff normal_iff
theorem Normal.out : Normal F K → ∀ x : K, IsIntegral F x ∧ Splits (algebraMap F K) (minpoly F x) :=
@@ -65,7 +65,7 @@ theorem Normal.out : Normal F K → ∀ x : K, IsIntegral F x ∧ Splits (algebr
variable (F K)
instance normal_self : Normal F F :=
- ⟨fun _ => isIntegral_algebraMap.isAlgebraic F, fun x =>
+ ⟨fun _ => isIntegral_algebraMap.isAlgebraic, fun x =>
(minpoly.eq_X_sub_C' x).symm ▸ splits_X_sub_C _⟩
#align normal_self normal_self
@@ -96,7 +96,7 @@ theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E :=
cases' h.out x with hx hhx
rw [algebraMap_eq F K E] at hhx
exact
- ⟨isIntegral_of_isScalarTower hx,
+ ⟨hx.tower_top,
Polynomial.splits_of_splits_of_dvd (algebraMap K E)
(Polynomial.map_ne_zero (minpoly.ne_zero hx))
((Polynomial.splits_map_iff (algebraMap F K) (algebraMap K E)).mpr hhx)
@@ -114,7 +114,7 @@ theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :
rw [normal_iff] at h ⊢
intro x; specialize h (f.symm x)
rw [← f.apply_symm_apply x, minpoly.algEquiv_eq, ← f.toAlgHom.comp_algebraMap]
- exact ⟨IsIntegral.map f h.1, splits_comp_of_splits _ _ h.2⟩
+ exact ⟨h.1.map f, splits_comp_of_splits _ _ h.2⟩
#align normal.of_alg_equiv Normal.of_algEquiv
theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F E' :=
@@ -217,8 +217,8 @@ def AlgHom.restrictNormalAux [h : Normal F E] :
Or.resolve_left (h.splits z).def (minpoly.ne_zero (h.isIntegral z)) (minpoly.irreducible _)
(minpoly.dvd E _ (by simp [aeval_algHom_apply]))
simp only [AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom]
- suffices IsIntegral F _ by exact isIntegral_of_isScalarTower this
- exact IsIntegral.map ϕ (IsIntegral.map (toAlgHom F E K₁) (h.isIntegral z))⟩
+ suffices IsIntegral F _ by exact this.tower_top
+ exact ((h.isIntegral z).map <| toAlgHom F E K₁).map ϕ⟩
map_zero' := Subtype.ext ϕ.map_zero
map_one' := Subtype.ext ϕ.map_one
map_add' x y := Subtype.ext (ϕ.map_add x y)
@@ -320,7 +320,7 @@ noncomputable def AlgHom.liftNormal [h : Normal F E] : E →ₐ[F] E :=
Nonempty.some <|
@IntermediateField.nonempty_algHom_of_adjoin_splits _ _ _ _ _ _ _
((IsScalarTower.toAlgHom F K₂ E).comp ϕ).toRingHom.toAlgebra _
- (fun x _ => ⟨isIntegral_of_isScalarTower (h.out x).1,
+ (fun x _ ↦ ⟨(h.out x).1.tower_top,
splits_of_splits_of_dvd _ (map_ne_zero (minpoly.ne_zero (h.out x).1))
-- Porting note: had to override typeclass inference below using `(_)`
(by rw [splits_map_iff, ← @IsScalarTower.algebraMap_eq _ _ _ _ _ _ (_) (_) (_)];
This PR tests a string-based tool for renaming declarations.
Inspired by this Zulip thread, I am trying to reduce the diff of #8406.
This PR makes the following renames:
| From | To |
@@ -114,7 +114,7 @@ theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :
rw [normal_iff] at h ⊢
intro x; specialize h (f.symm x)
rw [← f.apply_symm_apply x, minpoly.algEquiv_eq, ← f.toAlgHom.comp_algebraMap]
- exact ⟨map_isIntegral f h.1, splits_comp_of_splits _ _ h.2⟩
+ exact ⟨IsIntegral.map f h.1, splits_comp_of_splits _ _ h.2⟩
#align normal.of_alg_equiv Normal.of_algEquiv
theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F E' :=
@@ -131,7 +131,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
(AlgEquiv.ofBijective (Algebra.ofId F E) (Algebra.bijective_algebraMap_iff.2 this.symm))
refine normal_iff.mpr fun x ↦ ?_
haveI : FiniteDimensional F E := IsSplittingField.finiteDimensional E p
- have hx := isIntegral_of_finite F x
+ have hx := IsIntegral.of_finite F x
let L := (p * minpoly F x).SplittingField
have hL := splits_of_splits_mul' _ ?_ (SplittingField.splits (p * minpoly F x))
· let j : E →ₐ[F] L := IsSplittingField.lift E p hL.1
@@ -218,7 +218,7 @@ def AlgHom.restrictNormalAux [h : Normal F E] :
(minpoly.dvd E _ (by simp [aeval_algHom_apply]))
simp only [AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom]
suffices IsIntegral F _ by exact isIntegral_of_isScalarTower this
- exact map_isIntegral ϕ (map_isIntegral (toAlgHom F E K₁) (h.isIntegral z))⟩
+ exact IsIntegral.map ϕ (IsIntegral.map (toAlgHom F E K₁) (h.isIntegral z))⟩
map_zero' := Subtype.ext ϕ.map_zero
map_one' := Subtype.ext ϕ.map_one
map_add' x y := Subtype.ext (ϕ.map_add x y)
Inspired by the IsAlgClosed.lift.SubfieldWithHom counterpart:
Change Lifts
from a Sigma type to a structure with fields carrier
and emb
.
Change the definition of the partial order on Lifts
to use IntermediateField.inclusion
.
Use Subalgebra.iSupLift in the proof of Lifts.exists_upper_bound
.
Also:
Inline multiple auxiliary definitions for Lifts.exists_upper_bound
and Lifts.exists_lift_of_splits
into the proofs proper.
Move the Supremum
section much further up, in order to use the new lemma toSubalgebra_iSup_of_directed
to prove stuff about Lifts
(and golf a proof about CompactElement
). isAlgebraic_iSup
however can't be moved up, so I put it near adjoin.finiteDimensional
, the last lemma it depends on.
Co-authored-by: acmepjz <acme_pjz@hotmail.com>
@@ -318,15 +318,15 @@ noncomputable def AlgHom.liftNormal [h : Normal F E] : E →ₐ[F] E :=
@AlgHom.restrictScalars F K₁ E E _ _ _ _ _ _
((IsScalarTower.toAlgHom F K₂ E).comp ϕ).toRingHom.toAlgebra _ _ _ _ <|
Nonempty.some <|
- @IntermediateField.algHom_mk_adjoin_splits' _ _ _ _ _ _ _
+ @IntermediateField.nonempty_algHom_of_adjoin_splits _ _ _ _ _ _ _
((IsScalarTower.toAlgHom F K₂ E).comp ϕ).toRingHom.toAlgebra _
- (IntermediateField.adjoin_univ _ _) fun x _ =>
- ⟨isIntegral_of_isScalarTower (h.out x).1,
+ (fun x _ => ⟨isIntegral_of_isScalarTower (h.out x).1,
splits_of_splits_of_dvd _ (map_ne_zero (minpoly.ne_zero (h.out x).1))
-- Porting note: had to override typeclass inference below using `(_)`
(by rw [splits_map_iff, ← @IsScalarTower.algebraMap_eq _ _ _ _ _ _ (_) (_) (_)];
exact (h.out x).2)
- (minpoly.dvd_map_of_isScalarTower F K₁ x)⟩
+ (minpoly.dvd_map_of_isScalarTower F K₁ x)⟩)
+ (IntermediateField.adjoin_univ _ _)
#align alg_hom.lift_normal AlgHom.liftNormal
@[simp]
@@ -370,21 +370,12 @@ theorem AlgEquiv.restrictNormalHom_surjective [Normal F K₁] [Normal F E] :
⟨χ.liftNormal E, χ.restrict_liftNormal E⟩
#align alg_equiv.restrict_normal_hom_surjective AlgEquiv.restrictNormalHom_surjective
-open AdjoinRoot in
+open IntermediateField in
theorem Normal.minpoly_eq_iff_mem_orbit [h : Normal F E] {x y : E} :
minpoly F x = minpoly F y ↔ x ∈ MulAction.orbit (E ≃ₐ[F] E) y := by
refine ⟨fun he ↦ ?_, fun ⟨f, he⟩ ↦ he ▸ minpoly.algEquiv_eq f y⟩
- let Fx := AdjoinRoot (minpoly F x)
- have hx : aeval x (minpoly F x) = 0 := minpoly.aeval F x
- have hy : aeval y (minpoly F x) = 0 := he ▸ minpoly.aeval F y
- let Ax : Algebra Fx E := (lift (algebraMap F E) x hx).toAlgebra
- have Tx : IsScalarTower F Fx E := IsScalarTower.of_ring_hom (liftHom _ x hx)
- let Ay : Algebra Fx E := (lift (algebraMap F E) y hy).toAlgebra
- have Ty : IsScalarTower F Fx E := IsScalarTower.of_ring_hom (liftHom _ y hy)
- haveI : Fact (Irreducible <| minpoly F x) := ⟨minpoly.irreducible <| h.isIntegral x⟩
- let f : E ≃ₐ[F] E := @AlgEquiv.liftNormal F Fx Fx _ _ _ _ _ AlgEquiv.refl E _ _ Ay Ax Ty Tx _
- refine ⟨f, (congr_arg f (lift_root hy).symm).trans <| Eq.trans ?_ (lift_root hx)⟩
- exact @AlgEquiv.liftNormal_commutes F Fx Fx _ _ _ _ _ _ E _ _ Ay Ax Ty Tx _ (root _)
+ obtain ⟨φ, hφ⟩ := exists_algHom_of_splits_of_aeval (normal_iff.mp h) (he ▸ minpoly.aeval F x)
+ exact ⟨AlgEquiv.ofBijective φ (φ.normal_bijective F E E), hφ⟩
variable (F K₁)
Also golfs Normal.of_algEquiv
and Algebra.IsIntegral.of_finite
and refactors Algebra.IsAlgebraic.bijective_of_isScalarTower
.
@@ -110,24 +110,15 @@ theorem AlgHom.normal_bijective [h : Normal F E] (ϕ : E →ₐ[F] K) : Function
-- Porting note: `[Field F] [Field E] [Algebra F E]` added by hand.
variable {F E} {E' : Type*} [Field F] [Field E] [Algebra F E] [Field E'] [Algebra F E']
-theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :=
- normal_iff.2 fun x => by
- cases' h.out (f.symm x) with hx hhx
- have H := map_isIntegral f.toAlgHom hx
- simp [AlgEquiv.toAlgHom_eq_coe] at H
- use H
- apply Polynomial.splits_of_splits_of_dvd (algebraMap F E') (minpoly.ne_zero hx)
- · rw [← AlgHom.comp_algebraMap f.toAlgHom]
- exact Polynomial.splits_comp_of_splits (algebraMap F E) f.toAlgHom.toRingHom hhx
- · apply minpoly.dvd _ _
- rw [← AddEquiv.map_eq_zero_iff f.symm.toAddEquiv]
- exact
- Eq.trans (Polynomial.aeval_algHom_apply f.symm.toAlgHom x (minpoly F (f.symm x))).symm
- (minpoly.aeval _ _)
+theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' := by
+ rw [normal_iff] at h ⊢
+ intro x; specialize h (f.symm x)
+ rw [← f.apply_symm_apply x, minpoly.algEquiv_eq, ← f.toAlgHom.comp_algebraMap]
+ exact ⟨map_isIntegral f h.1, splits_comp_of_splits _ _ h.2⟩
#align normal.of_alg_equiv Normal.of_algEquiv
theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F E' :=
- ⟨fun _ => Normal.of_algEquiv f, fun _ => Normal.of_algEquiv f.symm⟩
+ ⟨fun _ ↦ Normal.of_algEquiv f, fun _ ↦ Normal.of_algEquiv f.symm⟩
#align alg_equiv.transfer_normal AlgEquiv.transfer_normal
open IntermediateField
Add Normal.minpoly_eq_iff_mem_orbit: addresses https://github.com/leanprover-community/mathlib4/pull/6718/files#r1328899532
Also generalize AlgHom.normal_bijective to Algebra.IsAlgebraic.bijective_of_isScalarTower'
and golf the proof using a set-theoretic lemma Surjective.of_comp_left
(slow to build, awaiting CI).
Co-authored-by: Junyan Xu <junyanxu.math@gmail.com>
@@ -104,26 +104,11 @@ theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E :=
#align normal.tower_top_of_normal Normal.tower_top_of_normal
theorem AlgHom.normal_bijective [h : Normal F E] (ϕ : E →ₐ[F] K) : Function.Bijective ϕ :=
- ⟨ϕ.toRingHom.injective, fun x => by
- letI : Algebra E K := ϕ.toRingHom.toAlgebra
- obtain ⟨h1, h2⟩ := h.out (algebraMap K E x)
- cases'
- minpoly.mem_range_of_degree_eq_one E x
- (h2.def.resolve_left (minpoly.ne_zero h1)
- (minpoly.irreducible
- (isIntegral_of_isScalarTower
- ((isIntegral_algebraMap_iff (algebraMap K E).injective).mp h1)))
- (minpoly.dvd E x
- ((algebraMap K E).injective
- (by
- rw [RingHom.map_zero, aeval_map_algebraMap, ← aeval_algebraMap_apply]
- exact minpoly.aeval F (algebraMap K E x))))) with
- y hy
- exact ⟨y, hy⟩⟩
+ h.isAlgebraic'.bijective_of_isScalarTower' ϕ
#align alg_hom.normal_bijective AlgHom.normal_bijective
-- Porting note: `[Field F] [Field E] [Algebra F E]` added by hand.
-variable {F} {E} {E' : Type*} [Field F] [Field E] [Algebra F E] [Field E'] [Algebra F E']
+variable {F E} {E' : Type*} [Field F] [Field E] [Algebra F E] [Field E'] [Algebra F E']
theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :=
normal_iff.2 fun x => by
@@ -394,7 +379,23 @@ theorem AlgEquiv.restrictNormalHom_surjective [Normal F K₁] [Normal F E] :
⟨χ.liftNormal E, χ.restrict_liftNormal E⟩
#align alg_equiv.restrict_normal_hom_surjective AlgEquiv.restrictNormalHom_surjective
-variable (F) (K₁)
+open AdjoinRoot in
+theorem Normal.minpoly_eq_iff_mem_orbit [h : Normal F E] {x y : E} :
+ minpoly F x = minpoly F y ↔ x ∈ MulAction.orbit (E ≃ₐ[F] E) y := by
+ refine ⟨fun he ↦ ?_, fun ⟨f, he⟩ ↦ he ▸ minpoly.algEquiv_eq f y⟩
+ let Fx := AdjoinRoot (minpoly F x)
+ have hx : aeval x (minpoly F x) = 0 := minpoly.aeval F x
+ have hy : aeval y (minpoly F x) = 0 := he ▸ minpoly.aeval F y
+ let Ax : Algebra Fx E := (lift (algebraMap F E) x hx).toAlgebra
+ have Tx : IsScalarTower F Fx E := IsScalarTower.of_ring_hom (liftHom _ x hx)
+ let Ay : Algebra Fx E := (lift (algebraMap F E) y hy).toAlgebra
+ have Ty : IsScalarTower F Fx E := IsScalarTower.of_ring_hom (liftHom _ y hy)
+ haveI : Fact (Irreducible <| minpoly F x) := ⟨minpoly.irreducible <| h.isIntegral x⟩
+ let f : E ≃ₐ[F] E := @AlgEquiv.liftNormal F Fx Fx _ _ _ _ _ AlgEquiv.refl E _ _ Ay Ax Ty Tx _
+ refine ⟨f, (congr_arg f (lift_root hy).symm).trans <| Eq.trans ?_ (lift_root hx)⟩
+ exact @AlgEquiv.liftNormal_commutes F Fx Fx _ _ _ _ _ _ E _ _ Ay Ax Ty Tx _ (root _)
+
+variable (F K₁)
theorem isSolvable_of_isScalarTower [Normal F K₁] [h1 : IsSolvable (K₁ ≃ₐ[F] K₁)]
[h2 : IsSolvable (E ≃ₐ[K₁] E)] : IsSolvable (E ≃ₐ[F] E) := by
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>
@@ -4,9 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
-/
import Mathlib.FieldTheory.Adjoin
-import Mathlib.FieldTheory.Tower
+import Mathlib.FieldTheory.SplittingField.Construction
import Mathlib.GroupTheory.Solvable
-import Mathlib.RingTheory.PowerBasis
#align_import field_theory.normal from "leanprover-community/mathlib"@"9fb8964792b4237dac6200193a0d533f1b3f7423"
@@ -70,10 +69,6 @@ instance normal_self : Normal F F :=
(minpoly.eq_X_sub_C' x).symm ▸ splits_X_sub_C _⟩
#align normal_self normal_self
-variable {K}
-
-variable (K)
-
theorem Normal.exists_isSplittingField [h : Normal F K] [FiniteDimensional F K] :
∃ p : F[X], IsSplittingField F K p := by
let s := Basis.ofVectorSpace F K
@@ -150,93 +145,37 @@ theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F
⟨fun _ => Normal.of_algEquiv f, fun _ => Normal.of_algEquiv f.symm⟩
#align alg_equiv.transfer_normal AlgEquiv.transfer_normal
--- seems to be causing a diamond in the below proof
--- however, this may be a fluke and the proof below uses non-canonical `Algebra` instances:
--- when I replaced all the instances inside the proof with the "canonical" instances we have,
--- I had the (unprovable) goal (of the form) `AdjoinRoot.mk f (C x) = AdjoinRoot.mk f X`
--- for some `x, f`. So maybe this is indeed the correct approach and rewriting this proof is
--- salient in the future, or at least taking a closer look at the algebra instances it uses.
-attribute [-instance] AdjoinRoot.instSMulAdjoinRoot
+open IntermediateField
theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] : Normal F E := by
rcases eq_or_ne p 0 with (rfl | hp)
· have := hFEp.adjoin_rootSet
- simp only [rootSet_zero, Algebra.adjoin_empty] at this
- exact
- Normal.of_algEquiv
- (AlgEquiv.ofBijective (Algebra.ofId F E) (Algebra.bijective_algebraMap_iff.2 this.symm))
- refine' normal_iff.2 fun x => _
- have hFE : FiniteDimensional F E := IsSplittingField.finiteDimensional E p
- have Hx : IsIntegral F x := isIntegral_of_noetherian (IsNoetherian.iff_fg.2 hFE) x
- refine' ⟨Hx, Or.inr _⟩
- rintro q q_irred ⟨r, hr⟩
- let D := AdjoinRoot q
- haveI := Fact.mk q_irred
- let pbED := AdjoinRoot.powerBasis q_irred.ne_zero
- haveI : FiniteDimensional E D := PowerBasis.finiteDimensional pbED
- have finrankED : FiniteDimensional.finrank E D = q.natDegree := by
- rw [PowerBasis.finrank pbED, AdjoinRoot.powerBasis_dim]
- haveI : FiniteDimensional F D := FiniteDimensional.trans F E D
- rsuffices ⟨ϕ⟩ : Nonempty (D →ₐ[F] E)
- --Porting note: the `change` was `rw [← WithBot.coe_one]`
- · change degree q = ↑(1 : ℕ)
- rw [degree_eq_iff_natDegree_eq q_irred.ne_zero, ← finrankED]
- have nat_lemma : ∀ a b c : ℕ, a * b = c → c ≤ a → 0 < c → b = 1 := by
- intro a b c h1 h2 h3
- nlinarith
- exact
- nat_lemma _ _ _ (FiniteDimensional.finrank_mul_finrank F E D)
- (LinearMap.finrank_le_finrank_of_injective
- (show Function.Injective ϕ.toLinearMap from ϕ.toRingHom.injective))
- FiniteDimensional.finrank_pos
- let C := AdjoinRoot (minpoly F x)
- haveI Hx_irred := Fact.mk (minpoly.irreducible Hx)
--- Porting note: `heval` added since now Lean wants the proof explicitly in several places.
- have heval : eval₂ (algebraMap F D) (AdjoinRoot.root q) (minpoly F x) = 0 := by
- rw [algebraMap_eq F E D, ← eval₂_map, hr, AdjoinRoot.algebraMap_eq, eval₂_mul,
- AdjoinRoot.eval₂_root, zero_mul]
- letI : Algebra C D :=
- RingHom.toAlgebra (AdjoinRoot.lift (algebraMap F D) (AdjoinRoot.root q) heval)
- letI : Algebra C E := RingHom.toAlgebra (AdjoinRoot.lift (algebraMap F E) x (minpoly.aeval F x))
- haveI : IsScalarTower F C D := of_algebraMap_eq fun y => (AdjoinRoot.lift_of heval).symm
- haveI : IsScalarTower F C E := by
- refine' of_algebraMap_eq fun y => (AdjoinRoot.lift_of _).symm
--- Porting note: the following proof was just `_`.
- rw [← aeval_def, minpoly.aeval]
- suffices Nonempty (D →ₐ[C] E) by exact Nonempty.map (AlgHom.restrictScalars F) this
- let S : Set D := ((p.aroots E).map (algebraMap E D)).toFinset
- suffices ⊤ ≤ IntermediateField.adjoin C S by
- refine' IntermediateField.algHom_mk_adjoin_splits' (top_le_iff.mp this) fun y hy => _
- rcases Multiset.mem_map.mp (Multiset.mem_toFinset.mp hy) with ⟨z, hz1, hz2⟩
- have Hz : IsIntegral F z := isIntegral_of_noetherian (IsNoetherian.iff_fg.2 hFE) z
- use
- show IsIntegral C y from
- isIntegral_of_noetherian (IsNoetherian.iff_fg.2 (FiniteDimensional.right F C D)) y
- apply splits_of_splits_of_dvd (algebraMap C E) (map_ne_zero (minpoly.ne_zero Hz))
- · rw [splits_map_iff, ← algebraMap_eq F C E]
- exact
- splits_of_splits_of_dvd _ hp hFEp.splits (minpoly.dvd F z (mem_aroots.mp hz1).2)
- · apply minpoly.dvd
- rw [← hz2, aeval_def, eval₂_map, ← algebraMap_eq F C D, algebraMap_eq F E D, ← hom_eval₂, ←
- aeval_def, minpoly.aeval F z, RingHom.map_zero]
- rw [← IntermediateField.toSubalgebra_le_toSubalgebra, IntermediateField.top_toSubalgebra]
- apply ge_trans (IntermediateField.algebra_adjoin_le_adjoin C S)
- suffices
- (Algebra.adjoin C S).restrictScalars F =
- (Algebra.adjoin E {AdjoinRoot.root q}).restrictScalars F by
- rw [AdjoinRoot.adjoinRoot_eq_top, Subalgebra.restrictScalars_top, ←
- @Subalgebra.restrictScalars_top F C] at this
- exact top_le_iff.mpr (Subalgebra.restrictScalars_injective F this)
-/- Porting note: the `change` was `dsimp only [S]`. Using `set S ... with hS` doesn't work. -/
- change Subalgebra.restrictScalars F (Algebra.adjoin C
- (((p.aroots E).map (algebraMap E D)).toFinset : Set D)) = _
- rw [← Finset.image_toFinset, Finset.coe_image]
- apply
- Eq.trans
- (Algebra.adjoin_res_eq_adjoin_res F E C D hFEp.adjoin_rootSet AdjoinRoot.adjoinRoot_eq_top)
- rw [Set.image_singleton, RingHom.algebraMap_toAlgebra, AdjoinRoot.lift_root]
+ rw [rootSet_zero, Algebra.adjoin_empty] at this
+ exact Normal.of_algEquiv
+ (AlgEquiv.ofBijective (Algebra.ofId F E) (Algebra.bijective_algebraMap_iff.2 this.symm))
+ refine normal_iff.mpr fun x ↦ ?_
+ haveI : FiniteDimensional F E := IsSplittingField.finiteDimensional E p
+ have hx := isIntegral_of_finite F x
+ let L := (p * minpoly F x).SplittingField
+ have hL := splits_of_splits_mul' _ ?_ (SplittingField.splits (p * minpoly F x))
+ · let j : E →ₐ[F] L := IsSplittingField.lift E p hL.1
+ refine ⟨hx, splits_of_comp _ (j : E →+* L) (j.comp_algebraMap ▸ hL.2) fun a ha ↦ ?_⟩
+ rw [j.comp_algebraMap] at ha
+ letI : Algebra F⟮x⟯ L := ((algHomAdjoinIntegralEquiv F hx).symm ⟨a, ha⟩).toRingHom.toAlgebra
+ let j' : E →ₐ[F⟮x⟯] L := IsSplittingField.lift E (p.map (algebraMap F F⟮x⟯)) ?_
+ · change a ∈ j.range
+ rw [← IsSplittingField.adjoin_rootSet_eq_range E p j,
+ IsSplittingField.adjoin_rootSet_eq_range E p (j'.restrictScalars F)]
+ exact ⟨x, (j'.commutes _).trans (algHomAdjoinIntegralEquiv_symm_apply_gen F hx _)⟩
+ · rw [splits_map_iff, ← IsScalarTower.algebraMap_eq]; exact hL.1
+ · rw [Polynomial.map_ne_zero_iff (algebraMap F L).injective, mul_ne_zero_iff]
+ exact ⟨hp, minpoly.ne_zero hx⟩
#align normal.of_is_splitting_field Normal.of_isSplittingField
+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 NormalTower
namespace IntermediateField
_root_
lost during porting (#7981)
You can tell this was a porting error because the #align
s were weird.
@@ -343,9 +343,9 @@ theorem AlgHom.fieldRange_of_normal [Algebra F K] {E : IntermediateField F K} [N
-- Porting note: this was `IsScalarTower F E E := by infer_instance`.
letI : Algebra E E := Algebra.id E
let g := f.restrictNormal' E
- rw [← show E.val.comp ↑g = f from FunLike.ext_iff.mpr (f.restrictNormal_commutes E), ←
- IntermediateField.AlgHom.map_fieldRange, IntermediateField.AlgEquiv.fieldRange_eq_top g,
- ← IntermediateField.AlgHom.fieldRange_eq_map, IntermediateField.fieldRange_val]
+ rw [← show E.val.comp ↑g = f from FunLike.ext_iff.mpr (f.restrictNormal_commutes E),
+ ← AlgHom.map_fieldRange, AlgEquiv.fieldRange_eq_top g, ← AlgHom.fieldRange_eq_map,
+ IntermediateField.fieldRange_val]
#align alg_hom.field_range_of_normal AlgHom.fieldRange_of_normal
/-- Restrict algebra isomorphism to a normal subfield -/
Due to recent changes in core we can reduce or remove many set_option maxHeartbeats
statements.
I have tried to be careful to not leave anything too close to the line, so don't be surprised if some of these can still be reduced further.
This reduces us from 96 maxHeartbeats
statements to 44
. (There are 10 false positives in meta or testing code.)
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -227,8 +227,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
rw [AdjoinRoot.adjoinRoot_eq_top, Subalgebra.restrictScalars_top, ←
@Subalgebra.restrictScalars_top F C] at this
exact top_le_iff.mpr (Subalgebra.restrictScalars_injective F this)
-/- Porting note: the `change` was `dsimp only [S]`. This is the step that requires increasing
-`maxHeartbeats`. Using `set S ... with hS` doesn't work. -/
+/- Porting note: the `change` was `dsimp only [S]`. Using `set S ... with hS` doesn't work. -/
change Subalgebra.restrictScalars F (Algebra.adjoin C
(((p.aroots E).map (algebraMap E D)).toFinset : Set D)) = _
rw [← Finset.image_toFinset, Finset.coe_image]
@@ -266,7 +266,7 @@ instance normal_iSup {ι : Type*} (t : ι → IntermediateField F K) [h : ∀ i,
instance normal_sup
(E E' : IntermediateField F K) [Normal F E] [Normal F E'] :
Normal F (E ⊔ E' : IntermediateField F K) :=
- iSup_bool_eq (f := Bool.rec E' E) ▸ normal_iSup (h := by intro i; cases i <;> infer_instance)
+ iSup_bool_eq (f := Bool.rec E' E) ▸ normal_iSup (h := by rintro (_|_) <;> infer_instance)
-- Porting note `[Field F] [Field K] [Algebra F K]` added by hand.
variable {F K} {L : Type*} [Field F] [Field K] [Field L] [Algebra F L] [Algebra K L]
minpoly.eq_of_algebraMap_eq
by algebraMap_eq
(#7228)
Also changes the repetitive names minpoly.minpoly_algHom/Equiv
to minpoly.algHom/Equiv_eq
@@ -62,7 +62,7 @@ theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
-- Now it can't find a proof by unification, so we have to do it ourselves.
apply PowerBasis.lift_gen
change aeval y (minpoly F (AdjoinSimple.gen F x)) = 0
- exact minpoly_gen (hi x) ▸ aeval_eq_zero_of_mem_rootSet (Multiset.mem_toFinset.mpr hy)
+ exact minpoly_gen F x ▸ aeval_eq_zero_of_mem_rootSet (Multiset.mem_toFinset.mpr hy)
#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure.restrictScalars_eq_iSup_adjoin
@@ -74,8 +74,7 @@ instance normal [h : Normal F L] : Normal F (normalClosure F K L) := by
intro x
-- Porting note: use the `(_)` trick to obtain an instance by unification.
apply Normal.of_isSplittingField (p := minpoly F x) (hFEp := _)
- exact adjoin_rootSet_isSplittingField ((minpoly.eq_of_algebraMap_eq ϕ.injective
- ((isIntegral_algebraMap_iff ϕ.injective).mp (h.isIntegral (ϕ x))) rfl).symm ▸ h.splits _)
+ exact adjoin_rootSet_isSplittingField (minpoly.algebraMap_eq ϕ.injective (A := F) x ▸ h.splits _)
#align normal_closure.normal normalClosure.normal
instance is_finiteDimensional [FiniteDimensional F K] :
@@ -204,7 +204,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
-- Porting note: the following proof was just `_`.
rw [← aeval_def, minpoly.aeval]
suffices Nonempty (D →ₐ[C] E) by exact Nonempty.map (AlgHom.restrictScalars F) this
- let S : Set D := ((p.map (algebraMap F E)).roots.map (algebraMap E D)).toFinset
+ let S : Set D := ((p.aroots E).map (algebraMap E D)).toFinset
suffices ⊤ ≤ IntermediateField.adjoin C S by
refine' IntermediateField.algHom_mk_adjoin_splits' (top_le_iff.mp this) fun y hy => _
rcases Multiset.mem_map.mp (Multiset.mem_toFinset.mp hy) with ⟨z, hz1, hz2⟩
@@ -215,8 +215,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
apply splits_of_splits_of_dvd (algebraMap C E) (map_ne_zero (minpoly.ne_zero Hz))
· rw [splits_map_iff, ← algebraMap_eq F C E]
exact
- splits_of_splits_of_dvd _ hp hFEp.splits
- (minpoly.dvd F z (Eq.trans (eval₂_eq_eval_map _) ((mem_roots (map_ne_zero hp)).mp hz1)))
+ splits_of_splits_of_dvd _ hp hFEp.splits (minpoly.dvd F z (mem_aroots.mp hz1).2)
· apply minpoly.dvd
rw [← hz2, aeval_def, eval₂_map, ← algebraMap_eq F C D, algebraMap_eq F E D, ← hom_eval₂, ←
aeval_def, minpoly.aeval F z, RingHom.map_zero]
@@ -231,7 +230,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
/- Porting note: the `change` was `dsimp only [S]`. This is the step that requires increasing
`maxHeartbeats`. Using `set S ... with hS` doesn't work. -/
change Subalgebra.restrictScalars F (Algebra.adjoin C
- (((p.map (algebraMap F E)).roots.map (algebraMap E D)).toFinset : Set D)) = _
+ (((p.aroots E).map (algebraMap E D)).toFinset : Set D)) = _
rw [← Finset.image_toFinset, Finset.coe_image]
apply
Eq.trans
This PR adds API and changes the definition of the normal closure of $F\leq K\leq L$ to be an intermediate field of L/F, rather than an intermediate field of L/K. For example, I think it would be more common to say that the normal closure of $\mathbb{Q}(\sqrt[3]{2})/\mathbb{Q}$ is $\mathbb{Q}(\sqrt[3]{2},\zeta_3)/\mathbb{Q}$ rather than $\mathbb{Q}(\sqrt[3]{2},\zeta_3)/\mathbb{Q}(\sqrt[3]{2})$. This change also means that the normal closure goes from being a dependent function (K : Type) → IntermediateField K L
to being a non-dependent function Type → IntermediateField F L
, making it easier to compare across the Galois corespondence.
Supersedes https://github.com/leanprover-community/mathlib/pull/18971
Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Thomas Browning <tb65536@users.noreply.github.com>
@@ -5,6 +5,7 @@ Authors: Thomas Browning
-/
import Mathlib.FieldTheory.Normal
+import Mathlib.Order.Closure
#align_import field_theory.normal from "leanprover-community/mathlib"@"9fb8964792b4237dac6200193a0d533f1b3f7423"
/-!
@@ -22,16 +23,27 @@ variable (F K L : Type*) [Field F] [Field K] [Field L] [Algebra F K] [Algebra F
[IsScalarTower F K L]
/-- The normal closure of `K` in `L`. -/
-noncomputable def normalClosure : IntermediateField K L :=
- { (⨆ f : K →ₐ[F] L, f.fieldRange) with
- algebraMap_mem' := fun r =>
- le_iSup (fun f : K →ₐ[F] L => f.fieldRange) (IsScalarTower.toAlgHom F K L) ⟨r, rfl⟩ }
-#align normal_closure normalClosure
+noncomputable def normalClosure : IntermediateField F L :=
+ ⨆ f : K →ₐ[F] L, f.fieldRange
+
+lemma normalClosure_def : normalClosure F K L = ⨆ f : K →ₐ[F] L, f.fieldRange :=
+ rfl
+
+variable {F K L}
+
+lemma normalClosure_le_iff {K' : IntermediateField F L} :
+ normalClosure F K L ≤ K' ↔ ∀ f : K →ₐ[F] L, f.fieldRange ≤ K' :=
+ iSup_le_iff
+
+lemma AlgHom.fieldRange_le_normalClosure (f : K →ₐ[F] L) : f.fieldRange ≤ normalClosure F K L :=
+ le_iSup AlgHom.fieldRange f
+
+variable (F K L)
namespace normalClosure
theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
- (normalClosure F K L).restrictScalars F = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) := by
+ normalClosure F K L = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) := by
classical
have hi : ∀ x : K, IsIntegral F x :=
fun x ↦ (isIntegral_algebraMap_iff (algebraMap K L).injective).mp (h.isIntegral _)
@@ -71,12 +83,89 @@ instance is_finiteDimensional [FiniteDimensional F K] :
haveI : ∀ f : K →ₐ[F] L, FiniteDimensional F f.fieldRange := fun f =>
f.toLinearMap.finiteDimensional_range
apply IntermediateField.finiteDimensional_iSup_of_finite
-#align normal_closure.is_finite_dimensional normalClosure.is_finiteDimensional
-instance isScalarTower : IsScalarTower F (normalClosure F K L) L :=
- -- Porting note: the last argument here `(⨆ (f : K →ₐ[F] L), f.fieldRange).toSubalgebra`
- -- was just written as `_` in mathlib3.
- IsScalarTower.subalgebra' F L L (⨆ (f : K →ₐ[F] L), f.fieldRange).toSubalgebra
-#align normal_closure.is_scalar_tower normalClosure.isScalarTower
+noncomputable instance algebra : Algebra K (normalClosure F K L) :=
+ IntermediateField.algebra
+ { ⨆ f : K →ₐ[F] L, f.fieldRange with
+ algebraMap_mem' := fun r => (toAlgHom F K L).fieldRange_le_normalClosure ⟨r, rfl⟩ }
+
+instance : IsScalarTower F K (normalClosure F K L) := by
+ apply of_algebraMap_eq'
+ ext x
+ exact algebraMap_apply F K L x
+
+instance : IsScalarTower K (normalClosure F K L) L :=
+ of_algebraMap_eq' rfl
+
+lemma restrictScalars_eq :
+ (toAlgHom K (normalClosure F K L) L).fieldRange.restrictScalars F = normalClosure F K L :=
+ SetLike.ext' Subtype.range_val
end normalClosure
+
+namespace IntermediateField
+
+variable {F L}
+variable (K K' : IntermediateField F L)
+
+lemma le_normalClosure : K ≤ normalClosure F K L :=
+K.fieldRange_val.symm.trans_le K.val.fieldRange_le_normalClosure
+
+lemma normalClosure_of_normal [Normal F K] : normalClosure F K L = K :=
+by simp only [normalClosure_def, AlgHom.fieldRange_of_normal, iSup_const]
+
+variable [Normal F L]
+
+lemma normalClosure_def' : normalClosure F K L = ⨆ f : L →ₐ[F] L, K.map f := by
+ refine' (normalClosure_def F K L).trans (le_antisymm (iSup_le (fun f ↦ _)) (iSup_le (fun f ↦ _)))
+ · exact le_iSup_of_le (f.liftNormal L) (fun b ⟨a, h⟩ ↦ ⟨a, a.2, h ▸ f.liftNormal_commutes L a⟩)
+ · exact le_iSup_of_le (f.comp K.val) (fun b ⟨a, h⟩ ↦ ⟨⟨a, h.1⟩, h.2⟩)
+
+lemma normalClosure_def'' : normalClosure F K L = ⨆ f : L ≃ₐ[F] L, K.map f := by
+ refine' (normalClosure_def' K).trans (le_antisymm (iSup_le (fun f ↦ _)) (iSup_le (fun f ↦ _)))
+ · exact le_iSup_of_le (f.restrictNormal' L)
+ (fun b ⟨a, h⟩ ↦ ⟨a, h.1, h.2 ▸ f.restrictNormal_commutes L a⟩)
+ · exact le_iSup_of_le f le_rfl
+
+lemma normalClosure_mono (h : K ≤ K') : normalClosure F K L ≤ normalClosure F K' L := by
+ rw [normalClosure_def', normalClosure_def']
+ exact iSup_mono (fun f ↦ map_mono f h)
+
+variable (F L)
+
+/-- `normalClosure` as a `ClosureOperator`. -/
+@[simps]
+noncomputable def closureOperator : ClosureOperator (IntermediateField F L) where
+ toFun := fun K ↦ normalClosure F K L
+ monotone' := fun K K' ↦ normalClosure_mono K K'
+ le_closure' := le_normalClosure
+ idempotent' := fun K ↦ normalClosure_of_normal (normalClosure F K L)
+
+variable {K : IntermediateField F L} {F L}
+
+lemma normal_iff_normalClosure_eq : Normal F K ↔ normalClosure F K L = K :=
+⟨@normalClosure_of_normal (K := K), fun h ↦ h ▸ normalClosure.normal F K L⟩
+
+lemma normal_iff_normalClosure_le : Normal F K ↔ normalClosure F K L ≤ K :=
+normal_iff_normalClosure_eq.trans (le_normalClosure K).le_iff_eq.symm
+
+lemma normal_iff_forall_fieldRange_le : Normal F K ↔ ∀ σ : K →ₐ[F] L, σ.fieldRange ≤ K :=
+by rw [normal_iff_normalClosure_le, normalClosure_def, iSup_le_iff]
+
+lemma normal_iff_forall_map_le : Normal F K ↔ ∀ σ : L →ₐ[F] L, K.map σ ≤ K :=
+by rw [normal_iff_normalClosure_le, normalClosure_def', iSup_le_iff]
+
+lemma normal_iff_forall_map_le' : Normal F K ↔ ∀ σ : L ≃ₐ[F] L, K.map ↑σ ≤ K :=
+by rw [normal_iff_normalClosure_le, normalClosure_def'', iSup_le_iff]
+
+lemma normal_iff_forall_fieldRange_eq : Normal F K ↔ ∀ σ : K →ₐ[F] L, σ.fieldRange = K :=
+⟨@AlgHom.fieldRange_of_normal (E := K), normal_iff_forall_fieldRange_le.2 ∘ fun h σ ↦ (h σ).le⟩
+
+lemma normal_iff_forall_map_eq : Normal F K ↔ ∀ σ : L →ₐ[F] L, K.map σ = K :=
+⟨fun h σ ↦ (K.fieldRange_val ▸ AlgHom.map_fieldRange K.val σ).trans
+ (normal_iff_forall_fieldRange_eq.1 h _), fun h ↦ normal_iff_forall_map_le.2 (fun σ ↦ (h σ).le)⟩
+
+lemma normal_iff_forall_map_eq' : Normal F K ↔ ∀ σ : L ≃ₐ[F] L, K.map ↑σ = K :=
+⟨fun h σ ↦ normal_iff_forall_map_eq.1 h σ, fun h ↦ normal_iff_forall_map_le'.2 (fun σ ↦ (h σ).le)⟩
+
+end IntermediateField
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).
@@ -194,7 +194,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
-- Porting note: `heval` added since now Lean wants the proof explicitly in several places.
have heval : eval₂ (algebraMap F D) (AdjoinRoot.root q) (minpoly F x) = 0 := by
rw [algebraMap_eq F E D, ← eval₂_map, hr, AdjoinRoot.algebraMap_eq, eval₂_mul,
- AdjoinRoot.eval₂_root, MulZeroClass.zero_mul]
+ AdjoinRoot.eval₂_root, zero_mul]
letI : Algebra C D :=
RingHom.toAlgebra (AdjoinRoot.lift (algebraMap F D) (AdjoinRoot.root q) heval)
letI : Algebra C E := RingHom.toAlgebra (AdjoinRoot.lift (algebraMap F E) x (minpoly.aeval F x))
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -18,7 +18,7 @@ contains the image of every `F`-algebra embedding `K →ₐ[F] L`.
open BigOperators IntermediateField IsScalarTower Polynomial
-variable (F K L : Type _) [Field F] [Field K] [Field L] [Algebra F K] [Algebra F L] [Algebra K L]
+variable (F K L : Type*) [Field F] [Field K] [Field L] [Algebra F K] [Algebra F L] [Algebra K L]
[IsScalarTower F K L]
/-- The normal closure of `K` in `L`. -/
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -31,7 +31,7 @@ open scoped Classical Polynomial
open Polynomial IsScalarTower
-variable (F K : Type _) [Field F] [Field K] [Algebra F K]
+variable (F K : Type*) [Field F] [Field K] [Algebra F K]
/-- Typeclass for normal field extension: `K` is a normal extension of `F` iff the minimal
polynomial of every element `x` in `K` splits in `K`, i.e. every conjugate of `x` is in `K`. -/
@@ -94,7 +94,7 @@ theorem Normal.exists_isSplittingField [h : Normal F K] [FiniteDimensional F K]
section NormalTower
-variable (E : Type _) [Field E] [Algebra F E] [Algebra K E] [IsScalarTower F K E]
+variable (E : Type*) [Field E] [Algebra F E] [Algebra K E] [IsScalarTower F K E]
theorem Normal.tower_top_of_normal [h : Normal F E] : Normal K E :=
normal_iff.2 fun x => by
@@ -128,7 +128,7 @@ theorem AlgHom.normal_bijective [h : Normal F E] (ϕ : E →ₐ[F] K) : Function
#align alg_hom.normal_bijective AlgHom.normal_bijective
-- Porting note: `[Field F] [Field E] [Algebra F E]` added by hand.
-variable {F} {E} {E' : Type _} [Field F] [Field E] [Algebra F E] [Field E'] [Algebra F E']
+variable {F} {E} {E' : Type*} [Field F] [Field E] [Algebra F E] [Field E'] [Algebra F E']
theorem Normal.of_algEquiv [h : Normal F E] (f : E ≃ₐ[F] E') : Normal F E' :=
normal_iff.2 fun x => by
@@ -244,7 +244,7 @@ end NormalTower
namespace IntermediateField
/-- A compositum of normal extensions is normal -/
-instance normal_iSup {ι : Type _} (t : ι → IntermediateField F K) [h : ∀ i, Normal F (t i)] :
+instance normal_iSup {ι : Type*} (t : ι → IntermediateField F K) [h : ∀ i, Normal F (t i)] :
Normal F (⨆ i, t i : IntermediateField F K) := by
refine' ⟨isAlgebraic_iSup fun i => (h i).1, fun x => _⟩
obtain ⟨s, hx⟩ := exists_finset_of_mem_supr'' (fun i => (h i).1) x.2
@@ -270,7 +270,7 @@ instance normal_sup
iSup_bool_eq (f := Bool.rec E' E) ▸ normal_iSup (h := by intro i; cases i <;> infer_instance)
-- Porting note `[Field F] [Field K] [Algebra F K]` added by hand.
-variable {F K} {L : Type _} [Field F] [Field K] [Field L] [Algebra F L] [Algebra K L]
+variable {F K} {L : Type*} [Field F] [Field K] [Field L] [Algebra F L] [Algebra K L]
[Algebra F K] [IsScalarTower F K L]
@[simp]
@@ -282,13 +282,13 @@ theorem restrictScalars_normal {E : IntermediateField K L} :
end IntermediateField
-- Porting note `[Field F]` added by hand.
-variable {F} {K} {K₁ K₂ K₃ : Type _} [Field F] [Field K₁] [Field K₂] [Field K₃] [Algebra F K₁]
+variable {F} {K} {K₁ K₂ K₃ : Type*} [Field F] [Field K₁] [Field K₂] [Field K₃] [Algebra F K₁]
[Algebra F K₂] [Algebra F K₃] (ϕ : K₁ →ₐ[F] K₂) (χ : K₁ ≃ₐ[F] K₂) (ψ : K₂ →ₐ[F] K₃)
(ω : K₂ ≃ₐ[F] K₃)
section Restrict
-variable (E : Type _) [Field E] [Algebra F E] [Algebra E K₁] [Algebra E K₂] [Algebra E K₃]
+variable (E : Type*) [Field E] [Algebra F E] [Algebra E K₁] [Algebra E K₂] [Algebra E K₃]
[IsScalarTower F E K₁] [IsScalarTower F E K₂] [IsScalarTower F E K₃]
/-- Restrict algebra homomorphism to image of normal subfield -/
@@ -396,7 +396,7 @@ end Restrict
section lift
-variable (E : Type _) [Field E] [Algebra F E] [Algebra K₁ E] [Algebra K₂ E] [IsScalarTower F K₁ E]
+variable (E : Type*) [Field E] [Algebra F E] [Algebra K₁ E] [Algebra K₂ E] [IsScalarTower F K₁ E]
[IsScalarTower F K₂ E]
/-- If `E/Kᵢ/F` are towers of fields with `E/F` normal then we can lift
@@ -23,9 +23,7 @@ variable (F K L : Type _) [Field F] [Field K] [Field L] [Algebra F K] [Algebra F
/-- The normal closure of `K` in `L`. -/
noncomputable def normalClosure : IntermediateField K L :=
- { (⨆ f : K →ₐ[F] L, f.fieldRange).toSubfield with
- -- Porting note: could not inherit neg_mem
- neg_mem' := fun _ hx => Subfield.neg_mem (⨆ f : K →ₐ[F] L, f.fieldRange).toSubfield hx
+ { (⨆ f : K →ₐ[F] L, f.fieldRange) with
algebraMap_mem' := fun r =>
le_iSup (fun f : K →ₐ[F] L => f.fieldRange) (IsScalarTower.toAlgHom F K L) ⟨r, rfl⟩ }
#align normal_closure normalClosure
@@ -35,36 +35,24 @@ namespace normalClosure
theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
(normalClosure F K L).restrictScalars F = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) := by
classical
+ have hi : ∀ x : K, IsIntegral F x :=
+ fun x ↦ (isIntegral_algebraMap_iff (algebraMap K L).injective).mp (h.isIntegral _)
refine' le_antisymm (iSup_le _) (iSup_le fun x => adjoin_le_iff.mpr fun y hy => _)
· rintro f _ ⟨x, rfl⟩
- refine'
- le_iSup (fun x => adjoin F ((minpoly F x).rootSet L)) x
+ refine' le_iSup (fun x => adjoin F ((minpoly F x).rootSet L)) x
(subset_adjoin F ((minpoly F x).rootSet L) _)
- rw [mem_rootSet_of_ne, AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom,
+ rw [mem_rootSet_of_ne (minpoly.ne_zero (hi x)), AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom,
Polynomial.aeval_algHom_apply, minpoly.aeval, map_zero]
- exact
- minpoly.ne_zero
- ((isIntegral_algebraMap_iff (algebraMap K L).injective).mp
- (h.isIntegral (algebraMap K L x)))
· rw [Polynomial.rootSet, Finset.mem_coe, Multiset.mem_toFinset] at hy
- let g :=
- (algHomAdjoinIntegralEquiv F
- ((isIntegral_algebraMap_iff (algebraMap K L).injective).mp
- (h.isIntegral (algebraMap K L x)))).symm
- ⟨y, hy⟩
- refine'
- le_iSup (fun f : K →ₐ[F] L => f.fieldRange)
- ((g.liftNormal L).comp (IsScalarTower.toAlgHom F K L))
+ let g := (algHomAdjoinIntegralEquiv F (hi x)).symm ⟨y, hy⟩
+ refine' le_iSup (fun f : K →ₐ[F] L => f.fieldRange) ((g.liftNormal L).comp (toAlgHom F K L))
⟨x, (g.liftNormal_commutes L (AdjoinSimple.gen F x)).trans _⟩
rw [Algebra.id.map_eq_id, RingHom.id_apply]
-- Porting note: in mathlib3 this next `apply` closed the goal.
-- Now it can't find a proof by unification, so we have to do it ourselves.
apply PowerBasis.lift_gen
change aeval y (minpoly F (AdjoinSimple.gen F x)) = 0
- suffices : minpoly F (AdjoinSimple.gen F x) = minpoly F x
- · exact this ▸ aeval_eq_zero_of_mem_rootSet (Multiset.mem_toFinset.mpr hy)
- exact minpoly_gen ((isIntegral_algebraMap_iff (algebraMap K L).injective).mp
- (h.isIntegral (algebraMap K L x)))
+ exact minpoly_gen (hi x) ▸ aeval_eq_zero_of_mem_rootSet (Multiset.mem_toFinset.mpr hy)
#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure.restrictScalars_eq_iSup_adjoin
@@ -72,15 +60,12 @@ instance normal [h : Normal F L] : Normal F (normalClosure F K L) := by
let ϕ := algebraMap K L
rw [← IntermediateField.restrictScalars_normal, restrictScalars_eq_iSup_adjoin]
-- Porting note: use the `(_)` trick to obtain an instance by unification.
- apply @IntermediateField.normal_iSup F L _ _ _ _ _ (_)
+ apply IntermediateField.normal_iSup (h := _)
intro x
-- Porting note: use the `(_)` trick to obtain an instance by unification.
- apply @Normal.of_isSplittingField _ _ _ _ _ (minpoly F x) (_)
- exact
- adjoin_rootSet_isSplittingField
- ((minpoly.eq_of_algebraMap_eq ϕ.injective
- ((isIntegral_algebraMap_iff ϕ.injective).mp (h.isIntegral (ϕ x))) rfl).symm ▸
- h.splits _)
+ apply Normal.of_isSplittingField (p := minpoly F x) (hFEp := _)
+ exact adjoin_rootSet_isSplittingField ((minpoly.eq_of_algebraMap_eq ϕ.injective
+ ((isIntegral_algebraMap_iff ϕ.injective).mp (h.isIntegral (ϕ x))) rfl).symm ▸ h.splits _)
#align normal_closure.normal normalClosure.normal
instance is_finiteDimensional [FiniteDimensional F K] :
@@ -474,89 +474,3 @@ theorem isSolvable_of_isScalarTower [Normal F K₁] [h1 : IsSolvable (K₁ ≃
#align is_solvable_of_is_scalar_tower isSolvable_of_isScalarTower
end lift
-
-section normalClosure
-
-open IntermediateField
-
-variable (F K)
-variable [Algebra F K]
-variable (L : Type _) [Field L] [Algebra F L] [Algebra K L] [IsScalarTower F K L]
-
-/-- The normal closure of `K` in `L`. -/
-noncomputable def normalClosure : IntermediateField K L :=
- { (⨆ f : K →ₐ[F] L, f.fieldRange).toSubfield with
- -- Porting note: could not inherit neg_mem
- neg_mem' := fun _ hx => Subfield.neg_mem (⨆ f : K →ₐ[F] L, f.fieldRange).toSubfield hx
- algebraMap_mem' := fun r =>
- le_iSup (fun f : K →ₐ[F] L => f.fieldRange) (IsScalarTower.toAlgHom F K L) ⟨r, rfl⟩ }
-#align normal_closure normalClosure
-
-namespace normalClosure
-
-theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
- (normalClosure F K L).restrictScalars F = ⨆ x : K, adjoin F ((minpoly F x).rootSet L) := by
- refine' le_antisymm (iSup_le _) (iSup_le fun x => adjoin_le_iff.mpr fun y hy => _)
- · rintro f _ ⟨x, rfl⟩
- refine'
- le_iSup (fun x => adjoin F ((minpoly F x).rootSet L)) x
- (subset_adjoin F ((minpoly F x).rootSet L) _)
- rw [mem_rootSet_of_ne, AlgHom.toRingHom_eq_coe, AlgHom.coe_toRingHom,
- Polynomial.aeval_algHom_apply, minpoly.aeval, map_zero]
- exact
- minpoly.ne_zero
- ((isIntegral_algebraMap_iff (algebraMap K L).injective).mp
- (h.isIntegral (algebraMap K L x)))
- · rw [Polynomial.rootSet, Finset.mem_coe, Multiset.mem_toFinset] at hy
- let g :=
- (algHomAdjoinIntegralEquiv F
- ((isIntegral_algebraMap_iff (algebraMap K L).injective).mp
- (h.isIntegral (algebraMap K L x)))).symm
- ⟨y, hy⟩
- refine'
- le_iSup (fun f : K →ₐ[F] L => f.fieldRange)
- ((g.liftNormal L).comp (IsScalarTower.toAlgHom F K L))
- ⟨x, (g.liftNormal_commutes L (AdjoinSimple.gen F x)).trans _⟩
- rw [Algebra.id.map_eq_id, RingHom.id_apply]
- -- Porting note: in mathlib3 this next `apply` closed the goal.
- -- Now it can't find a proof by unification, so we have to do it ourselves.
- apply PowerBasis.lift_gen
- change aeval y (minpoly F (AdjoinSimple.gen F x)) = 0
- suffices : minpoly F (AdjoinSimple.gen F x) = minpoly F x
- · exact this ▸ aeval_eq_zero_of_mem_rootSet (Multiset.mem_toFinset.mpr hy)
- exact minpoly_gen ((isIntegral_algebraMap_iff (algebraMap K L).injective).mp
- (h.isIntegral (algebraMap K L x)))
-
-#align normal_closure.restrict_scalars_eq_supr_adjoin normalClosure.restrictScalars_eq_iSup_adjoin
-
-instance normal [h : Normal F L] : Normal F (normalClosure F K L) := by
- let ϕ := algebraMap K L
- rw [← IntermediateField.restrictScalars_normal, restrictScalars_eq_iSup_adjoin]
- -- Porting note: use the `(_)` trick to obtain an instance by unification.
- apply @IntermediateField.normal_iSup F L _ _ _ _ _ (_)
- intro x
- -- Porting note: use the `(_)` trick to obtain an instance by unification.
- apply @Normal.of_isSplittingField _ _ _ _ _ (minpoly F x) (_)
- exact
- adjoin_rootSet_isSplittingField
- ((minpoly.eq_of_algebraMap_eq ϕ.injective
- ((isIntegral_algebraMap_iff ϕ.injective).mp (h.isIntegral (ϕ x))) rfl).symm ▸
- h.splits _)
-#align normal_closure.normal normalClosure.normal
-
-instance is_finiteDimensional [FiniteDimensional F K] :
- FiniteDimensional F (normalClosure F K L) := by
- haveI : ∀ f : K →ₐ[F] L, FiniteDimensional F f.fieldRange := fun f =>
- f.toLinearMap.finiteDimensional_range
- apply IntermediateField.finiteDimensional_iSup_of_finite
-#align normal_closure.is_finite_dimensional normalClosure.is_finiteDimensional
-
-instance isScalarTower : IsScalarTower F (normalClosure F K L) L :=
- -- Porting note: the last argument here `(⨆ (f : K →ₐ[F] L), f.fieldRange).toSubalgebra`
- -- was just written as `_` in mathlib3.
- IsScalarTower.subalgebra' F L L (⨆ (f : K →ₐ[F] L), f.fieldRange).toSubalgebra
-#align normal_closure.is_scalar_tower normalClosure.isScalarTower
-
-end normalClosure
-
-end normalClosure
This is a quick consequence of normal_iSup
which states than an arbitrary compositum of normal field extensions is normal.
@@ -264,6 +264,11 @@ instance normal_iSup {ι : Type _} (t : ι → IntermediateField F K) [h : ∀ i
exact Polynomial.splits_comp_of_splits _ (inclusion hE).toRingHom this
#align intermediate_field.normal_supr IntermediateField.normal_iSup
+instance normal_sup
+ (E E' : IntermediateField F K) [Normal F E] [Normal F E'] :
+ Normal F (E ⊔ E' : IntermediateField F K) :=
+ iSup_bool_eq (f := Bool.rec E' E) ▸ normal_iSup (h := by intro i; cases i <;> infer_instance)
+
-- Porting note `[Field F] [Field K] [Algebra F K]` added by hand.
variable {F K} {L : Type _} [Field F] [Field K] [Field L] [Algebra F L] [Algebra K L]
[Algebra F K] [IsScalarTower F K L]
@@ -2,17 +2,14 @@
Copyright (c) 2020 Kenny Lau. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
-
-! This file was ported from Lean 3 source module field_theory.normal
-! leanprover-community/mathlib commit 9fb8964792b4237dac6200193a0d533f1b3f7423
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathlib.FieldTheory.Adjoin
import Mathlib.FieldTheory.Tower
import Mathlib.GroupTheory.Solvable
import Mathlib.RingTheory.PowerBasis
+#align_import field_theory.normal from "leanprover-community/mathlib"@"9fb8964792b4237dac6200193a0d533f1b3f7423"
+
/-!
# Normal field extensions
This PR is the result of running
find . -type f -name "*.lean" -exec sed -i -E 's/^( +)\. /\1· /' {} \;
find . -type f -name "*.lean" -exec sed -i -E 'N;s/^( +·)\n +(.*)$/\1 \2/;P;D' {} \;
which firstly replaces .
focusing dots with ·
and secondly removes isolated instances of such dots, unifying them with the following line. A new rule is placed in the style linter to verify this.
@@ -521,7 +521,7 @@ theorem restrictScalars_eq_iSup_adjoin [h : Normal F L] :
apply PowerBasis.lift_gen
change aeval y (minpoly F (AdjoinSimple.gen F x)) = 0
suffices : minpoly F (AdjoinSimple.gen F x) = minpoly F x
- . exact this ▸ aeval_eq_zero_of_mem_rootSet (Multiset.mem_toFinset.mpr hy)
+ · exact this ▸ aeval_eq_zero_of_mem_rootSet (Multiset.mem_toFinset.mpr hy)
exact minpoly_gen ((isIntegral_algebraMap_iff (algebraMap K L).injective).mp
(h.isIntegral (algebraMap K L x)))
@@ -39,18 +39,18 @@ variable (F K : Type _) [Field F] [Field K] [Algebra F K]
/-- Typeclass for normal field extension: `K` is a normal extension of `F` iff the minimal
polynomial of every element `x` in `K` splits in `K`, i.e. every conjugate of `x` is in `K`. -/
class Normal : Prop where
- is_algebraic' : Algebra.IsAlgebraic F K
+ isAlgebraic' : Algebra.IsAlgebraic F K
splits' (x : K) : Splits (algebraMap F K) (minpoly F x)
#align normal Normal
variable {F K}
theorem Normal.isAlgebraic (_ : Normal F K) (x : K) : IsAlgebraic F x :=
- Normal.is_algebraic' x
+ Normal.isAlgebraic' x
#align normal.is_algebraic Normal.isAlgebraic
theorem Normal.isIntegral (h : Normal F K) (x : K) : IsIntegral F x :=
- isAlgebraic_iff_isIntegral.mp (h.is_algebraic' x)
+ isAlgebraic_iff_isIntegral.mp (h.isAlgebraic' x)
#align normal.is_integral Normal.isIntegral
theorem Normal.splits (_ : Normal F K) (x : K) : Splits (algebraMap F K) (minpoly F x) :=
@@ -89,8 +89,7 @@ theorem Normal.exists_isSplittingField [h : Normal F K] [FiniteDimensional F K]
(Multiset.mem_toFinset.mpr <|
(mem_roots <|
mt (Polynomial.map_eq_zero <| algebraMap F K).1 <|
- Finset.prod_ne_zero_iff.2 fun x _ => _).2
- _)
+ Finset.prod_ne_zero_iff.2 fun x _ => _).2 _)
· exact minpoly.ne_zero (h.isIntegral (s x))
rw [IsRoot.def, eval_map, ← aeval_def, AlgHom.map_prod]
exact Finset.prod_eq_zero (Finset.mem_univ _) (minpoly.aeval _ _)
Field.toEuclideanDomain
(#5266)
Modifying the definition of Field.toEuclideanDomain
makes some declaration faster.
Co-authored-by: Sébastien Gouëzel
@@ -162,7 +162,6 @@ theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F
-- salient in the future, or at least taking a closer look at the algebra instances it uses.
attribute [-instance] AdjoinRoot.instSMulAdjoinRoot
-set_option maxHeartbeats 300000 in
theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] : Normal F E := by
rcases eq_or_ne p 0 with (rfl | hp)
· have := hFEp.adjoin_rootSet
Strangely, making one proof use fewer simp lemmas has made the proof slower (and the hearbeats have been bumped accordingly)
Co-authored-by: Scott Morrison <scott.morrison@anu.edu.au>
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kenny Lau, Thomas Browning, Patrick Lutz
! This file was ported from Lean 3 source module field_theory.normal
-! 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.
-/
@@ -162,12 +162,11 @@ theorem AlgEquiv.transfer_normal (f : E ≃ₐ[F] E') : Normal F E ↔ Normal F
-- salient in the future, or at least taking a closer look at the algebra instances it uses.
attribute [-instance] AdjoinRoot.instSMulAdjoinRoot
-set_option maxHeartbeats 210000 in
+set_option maxHeartbeats 300000 in
theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] : Normal F E := by
rcases eq_or_ne p 0 with (rfl | hp)
- · have := hFEp.adjoin_roots
- simp only [Polynomial.map_zero, roots_zero, Multiset.toFinset_zero, Finset.coe_empty,
- Algebra.adjoin_empty] at this
+ · have := hFEp.adjoin_rootSet
+ simp only [rootSet_zero, Algebra.adjoin_empty] at this
exact
Normal.of_algEquiv
(AlgEquiv.ofBijective (Algebra.ofId F E) (Algebra.bijective_algebraMap_iff.2 this.symm))
@@ -241,7 +240,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
rw [← Finset.image_toFinset, Finset.coe_image]
apply
Eq.trans
- (Algebra.adjoin_res_eq_adjoin_res F E C D hFEp.adjoin_roots AdjoinRoot.adjoinRoot_eq_top)
+ (Algebra.adjoin_res_eq_adjoin_res F E C D hFEp.adjoin_rootSet AdjoinRoot.adjoinRoot_eq_top)
rw [Set.image_singleton, RingHom.algebraMap_toAlgebra, AdjoinRoot.lift_root]
#align normal.of_is_splitting_field Normal.of_isSplittingField
@@ -369,7 +369,7 @@ theorem AlgEquiv.restrictNormal_trans [Normal F E] :
(by simp only [AlgEquiv.trans_apply, AlgEquiv.restrictNormal_commutes])
#align alg_equiv.restrict_normal_trans AlgEquiv.restrictNormal_trans
-/-- Restriction to an normal subfield as a group homomorphism -/
+/-- Restriction to a normal subfield as a group homomorphism -/
def AlgEquiv.restrictNormalHom [Normal F E] : (K₁ ≃ₐ[F] K₁) →* E ≃ₐ[F] E :=
MonoidHom.mk' (fun χ => χ.restrictNormal E) fun ω χ => χ.restrictNormal_trans ω E
#align alg_equiv.restrict_normal_hom AlgEquiv.restrictNormalHom
@@ -197,7 +197,7 @@ theorem Normal.of_isSplittingField (p : F[X]) [hFEp : IsSplittingField F E p] :
FiniteDimensional.finrank_pos
let C := AdjoinRoot (minpoly F x)
haveI Hx_irred := Fact.mk (minpoly.irreducible Hx)
--- Porting note: `heval` added since now Lean wants the proof explictely in several places.
+-- Porting note: `heval` added since now Lean wants the proof explicitly in several places.
have heval : eval₂ (algebraMap F D) (AdjoinRoot.root q) (minpoly F x) = 0 := by
rw [algebraMap_eq F E D, ← eval₂_map, hr, AdjoinRoot.algebraMap_eq, eval₂_mul,
AdjoinRoot.eval₂_root, MulZeroClass.zero_mul]
The unported dependencies are