l3lab/ntp-mathlib huggingface dataset:
theorem Monic.not_irreducible_iff_exists_add_mul_eq_coeff (hm : p.Monic) (hnd : p.natDegree = 2) :
    ¬Irreducible p ↔ ∃ c₁ c₂, p.coeff 0 = c₁ * c₂ ∧ p.coeff 1 = c₁ + c₂ := by
  cases subsingleton_or_nontrivial R
  · simp [natDegree_of_subsingleton] at hnd
  rw [hm.irreducible_iff_natDegree', and_iff_right, hnd]
  push_neg; constructor
  · rintro ⟨a, b, ha, hb, rfl, hdb⟩
    simp only [zero_lt_two, Nat.div_self, ge_iff_le,
      Nat.Ioc_succ_singleton, zero_add, mem_singleton] at hdb
    have hda := hnd
    rw [ha.natDegree_mul hb, hdb] at hda
    use a.coeff 0, b.coeff 0, mul_coeff_zero a b
    simpa only [nextCoeff, hnd, add_right_cancel hda, hdb] using ha.nextCoeff_mul hb
  · rintro ⟨c₁, c₂, hmul, hadd⟩
    refine
      ⟨X + C c₁, X + C c₂, monic_X_add_C _, monic_X_add_C _, ?_, ?_ ⟩
    · rw [p.as_sum_range_C_mul_X_pow, hnd, Finset.sum_range_succ, Finset.sum_range_succ,
        Finset.sum_range_one, ← hnd, hm.coeff_natDegree, hnd, hmul, hadd, C_mul, C_add, C_1]
      ring
    · rw [mem_Ioc, natDegree_X_add_C _]
      simp
  · rintro rfl
    

Proof state:
case inr
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
q : R[X]
h✝ : Nontrivial R
hm : Monic 1
hnd : natDegree 1 = 2
⊢ False

Next tactic:
simp [natDegree_one] at hnd
theorem root_mul : IsRoot (p * q) a ↔ IsRoot p a ∨ IsRoot q a := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
p q : R[X]
⊢ IsRoot (p * q) a ↔ IsRoot p a ∨ IsRoot q a

Next tactic:
simp_rw [IsRoot, eval_mul, mul_eq_zero]
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
  `(X - a) ^ n` divides `p`. -/
theorem le_rootMultiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
    n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
n : ℕ
⊢ n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p

Next tactic:
classical
  rw [rootMultiplicity_eq_nat_find_of_nonzero p0, @Nat.le_find_iff _ (_)]
  simp_rw [Classical.not_not]
  refine ⟨fun h => ?_, fun h m hm => (pow_dvd_pow _ hm).trans h⟩
  cases' n with n;
  · rw [pow_zero]
    apply one_dvd;
  · exact h n n.lt_succ_self
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
  `(X - a) ^ n` divides `p`. -/
theorem le_rootMultiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
    n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p := by
  classical
  

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
n : ℕ
⊢ n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p

Next tactic:
rw [rootMultiplicity_eq_nat_find_of_nonzero p0, @Nat.le_find_iff _ (_)]
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
  `(X - a) ^ n` divides `p`. -/
theorem le_rootMultiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
    n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p := by
  classical
  rw [rootMultiplicity_eq_nat_find_of_nonzero p0, @Nat.le_find_iff _ (_)]
  

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
n : ℕ
⊢ (∀ m < n, ¬¬(X - C a) ^ (m + 1) ∣ p) ↔ (X - C a) ^ n ∣ p

Next tactic:
simp_rw [Classical.not_not]
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
  `(X - a) ^ n` divides `p`. -/
theorem le_rootMultiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
    n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p := by
  classical
  rw [rootMultiplicity_eq_nat_find_of_nonzero p0, @Nat.le_find_iff _ (_)]
  simp_rw [Classical.not_not]
  

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
n : ℕ
⊢ (∀ m < n, (X - C a) ^ (m + 1) ∣ p) ↔ (X - C a) ^ n ∣ p

Next tactic:
refine ⟨fun h => ?_, fun h m hm => (pow_dvd_pow _ hm).trans h⟩
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
  `(X - a) ^ n` divides `p`. -/
theorem le_rootMultiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
    n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p := by
  classical
  rw [rootMultiplicity_eq_nat_find_of_nonzero p0, @Nat.le_find_iff _ (_)]
  simp_rw [Classical.not_not]
  refine ⟨fun h => ?_, fun h m hm => (pow_dvd_pow _ hm).trans h⟩
  

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
n : ℕ
h : ∀ m < n, (X - C a) ^ (m + 1) ∣ p
⊢ (X - C a) ^ n ∣ p

Next tactic:
cases' n with n
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
  `(X - a) ^ n` divides `p`. -/
theorem le_rootMultiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
    n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p := by
  classical
  rw [rootMultiplicity_eq_nat_find_of_nonzero p0, @Nat.le_find_iff _ (_)]
  simp_rw [Classical.not_not]
  refine ⟨fun h => ?_, fun h m hm => (pow_dvd_pow _ hm).trans h⟩
  cases' n with n;
  · 

Proof state:
case zero
R : Type u
S : Type v
T : Type w
a✝ b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
h : ∀ m < Nat.zero, (X - C a) ^ (m + 1) ∣ p
⊢ (X - C a) ^ Nat.zero ∣ p

Next tactic:
rw [pow_zero]
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
  `(X - a) ^ n` divides `p`. -/
theorem le_rootMultiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
    n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p := by
  classical
  rw [rootMultiplicity_eq_nat_find_of_nonzero p0, @Nat.le_find_iff _ (_)]
  simp_rw [Classical.not_not]
  refine ⟨fun h => ?_, fun h m hm => (pow_dvd_pow _ hm).trans h⟩
  cases' n with n;
  · rw [pow_zero]
    

Proof state:
case zero
R : Type u
S : Type v
T : Type w
a✝ b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
h : ∀ m < Nat.zero, (X - C a) ^ (m + 1) ∣ p
⊢ 1 ∣ p

Next tactic:
apply one_dvd
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
  `(X - a) ^ n` divides `p`. -/
theorem le_rootMultiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
    n ≤ rootMultiplicity a p ↔ (X - C a) ^ n ∣ p := by
  classical
  rw [rootMultiplicity_eq_nat_find_of_nonzero p0, @Nat.le_find_iff _ (_)]
  simp_rw [Classical.not_not]
  refine ⟨fun h => ?_, fun h m hm => (pow_dvd_pow _ hm).trans h⟩
  cases' n with n;
  · rw [pow_zero]
    apply one_dvd;
  · 

Proof state:
case succ
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
n : ℕ
h : ∀ m < Nat.succ n, (X - C a) ^ (m + 1) ∣ p
⊢ (X - C a) ^ Nat.succ n ∣ p

Next tactic:
exact h n n.lt_succ_self
theorem rootMultiplicity_le_iff {p : R[X]} (p0 : p ≠ 0) (a : R) (n : ℕ) :
    rootMultiplicity a p ≤ n ↔ ¬(X - C a) ^ (n + 1) ∣ p := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
n : ℕ
⊢ rootMultiplicity a p ≤ n ↔ ¬(X - C a) ^ (n + 1) ∣ p

Next tactic:
rw [← (le_rootMultiplicity_iff p0).not, not_le, Nat.lt_add_one_iff]
theorem pow_rootMultiplicity_not_dvd {p : R[X]} (p0 : p ≠ 0) (a : R) :
    ¬(X - C a) ^ (rootMultiplicity a p + 1) ∣ p := by 

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
p0 : p ≠ 0
a : R
⊢ ¬(X - C a) ^ (rootMultiplicity a p + 1) ∣ p

Next tactic:
rw [← rootMultiplicity_le_iff p0]
theorem X_sub_C_pow_dvd_iff {p : R[X]} {t : R} {n : ℕ} :
    (X - C t) ^ n ∣ p ↔ X ^ n ∣ p.comp (X + C t) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
t : R
n : ℕ
⊢ (X - C t) ^ n ∣ p ↔ X ^ n ∣ comp p (X + C t)

Next tactic:
convert (map_dvd_iff <| algEquivAevalXAddC t).symm using 2
theorem X_sub_C_pow_dvd_iff {p : R[X]} {t : R} {n : ℕ} :
    (X - C t) ^ n ∣ p ↔ X ^ n ∣ p.comp (X + C t) := by
  convert (map_dvd_iff <| algEquivAevalXAddC t).symm using 2
  

Proof state:
case h.e'_2.h.e'_3
R : Type u
S : Type v
T : Type w
a b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
t : R
n : ℕ
⊢ X ^ n = (algEquivAevalXAddC t) ((X - C t) ^ n)

Next tactic:
simp [C_eq_algebraMap]
theorem rootMultiplicity_eq_rootMultiplicity {p : R[X]} {t : R} :
    p.rootMultiplicity t = (p.comp (X + C t)).rootMultiplicity 0 := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
⊢ rootMultiplicity t p = rootMultiplicity 0 (comp p (X + C t))

Next tactic:
classical
  simp_rw [rootMultiplicity_eq_multiplicity, comp_X_add_C_eq_zero_iff]
  congr; ext; congr 1
  rw [C_0, sub_zero]
  convert (multiplicity.multiplicity_map_eq <| algEquivAevalXAddC t).symm using 2
  simp [C_eq_algebraMap]
theorem rootMultiplicity_eq_rootMultiplicity {p : R[X]} {t : R} :
    p.rootMultiplicity t = (p.comp (X + C t)).rootMultiplicity 0 := by
  classical
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
⊢ rootMultiplicity t p = rootMultiplicity 0 (comp p (X + C t))

Next tactic:
simp_rw [rootMultiplicity_eq_multiplicity, comp_X_add_C_eq_zero_iff]
theorem rootMultiplicity_eq_rootMultiplicity {p : R[X]} {t : R} :
    p.rootMultiplicity t = (p.comp (X + C t)).rootMultiplicity 0 := by
  classical
  simp_rw [rootMultiplicity_eq_multiplicity, comp_X_add_C_eq_zero_iff]
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
⊢ (if h0 : p = 0 then 0 else Part.get (multiplicity (X - C t) p) (_ : multiplicity.Finite (X - C t) p)) =
    if h : p = 0 then 0
    else Part.get (multiplicity (X - C 0) (comp p (X + C t))) (_ : multiplicity.Finite (X - C 0) (comp p (X + C t)))

Next tactic:
congr
theorem rootMultiplicity_eq_rootMultiplicity {p : R[X]} {t : R} :
    p.rootMultiplicity t = (p.comp (X + C t)).rootMultiplicity 0 := by
  classical
  simp_rw [rootMultiplicity_eq_multiplicity, comp_X_add_C_eq_zero_iff]
  congr; 

Proof state:
case e_e
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
⊢ (fun h0 => Part.get (multiplicity (X - C t) p) (_ : multiplicity.Finite (X - C t) p)) = fun h =>
    Part.get (multiplicity (X - C 0) (comp p (X + C t))) (_ : multiplicity.Finite (X - C 0) (comp p (X + C t)))

Next tactic:
ext
theorem rootMultiplicity_eq_rootMultiplicity {p : R[X]} {t : R} :
    p.rootMultiplicity t = (p.comp (X + C t)).rootMultiplicity 0 := by
  classical
  simp_rw [rootMultiplicity_eq_multiplicity, comp_X_add_C_eq_zero_iff]
  congr; ext; 

Proof state:
case e_e.h
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
x✝ : ¬p = 0
⊢ Part.get (multiplicity (X - C t) p) (_ : multiplicity.Finite (X - C t) p) =
    Part.get (multiplicity (X - C 0) (comp p (X + C t))) (_ : multiplicity.Finite (X - C 0) (comp p (X + C t)))

Next tactic:
congr 1
theorem rootMultiplicity_eq_rootMultiplicity {p : R[X]} {t : R} :
    p.rootMultiplicity t = (p.comp (X + C t)).rootMultiplicity 0 := by
  classical
  simp_rw [rootMultiplicity_eq_multiplicity, comp_X_add_C_eq_zero_iff]
  congr; ext; congr 1
  

Proof state:
case e_e.h.e_self
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
x✝ : ¬p = 0
⊢ multiplicity (X - C t) p = multiplicity (X - C 0) (comp p (X + C t))

Next tactic:
rw [C_0, sub_zero]
theorem rootMultiplicity_eq_rootMultiplicity {p : R[X]} {t : R} :
    p.rootMultiplicity t = (p.comp (X + C t)).rootMultiplicity 0 := by
  classical
  simp_rw [rootMultiplicity_eq_multiplicity, comp_X_add_C_eq_zero_iff]
  congr; ext; congr 1
  rw [C_0, sub_zero]
  

Proof state:
case e_e.h.e_self
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
x✝ : ¬p = 0
⊢ multiplicity (X - C t) p = multiplicity X (comp p (X + C t))

Next tactic:
convert (multiplicity.multiplicity_map_eq <| algEquivAevalXAddC t).symm using 2
theorem rootMultiplicity_eq_rootMultiplicity {p : R[X]} {t : R} :
    p.rootMultiplicity t = (p.comp (X + C t)).rootMultiplicity 0 := by
  classical
  simp_rw [rootMultiplicity_eq_multiplicity, comp_X_add_C_eq_zero_iff]
  congr; ext; congr 1
  rw [C_0, sub_zero]
  convert (multiplicity.multiplicity_map_eq <| algEquivAevalXAddC t).symm using 2
  

Proof state:
case h.e'_3.h.h.e'_4
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
x✝ : ¬p = 0
e_1✝ : Part ℕ = PartENat
⊢ X = (algEquivAevalXAddC t) (X - C t)

Next tactic:
simp [C_eq_algebraMap]
theorem rootMultiplicity_eq_natTrailingDegree' {p : R[X]} :
    p.rootMultiplicity 0 = p.natTrailingDegree := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
⊢ rootMultiplicity 0 p = natTrailingDegree p

Next tactic:
by_cases h : p = 0
theorem rootMultiplicity_eq_natTrailingDegree' {p : R[X]} :
    p.rootMultiplicity 0 = p.natTrailingDegree := by
  by_cases h : p = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : p = 0
⊢ rootMultiplicity 0 p = natTrailingDegree p

Next tactic:
simp only [h, rootMultiplicity_zero, natTrailingDegree_zero]
theorem rootMultiplicity_eq_natTrailingDegree' {p : R[X]} :
    p.rootMultiplicity 0 = p.natTrailingDegree := by
  by_cases h : p = 0
  · simp only [h, rootMultiplicity_zero, natTrailingDegree_zero]
  

Proof state:
case neg
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : ¬p = 0
⊢ rootMultiplicity 0 p = natTrailingDegree p

Next tactic:
refine le_antisymm ?_ ?_
theorem rootMultiplicity_eq_natTrailingDegree' {p : R[X]} :
    p.rootMultiplicity 0 = p.natTrailingDegree := by
  by_cases h : p = 0
  · simp only [h, rootMultiplicity_zero, natTrailingDegree_zero]
  refine le_antisymm ?_ ?_
  · 

Proof state:
case neg.refine_1
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : ¬p = 0
⊢ rootMultiplicity 0 p ≤ natTrailingDegree p

Next tactic:
rw [rootMultiplicity_le_iff h, map_zero, sub_zero, X_pow_dvd_iff, not_forall]
theorem rootMultiplicity_eq_natTrailingDegree' {p : R[X]} :
    p.rootMultiplicity 0 = p.natTrailingDegree := by
  by_cases h : p = 0
  · simp only [h, rootMultiplicity_zero, natTrailingDegree_zero]
  refine le_antisymm ?_ ?_
  · rw [rootMultiplicity_le_iff h, map_zero, sub_zero, X_pow_dvd_iff, not_forall]
    

Proof state:
case neg.refine_1
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : ¬p = 0
⊢ ∃ x, ¬(x < natTrailingDegree p + 1 → coeff p x = 0)

Next tactic:
exact ⟨p.natTrailingDegree,
      fun h' ↦ trailingCoeff_nonzero_iff_nonzero.2 h <| h' <| Nat.lt.base _⟩
theorem rootMultiplicity_eq_natTrailingDegree' {p : R[X]} :
    p.rootMultiplicity 0 = p.natTrailingDegree := by
  by_cases h : p = 0
  · simp only [h, rootMultiplicity_zero, natTrailingDegree_zero]
  refine le_antisymm ?_ ?_
  · rw [rootMultiplicity_le_iff h, map_zero, sub_zero, X_pow_dvd_iff, not_forall]
    exact ⟨p.natTrailingDegree,
      fun h' ↦ trailingCoeff_nonzero_iff_nonzero.2 h <| h' <| Nat.lt.base _⟩
  · 

Proof state:
case neg.refine_2
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : ¬p = 0
⊢ natTrailingDegree p ≤ rootMultiplicity 0 p

Next tactic:
rw [le_rootMultiplicity_iff h, map_zero, sub_zero, X_pow_dvd_iff]
theorem rootMultiplicity_eq_natTrailingDegree' {p : R[X]} :
    p.rootMultiplicity 0 = p.natTrailingDegree := by
  by_cases h : p = 0
  · simp only [h, rootMultiplicity_zero, natTrailingDegree_zero]
  refine le_antisymm ?_ ?_
  · rw [rootMultiplicity_le_iff h, map_zero, sub_zero, X_pow_dvd_iff, not_forall]
    exact ⟨p.natTrailingDegree,
      fun h' ↦ trailingCoeff_nonzero_iff_nonzero.2 h <| h' <| Nat.lt.base _⟩
  · rw [le_rootMultiplicity_iff h, map_zero, sub_zero, X_pow_dvd_iff]
    

Proof state:
case neg.refine_2
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : ¬p = 0
⊢ ∀ d < natTrailingDegree p, coeff p d = 0

Next tactic:
exact fun _ ↦ coeff_eq_zero_of_lt_natTrailingDegree
theorem eval_divByMonic_eq_trailingCoeff_comp {p : R[X]} {t : R} :
    (p /ₘ (X - C t) ^ p.rootMultiplicity t).eval t = (p.comp (X + C t)).trailingCoeff := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
⊢ eval t (p /ₘ (X - C t) ^ rootMultiplicity t p) = trailingCoeff (comp p (X + C t))

Next tactic:
obtain rfl | hp := eq_or_ne p 0
theorem eval_divByMonic_eq_trailingCoeff_comp {p : R[X]} {t : R} :
    (p /ₘ (X - C t) ^ p.rootMultiplicity t).eval t = (p.comp (X + C t)).trailingCoeff := by
  obtain rfl | hp := eq_or_ne p 0
  · 

Proof state:
case inl
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
t : R
⊢ eval t (0 /ₘ (X - C t) ^ rootMultiplicity t 0) = trailingCoeff (comp 0 (X + C t))

Next tactic:
rw [zero_divByMonic, eval_zero, zero_comp, trailingCoeff_zero]
theorem eval_divByMonic_eq_trailingCoeff_comp {p : R[X]} {t : R} :
    (p /ₘ (X - C t) ^ p.rootMultiplicity t).eval t = (p.comp (X + C t)).trailingCoeff := by
  obtain rfl | hp := eq_or_ne p 0
  · rw [zero_divByMonic, eval_zero, zero_comp, trailingCoeff_zero]
  

Proof state:
case inr
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
hp : p ≠ 0
⊢ eval t (p /ₘ (X - C t) ^ rootMultiplicity t p) = trailingCoeff (comp p (X + C t))

Next tactic:
have mul_eq := p.pow_mul_divByMonic_rootMultiplicity_eq t
theorem eval_divByMonic_eq_trailingCoeff_comp {p : R[X]} {t : R} :
    (p /ₘ (X - C t) ^ p.rootMultiplicity t).eval t = (p.comp (X + C t)).trailingCoeff := by
  obtain rfl | hp := eq_or_ne p 0
  · rw [zero_divByMonic, eval_zero, zero_comp, trailingCoeff_zero]
  have mul_eq := p.pow_mul_divByMonic_rootMultiplicity_eq t
  

Proof state:
case inr
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
hp : p ≠ 0
mul_eq : (X - C t) ^ rootMultiplicity t p * (p /ₘ (X - C t) ^ rootMultiplicity t p) = p
⊢ eval t (p /ₘ (X - C t) ^ rootMultiplicity t p) = trailingCoeff (comp p (X + C t))

Next tactic:
set m := p.rootMultiplicity t
theorem eval_divByMonic_eq_trailingCoeff_comp {p : R[X]} {t : R} :
    (p /ₘ (X - C t) ^ p.rootMultiplicity t).eval t = (p.comp (X + C t)).trailingCoeff := by
  obtain rfl | hp := eq_or_ne p 0
  · rw [zero_divByMonic, eval_zero, zero_comp, trailingCoeff_zero]
  have mul_eq := p.pow_mul_divByMonic_rootMultiplicity_eq t
  set m := p.rootMultiplicity t
  

Proof state:
case inr
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
hp : p ≠ 0
m : ℕ := rootMultiplicity t p
mul_eq : (X - C t) ^ m * (p /ₘ (X - C t) ^ m) = p
⊢ eval t (p /ₘ (X - C t) ^ m) = trailingCoeff (comp p (X + C t))

Next tactic:
set g := p /ₘ (X - C t) ^ m
theorem eval_divByMonic_eq_trailingCoeff_comp {p : R[X]} {t : R} :
    (p /ₘ (X - C t) ^ p.rootMultiplicity t).eval t = (p.comp (X + C t)).trailingCoeff := by
  obtain rfl | hp := eq_or_ne p 0
  · rw [zero_divByMonic, eval_zero, zero_comp, trailingCoeff_zero]
  have mul_eq := p.pow_mul_divByMonic_rootMultiplicity_eq t
  set m := p.rootMultiplicity t
  set g := p /ₘ (X - C t) ^ m
  

Proof state:
case inr
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
hp : p ≠ 0
m : ℕ := rootMultiplicity t p
g : R[X] := p /ₘ (X - C t) ^ m
mul_eq : (X - C t) ^ m * g = p
⊢ eval t g = trailingCoeff (comp p (X + C t))

Next tactic:
have : (g.comp (X + C t)).coeff 0 = g.eval t
theorem eval_divByMonic_eq_trailingCoeff_comp {p : R[X]} {t : R} :
    (p /ₘ (X - C t) ^ p.rootMultiplicity t).eval t = (p.comp (X + C t)).trailingCoeff := by
  obtain rfl | hp := eq_or_ne p 0
  · rw [zero_divByMonic, eval_zero, zero_comp, trailingCoeff_zero]
  have mul_eq := p.pow_mul_divByMonic_rootMultiplicity_eq t
  set m := p.rootMultiplicity t
  set g := p /ₘ (X - C t) ^ m
  have : (g.comp (X + C t)).coeff 0 = g.eval t
  · 

Proof state:
case this
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
hp : p ≠ 0
m : ℕ := rootMultiplicity t p
g : R[X] := p /ₘ (X - C t) ^ m
mul_eq : (X - C t) ^ m * g = p
⊢ coeff (comp g (X + C t)) 0 = eval t g

Next tactic:
rw [coeff_zero_eq_eval_zero, eval_comp, eval_add, eval_X, eval_C, zero_add]
theorem eval_divByMonic_eq_trailingCoeff_comp {p : R[X]} {t : R} :
    (p /ₘ (X - C t) ^ p.rootMultiplicity t).eval t = (p.comp (X + C t)).trailingCoeff := by
  obtain rfl | hp := eq_or_ne p 0
  · rw [zero_divByMonic, eval_zero, zero_comp, trailingCoeff_zero]
  have mul_eq := p.pow_mul_divByMonic_rootMultiplicity_eq t
  set m := p.rootMultiplicity t
  set g := p /ₘ (X - C t) ^ m
  have : (g.comp (X + C t)).coeff 0 = g.eval t
  · rw [coeff_zero_eq_eval_zero, eval_comp, eval_add, eval_X, eval_C, zero_add]
  

Proof state:
case inr
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
hp : p ≠ 0
m : ℕ := rootMultiplicity t p
g : R[X] := p /ₘ (X - C t) ^ m
mul_eq : (X - C t) ^ m * g = p
this : coeff (comp g (X + C t)) 0 = eval t g
⊢ eval t g = trailingCoeff (comp p (X + C t))

Next tactic:
rw [← congr_arg (comp · <| X + C t) mul_eq, mul_comp, pow_comp, sub_comp, X_comp, C_comp,
    add_sub_cancel, ← reverse_leadingCoeff, reverse_X_pow_mul, reverse_leadingCoeff, trailingCoeff,
    Nat.le_zero.mp (natTrailingDegree_le_of_ne_zero <|
      this ▸ eval_divByMonic_pow_rootMultiplicity_ne_zero t hp), this]
theorem mem_nonZeroDivisors_of_leadingCoeff {p : R[X]} (h : p.leadingCoeff ∈ R⁰) : p ∈ R[X]⁰ := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : leadingCoeff p ∈ R⁰
⊢ p ∈ R[X]⁰

Next tactic:
refine mem_nonZeroDivisors_iff.2 fun x hx ↦ leadingCoeff_eq_zero.1 ?_
theorem mem_nonZeroDivisors_of_leadingCoeff {p : R[X]} (h : p.leadingCoeff ∈ R⁰) : p ∈ R[X]⁰ := by
  refine mem_nonZeroDivisors_iff.2 fun x hx ↦ leadingCoeff_eq_zero.1 ?_
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : leadingCoeff p ∈ R⁰
x : R[X]
hx : x * p = 0
⊢ leadingCoeff x = 0

Next tactic:
by_contra hx'
theorem mem_nonZeroDivisors_of_leadingCoeff {p : R[X]} (h : p.leadingCoeff ∈ R⁰) : p ∈ R[X]⁰ := by
  refine mem_nonZeroDivisors_iff.2 fun x hx ↦ leadingCoeff_eq_zero.1 ?_
  by_contra hx'
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : leadingCoeff p ∈ R⁰
x : R[X]
hx : x * p = 0
hx' : ¬leadingCoeff x = 0
⊢ False

Next tactic:
rw [← mul_right_mem_nonZeroDivisors_eq_zero_iff h] at hx'
theorem mem_nonZeroDivisors_of_leadingCoeff {p : R[X]} (h : p.leadingCoeff ∈ R⁰) : p ∈ R[X]⁰ := by
  refine mem_nonZeroDivisors_iff.2 fun x hx ↦ leadingCoeff_eq_zero.1 ?_
  by_contra hx'
  rw [← mul_right_mem_nonZeroDivisors_eq_zero_iff h] at hx'
  

Proof state:
R : Type u
S : Type v
T : Type w
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
h : leadingCoeff p ∈ R⁰
x : R[X]
hx : x * p = 0
hx' : ¬leadingCoeff x * leadingCoeff p = 0
⊢ False

Next tactic:
simp only [← leadingCoeff_mul' hx', hx, leadingCoeff_zero, not_true] at hx'
theorem rootMultiplicity_mul_X_sub_C_pow {p : R[X]} {a : R} {n : ℕ} (h : p ≠ 0) :
    (p * (X - C a) ^ n).rootMultiplicity a = p.rootMultiplicity a + n := by
  

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
a : R
n : ℕ
h : p ≠ 0
⊢ rootMultiplicity a (p * (X - C a) ^ n) = rootMultiplicity a p + n

Next tactic:
have h2 := monic_X_sub_C a |>.pow n |>.mul_left_ne_zero h
theorem rootMultiplicity_mul_X_sub_C_pow {p : R[X]} {a : R} {n : ℕ} (h : p ≠ 0) :
    (p * (X - C a) ^ n).rootMultiplicity a = p.rootMultiplicity a + n := by
  have h2 := monic_X_sub_C a |>.pow n |>.mul_left_ne_zero h
  

Proof state:
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
a : R
n : ℕ
h : p ≠ 0
h2 : p * (X - C a) ^ n ≠ 0
⊢ rootMultiplicity a (p * (X - C a) ^ n) = rootMultiplicity a p + n

Next tactic:
refine le_antisymm ?_ ?_
theorem rootMultiplicity_mul_X_sub_C_pow {p : R[X]} {a : R} {n : ℕ} (h : p ≠ 0) :
    (p * (X - C a) ^ n).rootMultiplicity a = p.rootMultiplicity a + n := by
  have h2 := monic_X_sub_C a |>.pow n |>.mul_left_ne_zero h
  refine le_antisymm ?_ ?_
  · 

Proof state:
case refine_1
R : Type u
S : Type v
T : Type w
a✝ b : R
n✝ : ℕ
inst✝ : CommRing R
p : R[X]
a : R
n : ℕ
h : p ≠ 0
h2 : p * (X - C a) ^ n ≠ 0
⊢ rootMultiplicity a (p * (X - C a) ^ n) ≤ rootMultiplicity a p + n

Next tactic:
rw [rootMultiplicity_le_iff h2, add_assoc, add_comm n, ← add_assoc, pow_add,
      dvd_cancel_right_mem_nonZeroDivisors (monic_X_sub_C a |>.pow n |>.mem_nonZeroDivisors)]