Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit ecd889a

Browse files
committed
feat(data/polynomial/*): higher order derivative (#4187)
1 parent 5ab7eb0 commit ecd889a

File tree

1 file changed

+215
-0
lines changed

1 file changed

+215
-0
lines changed
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/-
2+
Copyright (c) 2020 Jujian Zhang. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Jujian Zhang
5+
-/
6+
7+
import data.polynomial.derivative
8+
import logic.function.iterate
9+
import tactic.ring
10+
import tactic.linarith
11+
12+
/-!
13+
# Theory of iterated derivative
14+
We define and prove some lemmas about iterated (formal) derivative for polynomials over a semiring.
15+
-/
16+
17+
noncomputable theory
18+
19+
open finset nat polynomial
20+
open_locale big_operators
21+
22+
namespace polynomial
23+
universes u
24+
variable {R : Type u}
25+
26+
section semiring
27+
28+
variables [semiring R] (r : R) (f p q : polynomial R) (n k : ℕ)
29+
30+
/-- `iterated_deriv f n` is the `n`-th formal derivative of the polynomial `f` -/
31+
def iterated_deriv : polynomial R := derivative ^[n] f
32+
33+
@[simp] lemma iterated_deriv_zero_right : iterated_deriv f 0 = f := rfl
34+
35+
lemma iterated_deriv_succ : iterated_deriv f (n + 1) = (iterated_deriv f n).derivative :=
36+
by rw [iterated_deriv, iterated_deriv, function.iterate_succ']
37+
38+
@[simp] lemma iterated_deriv_zero_left : iterated_deriv (0 : polynomial R) n = 0 :=
39+
begin
40+
induction n with n hn,
41+
{ exact iterated_deriv_zero_right _ },
42+
{ rw [iterated_deriv_succ, hn, derivative_zero] },
43+
end
44+
45+
@[simp] lemma iterated_deriv_add : iterated_deriv (p + q) n = iterated_deriv p n + iterated_deriv q n :=
46+
begin
47+
induction n with n ih,
48+
{ simp only [iterated_deriv_zero_right], },
49+
{ simp only [iterated_deriv_succ, ih, derivative_add] }
50+
end
51+
52+
@[simp] lemma iterated_deriv_smul : iterated_deriv (r • p) n = r • iterated_deriv p n :=
53+
begin
54+
induction n with n ih,
55+
{ simp only [iterated_deriv_zero_right] },
56+
{ simp only [iterated_deriv_succ, ih, derivative_smul] }
57+
end
58+
59+
@[simp] lemma iterated_deriv_X_zero : iterated_deriv (X : polynomial R) 0 = X :=
60+
by simp only [iterated_deriv_zero_right]
61+
62+
@[simp] lemma iterated_deriv_X_one : iterated_deriv (X : polynomial R) 1 = 1 :=
63+
by simp only [iterated_deriv, derivative_X, function.iterate_one]
64+
65+
@[simp] lemma iterated_deriv_X (h : 1 < n) : iterated_deriv (X : polynomial R) n = 0 :=
66+
begin
67+
induction n with n ih,
68+
{ exfalso, exact not_lt_zero 1 h},
69+
{ simp only [iterated_deriv_succ],
70+
by_cases H : n = 1,
71+
{ rw H, simp only [iterated_deriv_X_one, derivative_one] },
72+
{ replace h : 1 < n := array.push_back_idx h (ne.symm H),
73+
rw ih h, simp only [derivative_zero] } }
74+
end
75+
76+
77+
@[simp] lemma iterated_deriv_C_zero : iterated_deriv (C r) 0 = C r :=
78+
by simp only [iterated_deriv_zero_right]
79+
80+
@[simp] lemma iterated_deriv_C (h : 0 < n) : iterated_deriv (C r) n = 0 :=
81+
begin
82+
induction n with n ih,
83+
{ exfalso, exact nat.lt_asymm h h },
84+
{ by_cases H : n = 0,
85+
{ rw [iterated_deriv_succ, H], simp only [iterated_deriv_C_zero, derivative_C]},
86+
{ replace h : 0 < n := nat.pos_of_ne_zero H,
87+
rw [iterated_deriv_succ, ih h], simp only [derivative_zero] } }
88+
end
89+
90+
@[simp] lemma iterated_deriv_one_zero : iterated_deriv (1 : polynomial R) 0 = 1 :=
91+
by simp only [iterated_deriv_zero_right]
92+
93+
@[simp] lemma iterated_deriv_one : 0 < n → iterated_deriv (1 : polynomial R) n = 0 := λ h,
94+
begin
95+
have eq1 : (1 : polynomial R) = C 1 := by simp only [ring_hom.map_one],
96+
rw eq1, exact iterated_deriv_C _ _ h,
97+
end
98+
99+
end semiring
100+
101+
section ring
102+
variables [ring R] (p q : polynomial R) (n : ℕ)
103+
104+
@[simp] lemma iterated_deriv_neg : iterated_deriv (-p) n = - iterated_deriv p n :=
105+
begin
106+
induction n with n ih,
107+
{ simp only [iterated_deriv_zero_right] },
108+
{ simp only [iterated_deriv_succ, ih, derivative_neg] }
109+
end
110+
111+
@[simp] lemma iterated_deriv_sub : iterated_deriv (p - q) n = iterated_deriv p n - iterated_deriv q n :=
112+
by rw [sub_eq_add_neg, iterated_deriv_add, iterated_deriv_neg, ←sub_eq_add_neg]
113+
114+
115+
end ring
116+
117+
section comm_semiring
118+
variable [comm_semiring R]
119+
variables (f p q : polynomial R) (n k : ℕ)
120+
121+
lemma coeff_iterated_deriv_as_prod_Ico :
122+
∀ m : ℕ, (iterated_deriv f k).coeff m = (∏ i in Ico m.succ (m + k.succ), i) * (f.coeff (m+k)) :=
123+
begin
124+
induction k with k ih,
125+
{ simp only [add_zero, forall_const, one_mul, Ico.self_eq_empty, eq_self_iff_true,
126+
iterated_deriv_zero_right, prod_empty] },
127+
{ intro m, rw [iterated_deriv_succ, coeff_derivative, ih (m+1), mul_right_comm],
128+
apply congr_arg2,
129+
{ have set_eq : (Ico m.succ (m + k.succ.succ)) = (Ico (m + 1).succ (m + 1 + k.succ)) ∪ {m+1},
130+
{ rw [union_comm, ←insert_eq, Ico.insert_succ_bot, add_succ, add_succ, add_succ _ k,
131+
←succ_eq_add_one, succ_add],
132+
rw succ_eq_add_one,
133+
linarith },
134+
rw [set_eq, prod_union],
135+
apply congr_arg2,
136+
{ refl },
137+
{ simp only [prod_singleton], norm_cast },
138+
{ simp only [succ_pos', disjoint_singleton, and_true, lt_add_iff_pos_right, not_le, Ico.mem],
139+
exact lt_add_one (m + 1) } },
140+
{ exact congr_arg _ (succ_add m k) } },
141+
end
142+
143+
lemma coeff_iterated_deriv_as_prod_range :
144+
∀ m : ℕ, (iterated_deriv f k).coeff m = f.coeff (m + k) * (∏ i in finset.range k, ↑(m + k - i)) :=
145+
begin
146+
induction k with k ih,
147+
{ simp },
148+
149+
intro m,
150+
calc (f.iterated_deriv k.succ).coeff m
151+
= f.coeff (m + k.succ) * (∏ i in finset.range k, ↑(m + k.succ - i)) * (m + 1) :
152+
by rw [iterated_deriv_succ, coeff_derivative, ih m.succ, succ_add, add_succ]
153+
... = f.coeff (m + k.succ) * (↑(m + 1) * (∏ (i : ℕ) in range k, ↑(m + k.succ - i))) :
154+
by { push_cast, ring }
155+
... = f.coeff (m + k.succ) * (∏ (i : ℕ) in range k.succ, ↑(m + k.succ - i)) :
156+
by { rw [prod_range_succ, nat.add_sub_assoc (le_succ k), nat.succ_sub le_rfl, nat.sub_self] }
157+
end
158+
159+
lemma iterated_deriv_eq_zero_of_nat_degree_lt (h : f.nat_degree < n) : iterated_deriv f n = 0 :=
160+
begin
161+
ext m,
162+
rw [coeff_iterated_deriv_as_prod_range, coeff_zero, coeff_eq_zero_of_nat_degree_lt, zero_mul],
163+
linarith
164+
end
165+
166+
lemma iterated_deriv_mul :
167+
iterated_deriv (p * q) n =
168+
∑ k in range n.succ,
169+
(C (n.choose k : R)) * iterated_deriv p (n - k) * iterated_deriv q k :=
170+
begin
171+
induction n with n IH,
172+
{ simp },
173+
174+
calc (p * q).iterated_deriv n.succ
175+
= (∑ (k : ℕ) in range n.succ,
176+
C ↑(n.choose k) * p.iterated_deriv (n - k) * q.iterated_deriv k).derivative :
177+
by rw [iterated_deriv_succ, IH]
178+
... = ∑ (k : ℕ) in range n.succ,
179+
C ↑(n.choose k) * p.iterated_deriv (n - k + 1) * q.iterated_deriv k +
180+
∑ (k : ℕ) in range n.succ,
181+
C ↑(n.choose k) * p.iterated_deriv (n - k) * q.iterated_deriv (k + 1) :
182+
by simp_rw [derivative_sum, derivative_mul, derivative_C, zero_mul, zero_add,
183+
iterated_deriv_succ, sum_add_distrib]
184+
... = (∑ (k : ℕ) in range n.succ,
185+
C ↑(n.choose k.succ) * p.iterated_deriv (n - k) * q.iterated_deriv (k + 1) +
186+
C ↑1 * p.iterated_deriv n.succ * q.iterated_deriv 0) +
187+
∑ (k : ℕ) in range n.succ,
188+
C ↑(n.choose k) * p.iterated_deriv (n - k) * q.iterated_deriv (k + 1) : _
189+
... = ∑ (k : ℕ) in range n.succ,
190+
C ↑(n.choose k) * p.iterated_deriv (n - k) * q.iterated_deriv (k + 1) +
191+
∑ (k : ℕ) in range n.succ,
192+
C ↑(n.choose k.succ) * p.iterated_deriv (n - k) * q.iterated_deriv (k + 1) +
193+
C ↑1 * p.iterated_deriv n.succ * q.iterated_deriv 0 :
194+
by ring
195+
... = ∑ (i : ℕ) in range n.succ,
196+
C ↑(n.succ.choose (i + 1)) * p.iterated_deriv (n + 1 - (i + 1)) * q.iterated_deriv (i + 1) +
197+
C ↑1 * p.iterated_deriv n.succ * q.iterated_deriv 0 :
198+
by simp_rw [choose_succ_succ, succ_sub_succ, cast_add, C.map_add, add_mul, sum_add_distrib]
199+
... = ∑ (k : ℕ) in range n.succ.succ,
200+
C ↑(n.succ.choose k) * p.iterated_deriv (n.succ - k) * q.iterated_deriv k :
201+
by rw [sum_range_succ' _ n.succ, choose_zero_right, nat.sub_zero],
202+
203+
congr,
204+
refine (sum_range_succ' _ _).trans (congr_arg2 (+) _ _),
205+
{ rw [sum_range_succ, nat.choose_succ_self, cast_zero, C.map_zero, zero_mul, zero_mul, zero_add],
206+
refine sum_congr rfl (λ k hk, _),
207+
rw mem_range at hk,
208+
congr,
209+
rw [← nat.sub_add_comm (nat.succ_le_of_lt hk), nat.succ_sub_succ] },
210+
{ rw [choose_zero_right, nat.sub_zero] },
211+
end
212+
213+
end comm_semiring
214+
215+
end polynomial

0 commit comments

Comments
 (0)