l3lab/ntp-mathlib huggingface dataset:
theorem iterate_derivative_X_add_pow (n k : ℕ) (c : R) :
    derivative^[k] ((X + C c) ^ n) = Nat.descFactorial n k • (X + C c) ^ (n - k) := by
  induction k with
  | zero => simp
  

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : CommSemiring R
n : ℕ
c : R
k : ℕ
IH : (⇑derivative)^[k] ((X + C c) ^ n) = Nat.descFactorial n k • (X + C c) ^ (n - k)
⊢ (⇑derivative)^[Nat.succ k] ((X + C c) ^ n) = Nat.descFactorial n (Nat.succ k) • (X + C c) ^ (n - Nat.succ k)

Next tactic:
| succ k IH =>
      rw [Nat.sub_succ', Function.iterate_succ_apply', IH, derivative_smul,
        derivative_X_add_C_pow, map_natCast, Nat.descFactorial_succ, nsmul_eq_mul, nsmul_eq_mul,
        Nat.cast_mul]
      ring
theorem iterate_derivative_X_add_pow (n k : ℕ) (c : R) :
    derivative^[k] ((X + C c) ^ n) = Nat.descFactorial n k • (X + C c) ^ (n - k) := by
  induction k with
  | zero => simp
  | succ k IH =>
      

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : CommSemiring R
n : ℕ
c : R
k : ℕ
IH : (⇑derivative)^[k] ((X + C c) ^ n) = Nat.descFactorial n k • (X + C c) ^ (n - k)
⊢ (⇑derivative)^[Nat.succ k] ((X + C c) ^ n) = Nat.descFactorial n (Nat.succ k) • (X + C c) ^ (n - Nat.succ k)

Next tactic:
rw [Nat.sub_succ', Function.iterate_succ_apply', IH, derivative_smul,
        derivative_X_add_C_pow, map_natCast, Nat.descFactorial_succ, nsmul_eq_mul, nsmul_eq_mul,
        Nat.cast_mul]
theorem iterate_derivative_X_add_pow (n k : ℕ) (c : R) :
    derivative^[k] ((X + C c) ^ n) = Nat.descFactorial n k • (X + C c) ^ (n - k) := by
  induction k with
  | zero => simp
  | succ k IH =>
      rw [Nat.sub_succ', Function.iterate_succ_apply', IH, derivative_smul,
        derivative_X_add_C_pow, map_natCast, Nat.descFactorial_succ, nsmul_eq_mul, nsmul_eq_mul,
        Nat.cast_mul]
      

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : CommSemiring R
n : ℕ
c : R
k : ℕ
IH : (⇑derivative)^[k] ((X + C c) ^ n) = Nat.descFactorial n k • (X + C c) ^ (n - k)
⊢ ↑(Nat.descFactorial n k) * (↑(n - k) * (X + C c) ^ (n - k - 1)) =
    ↑(n - k) * ↑(Nat.descFactorial n k) * (X + C c) ^ (n - k - 1)

Next tactic:
ring
theorem derivative_comp (p q : R[X]) :
    derivative (p.comp q) = derivative q * p.derivative.comp q := by
  

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

Next tactic:
induction p using Polynomial.induction_on'
theorem derivative_comp (p q : R[X]) :
    derivative (p.comp q) = derivative q * p.derivative.comp q := by
  induction p using Polynomial.induction_on'
  · 

Proof state:
case h_add
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommSemiring R
q p✝ q✝ : R[X]
a✝¹ : derivative (comp p✝ q) = derivative q * comp (derivative p✝) q
a✝ : derivative (comp q✝ q) = derivative q * comp (derivative q✝) q
⊢ derivative (comp (p✝ + q✝) q) = derivative q * comp (derivative (p✝ + q✝)) q

Next tactic:
simp [*, mul_add]
theorem derivative_comp (p q : R[X]) :
    derivative (p.comp q) = derivative q * p.derivative.comp q := by
  induction p using Polynomial.induction_on'
  · simp [*, mul_add]
  · 

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommSemiring R
q : R[X]
n✝ : ℕ
a✝ : R
⊢ derivative (comp ((monomial n✝) a✝) q) = derivative q * comp (derivative ((monomial n✝) a✝)) q

Next tactic:
simp only [derivative_pow, derivative_mul, monomial_comp, derivative_monomial, derivative_C,
      zero_mul, C_eq_nat_cast, zero_add, RingHom.map_mul]
theorem derivative_comp (p q : R[X]) :
    derivative (p.comp q) = derivative q * p.derivative.comp q := by
  induction p using Polynomial.induction_on'
  · simp [*, mul_add]
  · simp only [derivative_pow, derivative_mul, monomial_comp, derivative_monomial, derivative_C,
      zero_mul, C_eq_nat_cast, zero_add, RingHom.map_mul]
    

Proof state:
case h_monomial
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommSemiring R
q : R[X]
n✝ : ℕ
a✝ : R
⊢ C a✝ * (↑n✝ * q ^ (n✝ - 1) * derivative q) = derivative q * (C a✝ * ↑n✝ * q ^ (n✝ - 1))

Next tactic:
ring
/-- Chain rule for formal derivative of polynomials. -/
theorem derivative_eval₂_C (p q : R[X]) :
    derivative (p.eval₂ C q) = p.derivative.eval₂ C q * derivative q :=
  Polynomial.induction_on p (fun r => by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommSemiring R
p q : R[X]
r : R
⊢ derivative (eval₂ C q (C r)) = eval₂ C q (derivative (C r)) * derivative q

Next tactic:
rw [eval₂_C, derivative_C, eval₂_zero, zero_mul]
/-- Chain rule for formal derivative of polynomials. -/
theorem derivative_eval₂_C (p q : R[X]) :
    derivative (p.eval₂ C q) = p.derivative.eval₂ C q * derivative q :=
  Polynomial.induction_on p (fun r => by rw [eval₂_C, derivative_C, eval₂_zero, zero_mul])
    (fun p₁ p₂ ih₁ ih₂ => by
      

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommSemiring R
p q p₁ p₂ : R[X]
ih₁ : derivative (eval₂ C q p₁) = eval₂ C q (derivative p₁) * derivative q
ih₂ : derivative (eval₂ C q p₂) = eval₂ C q (derivative p₂) * derivative q
⊢ derivative (eval₂ C q (p₁ + p₂)) = eval₂ C q (derivative (p₁ + p₂)) * derivative q

Next tactic:
rw [eval₂_add, derivative_add, ih₁, ih₂, derivative_add, eval₂_add, add_mul]
/-- Chain rule for formal derivative of polynomials. -/
theorem derivative_eval₂_C (p q : R[X]) :
    derivative (p.eval₂ C q) = p.derivative.eval₂ C q * derivative q :=
  Polynomial.induction_on p (fun r => by rw [eval₂_C, derivative_C, eval₂_zero, zero_mul])
    (fun p₁ p₂ ih₁ ih₂ => by
      rw [eval₂_add, derivative_add, ih₁, ih₂, derivative_add, eval₂_add, add_mul])
    fun n r ih => by
    

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : CommSemiring R
p q : R[X]
n : ℕ
r : R
ih : derivative (eval₂ C q (C r * X ^ n)) = eval₂ C q (derivative (C r * X ^ n)) * derivative q
⊢ derivative (eval₂ C q (C r * X ^ (n + 1))) = eval₂ C q (derivative (C r * X ^ (n + 1))) * derivative q

Next tactic:
rw [pow_succ', ← mul_assoc, eval₂_mul, eval₂_X, derivative_mul, ih, @derivative_mul _ _ _ X,
      derivative_X, mul_one, eval₂_add, @eval₂_mul _ _ _ _ X, eval₂_X, add_mul, mul_right_comm]
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s : Multiset ι
f : ι → R[X]
⊢ derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)

Next tactic:
refine' Multiset.induction_on s (by simp) fun i s h => _
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s : Multiset ι
f : ι → R[X]
⊢ derivative (Multiset.prod (Multiset.map f 0)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase 0 i)) * derivative (f i)) 0)

Next tactic:
simp
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
⊢ derivative (Multiset.prod (Multiset.map f (i ::ₘ s))) =
    Multiset.sum
      (Multiset.map (fun i_1 => Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) i_1)) * derivative (f i_1))
        (i ::ₘ s))

Next tactic:
rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
⊢ Multiset.prod (Multiset.map f s) * derivative (f i) + f i * derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.prod (Multiset.map f s) * derivative (f i) +
      Multiset.sum
        (Multiset.map (fun i_1 => Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) i_1)) * derivative (f i_1)) s)

Next tactic:
congr
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
  congr
  

Proof state:
case e_a
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
⊢ f i * derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum
      (Multiset.map (fun i_1 => Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) i_1)) * derivative (f i_1)) s)

Next tactic:
rw [h, ← AddMonoidHom.coe_mulLeft, (AddMonoidHom.mulLeft (f i)).map_multiset_sum _,
    AddMonoidHom.coe_mulLeft]
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
  congr
  rw [h, ← AddMonoidHom.coe_mulLeft, (AddMonoidHom.mulLeft (f i)).map_multiset_sum _,
    AddMonoidHom.coe_mulLeft]
  

Proof state:
case e_a
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
⊢ Multiset.sum
      (Multiset.map (HMul.hMul (f i))
        (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)) =
    Multiset.sum
      (Multiset.map (fun i_1 => Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) i_1)) * derivative (f i_1)) s)

Next tactic:
simp only [Function.comp_apply, Multiset.map_map]
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
  congr
  rw [h, ← AddMonoidHom.coe_mulLeft, (AddMonoidHom.mulLeft (f i)).map_multiset_sum _,
    AddMonoidHom.coe_mulLeft]
  simp only [Function.comp_apply, Multiset.map_map]
  

Proof state:
case e_a
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
⊢ Multiset.sum
      (Multiset.map (fun x => f i * (Multiset.prod (Multiset.map f (Multiset.erase s x)) * derivative (f x))) s) =
    Multiset.sum
      (Multiset.map (fun i_1 => Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) i_1)) * derivative (f i_1)) s)

Next tactic:
refine' congr_arg _ (Multiset.map_congr rfl fun j hj => _)
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
  congr
  rw [h, ← AddMonoidHom.coe_mulLeft, (AddMonoidHom.mulLeft (f i)).map_multiset_sum _,
    AddMonoidHom.coe_mulLeft]
  simp only [Function.comp_apply, Multiset.map_map]
  refine' congr_arg _ (Multiset.map_congr rfl fun j hj => _)
  

Proof state:
case e_a
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
j : ι
hj : j ∈ s
⊢ f i * (Multiset.prod (Multiset.map f (Multiset.erase s j)) * derivative (f j)) =
    Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) j)) * derivative (f j)

Next tactic:
rw [← mul_assoc, ← Multiset.prod_cons, ← Multiset.map_cons]
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
  congr
  rw [h, ← AddMonoidHom.coe_mulLeft, (AddMonoidHom.mulLeft (f i)).map_multiset_sum _,
    AddMonoidHom.coe_mulLeft]
  simp only [Function.comp_apply, Multiset.map_map]
  refine' congr_arg _ (Multiset.map_congr rfl fun j hj => _)
  rw [← mul_assoc, ← Multiset.prod_cons, ← Multiset.map_cons]
  

Proof state:
case e_a
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
j : ι
hj : j ∈ s
⊢ Multiset.prod (Multiset.map f (i ::ₘ Multiset.erase s j)) * derivative (f j) =
    Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) j)) * derivative (f j)

Next tactic:
by_cases hij : i = j
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
  congr
  rw [h, ← AddMonoidHom.coe_mulLeft, (AddMonoidHom.mulLeft (f i)).map_multiset_sum _,
    AddMonoidHom.coe_mulLeft]
  simp only [Function.comp_apply, Multiset.map_map]
  refine' congr_arg _ (Multiset.map_congr rfl fun j hj => _)
  rw [← mul_assoc, ← Multiset.prod_cons, ← Multiset.map_cons]
  by_cases hij : i = j
  · 

Proof state:
case pos
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
j : ι
hj : j ∈ s
hij : i = j
⊢ Multiset.prod (Multiset.map f (i ::ₘ Multiset.erase s j)) * derivative (f j) =
    Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) j)) * derivative (f j)

Next tactic:
simp [hij, ← Multiset.prod_cons, ← Multiset.map_cons, Multiset.cons_erase hj]
theorem derivative_prod [DecidableEq ι] {s : Multiset ι} {f : ι → R[X]} :
    derivative (Multiset.map f s).prod =
      (Multiset.map (fun i => (Multiset.map f (s.erase i)).prod * derivative (f i)) s).sum := by
  refine' Multiset.induction_on s (by simp) fun i s h => _
  rw [Multiset.map_cons, Multiset.prod_cons, derivative_mul, Multiset.map_cons _ i s,
    Multiset.sum_cons, Multiset.erase_cons_head, mul_comm (derivative (f i))]
  congr
  rw [h, ← AddMonoidHom.coe_mulLeft, (AddMonoidHom.mulLeft (f i)).map_multiset_sum _,
    AddMonoidHom.coe_mulLeft]
  simp only [Function.comp_apply, Multiset.map_map]
  refine' congr_arg _ (Multiset.map_congr rfl fun j hj => _)
  rw [← mul_assoc, ← Multiset.prod_cons, ← Multiset.map_cons]
  by_cases hij : i = j
  · simp [hij, ← Multiset.prod_cons, ← Multiset.map_cons, Multiset.cons_erase hj]
  · 

Proof state:
case neg
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝¹ : CommSemiring R
inst✝ : DecidableEq ι
s✝ : Multiset ι
f : ι → R[X]
i : ι
s : Multiset ι
h :
  derivative (Multiset.prod (Multiset.map f s)) =
    Multiset.sum (Multiset.map (fun i => Multiset.prod (Multiset.map f (Multiset.erase s i)) * derivative (f i)) s)
j : ι
hj : j ∈ s
hij : ¬i = j
⊢ Multiset.prod (Multiset.map f (i ::ₘ Multiset.erase s j)) * derivative (f j) =
    Multiset.prod (Multiset.map f (Multiset.erase (i ::ₘ s) j)) * derivative (f j)

Next tactic:
simp [hij]
theorem derivative_X_sub_C (c : R) : derivative (X - C c) = 1 := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
c : R
⊢ derivative (X - C c) = 1

Next tactic:
rw [derivative_sub, derivative_X, derivative_C, sub_zero]
@[simp]
theorem iterate_derivative_sub {k : ℕ} {f g : R[X]} :
    derivative^[k] (f - g) = derivative^[k] f - derivative^[k] g := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
k : ℕ
f g : R[X]
⊢ (⇑derivative)^[k] (f - g) = (⇑derivative)^[k] f - (⇑derivative)^[k] g

Next tactic:
induction' k with k ih generalizing f g
@[simp]
theorem iterate_derivative_sub {k : ℕ} {f g : R[X]} :
    derivative^[k] (f - g) = derivative^[k] f - derivative^[k] g := by
  induction' k with k ih generalizing f g <;> 

Proof state:
case zero
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
f g : R[X]
⊢ (⇑derivative)^[Nat.zero] (f - g) = (⇑derivative)^[Nat.zero] f - (⇑derivative)^[Nat.zero] g

Next tactic:
simp [*]
@[simp]
theorem iterate_derivative_sub {k : ℕ} {f g : R[X]} :
    derivative^[k] (f - g) = derivative^[k] f - derivative^[k] g := by
  induction' k with k ih generalizing f g <;> 

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
k : ℕ
ih : ∀ {f g : R[X]}, (⇑derivative)^[k] (f - g) = (⇑derivative)^[k] f - (⇑derivative)^[k] g
f g : R[X]
⊢ (⇑derivative)^[Nat.succ k] (f - g) = (⇑derivative)^[Nat.succ k] f - (⇑derivative)^[Nat.succ k] g

Next tactic:
simp [*]
@[simp]
theorem derivative_int_cast {n : ℤ} : derivative (n : R[X]) = 0 := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
n : ℤ
⊢ derivative ↑n = 0

Next tactic:
rw [← C_eq_int_cast n]
@[simp]
theorem derivative_int_cast {n : ℤ} : derivative (n : R[X]) = 0 := by
  rw [← C_eq_int_cast n]
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
n : ℤ
⊢ derivative (C ↑n) = 0

Next tactic:
exact derivative_C
theorem derivative_int_cast_mul {n : ℤ} {f : R[X]} : derivative ((n : R[X]) * f) =
    n * derivative f := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
n : ℤ
f : R[X]
⊢ derivative (↑n * f) = ↑n * derivative f

Next tactic:
simp
@[simp]
theorem iterate_derivative_int_cast_mul {n : ℤ} {k : ℕ} {f : R[X]} :
    derivative^[k] ((n : R[X]) * f) = n * derivative^[k] f := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
n : ℤ
k : ℕ
f : R[X]
⊢ (⇑derivative)^[k] (↑n * f) = ↑n * (⇑derivative)^[k] f

Next tactic:
induction' k with k ih generalizing f
@[simp]
theorem iterate_derivative_int_cast_mul {n : ℤ} {k : ℕ} {f : R[X]} :
    derivative^[k] ((n : R[X]) * f) = n * derivative^[k] f := by
  induction' k with k ih generalizing f <;> 

Proof state:
case zero
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
n : ℤ
f : R[X]
⊢ (⇑derivative)^[Nat.zero] (↑n * f) = ↑n * (⇑derivative)^[Nat.zero] f

Next tactic:
simp [*]
@[simp]
theorem iterate_derivative_int_cast_mul {n : ℤ} {k : ℕ} {f : R[X]} :
    derivative^[k] ((n : R[X]) * f) = n * derivative^[k] f := by
  induction' k with k ih generalizing f <;> 

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
n : ℤ
k : ℕ
ih : ∀ {f : R[X]}, (⇑derivative)^[k] (↑n * f) = ↑n * (⇑derivative)^[k] f
f : R[X]
⊢ (⇑derivative)^[Nat.succ k] (↑n * f) = ↑n * (⇑derivative)^[Nat.succ k] f

Next tactic:
simp [*]
theorem derivative_comp_one_sub_X (p : R[X]) :
    derivative (p.comp (1 - X)) = -p.derivative.comp (1 - X) := by 

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
⊢ derivative (comp p (1 - X)) = -comp (derivative p) (1 - X)

Next tactic:
simp [derivative_comp]
@[simp]
theorem iterate_derivative_comp_one_sub_X (p : R[X]) (k : ℕ) :
    derivative^[k] (p.comp (1 - X)) = (-1) ^ k * (derivative^[k] p).comp (1 - X) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
k : ℕ
⊢ (⇑derivative)^[k] (comp p (1 - X)) = (-1) ^ k * comp ((⇑derivative)^[k] p) (1 - X)

Next tactic:
induction' k with k ih generalizing p
@[simp]
theorem iterate_derivative_comp_one_sub_X (p : R[X]) (k : ℕ) :
    derivative^[k] (p.comp (1 - X)) = (-1) ^ k * (derivative^[k] p).comp (1 - X) := by
  induction' k with k ih generalizing p
  · 

Proof state:
case zero
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
⊢ (⇑derivative)^[Nat.zero] (comp p (1 - X)) = (-1) ^ Nat.zero * comp ((⇑derivative)^[Nat.zero] p) (1 - X)

Next tactic:
simp
@[simp]
theorem iterate_derivative_comp_one_sub_X (p : R[X]) (k : ℕ) :
    derivative^[k] (p.comp (1 - X)) = (-1) ^ k * (derivative^[k] p).comp (1 - X) := by
  induction' k with k ih generalizing p
  · simp
  · 

Proof state:
case succ
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
k : ℕ
ih : ∀ (p : R[X]), (⇑derivative)^[k] (comp p (1 - X)) = (-1) ^ k * comp ((⇑derivative)^[k] p) (1 - X)
p : R[X]
⊢ (⇑derivative)^[Nat.succ k] (comp p (1 - X)) = (-1) ^ Nat.succ k * comp ((⇑derivative)^[Nat.succ k] p) (1 - X)

Next tactic:
simp [ih (derivative p), iterate_derivative_neg, derivative_comp, pow_succ]