Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat: roots in an algebra #6740

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions Mathlib/Data/Polynomial/FieldDivision.lean
Expand Up @@ -373,7 +373,7 @@ theorem mem_roots_map [CommRing k] [IsDomain k] {f : R →+* k} {x : k} (hp : p
theorem rootSet_monomial [CommRing S] [IsDomain S] [Algebra R S] {n : ℕ} (hn : n ≠ 0) {a : R}
(ha : a ≠ 0) : (monomial n a).rootSet S = {0} := by
classical
rw [rootSet, map_monomial, roots_monomial ((_root_.map_ne_zero (algebraMap R S)).2 ha),
rw [rootSet, aroots_monomial ha,
Multiset.toFinset_nsmul _ _ hn, Multiset.toFinset_singleton, Finset.coe_singleton]
#align polynomial.root_set_monomial Polynomial.rootSet_monomial

Expand All @@ -393,7 +393,7 @@ set_option linter.uppercaseLean3 false in
theorem rootSet_prod [CommRing S] [IsDomain S] [Algebra R S] {ι : Type*} (f : ι → R[X])
(s : Finset ι) (h : s.prod f ≠ 0) : (s.prod f).rootSet S = ⋃ i ∈ s, (f i).rootSet S := by
classical
simp only [rootSet, ← Finset.mem_coe]
simp only [rootSet, aroots, ← Finset.mem_coe]
rw [Polynomial.map_prod, roots_prod, Finset.bind_toFinset, s.val_toFinset, Finset.coe_biUnion]
rwa [← Polynomial.map_prod, Ne, map_eq_zero]
#align polynomial.root_set_prod Polynomial.rootSet_prod
Expand Down
99 changes: 90 additions & 9 deletions Mathlib/Data/Polynomial/RingDivision.lean
Expand Up @@ -912,25 +912,108 @@ theorem funext [Infinite R] {p q : R[X]} (ext : ∀ r : R, p.eval r = q.eval r)

variable [CommRing T]

/-- The set of distinct roots of `p` in `E`.
/-- Given a polynomial `p` with coefficients in a ring `T` and a `T`-algebra `S`, `aroots p S` is
the multiset of roots of `p` regarded as a polynomial over `S`. -/
noncomputable abbrev aroots (p : T[X]) (S) [CommRing S] [IsDomain S] [Algebra T S] : Multiset S :=
(p.map (algebraMap T S)).roots

If you have a non-separable polynomial, use `Polynomial.roots` for the multiset
theorem aroots_def (p : T[X]) (S) [CommRing S] [IsDomain S] [Algebra T S] :
p.aroots S = (p.map (algebraMap T S)).roots :=
rfl

theorem mem_aroots' [CommRing S] [IsDomain S] [Algebra T S] {p : T[X]} {a : S} :
a ∈ p.aroots S ↔ p.map (algebraMap T S) ≠ 0 ∧ aeval a p = 0 := by
rw [mem_roots', IsRoot.def, ← eval₂_eq_eval_map, aeval_def]

theorem mem_aroots [CommRing S] [IsDomain S] [Algebra T S]
[NoZeroSMulDivisors T S] {p : T[X]} {a : S} : a ∈ p.aroots S ↔ p ≠ 0 ∧ aeval a p = 0 := by
rw [mem_aroots', Polynomial.map_ne_zero_iff]
exact NoZeroSMulDivisors.algebraMap_injective T S

theorem aroots_mul [CommRing S] [IsDomain S] [Algebra T S]
[NoZeroSMulDivisors T S] {p q : T[X]} (hpq : p * q ≠ 0) :
(p * q).aroots S = p.aroots S + q.aroots S := by
suffices : map (algebraMap T S) p * map (algebraMap T S) q ≠ 0
· rw [aroots_def, Polynomial.map_mul, roots_mul this]
rwa [← Polynomial.map_mul, Polynomial.map_ne_zero_iff
(NoZeroSMulDivisors.algebraMap_injective T S)]

@[simp]
theorem aroots_X_sub_C [CommRing S] [IsDomain S] [Algebra T S]
(r : T) : aroots (X - C r) S = {algebraMap T S r} := by
rw [aroots_def, Polynomial.map_sub, map_X, map_C, roots_X_sub_C]

@[simp]
theorem aroots_X [CommRing S] [IsDomain S] [Algebra T S] :
aroots (X : T[X]) S = {0} := by
rw [aroots_def, map_X, roots_X]

@[simp]
theorem aroots_C [CommRing S] [IsDomain S] [Algebra T S] (a : T) : (C a).aroots S = 0 := by
rw [aroots_def, map_C, roots_C]

@[simp]
theorem aroots_zero (S) [CommRing S] [IsDomain S] [Algebra T S] : (0 : T[X]).aroots S = 0 := by
rw [← C_0, aroots_C]

@[simp]
theorem aroots_one [CommRing S] [IsDomain S] [Algebra T S] :
(1 : T[X]).aroots S = 0 :=
aroots_C 1

@[simp]
theorem aroots_C_mul [CommRing S] [IsDomain S] [Algebra T S]
[NoZeroSMulDivisors T S] {a : T} (p : T[X]) (ha : a ≠ 0) :
(C a * p).aroots S = p.aroots S := by
rw [aroots_def, Polynomial.map_mul, map_C, roots_C_mul]
rwa [map_ne_zero_iff]
exact NoZeroSMulDivisors.algebraMap_injective T S

@[simp]
theorem aroots_smul_nonzero [CommRing S] [IsDomain S] [Algebra T S]
[NoZeroSMulDivisors T S] {a : T} (p : T[X]) (ha : a ≠ 0) :
(a • p).aroots S = p.aroots S := by
rw [smul_eq_C_mul, aroots_C_mul _ ha]

@[simp]
theorem aroots_pow [CommRing S] [IsDomain S] [Algebra T S] (p : T[X]) (n : ℕ) :
(p ^ n).aroots S = n • p.aroots S := by
rw [aroots_def, Polynomial.map_pow, roots_pow]

theorem aroots_X_pow [CommRing S] [IsDomain S] [Algebra T S] (n : ℕ) :
(X ^ n : T[X]).aroots S = n • ({0} : Multiset S) := by
rw [aroots_pow, aroots_X]

theorem aroots_C_mul_X_pow [CommRing S] [IsDomain S] [Algebra T S]
[NoZeroSMulDivisors T S] {a : T} (ha : a ≠ 0) (n : ℕ) :
(C a * X ^ n : T[X]).aroots S = n • ({0} : Multiset S) := by
rw [aroots_C_mul _ ha, aroots_X_pow]

@[simp]
theorem aroots_monomial [CommRing S] [IsDomain S] [Algebra T S]
[NoZeroSMulDivisors T S] {a : T} (ha : a ≠ 0) (n : ℕ) :
(monomial n a).aroots S = n • ({0} : Multiset S) := by
rw [← C_mul_X_pow_eq_monomial, aroots_C_mul_X_pow ha]

/-- The set of distinct roots of `p` in `S`.

If you have a non-separable polynomial, use `Polynomial.aroots` for the multiset
where multiple roots have the appropriate multiplicity. -/
def rootSet (p : T[X]) (S) [CommRing S] [IsDomain S] [Algebra T S] : Set S :=
haveI := Classical.decEq S
(p.map (algebraMap T S)).roots.toFinset
(p.aroots S).toFinset
#align polynomial.root_set Polynomial.rootSet

theorem rootSet_def (p : T[X]) (S) [CommRing S] [IsDomain S] [Algebra T S] [DecidableEq S] :
p.rootSet S = (p.map (algebraMap T S)).roots.toFinset := by
p.rootSet S = (p.aroots S).toFinset := by
rw [rootSet]
convert rfl
#align polynomial.root_set_def Polynomial.rootSet_def

@[simp]
theorem rootSet_C [CommRing S] [IsDomain S] [Algebra T S] (a : T) : (C a).rootSet S = ∅ := by
classical
rw [rootSet_def, map_C, roots_C, Multiset.toFinset_zero, Finset.coe_empty]
rw [rootSet_def, aroots_C, Multiset.toFinset_zero, Finset.coe_empty]
set_option linter.uppercaseLean3 false in
#align polynomial.root_set_C Polynomial.rootSet_C

Expand Down Expand Up @@ -970,14 +1053,12 @@ theorem bUnion_roots_finite {R S : Type*} [Semiring R] [CommRing S] [IsDomain S]
theorem mem_rootSet' {p : T[X]} {S : Type*} [CommRing S] [IsDomain S] [Algebra T S] {a : S} :
a ∈ p.rootSet S ↔ p.map (algebraMap T S) ≠ 0 ∧ aeval a p = 0 := by
classical
rw [rootSet_def, Finset.mem_coe, mem_toFinset, mem_roots', IsRoot.def, ← eval₂_eq_eval_map,
aeval_def]
rw [rootSet_def, Finset.mem_coe, mem_toFinset, mem_aroots']
#align polynomial.mem_root_set' Polynomial.mem_rootSet'

theorem mem_rootSet {p : T[X]} {S : Type*} [CommRing S] [IsDomain S] [Algebra T S]
[NoZeroSMulDivisors T S] {a : S} : a ∈ p.rootSet S ↔ p ≠ 0 ∧ aeval a p = 0 := by
rw [mem_rootSet',
(map_injective _ (NoZeroSMulDivisors.algebraMap_injective T S)).ne_iff' (Polynomial.map_zero _)]
rw [mem_rootSet', Polynomial.map_ne_zero_iff (NoZeroSMulDivisors.algebraMap_injective T S)]
#align polynomial.mem_root_set Polynomial.mem_rootSet

theorem mem_rootSet_of_ne {p : T[X]} {S : Type*} [CommRing S] [IsDomain S] [Algebra T S]
Expand Down
4 changes: 2 additions & 2 deletions Mathlib/Data/Polynomial/Splits.lean
Expand Up @@ -446,9 +446,9 @@ theorem splits_iff_card_roots {p : K[X]} :
#align polynomial.splits_iff_card_roots Polynomial.splits_iff_card_roots

theorem aeval_root_derivative_of_splits [Algebra K L] {P : K[X]} (hmo : P.Monic)
(hP : P.Splits (algebraMap K L)) {r : L} (hr : r ∈ (P.map (algebraMap K L)).roots) :
(hP : P.Splits (algebraMap K L)) {r : L} (hr : r ∈ P.aroots L) :
aeval r (Polynomial.derivative P) =
(((P.map <| algebraMap K L).roots.erase r).map fun a => r - a).prod := by
(((P.aroots L).erase r).map fun a => r - a).prod := by
replace hmo := hmo.map (algebraMap K L)
replace hP := (splits_id_iff_splits (algebraMap K L)).2 hP
rw [aeval_def, ← eval_map, ← derivative_map]
Expand Down
13 changes: 7 additions & 6 deletions Mathlib/FieldTheory/Adjoin.lean
Expand Up @@ -896,7 +896,7 @@ end PowerBasis
/-- Algebra homomorphism `F⟮α⟯ →ₐ[F] K` are in bijection with the set of roots
of `minpoly α` in `K`. -/
noncomputable def algHomAdjoinIntegralEquiv (h : IsIntegral F α) :
(F⟮α⟯ →ₐ[F] K) ≃ { x // x ∈ ((minpoly F α).map (algebraMap F K)).roots } :=
(F⟮α⟯ →ₐ[F] K) ≃ { x // x ∈ (minpoly F α).aroots K } :=
(adjoin.powerBasis h).liftEquiv'.trans
((Equiv.refl _).subtypeEquiv fun x => by
rw [adjoin.powerBasis_gen, minpoly_gen h, Equiv.refl_apply])
Expand Down Expand Up @@ -1099,15 +1099,16 @@ noncomputable def Lifts.liftOfSplits (x : Lifts F E K) {s : E} (h1 : IsIntegral
splits_of_splits_of_dvd _ (map_ne_zero (minpoly.ne_zero h1))
((splits_map_iff _ _).mpr (by convert h2; exact RingHom.ext fun y => x.2.commutes y))
(minpoly.dvd_map_of_isScalarTower _ _ _)
let alg : Algebra {y // y ∈ x.fst} {y // y ∈ restrictScalars F {z // z ∈ x.fst}⟮s⟯} :=
letI : Algebra {y // y ∈ x.fst} {y // y ∈ restrictScalars F {z // z ∈ x.fst}⟮s⟯} :=
{z // z ∈ x.fst}⟮s⟯.toSubalgebra.algebra
letI := x.2.toRingHom.toAlgebra
⟨x.1⟮s⟯.restrictScalars F,
(@algHomEquivSigma F x.1 (x.1⟮s⟯.restrictScalars F) K _ _ _ _ _ _ _
(IntermediateField.algebra x.1⟮s⟯) (IsScalarTower.of_algebraMap_eq fun _ => rfl)).invFun
⟨x.2,
(@algHomAdjoinIntegralEquiv x.1 _ E _ _ s K _ x.2.toRingHom.toAlgebra h3).invFun
(@algHomAdjoinIntegralEquiv x.1 _ E _ _ s K _ _ h3).invFun
⟨rootOfSplits x.2.toRingHom key (ne_of_gt (minpoly.degree_pos h3)), by
rw [mem_roots (map_ne_zero (minpoly.ne_zero h3)), IsRoot, ← eval₂_eq_eval_map]
rw [mem_aroots, and_iff_right (minpoly.ne_zero h3)]
exact map_rootOfSplits x.2.toRingHom key (ne_of_gt (minpoly.degree_pos h3))⟩⟩⟩
#align intermediate_field.lifts.lift_of_splits IntermediateField.Lifts.liftOfSplits

Expand All @@ -1128,8 +1129,8 @@ theorem Lifts.le_lifts_of_splits (x : Lifts F E K) {s : E} (h1 : IsIntegral F s)
(minpoly.dvd_map_of_isScalarTower _ _ _)
have I2 := (ne_of_gt (minpoly.degree_pos I1))
have I3 : rootOfSplits (AlgHom.toRingHom x.2) key (ne_of_gt (minpoly.degree_pos I1)) ∈
(Polynomial.map (algebraMap x.1 K) (minpoly x.1 s)).roots := by
rw [mem_roots (map_ne_zero (minpoly.ne_zero I1)), IsRoot, ← eval₂_eq_eval_map]
(minpoly x.1 s).aroots K := by
rw [mem_aroots, and_iff_right (minpoly.ne_zero I1)]
exact map_rootOfSplits x.2.toRingHom key (ne_of_gt (minpoly.degree_pos I1))
let φ : x.1⟮s⟯ →ₐ[x.1] K := ((algHomAdjoinIntegralEquiv x.1 I1).invFun
⟨rootOfSplits (AlgHom.toRingHom x.2) key I2, I3⟩)
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/FieldTheory/Finite/GaloisField.lean
Expand Up @@ -48,7 +48,7 @@ instance FiniteField.isSplittingField_sub (K F : Type*) [Field K] [Fintype K]
adjoin_rootSet' := by
classical
trans Algebra.adjoin F ((roots (X ^ Fintype.card K - X : K[X])).toFinset : Set K)
· simp only [rootSet, Polynomial.map_pow, map_X, Polynomial.map_sub]
· simp only [rootSet, aroots, Polynomial.map_pow, map_X, Polynomial.map_sub]
· rw [FiniteField.roots_X_pow_card_sub_X, val_toFinset, coe_univ, Algebra.adjoin_univ]
#align finite_field.has_sub.sub.polynomial.is_splitting_field FiniteField.isSplittingField_sub

Expand Down
12 changes: 6 additions & 6 deletions Mathlib/FieldTheory/Galois.lean
Expand Up @@ -358,15 +358,15 @@ variable {p : F[X]}

theorem of_separable_splitting_field_aux [hFE : FiniteDimensional F E] [sp : p.IsSplittingField F E]
(hp : p.Separable) (K : Type*) [Field K] [Algebra F K] [Algebra K E] [IsScalarTower F K E]
{x : E} (hx : x ∈ (p.map (algebraMap F E)).roots)
{x : E} (hx : x ∈ p.aroots E)
-- these are both implied by `hFE`, but as they carry data this makes the lemma more general
[Fintype (K →ₐ[F] E)]
[Fintype (K⟮x⟯.restrictScalars F →ₐ[F] E)] :
Fintype.card (K⟮x⟯.restrictScalars F →ₐ[F] E) = Fintype.card (K →ₐ[F] E) * finrank K K⟮x⟯ := by
have h : IsIntegral K x :=
isIntegral_of_isScalarTower (isIntegral_of_noetherian (IsNoetherian.iff_fg.2 hFE) x)
have h1 : p ≠ 0 := fun hp => by
rw [hp, Polynomial.map_zero, Polynomial.roots_zero] at hx
rw [hp, Polynomial.aroots_zero] at hx
exact Multiset.not_mem_zero x hx
have h2 : minpoly K x ∣ p.map (algebraMap F K) := by
apply minpoly.dvd
Expand Down Expand Up @@ -396,19 +396,19 @@ theorem of_separable_splitting_field [sp : p.IsSplittingField F E] (hp : p.Separ
IsGalois F E := by
haveI hFE : FiniteDimensional F E := Polynomial.IsSplittingField.finiteDimensional E p
letI := Classical.decEq E
let s := (p.map (algebraMap F E)).roots.toFinset
have adjoin_root : IntermediateField.adjoin F (s : Set E) = ⊤ := by
let s := p.rootSet E
have adjoin_root : IntermediateField.adjoin F s = ⊤ := by
apply IntermediateField.toSubalgebra_injective
rw [IntermediateField.top_toSubalgebra, ← top_le_iff, ← sp.adjoin_rootSet]
apply IntermediateField.algebra_adjoin_le_adjoin
let P : IntermediateField F E → Prop := fun K => Fintype.card (K →ₐ[F] E) = finrank F K
suffices P (IntermediateField.adjoin F s) by
suffices P (IntermediateField.adjoin F s) by
rw [adjoin_root] at this
apply of_card_aut_eq_finrank
rw [← Eq.trans this (LinearEquiv.finrank_eq IntermediateField.topEquiv.toLinearEquiv)]
exact Fintype.card_congr ((algEquivEquivAlgHom F E).toEquiv.trans
(IntermediateField.topEquiv.symm.arrowCongr AlgEquiv.refl))
apply IntermediateField.induction_on_adjoin_finset s P
apply IntermediateField.induction_on_adjoin_finset _ P
· have key := IntermediateField.card_algHom_adjoin_integral F (K := E)
(show IsIntegral F (0 : E) from isIntegral_zero)
rw [minpoly.zero, Polynomial.natDegree_X] at key
Expand Down
8 changes: 4 additions & 4 deletions Mathlib/FieldTheory/IsAlgClosed/Classification.lean
Expand Up @@ -40,8 +40,8 @@ variable (R L : Type u) [CommRing R] [CommRing L] [IsDomain L] [Algebra R L]
variable [NoZeroSMulDivisors R L] (halg : Algebra.IsAlgebraic R L)

theorem cardinal_mk_le_sigma_polynomial :
#L ≤ #(Σ p : R[X], { x : L // x ∈ (p.map (algebraMap R L)).roots }) :=
@mk_le_of_injective L (Σ p : R[X], {x : L | x ∈ (p.map (algebraMap R L)).roots})
#L ≤ #(Σ p : R[X], { x : L // x ∈ p.aroots L }) :=
@mk_le_of_injective L (Σ p : R[X], {x : L | x ∈ p.aroots L})
(fun x : L =>
let p := Classical.indefiniteDescription _ (halg x)
⟨p.1, x, by
Expand All @@ -64,9 +64,9 @@ theorem cardinal_mk_le_sigma_polynomial :
of the base ring or `ℵ₀` -/
theorem cardinal_mk_le_max : #L ≤ max #R ℵ₀ :=
calc
#L ≤ #(Σ p : R[X], { x : L // x ∈ (p.map (algebraMap R L)).roots }) :=
#L ≤ #(Σ p : R[X], { x : L // x ∈ p.aroots L }) :=
cardinal_mk_le_sigma_polynomial R L halg
_ = Cardinal.sum fun p : R[X] => #{x : L | x ∈ (p.map (algebraMap R L)).roots} := by
_ = Cardinal.sum fun p : R[X] => #{x : L | x ∈ p.aroots L} := by
rw [← mk_sigma]; rfl
_ ≤ Cardinal.sum.{u, u} fun _ : R[X] => ℵ₀ :=
(sum_le_sum _ _ fun p => (Multiset.finite_toSet _).lt_aleph0.le)
Expand Down
4 changes: 2 additions & 2 deletions Mathlib/FieldTheory/Minpoly/Field.lean
Expand Up @@ -176,7 +176,7 @@ variable (F E K : Type*) [Field F] [Ring E] [CommRing K] [IsDomain K] [Algebra F
/-- Function from Hom_K(E,L) to pi type Π (x : basis), roots of min poly of x -/
def rootsOfMinPolyPiType (φ : E →ₐ[F] K)
(x : range (FiniteDimensional.finBasis F E : _ → E)) :
{ l : K // l ∈ (((minpoly F x.1).map (algebraMap F K)).roots : Multiset K) } :=
{ l : K // l ∈ (minpoly F x.1).aroots K } :=
⟨φ x, by
rw [mem_roots_map (minpoly.ne_zero_of_finite F x.val),
← aeval_def, aeval_algHom_apply, minpoly.aeval, map_zero]⟩
Expand All @@ -195,7 +195,7 @@ theorem aux_inj_roots_of_min_poly : Injective (rootsOfMinPolyPiType F E K) := by
noncomputable instance AlgHom.fintype : Fintype (E →ₐ[F] K) :=
@Fintype.ofInjective _ _
(Fintype.subtypeProd (finite_range (FiniteDimensional.finBasis F E)) fun e =>
((minpoly F e).map (algebraMap F K)).roots)
(minpoly F e).aroots K)
_ (aux_inj_roots_of_min_poly F E K)
#align minpoly.alg_hom.fintype minpoly.AlgHom.fintype

Expand Down
7 changes: 3 additions & 4 deletions Mathlib/FieldTheory/Normal.lean
Expand Up @@ -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⟩
Expand All @@ -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]
Expand All @@ -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
Expand Down
3 changes: 1 addition & 2 deletions Mathlib/FieldTheory/PolynomialGaloisGroup.lean
Expand Up @@ -289,7 +289,7 @@ theorem restrictProd_injective : Function.Injective (restrictProd p q) := by
simp only [restrictProd, restrictDvd_def] at hfg
simp only [dif_neg hpq, MonoidHom.prod_apply, Prod.mk.inj_iff] at hfg
ext (x hx)
rw [rootSet_def, Polynomial.map_mul, Polynomial.roots_mul] at hx
rw [rootSet_def, aroots_mul hpq] at hx
cases' Multiset.mem_add.mp (Multiset.mem_toFinset.mp hx) with h h
· haveI : Fact (p.Splits (algebraMap F (p * q).SplittingField)) :=
⟨splits_of_splits_of_dvd _ hpq (SplittingField.splits (p * q)) (dvd_mul_right p q)⟩
Expand All @@ -311,7 +311,6 @@ theorem restrictProd_injective : Function.Injective (restrictProd p q) := by
Subtype.ext_iff.mp (Equiv.apply_symm_apply (rootsEquivRoots q _) ⟨x, _⟩).symm
rw [key, ← AlgEquiv.restrictNormal_commutes, ← AlgEquiv.restrictNormal_commutes]
exact congr_arg _ (AlgEquiv.ext_iff.mp hfg.2 _)
· rwa [Ne.def, mul_eq_zero, map_eq_zero, map_eq_zero, ← mul_eq_zero]
#align polynomial.gal.restrict_prod_injective Polynomial.Gal.restrictProd_injective

theorem mul_splits_in_splittingField_of_mul {p₁ q₁ p₂ q₂ : F[X]} (hq₁ : q₁ ≠ 0) (hq₂ : q₂ ≠ 0)
Expand Down
3 changes: 1 addition & 2 deletions Mathlib/FieldTheory/Separable.lean
Expand Up @@ -575,9 +575,8 @@ variable [Algebra K S] [Algebra K L]
theorem AlgHom.card_of_powerBasis (pb : PowerBasis K S) (h_sep : (minpoly K pb.gen).Separable)
(h_splits : (minpoly K pb.gen).Splits (algebraMap K L)) :
@Fintype.card (S →ₐ[K] L) (PowerBasis.AlgHom.fintype pb) = pb.dim := by
let s := ((minpoly K pb.gen).map (algebraMap K L)).roots.toFinset
let _ := (PowerBasis.AlgHom.fintype pb : Fintype (S →ₐ[K] L))
rw [Fintype.card_congr pb.liftEquiv', Fintype.card_of_subtype s (fun x => Multiset.mem_toFinset),
rw [Fintype.card_congr pb.liftEquiv', Fintype.card_of_subtype _ (fun x => Multiset.mem_toFinset),
← pb.natDegree_minpoly, natDegree_eq_card_roots h_splits, Multiset.toFinset_card_of_nodup]
exact nodup_roots ((separable_map (algebraMap K L)).mpr h_sep)
#align alg_hom.card_of_power_basis AlgHom.card_of_powerBasis
Expand Down