Theorem: Polynomial.iterate_derivative_mul
File: Mathlib/Data/Polynomial/Derivative.lean

tactic: induction' n with n IH
state_before: R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
n : ℕ
p q : R[X]
⊢ (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)

tactic: calc
  (derivative^[n + 1]) (p * q) =
      derivative (∑ k : ℕ in range n.succ,
          n.choose k • ((derivative^[n - k]) p * (derivative^[k]) q)) :=
    by rw [Function.iterate_succ_apply', IH]
  _ = (∑ k : ℕ in range n.succ,
        n.choose k • ((derivative^[n - k + 1]) p * (derivative^[k]) q)) +
      ∑ k : ℕ in range n.succ,
        n.choose k • ((derivative^[n - k]) p * (derivative^[k + 1]) q) := by
    simp_rw [derivative_sum, derivative_smul, derivative_mul, Function.iterate_succ_apply',
      smul_add, sum_add_distrib]
  _ = (∑ k : ℕ in range n.succ,
            n.choose k.succ • ((derivative^[n - k]) p * (derivative^[k + 1]) q)) +
          1 • ((derivative^[n + 1]) p * (derivative^[0]) q) +
        ∑ k : ℕ in range n.succ, n.choose k • ((derivative^[n - k]) p * (derivative^[k + 1]) q) :=
    ?_
  _ = ((∑ k : ℕ in range n.succ, n.choose k • ((derivative^[n - k]) p * (derivative^[k + 1]) q)) +
          ∑ k : ℕ in range n.succ,
            n.choose k.succ • ((derivative^[n - k]) p * (derivative^[k + 1]) q)) +
        1 • ((derivative^[n + 1]) p * (derivative^[0]) q) :=
    by rw [add_comm, add_assoc]
  _ = (∑ i : ℕ in range n.succ,
          (n + 1).choose (i + 1) • ((derivative^[n + 1 - (i + 1)]) p * (derivative^[i + 1]) q)) +
        1 • ((derivative^[n + 1]) p * (derivative^[0]) q) :=
    by simp_rw [Nat.choose_succ_succ, Nat.succ_sub_succ, add_smul, sum_add_distrib]
  _ = ∑ k : ℕ in range n.succ.succ,
        n.succ.choose k • ((derivative^[n.succ - k]) p * (derivative^[k]) q) :=
    by rw [sum_range_succ' _ n.succ, Nat.choose_zero_right, tsub_zero]
state_before: case succ
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ (↑derivative^[Nat.succ n]) (p * q) =
    ∑ k in range (Nat.succ (Nat.succ n)),
      Nat.choose (Nat.succ n) k • ((↑derivative^[Nat.succ n - k]) p * (↑derivative^[k]) q)

tactic: congr
state_before: case succ
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k + 1]) p * (↑derivative^[k]) q) +
      ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q) =
    ∑ k in range (Nat.succ n), Nat.choose n (Nat.succ k) • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q) +
        1 • ((↑derivative^[n + 1]) p * (↑derivative^[0]) q) +
      ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q)

tactic: simp [Finset.range]
state_before: case zero
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n : ℕ
inst✝ : Semiring R
p q : R[X]
⊢ (↑derivative^[Nat.zero]) (p * q) =
    ∑ k in range (Nat.succ Nat.zero), Nat.choose Nat.zero k • ((↑derivative^[Nat.zero - k]) p * (↑derivative^[k]) q)

tactic: rw [Function.iterate_succ_apply', IH]
state_before: R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ (↑derivative^[n + 1]) (p * q) =
    ↑derivative (∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q))

tactic: simp_rw [derivative_sum, derivative_smul, derivative_mul, Function.iterate_succ_apply',
  smul_add, sum_add_distrib]
state_before: R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ ↑derivative (∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k + 1]) p * (↑derivative^[k]) q) +
      ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q)

tactic: rw [add_comm, add_assoc]
state_before: R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ ∑ k in range (Nat.succ n), Nat.choose n (Nat.succ k) • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q) +
        1 • ((↑derivative^[n + 1]) p * (↑derivative^[0]) q) +
      ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q) +
        ∑ k in range (Nat.succ n), Nat.choose n (Nat.succ k) • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q) +
      1 • ((↑derivative^[n + 1]) p * (↑derivative^[0]) q)

tactic: simp_rw [Nat.choose_succ_succ, Nat.succ_sub_succ, add_smul, sum_add_distrib]
state_before: R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q) +
        ∑ k in range (Nat.succ n), Nat.choose n (Nat.succ k) • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q) +
      1 • ((↑derivative^[n + 1]) p * (↑derivative^[0]) q) =
    ∑ i in range (Nat.succ n),
        Nat.choose (n + 1) (i + 1) • ((↑derivative^[n + 1 - (i + 1)]) p * (↑derivative^[i + 1]) q) +
      1 • ((↑derivative^[n + 1]) p * (↑derivative^[0]) q)

tactic: rw [sum_range_succ' _ n.succ, Nat.choose_zero_right, tsub_zero]
state_before: R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ ∑ i in range (Nat.succ n),
        Nat.choose (n + 1) (i + 1) • ((↑derivative^[n + 1 - (i + 1)]) p * (↑derivative^[i + 1]) q) +
      1 • ((↑derivative^[n + 1]) p * (↑derivative^[0]) q) =
    ∑ k in range (Nat.succ (Nat.succ n)),
      Nat.choose (Nat.succ n) k • ((↑derivative^[Nat.succ n - k]) p * (↑derivative^[k]) q)

tactic: rw [sum_range_succ, Nat.choose_succ_self, zero_smul, add_zero]
state_before: case succ.e_a.refine'_1
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ ∑ k in range n, Nat.choose n (k + 1) • ((↑derivative^[n - (k + 1) + 1]) p * (↑derivative^[k + 1]) q) =
    ∑ k in range (Nat.succ n), Nat.choose n (Nat.succ k) • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q)

tactic: refine' sum_congr rfl fun k hk => _
state_before: case succ.e_a.refine'_1
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ ∑ k in range n, Nat.choose n (k + 1) • ((↑derivative^[n - (k + 1) + 1]) p * (↑derivative^[k + 1]) q) =
    ∑ x in range n, Nat.choose n (Nat.succ x) • ((↑derivative^[n - x]) p * (↑derivative^[x + 1]) q)

tactic: rw [mem_range] at hk
state_before: case succ.e_a.refine'_1
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
k : ℕ
hk : k ∈ range n
⊢ Nat.choose n (k + 1) • ((↑derivative^[n - (k + 1) + 1]) p * (↑derivative^[k + 1]) q) =
    Nat.choose n (Nat.succ k) • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q)

tactic: congr
state_before: case succ.e_a.refine'_1
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
k : ℕ
hk : k < n
⊢ Nat.choose n (k + 1) • ((↑derivative^[n - (k + 1) + 1]) p * (↑derivative^[k + 1]) q) =
    Nat.choose n (Nat.succ k) • ((↑derivative^[n - k]) p * (↑derivative^[k + 1]) q)

tactic: rw [tsub_add_eq_add_tsub (Nat.succ_le_of_lt hk), Nat.succ_sub_succ]
state_before: case succ.e_a.refine'_1.e_a.e_a.e_a
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
k : ℕ
hk : k < n
⊢ n - (k + 1) + 1 = n - k

tactic: rw [Nat.choose_zero_right, tsub_zero]
state_before: case succ.e_a.refine'_2
R : Type u
S : Type v
T : Type w
ι : Type y
A : Type z
a b : R
n✝ : ℕ
inst✝ : Semiring R
p q : R[X]
n : ℕ
IH :
  (↑derivative^[n]) (p * q) =
    ∑ k in range (Nat.succ n), Nat.choose n k • ((↑derivative^[n - k]) p * (↑derivative^[k]) q)
⊢ Nat.choose n 0 • ((↑derivative^[n - 0 + 1]) p * (↑derivative^[0]) q) =
    1 • ((↑derivative^[n + 1]) p * (↑derivative^[0]) q)