l3lab/ntp-mathlib huggingface dataset:
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  rw [← hd, add_right_eq_self]
  by_contra h
  have h' : (map (RingHom.id L) q).natDegree ≠ 0 := by simp [h]
  have := roots_ne_zero_of_splits' (RingHom.id L) (splits_of_splits_mul' _ ?_ hsplit).2 h'
  · 

Proof state:
case neg.intro.intro.intro.refine_2
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
h : ¬natDegree q = 0
h' : natDegree (map (RingHom.id L) q) ≠ 0
this : roots (map (RingHom.id L) q) ≠ 0
⊢ False

Next tactic:
rw [map_id] at this
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  rw [← hd, add_right_eq_self]
  by_contra h
  have h' : (map (RingHom.id L) q).natDegree ≠ 0 := by simp [h]
  have := roots_ne_zero_of_splits' (RingHom.id L) (splits_of_splits_mul' _ ?_ hsplit).2 h'
  · rw [map_id] at this
    

Proof state:
case neg.intro.intro.intro.refine_2
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
h : ¬natDegree q = 0
h' : natDegree (map (RingHom.id L) q) ≠ 0
this : roots q ≠ 0
⊢ False

Next tactic:
exact this hr
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  rw [← hd, add_right_eq_self]
  by_contra h
  have h' : (map (RingHom.id L) q).natDegree ≠ 0 := by simp [h]
  have := roots_ne_zero_of_splits' (RingHom.id L) (splits_of_splits_mul' _ ?_ hsplit).2 h'
  · rw [map_id] at this
    exact this hr
  · 

Proof state:
case neg.intro.intro.intro.refine_1
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
h : ¬natDegree q = 0
h' : natDegree (map (RingHom.id L) q) ≠ 0
⊢ map (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q) ≠ 0

Next tactic:
rw [map_id]
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  rw [← hd, add_right_eq_self]
  by_contra h
  have h' : (map (RingHom.id L) q).natDegree ≠ 0 := by simp [h]
  have := roots_ne_zero_of_splits' (RingHom.id L) (splits_of_splits_mul' _ ?_ hsplit).2 h'
  · rw [map_id] at this
    exact this hr
  · rw [map_id]
    

Proof state:
case neg.intro.intro.intro.refine_1
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
h : ¬natDegree q = 0
h' : natDegree (map (RingHom.id L) q) ≠ 0
⊢ Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q ≠ 0

Next tactic:
exact mul_ne_zero monic_prod_multiset_X_sub_C.ne_zero hq
theorem degree_eq_card_roots' {p : K[X]} {i : K →+* L} (p_ne_zero : p.map i ≠ 0)
    (hsplit : Splits i p) : (p.map i).degree = Multiset.card (p.map i).roots := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
p_ne_zero : map i p ≠ 0
hsplit : Splits i p
⊢ degree (map i p) = ↑(Multiset.card (roots (map i p)))

Next tactic:
simp [degree_eq_natDegree p_ne_zero, natDegree_eq_card_roots' hsplit]
/-- This lemma is for polynomials over a field. -/
theorem splits_iff (f : K[X]) :
    Splits i f ↔ f = 0 ∨ ∀ {g : L[X]}, Irreducible g → g ∣ f.map i → degree g = 1 := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
⊢ Splits i f ↔ f = 0 ∨ ∀ {g : L[X]}, Irreducible g → g ∣ map i f → degree g = 1

Next tactic:
rw [Splits, map_eq_zero]
theorem splits_of_splits_of_dvd {f g : K[X]} (hf0 : f ≠ 0) (hf : Splits i f) (hgf : g ∣ f) :
    Splits i g := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g : K[X]
hf0 : f ≠ 0
hf : Splits i f
hgf : g ∣ f
⊢ Splits i g

Next tactic:
obtain ⟨f, rfl⟩ := hgf
theorem splits_of_splits_of_dvd {f g : K[X]} (hf0 : f ≠ 0) (hf : Splits i f) (hgf : g ∣ f) :
    Splits i g := by
  obtain ⟨f, rfl⟩ := hgf
  

Proof state:
case intro
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
g f : K[X]
hf0 : g * f ≠ 0
hf : Splits i (g * f)
⊢ Splits i g

Next tactic:
exact (splits_of_splits_mul i hf0 hf).1
theorem splits_prod_iff {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, s j ≠ 0) → ((∏ x in t, s x).Splits i ↔ ∀ j ∈ t, (s j).Splits i) := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t : Finset ι
⊢ (∀ j ∈ t, s j ≠ 0) → (Splits i (∏ x in t, s x) ↔ ∀ j ∈ t, Splits i (s j))

Next tactic:
classical
  refine'
    Finset.induction_on t (fun _ =>
        ⟨fun _ _ h => by simp only [Finset.not_mem_empty] at h, fun _ => splits_one i⟩)
      fun a t hat ih ht => _
  rw [Finset.forall_mem_insert] at ht ⊢
  rw [Finset.prod_insert hat, splits_mul_iff i ht.1 (Finset.prod_ne_zero_iff.2 ht.2), ih ht.2]
theorem splits_prod_iff {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, s j ≠ 0) → ((∏ x in t, s x).Splits i ↔ ∀ j ∈ t, (s j).Splits i) := by
  classical
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t : Finset ι
⊢ (∀ j ∈ t, s j ≠ 0) → (Splits i (∏ x in t, s x) ↔ ∀ j ∈ t, Splits i (s j))

Next tactic:
refine'
    Finset.induction_on t (fun _ =>
        ⟨fun _ _ h => by simp only [Finset.not_mem_empty] at h, fun _ => splits_one i⟩)
      fun a t hat ih ht => _
theorem splits_prod_iff {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, s j ≠ 0) → ((∏ x in t, s x).Splits i ↔ ∀ j ∈ t, (s j).Splits i) := by
  classical
  refine'
    Finset.induction_on t (fun _ =>
        ⟨fun _ _ h => by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t : Finset ι
x✝² : ∀ j ∈ ∅, s j ≠ 0
x✝¹ : Splits i (∏ x in ∅, s x)
x✝ : ι
h : x✝ ∈ ∅
⊢ Splits i (s x✝)

Next tactic:
simp only [Finset.not_mem_empty] at h
theorem splits_prod_iff {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, s j ≠ 0) → ((∏ x in t, s x).Splits i ↔ ∀ j ∈ t, (s j).Splits i) := by
  classical
  refine'
    Finset.induction_on t (fun _ =>
        ⟨fun _ _ h => by simp only [Finset.not_mem_empty] at h, fun _ => splits_one i⟩)
      fun a t hat ih ht => _
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t✝ : Finset ι
a : ι
t : Finset ι
hat : a ∉ t
ih : (∀ j ∈ t, s j ≠ 0) → (Splits i (∏ x in t, s x) ↔ ∀ j ∈ t, Splits i (s j))
ht : ∀ j ∈ insert a t, s j ≠ 0
⊢ Splits i (∏ x in insert a t, s x) ↔ ∀ j ∈ insert a t, Splits i (s j)

Next tactic:
rw [Finset.forall_mem_insert] at ht ⊢
theorem splits_prod_iff {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, s j ≠ 0) → ((∏ x in t, s x).Splits i ↔ ∀ j ∈ t, (s j).Splits i) := by
  classical
  refine'
    Finset.induction_on t (fun _ =>
        ⟨fun _ _ h => by simp only [Finset.not_mem_empty] at h, fun _ => splits_one i⟩)
      fun a t hat ih ht => _
  rw [Finset.forall_mem_insert] at ht ⊢
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t✝ : Finset ι
a : ι
t : Finset ι
hat : a ∉ t
ih : (∀ j ∈ t, s j ≠ 0) → (Splits i (∏ x in t, s x) ↔ ∀ j ∈ t, Splits i (s j))
ht : s a ≠ 0 ∧ ∀ x ∈ t, s x ≠ 0
⊢ Splits i (∏ x in insert a t, s x) ↔ Splits i (s a) ∧ ∀ x ∈ t, Splits i (s x)

Next tactic:
rw [Finset.prod_insert hat, splits_mul_iff i ht.1 (Finset.prod_ne_zero_iff.2 ht.2), ih ht.2]
theorem degree_eq_one_of_irreducible_of_splits {p : K[X]} (hp : Irreducible p)
    (hp_splits : Splits (RingHom.id K) p) : p.degree = 1 := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
p : K[X]
hp : Irreducible p
hp_splits : Splits (RingHom.id K) p
⊢ degree p = 1

Next tactic:
rcases hp_splits with ⟨⟩ | hp_splits
theorem degree_eq_one_of_irreducible_of_splits {p : K[X]} (hp : Irreducible p)
    (hp_splits : Splits (RingHom.id K) p) : p.degree = 1 := by
  rcases hp_splits with ⟨⟩ | hp_splits
  · 

Proof state:
case inl
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
p : K[X]
hp : Irreducible p
h✝ : map (RingHom.id K) p = 0
⊢ degree p = 1

Next tactic:
exfalso
theorem degree_eq_one_of_irreducible_of_splits {p : K[X]} (hp : Irreducible p)
    (hp_splits : Splits (RingHom.id K) p) : p.degree = 1 := by
  rcases hp_splits with ⟨⟩ | hp_splits
  · exfalso
    

Proof state:
case inl.h
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
p : K[X]
hp : Irreducible p
h✝ : map (RingHom.id K) p = 0
⊢ False

Next tactic:
simp_all
theorem degree_eq_one_of_irreducible_of_splits {p : K[X]} (hp : Irreducible p)
    (hp_splits : Splits (RingHom.id K) p) : p.degree = 1 := by
  rcases hp_splits with ⟨⟩ | hp_splits
  · exfalso
    simp_all
  · 

Proof state:
case inr
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
p : K[X]
hp : Irreducible p
hp_splits : ∀ {g : K[X]}, Irreducible g → g ∣ map (RingHom.id K) p → degree g = 1
⊢ degree p = 1

Next tactic:
apply hp_splits hp
theorem degree_eq_one_of_irreducible_of_splits {p : K[X]} (hp : Irreducible p)
    (hp_splits : Splits (RingHom.id K) p) : p.degree = 1 := by
  rcases hp_splits with ⟨⟩ | hp_splits
  · exfalso
    simp_all
  · apply hp_splits hp
    

Proof state:
case inr
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
p : K[X]
hp : Irreducible p
hp_splits : ∀ {g : K[X]}, Irreducible g → g ∣ map (RingHom.id K) p → degree g = 1
⊢ p ∣ map (RingHom.id K) p

Next tactic:
simp
theorem degree_eq_card_roots {p : K[X]} {i : K →+* L} (p_ne_zero : p ≠ 0) (hsplit : Splits i p) :
    p.degree = Multiset.card (p.map i).roots := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
p_ne_zero : p ≠ 0
hsplit : Splits i p
⊢ degree p = ↑(Multiset.card (roots (map i p)))

Next tactic:
rw [degree_eq_natDegree p_ne_zero, natDegree_eq_card_roots hsplit]
theorem roots_map {f : K[X]} (hf : f.Splits <| RingHom.id K) : (f.map i).roots = f.roots.map i :=
  (roots_map_of_injective_of_card_eq_natDegree i.injective <| by
      

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hf : Splits (RingHom.id K) f
⊢ Multiset.card (roots f) = natDegree f

Next tactic:
convert (natDegree_eq_card_roots hf).symm
theorem roots_map {f : K[X]} (hf : f.Splits <| RingHom.id K) : (f.map i).roots = f.roots.map i :=
  (roots_map_of_injective_of_card_eq_natDegree i.injective <| by
      convert (natDegree_eq_card_roots hf).symm
      

Proof state:
case h.e'_2.h.e'_6.h.e'_4
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hf : Splits (RingHom.id K) f
⊢ f = map (RingHom.id K) f

Next tactic:
rw [map_id]
theorem image_rootSet [Algebra R K] [Algebra R L] {p : R[X]} (h : p.Splits (algebraMap R K))
    (f : K →ₐ[R] L) : f '' p.rootSet K = p.rootSet L := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
p : R[X]
h : Splits (algebraMap R K) p
f : K →ₐ[R] L
⊢ ⇑f '' rootSet p K = rootSet p L

Next tactic:
classical
    rw [rootSet, ← Finset.coe_image, ← Multiset.toFinset_map, ← f.coe_toRingHom,
      ← roots_map _ ((splits_id_iff_splits (algebraMap R K)).mpr h), map_map, f.comp_algebraMap,
      ← rootSet]
theorem image_rootSet [Algebra R K] [Algebra R L] {p : R[X]} (h : p.Splits (algebraMap R K))
    (f : K →ₐ[R] L) : f '' p.rootSet K = p.rootSet L := by
  classical
    

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
p : R[X]
h : Splits (algebraMap R K) p
f : K →ₐ[R] L
⊢ ⇑f '' rootSet p K = rootSet p L

Next tactic:
rw [rootSet, ← Finset.coe_image, ← Multiset.toFinset_map, ← f.coe_toRingHom,
      ← roots_map _ ((splits_id_iff_splits (algebraMap R K)).mpr h), map_map, f.comp_algebraMap,
      ← rootSet]
theorem adjoin_rootSet_eq_range [Algebra R K] [Algebra R L] {p : R[X]}
    (h : p.Splits (algebraMap R K)) (f : K →ₐ[R] L) :
    Algebra.adjoin R (p.rootSet L) = f.range ↔ Algebra.adjoin R (p.rootSet K) = ⊤ := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
p : R[X]
h : Splits (algebraMap R K) p
f : K →ₐ[R] L
⊢ Algebra.adjoin R (rootSet p L) = AlgHom.range f ↔ Algebra.adjoin R (rootSet p K) = ⊤

Next tactic:
rw [← image_rootSet h f, Algebra.adjoin_image, ← Algebra.map_top]
theorem adjoin_rootSet_eq_range [Algebra R K] [Algebra R L] {p : R[X]}
    (h : p.Splits (algebraMap R K)) (f : K →ₐ[R] L) :
    Algebra.adjoin R (p.rootSet L) = f.range ↔ Algebra.adjoin R (p.rootSet K) = ⊤ := by
  rw [← image_rootSet h f, Algebra.adjoin_image, ← Algebra.map_top]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
p : R[X]
h : Splits (algebraMap R K) p
f : K →ₐ[R] L
⊢ Subalgebra.map f (Algebra.adjoin R (rootSet p K)) = Subalgebra.map f ⊤ ↔ Algebra.adjoin R (rootSet p K) = ⊤

Next tactic:
exact (Subalgebra.map_injective f.toRingHom.injective).eq_iff
theorem eq_prod_roots_of_splits {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    p.map i = C (i p.leadingCoeff) * ((p.map i).roots.map fun a => X - C a).prod := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
⊢ map i p = C (i (leadingCoeff p)) * Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p)))

Next tactic:
rw [← leadingCoeff_map]
theorem eq_prod_roots_of_splits {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    p.map i = C (i p.leadingCoeff) * ((p.map i).roots.map fun a => X - C a).prod := by
  rw [← leadingCoeff_map]; 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
⊢ map i p = C (leadingCoeff (map i p)) * Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p)))

Next tactic:
symm
theorem eq_prod_roots_of_splits {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    p.map i = C (i p.leadingCoeff) * ((p.map i).roots.map fun a => X - C a).prod := by
  rw [← leadingCoeff_map]; symm
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
⊢ C (leadingCoeff (map i p)) * Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) = map i p

Next tactic:
apply C_leadingCoeff_mul_prod_multiset_X_sub_C
theorem eq_prod_roots_of_splits {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    p.map i = C (i p.leadingCoeff) * ((p.map i).roots.map fun a => X - C a).prod := by
  rw [← leadingCoeff_map]; symm
  apply C_leadingCoeff_mul_prod_multiset_X_sub_C
  

Proof state:
case hroots
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
⊢ Multiset.card (roots (map i p)) = natDegree (map i p)

Next tactic:
rw [natDegree_map]
theorem eq_prod_roots_of_splits {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    p.map i = C (i p.leadingCoeff) * ((p.map i).roots.map fun a => X - C a).prod := by
  rw [← leadingCoeff_map]; symm
  apply C_leadingCoeff_mul_prod_multiset_X_sub_C
  rw [natDegree_map]; 

Proof state:
case hroots
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
⊢ Multiset.card (roots (map i p)) = natDegree p

Next tactic:
exact (natDegree_eq_card_roots hsplit).symm
theorem eq_prod_roots_of_splits_id {p : K[X]} (hsplit : Splits (RingHom.id K) p) :
    p = C p.leadingCoeff * (p.roots.map fun a => X - C a).prod := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
p : K[X]
hsplit : Splits (RingHom.id K) p
⊢ p = C (leadingCoeff p) * Multiset.prod (Multiset.map (fun a => X - C a) (roots p))

Next tactic:
simpa using eq_prod_roots_of_splits hsplit
theorem eq_prod_roots_of_monic_of_splits_id {p : K[X]} (m : Monic p)
    (hsplit : Splits (RingHom.id K) p) : p = (p.roots.map fun a => X - C a).prod := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
p : K[X]
m : Monic p
hsplit : Splits (RingHom.id K) p
⊢ p = Multiset.prod (Multiset.map (fun a => X - C a) (roots p))

Next tactic:
convert eq_prod_roots_of_splits_id hsplit
theorem eq_prod_roots_of_monic_of_splits_id {p : K[X]} (m : Monic p)
    (hsplit : Splits (RingHom.id K) p) : p = (p.roots.map fun a => X - C a).prod := by
  convert eq_prod_roots_of_splits_id hsplit
  

Proof state:
case h.e'_3
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
p : K[X]
m : Monic p
hsplit : Splits (RingHom.id K) p
⊢ Multiset.prod (Multiset.map (fun a => X - C a) (roots p)) =
    C (leadingCoeff p) * Multiset.prod (Multiset.map (fun a => X - C a) (roots p))

Next tactic:
simp [m]
theorem eq_X_sub_C_of_splits_of_single_root {x : K} {h : K[X]} (h_splits : Splits i h)
    (h_roots : (h.map i).roots = {i x}) : h = C h.leadingCoeff * (X - C x) := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
x : K
h : K[X]
h_splits : Splits i h
h_roots : roots (map i h) = {i x}
⊢ h = C (leadingCoeff h) * (X - C x)

Next tactic:
apply Polynomial.map_injective _ i.injective
theorem eq_X_sub_C_of_splits_of_single_root {x : K} {h : K[X]} (h_splits : Splits i h)
    (h_roots : (h.map i).roots = {i x}) : h = C h.leadingCoeff * (X - C x) := by
  apply Polynomial.map_injective _ i.injective
  

Proof state:
case a
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
x : K
h : K[X]
h_splits : Splits i h
h_roots : roots (map i h) = {i x}
⊢ map i h = map i (C (leadingCoeff h) * (X - C x))

Next tactic:
rw [eq_prod_roots_of_splits h_splits, h_roots]
theorem eq_X_sub_C_of_splits_of_single_root {x : K} {h : K[X]} (h_splits : Splits i h)
    (h_roots : (h.map i).roots = {i x}) : h = C h.leadingCoeff * (X - C x) := by
  apply Polynomial.map_injective _ i.injective
  rw [eq_prod_roots_of_splits h_splits, h_roots]
  

Proof state:
case a
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝³ : CommRing R
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
x : K
h : K[X]
h_splits : Splits i h
h_roots : roots (map i h) = {i x}
⊢ C (i (leadingCoeff h)) * Multiset.prod (Multiset.map (fun a => X - C a) {i x}) =
    map i (C (leadingCoeff h) * (X - C x))

Next tactic:
simp
variable (R) in
theorem mem_lift_of_splits_of_roots_mem_range [Algebra R K] {f : K[X]}
    (hs : f.Splits (RingHom.id K)) (hm : f.Monic) (hr : ∀ a ∈ f.roots, a ∈ (algebraMap R K).range) :
    f ∈ Polynomial.lifts (algebraMap R K) := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁴ : CommRing R
inst✝³ : Field K
inst✝² : Field L
inst✝¹ : Field F
i : K →+* L
inst✝ : Algebra R K
f : K[X]
hs : Splits (RingHom.id K) f
hm : Monic f
hr : ∀ a ∈ roots f, a ∈ RingHom.range (algebraMap R K)
⊢ f ∈ lifts (algebraMap R K)

Next tactic:
rw [eq_prod_roots_of_monic_of_splits_id hm hs, lifts_iff_liftsRing]
variable (R) in
theorem mem_lift_of_splits_of_roots_mem_range [Algebra R K] {f : K[X]}
    (hs : f.Splits (RingHom.id K)) (hm : f.Monic) (hr : ∀ a ∈ f.roots, a ∈ (algebraMap R K).range) :
    f ∈ Polynomial.lifts (algebraMap R K) := by
  rw [eq_prod_roots_of_monic_of_splits_id hm hs, lifts_iff_liftsRing]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁴ : CommRing R
inst✝³ : Field K
inst✝² : Field L
inst✝¹ : Field F
i : K →+* L
inst✝ : Algebra R K
f : K[X]
hs : Splits (RingHom.id K) f
hm : Monic f
hr : ∀ a ∈ roots f, a ∈ RingHom.range (algebraMap R K)
⊢ Multiset.prod (Multiset.map (fun a => X - C a) (roots f)) ∈ liftsRing (algebraMap R K)

Next tactic:
refine' Subring.multiset_prod_mem _ _ fun P hP => _