l3lab/ntp-mathlib huggingface dataset:
/-- A reformulation of the expansion of (1 + y)^d:
$$(d + 1) (1 + y)^d - (d + 1)y^d = \sum_{i = 0}^d {d + 1 \choose i} \cdot i \cdot y^{i - 1}.$$
-/
theorem eval_monomial_one_add_sub [CommRing S] (d : ℕ) (y : S) :
    eval (1 + y) (monomial d (d + 1 : S)) - eval y (monomial d (d + 1 : S)) =
      ∑ x_1 : ℕ in range (d + 1), ↑((d + 1).choose x_1) * (↑x_1 * y ^ (x_1 - 1)) := by
  have cast_succ : (d + 1 : S) = ((d.succ : ℕ) : S) := by simp only [Nat.cast_succ]
  rw [cast_succ, eval_monomial, eval_monomial, add_comm, add_pow]
  -- Porting note: `apply_congr` hadn't been ported yet, so `congr` & `ext` is used.
  conv_lhs =>
    congr
    · congr
      · skip
      · congr
        · skip
        · 

Proof state:
case a.a.f
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
x : R
inst✝ : CommRing S
d : ℕ
y : S
cast_succ : ↑d + 1 = ↑(Nat.succ d)
| fun m => y ^ m * 1 ^ (d - m) * ↑(Nat.choose d m)

Next tactic:
ext
          rw [one_pow, mul_one, mul_comm]
/-- A reformulation of the expansion of (1 + y)^d:
$$(d + 1) (1 + y)^d - (d + 1)y^d = \sum_{i = 0}^d {d + 1 \choose i} \cdot i \cdot y^{i - 1}.$$
-/
theorem eval_monomial_one_add_sub [CommRing S] (d : ℕ) (y : S) :
    eval (1 + y) (monomial d (d + 1 : S)) - eval y (monomial d (d + 1 : S)) =
      ∑ x_1 : ℕ in range (d + 1), ↑((d + 1).choose x_1) * (↑x_1 * y ^ (x_1 - 1)) := by
  have cast_succ : (d + 1 : S) = ((d.succ : ℕ) : S) := by simp only [Nat.cast_succ]
  rw [cast_succ, eval_monomial, eval_monomial, add_comm, add_pow]
  -- Porting note: `apply_congr` hadn't been ported yet, so `congr` & `ext` is used.
  conv_lhs =>
    congr
    · congr
      · skip
      · congr
        · skip
        · 

Proof state:
case a.a.f
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
x : R
inst✝ : CommRing S
d : ℕ
y : S
cast_succ : ↑d + 1 = ↑(Nat.succ d)
| fun m => y ^ m * 1 ^ (d - m) * ↑(Nat.choose d m)

Next tactic:
ext
/-- A reformulation of the expansion of (1 + y)^d:
$$(d + 1) (1 + y)^d - (d + 1)y^d = \sum_{i = 0}^d {d + 1 \choose i} \cdot i \cdot y^{i - 1}.$$
-/
theorem eval_monomial_one_add_sub [CommRing S] (d : ℕ) (y : S) :
    eval (1 + y) (monomial d (d + 1 : S)) - eval y (monomial d (d + 1 : S)) =
      ∑ x_1 : ℕ in range (d + 1), ↑((d + 1).choose x_1) * (↑x_1 * y ^ (x_1 - 1)) := by
  have cast_succ : (d + 1 : S) = ((d.succ : ℕ) : S) := by simp only [Nat.cast_succ]
  rw [cast_succ, eval_monomial, eval_monomial, add_comm, add_pow]
  -- Porting note: `apply_congr` hadn't been ported yet, so `congr` & `ext` is used.
  conv_lhs =>
    congr
    · congr
      · skip
      · congr
        · skip
        · ext
          

Proof state:
case a.a.f.h
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
x : R
inst✝ : CommRing S
d : ℕ
y : S
cast_succ : ↑d + 1 = ↑(Nat.succ d)
x✝ : ℕ
| y ^ x✝ * 1 ^ (d - x✝) * ↑(Nat.choose d x✝)

Next tactic:
rw [one_pow, mul_one, mul_comm]
/-- A reformulation of the expansion of (1 + y)^d:
$$(d + 1) (1 + y)^d - (d + 1)y^d = \sum_{i = 0}^d {d + 1 \choose i} \cdot i \cdot y^{i - 1}.$$
-/
theorem eval_monomial_one_add_sub [CommRing S] (d : ℕ) (y : S) :
    eval (1 + y) (monomial d (d + 1 : S)) - eval y (monomial d (d + 1 : S)) =
      ∑ x_1 : ℕ in range (d + 1), ↑((d + 1).choose x_1) * (↑x_1 * y ^ (x_1 - 1)) := by
  have cast_succ : (d + 1 : S) = ((d.succ : ℕ) : S) := by simp only [Nat.cast_succ]
  rw [cast_succ, eval_monomial, eval_monomial, add_comm, add_pow]
  -- Porting note: `apply_congr` hadn't been ported yet, so `congr` & `ext` is used.
  conv_lhs =>
    congr
    · congr
      · skip
      · congr
        · skip
        · ext
          rw [one_pow, mul_one, mul_comm]
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
x : R
inst✝ : CommRing S
d : ℕ
y : S
cast_succ : ↑d + 1 = ↑(Nat.succ d)
⊢ ↑(Nat.succ d) * ∑ x in range (d + 1), ↑(Nat.choose d x) * y ^ x - ↑(Nat.succ d) * y ^ d =
    ∑ x_1 in range (d + 1), ↑(Nat.choose (d + 1) x_1) * (↑x_1 * y ^ (x_1 - 1))

Next tactic:
rw [sum_range_succ, mul_add, Nat.choose_self, Nat.cast_one, one_mul, add_sub_cancel, mul_sum,
    sum_range_succ', Nat.cast_zero, zero_mul, mul_zero, add_zero]
/-- A reformulation of the expansion of (1 + y)^d:
$$(d + 1) (1 + y)^d - (d + 1)y^d = \sum_{i = 0}^d {d + 1 \choose i} \cdot i \cdot y^{i - 1}.$$
-/
theorem eval_monomial_one_add_sub [CommRing S] (d : ℕ) (y : S) :
    eval (1 + y) (monomial d (d + 1 : S)) - eval y (monomial d (d + 1 : S)) =
      ∑ x_1 : ℕ in range (d + 1), ↑((d + 1).choose x_1) * (↑x_1 * y ^ (x_1 - 1)) := by
  have cast_succ : (d + 1 : S) = ((d.succ : ℕ) : S) := by simp only [Nat.cast_succ]
  rw [cast_succ, eval_monomial, eval_monomial, add_comm, add_pow]
  -- Porting note: `apply_congr` hadn't been ported yet, so `congr` & `ext` is used.
  conv_lhs =>
    congr
    · congr
      · skip
      · congr
        · skip
        · ext
          rw [one_pow, mul_one, mul_comm]
  rw [sum_range_succ, mul_add, Nat.choose_self, Nat.cast_one, one_mul, add_sub_cancel, mul_sum,
    sum_range_succ', Nat.cast_zero, zero_mul, mul_zero, add_zero]
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
x : R
inst✝ : CommRing S
d : ℕ
y : S
cast_succ : ↑d + 1 = ↑(Nat.succ d)
⊢ ∑ x in range d, ↑(Nat.succ d) * (↑(Nat.choose d x) * y ^ x) =
    ∑ k in range d, ↑(Nat.choose (d + 1) (k + 1)) * (↑(k + 1) * y ^ (k + 1 - 1))

Next tactic:
refine sum_congr rfl fun y _hy => ?_
/-- A reformulation of the expansion of (1 + y)^d:
$$(d + 1) (1 + y)^d - (d + 1)y^d = \sum_{i = 0}^d {d + 1 \choose i} \cdot i \cdot y^{i - 1}.$$
-/
theorem eval_monomial_one_add_sub [CommRing S] (d : ℕ) (y : S) :
    eval (1 + y) (monomial d (d + 1 : S)) - eval y (monomial d (d + 1 : S)) =
      ∑ x_1 : ℕ in range (d + 1), ↑((d + 1).choose x_1) * (↑x_1 * y ^ (x_1 - 1)) := by
  have cast_succ : (d + 1 : S) = ((d.succ : ℕ) : S) := by simp only [Nat.cast_succ]
  rw [cast_succ, eval_monomial, eval_monomial, add_comm, add_pow]
  -- Porting note: `apply_congr` hadn't been ported yet, so `congr` & `ext` is used.
  conv_lhs =>
    congr
    · congr
      · skip
      · congr
        · skip
        · ext
          rw [one_pow, mul_one, mul_comm]
  rw [sum_range_succ, mul_add, Nat.choose_self, Nat.cast_one, one_mul, add_sub_cancel, mul_sum,
    sum_range_succ', Nat.cast_zero, zero_mul, mul_zero, add_zero]
  refine sum_congr rfl fun y _hy => ?_
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
x : R
inst✝ : CommRing S
d : ℕ
y✝ : S
cast_succ : ↑d + 1 = ↑(Nat.succ d)
y : ℕ
_hy : y ∈ range d
⊢ ↑(Nat.succ d) * (↑(Nat.choose d y) * y✝ ^ y) = ↑(Nat.choose (d + 1) (y + 1)) * (↑(y + 1) * y✝ ^ (y + 1 - 1))

Next tactic:
rw [← mul_assoc, ← mul_assoc, ← Nat.cast_mul, Nat.succ_mul_choose_eq, Nat.cast_mul,
    Nat.add_sub_cancel]
@[simp]
theorem eval_nat_cast_mul {n : ℕ} : ((n : R[X]) * p).eval x = n * p.eval x := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
x : R
n : ℕ
⊢ eval x (↑n * p) = ↑n * eval x p

Next tactic:
rw [← C_eq_nat_cast, eval_C_mul]
@[simp]
theorem eval_mul_X : (p * X).eval x = p.eval x * x := by
  -- Porting note: `apply` → `induction`
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
x : R
⊢ eval x (p * X) = eval x p * x

Next tactic:
induction p using Polynomial.induction_on' with
  | h_add p q ph qh =>
    simp only [add_mul, eval_add, ph, qh]
  | h_monomial n a =>
    simp only [← monomial_one_one_eq_X, monomial_mul_monomial, eval_monomial, mul_one, pow_succ',
      mul_assoc]
@[simp]
theorem eval_mul_X : (p * X).eval x = p.eval x * x := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q✝ r : R[X]
x : R
p q : R[X]
ph : eval x (p * X) = eval x p * x
qh : eval x (q * X) = eval x q * x
⊢ eval x ((p + q) * X) = eval x (p + q) * x

Next tactic:
| h_add p q ph qh =>
    simp only [add_mul, eval_add, ph, qh]
@[simp]
theorem eval_mul_X : (p * X).eval x = p.eval x * x := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q ph qh =>
    

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q✝ r : R[X]
x : R
p q : R[X]
ph : eval x (p * X) = eval x p * x
qh : eval x (q * X) = eval x q * x
⊢ eval x ((p + q) * X) = eval x (p + q) * x

Next tactic:
simp only [add_mul, eval_add, ph, qh]
@[simp]
theorem eval_mul_X : (p * X).eval x = p.eval x * x := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q ph qh =>
    simp only [add_mul, eval_add, ph, qh]
  

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
a✝ b : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
x : R
n : ℕ
a : R
⊢ eval x ((monomial n) a * X) = eval x ((monomial n) a) * x

Next tactic:
| h_monomial n a =>
    simp only [← monomial_one_one_eq_X, monomial_mul_monomial, eval_monomial, mul_one, pow_succ',
      mul_assoc]
@[simp]
theorem eval_mul_X : (p * X).eval x = p.eval x * x := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q ph qh =>
    simp only [add_mul, eval_add, ph, qh]
  | h_monomial n a =>
    

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
a✝ b : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
x : R
n : ℕ
a : R
⊢ eval x ((monomial n) a * X) = eval x ((monomial n) a) * x

Next tactic:
simp only [← monomial_one_one_eq_X, monomial_mul_monomial, eval_monomial, mul_one, pow_succ',
      mul_assoc]
@[simp]
theorem eval_mul_X_pow {k : ℕ} : (p * X ^ k).eval x = p.eval x * x ^ k := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
x : R
k : ℕ
⊢ eval x (p * X ^ k) = eval x p * x ^ k

Next tactic:
induction' k with k ih
@[simp]
theorem eval_mul_X_pow {k : ℕ} : (p * X ^ k).eval x = p.eval x * x ^ k := by
  induction' k with k ih
  · 

Proof state:
case zero
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
x : R
⊢ eval x (p * X ^ Nat.zero) = eval x p * x ^ Nat.zero

Next tactic:
simp
@[simp]
theorem eval_mul_X_pow {k : ℕ} : (p * X ^ k).eval x = p.eval x * x ^ k := by
  induction' k with k ih
  · simp
  · 

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
x : R
k : ℕ
ih : eval x (p * X ^ k) = eval x p * x ^ k
⊢ eval x (p * X ^ Nat.succ k) = eval x p * x ^ Nat.succ k

Next tactic:
simp [pow_succ', ← mul_assoc, ih]
instance IsRoot.decidable [DecidableEq R] : Decidable (IsRoot p a) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
x : R
inst✝ : DecidableEq R
⊢ Decidable (IsRoot p a)

Next tactic:
unfold IsRoot
instance IsRoot.decidable [DecidableEq R] : Decidable (IsRoot p a) := by
  unfold IsRoot; 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
x : R
inst✝ : DecidableEq R
⊢ Decidable (eval a p = 0)

Next tactic:
infer_instance
theorem coeff_zero_eq_eval_zero (p : R[X]) : coeff p 0 = p.eval 0 :=
  calc
    coeff p 0 = coeff p 0 * 0 ^ 0 := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q r : R[X]
x : R
p : R[X]
⊢ coeff p 0 = coeff p 0 * 0 ^ 0

Next tactic:
simp
theorem coeff_zero_eq_eval_zero (p : R[X]) : coeff p 0 = p.eval 0 :=
  calc
    coeff p 0 = coeff p 0 * 0 ^ 0 := by simp
    _ = p.eval 0 := by
      

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q r : R[X]
x : R
p : R[X]
⊢ coeff p 0 * 0 ^ 0 = eval 0 p

Next tactic:
symm
theorem coeff_zero_eq_eval_zero (p : R[X]) : coeff p 0 = p.eval 0 :=
  calc
    coeff p 0 = coeff p 0 * 0 ^ 0 := by simp
    _ = p.eval 0 := by
      symm
      

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q r : R[X]
x : R
p : R[X]
⊢ eval 0 p = coeff p 0 * 0 ^ 0

Next tactic:
rw [eval_eq_sum]
theorem coeff_zero_eq_eval_zero (p : R[X]) : coeff p 0 = p.eval 0 :=
  calc
    coeff p 0 = coeff p 0 * 0 ^ 0 := by simp
    _ = p.eval 0 := by
      symm
      rw [eval_eq_sum]
      

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q r : R[X]
x : R
p : R[X]
⊢ (sum p fun e a => a * 0 ^ e) = coeff p 0 * 0 ^ 0

Next tactic:
exact
        Finset.sum_eq_single _ (fun b _ hb => by simp [zero_pow (Nat.pos_of_ne_zero hb)]) (by simp)
theorem coeff_zero_eq_eval_zero (p : R[X]) : coeff p 0 = p.eval 0 :=
  calc
    coeff p 0 = coeff p 0 * 0 ^ 0 := by simp
    _ = p.eval 0 := by
      symm
      rw [eval_eq_sum]
      exact
        Finset.sum_eq_single _ (fun b _ hb => by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b✝ : R
m n : ℕ
inst✝ : Semiring R
p✝ q r : R[X]
x : R
p : R[X]
b : ℕ
x✝ : b ∈ support p
hb : b ≠ 0
⊢ (fun e a => a * 0 ^ e) b (coeff p b) = 0

Next tactic:
simp [zero_pow (Nat.pos_of_ne_zero hb)]
theorem coeff_zero_eq_eval_zero (p : R[X]) : coeff p 0 = p.eval 0 :=
  calc
    coeff p 0 = coeff p 0 * 0 ^ 0 := by simp
    _ = p.eval 0 := by
      symm
      rw [eval_eq_sum]
      exact
        Finset.sum_eq_single _ (fun b _ hb => by simp [zero_pow (Nat.pos_of_ne_zero hb)]) (by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q r : R[X]
x : R
p : R[X]
⊢ 0 ∉ support p → (fun e a => a * 0 ^ e) 0 (coeff p 0) = 0

Next tactic:
simp
theorem zero_isRoot_of_coeff_zero_eq_zero {p : R[X]} (hp : p.coeff 0 = 0) : IsRoot p 0 := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q r : R[X]
x : R
p : R[X]
hp : coeff p 0 = 0
⊢ IsRoot p 0

Next tactic:
rwa [coeff_zero_eq_eval_zero] at hp
theorem IsRoot.dvd {R : Type*} [CommSemiring R] {p q : R[X]} {x : R} (h : p.IsRoot x)
    (hpq : p ∣ q) : q.IsRoot x := by
  

Proof state:
R✝ : Type u
S : Type v
T : Type w
ι : Type y
a b : R✝
m n : ℕ
inst✝¹ : Semiring R✝
p✝ q✝ r : R✝[X]
x✝ : R✝
R : Type u_1
inst✝ : CommSemiring R
p q : R[X]
x : R
h : IsRoot p x
hpq : p ∣ q
⊢ IsRoot q x

Next tactic:
rwa [IsRoot, eval, eval₂_eq_zero_of_dvd_of_eval₂_eq_zero _ _ hpq]
theorem not_isRoot_C (r a : R) (hr : r ≠ 0) : ¬IsRoot (C r) a := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a✝ b : R
m n : ℕ
inst✝ : Semiring R
p q r✝ : R[X]
x r a : R
hr : r ≠ 0
⊢ ¬IsRoot (C r) a

Next tactic:
simpa using hr
theorem comp_eq_sum_left : p.comp q = p.sum fun e a => C a * q ^ e := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp p q = sum p fun e a => C a * q ^ e

Next tactic:
rw [comp, eval₂_eq_sum]
@[simp]
theorem comp_X : p.comp X = p := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp p X = p

Next tactic:
simp only [comp, eval₂_def, C_mul_X_pow_eq_monomial]
@[simp]
theorem comp_X : p.comp X = p := by
  simp only [comp, eval₂_def, C_mul_X_pow_eq_monomial]
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ (sum p fun e a => (monomial e) a) = p

Next tactic:
exact sum_monomial_eq _
@[simp]
theorem comp_C : p.comp (C a) = C (p.eval a) := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp p (C a) = C (eval a p)

Next tactic:
simp [comp, (C : R →+* _).map_sum]
@[simp]
theorem nat_cast_comp {n : ℕ} : (n : R[X]).comp p = n := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
⊢ comp (↑n) p = ↑n

Next tactic:
rw [← C_eq_nat_cast, C_comp]
@[simp]
theorem comp_zero : p.comp (0 : R[X]) = C (p.eval 0) := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp p 0 = C (eval 0 p)

Next tactic:
rw [← C_0, comp_C]
@[simp]
theorem zero_comp : comp (0 : R[X]) p = 0 := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp 0 p = 0

Next tactic:
rw [← C_0, C_comp]
@[simp]
theorem comp_one : p.comp 1 = C (p.eval 1) := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp p 1 = C (eval 1 p)

Next tactic:
rw [← C_1, comp_C]
@[simp]
theorem one_comp : comp (1 : R[X]) p = 1 := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp 1 p = 1

Next tactic:
rw [← C_1, C_comp]
@[simp]
theorem mul_X_comp : (p * X).comp r = p.comp r * r := by
  -- Porting note: `apply` → `induction`
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp (p * X) r = comp p r * r

Next tactic:
induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp only [hp, hq, add_mul, add_comp]
  | h_monomial n b =>
    simp only [pow_succ', mul_assoc, monomial_mul_X, monomial_comp]
@[simp]
theorem mul_X_comp : (p * X).comp r = p.comp r * r := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q✝ r p q : R[X]
hp : comp (p * X) r = comp p r * r
hq : comp (q * X) r = comp q r * r
⊢ comp ((p + q) * X) r = comp (p + q) r * r

Next tactic:
| h_add p q hp hq =>
    simp only [hp, hq, add_mul, add_comp]
@[simp]
theorem mul_X_comp : (p * X).comp r = p.comp r * r := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q✝ r p q : R[X]
hp : comp (p * X) r = comp p r * r
hq : comp (q * X) r = comp q r * r
⊢ comp ((p + q) * X) r = comp (p + q) r * r

Next tactic:
simp only [hp, hq, add_mul, add_comp]
@[simp]
theorem mul_X_comp : (p * X).comp r = p.comp r * r := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp only [hp, hq, add_mul, add_comp]
  

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
a b✝ : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
b : R
⊢ comp ((monomial n) b * X) r = comp ((monomial n) b) r * r

Next tactic:
| h_monomial n b =>
    simp only [pow_succ', mul_assoc, monomial_mul_X, monomial_comp]
@[simp]
theorem mul_X_comp : (p * X).comp r = p.comp r * r := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp only [hp, hq, add_mul, add_comp]
  | h_monomial n b =>
    

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
a b✝ : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
b : R
⊢ comp ((monomial n) b * X) r = comp ((monomial n) b) r * r

Next tactic:
simp only [pow_succ', mul_assoc, monomial_mul_X, monomial_comp]
@[simp]
theorem X_pow_comp {k : ℕ} : (X ^ k).comp p = p ^ k := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
k : ℕ
⊢ comp (X ^ k) p = p ^ k

Next tactic:
induction' k with k ih
@[simp]
theorem X_pow_comp {k : ℕ} : (X ^ k).comp p = p ^ k := by
  induction' k with k ih
  · 

Proof state:
case zero
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp (X ^ Nat.zero) p = p ^ Nat.zero

Next tactic:
simp
@[simp]
theorem X_pow_comp {k : ℕ} : (X ^ k).comp p = p ^ k := by
  induction' k with k ih
  · simp
  · 

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
k : ℕ
ih : comp (X ^ k) p = p ^ k
⊢ comp (X ^ Nat.succ k) p = p ^ Nat.succ k

Next tactic:
simp [pow_succ', mul_X_comp, ih]
@[simp]
theorem mul_X_pow_comp {k : ℕ} : (p * X ^ k).comp r = p.comp r * r ^ k := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
k : ℕ
⊢ comp (p * X ^ k) r = comp p r * r ^ k

Next tactic:
induction' k with k ih
@[simp]
theorem mul_X_pow_comp {k : ℕ} : (p * X ^ k).comp r = p.comp r * r ^ k := by
  induction' k with k ih
  · 

Proof state:
case zero
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp (p * X ^ Nat.zero) r = comp p r * r ^ Nat.zero

Next tactic:
simp
@[simp]
theorem mul_X_pow_comp {k : ℕ} : (p * X ^ k).comp r = p.comp r * r ^ k := by
  induction' k with k ih
  · simp
  · 

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
k : ℕ
ih : comp (p * X ^ k) r = comp p r * r ^ k
⊢ comp (p * X ^ Nat.succ k) r = comp p r * r ^ Nat.succ k

Next tactic:
simp [ih, pow_succ', ← mul_assoc, mul_X_comp]
@[simp]
theorem C_mul_comp : (C a * p).comp r = C a * p.comp r := by
  -- Porting note: `apply` → `induction`
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ comp (C a * p) r = C a * comp p r

Next tactic:
induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp [hp, hq, mul_add]
  | h_monomial n b =>
    simp [mul_assoc]
@[simp]
theorem C_mul_comp : (C a * p).comp r = C a * p.comp r := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q✝ r p q : R[X]
hp : comp (C a * p) r = C a * comp p r
hq : comp (C a * q) r = C a * comp q r
⊢ comp (C a * (p + q)) r = C a * comp (p + q) r

Next tactic:
| h_add p q hp hq =>
    simp [hp, hq, mul_add]
@[simp]
theorem C_mul_comp : (C a * p).comp r = C a * p.comp r := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n : ℕ
inst✝ : Semiring R
p✝ q✝ r p q : R[X]
hp : comp (C a * p) r = C a * comp p r
hq : comp (C a * q) r = C a * comp q r
⊢ comp (C a * (p + q)) r = C a * comp (p + q) r

Next tactic:
simp [hp, hq, mul_add]
@[simp]
theorem C_mul_comp : (C a * p).comp r = C a * p.comp r := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp [hp, hq, mul_add]
  

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
a b✝ : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
b : R
⊢ comp (C a * (monomial n) b) r = C a * comp ((monomial n) b) r

Next tactic:
| h_monomial n b =>
    simp [mul_assoc]
@[simp]
theorem C_mul_comp : (C a * p).comp r = C a * p.comp r := by
  -- Porting note: `apply` → `induction`
  induction p using Polynomial.induction_on' with
  | h_add p q hp hq =>
    simp [hp, hq, mul_add]
  | h_monomial n b =>
    

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
a b✝ : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
b : R
⊢ comp (C a * (monomial n) b) r = C a * comp ((monomial n) b) r

Next tactic:
simp [mul_assoc]
@[simp]
theorem nat_cast_mul_comp {n : ℕ} : ((n : R[X]) * p).comp r = n * p.comp r := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
⊢ comp (↑n * p) r = ↑n * comp p r

Next tactic:
rw [← C_eq_nat_cast, C_mul_comp, C_eq_nat_cast]
theorem mul_X_add_nat_cast_comp {n : ℕ} :
    (p * (X + (n : R[X]))).comp q = p.comp q * (q + n) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
a b : R
m n✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
⊢ comp (p * (X + ↑n)) q = comp p q * (q + ↑n)

Next tactic:
rw [mul_add, add_comp, mul_X_comp, ← Nat.cast_comm, nat_cast_mul_comp, Nat.cast_comm, mul_add]