Skip to content

Commit f015b2b

Browse files
committed
Strengthened main results
1 parent c488d66 commit f015b2b

1 file changed

Lines changed: 75 additions & 36 deletions

File tree

  • Mathlib/Analysis/SpecialFunctions/Trigonometric/Chebyshev

Mathlib/Analysis/SpecialFunctions/Trigonometric/Chebyshev/Extremal.lean

Lines changed: 75 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,20 @@ following proof in https://math.stackexchange.com/a/978145/1277
1919
2020
## Main statements
2121
22-
* leadingCoeff_le_of_bounded: If `P` is a degree `n` real polynomial and `|P (x)| ≤ 1` for all
23-
`|x| ≤ 1` then the leading coefficient of `P` is at most `2 ^ (n-1)`
24-
* leadingCoeff_eq_iff_of_bounded: If `P` is a degree `n` polynomial and `|P (x)| ≤ 1` for all
25-
`|x| ≤ 1` then the leading coefficient of `P` equals `2 ^ (n-1)` iff `P = T_n`, the `n`'th
26-
Chebyshev polynomial
22+
* leadingCoeff_le_of_bounded: If `P` is a real polynomial of degree at most `n` and `|P (x)| ≤ 1`
23+
for all `|x| ≤ 1` then the leading coefficient of `P` is at most `2 ^ (n-1)`
24+
* leadingCoeff_eq_iff_of_bounded: When `n ≥ 2`, equality holds iff `P = T_n`
25+
26+
## Implementation
27+
28+
By monotonicity of `2 ^ (n-1)`, we can assume that `P` has degree exactly `n`.
29+
Using Lagrange interpolation, we can give a formula for the leading coefficient of `P`
30+
as a linear combination of the values of `P` on the Chebyshev nodes (leadingCoeff_eq_sum_node).
31+
The Chebyshev polynomial `T_n` has value `±1` on the nodes, with the same signs as the
32+
coefficients of the linear combination (leadingCoeff_eq_sum_node_coeff_pos).
33+
Since `|P (x)| ≤ 1` on the nodes, this implies that the leading coefficient of `P` is bounded
34+
by that of `T_n`, which is known to equal `2 ^ (n-1)`.
35+
Moreover, equality holds iff `P` and `T_n` agree on the nodes, which implies that they coincide.
2736
-/
2837
@[expose] public section
2938
namespace Polynomial.Chebyshev
@@ -94,20 +103,22 @@ private lemma negOnePow_mul_le {α : ℝ} {i : ℕ} (hα : α ∈ Set.Icc (-1) 1
94103
rw [abs_mul, abs_neg_one_pow, one_mul]
95104
exact abs_le.mpr hα
96105

97-
theorem apply_le_apply_T_real {n : ℕ} {param : ℝ[X] → ℝ} {c : ℕ → ℝ}
98-
(hparam : (P : ℝ[X]) → P.degree = n → param P = ∑ i ≤ n, P.eval (node n i) * (c i))
106+
/-- For a polynomial P and coefficient function c, param n c P is a linear combination of
107+
P evaluated at the n'th order Chebyshev nodes, with coefficients taken from c. -/
108+
noncomputable def param (n : ℕ) (c : ℕ → ℝ) (P : ℝ[X]) := ∑ i ≤ n, P.eval (node n i) * (c i)
109+
110+
theorem apply_le_apply_T_real {n : ℕ} {c : ℕ → ℝ}
99111
(hcnonneg : ∀ i ≤ n, 0 ≤ (-1) ^ i * (c i))
100-
{P : ℝ[X]} (hPdeg : P.degree = n) (hPbnd : ∀ x ∈ Set.Icc (-1) 1, P.eval x ∈ Set.Icc (-1) 1) :
101-
param P ≤ param (T ℝ n) := by
112+
{P : ℝ[X]} (hPbnd : ∀ x ∈ Set.Icc (-1) 1, P.eval x ∈ Set.Icc (-1) 1) :
113+
param n c P ≤ param n c (T ℝ n) := by
114+
rw [param, param]
102115
wlog! hn : n ≠ 0
103-
· rw [hparam P hPdeg, hparam (T ℝ n) (degree_T ℝ n), hn, show Finset.Iic 0 = {0} by rfl,
104-
Nat.cast_zero, T_zero, Finset.sum_singleton, Finset.sum_singleton, node_eq_one,
105-
eval_one]
116+
· rw [hn, show Finset.Iic 0 = {0} by rfl, Nat.cast_zero, T_zero,
117+
Finset.sum_singleton, Finset.sum_singleton, node_eq_one, eval_one]
106118
exact mul_le_mul_of_nonneg_right (hPbnd 1 (by simp) |> Set.mem_Icc.mp).2
107119
(le_of_le_of_eq (hcnonneg 0 n.zero_le) (one_mul _))
108120
calc
109-
param P = ∑ i ≤ n, P.eval (node n i) * (c i) := hparam P hPdeg
110-
_ ≤ ∑ i ≤ n, (T ℝ n).eval (node n i) * (c i) := by
121+
∑ i ≤ n, P.eval (node n i) * (c i) ≤ ∑ i ≤ n, (T ℝ n).eval (node n i) * (c i) := by
111122
refine Finset.sum_le_sum (fun i hi => ?_)
112123
calc
113124
P.eval (node n i) * (c i) =
@@ -118,18 +129,16 @@ theorem apply_le_apply_T_real {n : ℕ} {param : ℝ[X] → ℝ} {c : ℕ →
118129
(hcnonneg i (Finset.mem_Iic.mp hi))
119130
_ = (T ℝ n).eval (node n i) * (c i) := by
120131
rw [eval_T_real_node hn, one_mul]
121-
_ = param (T ℝ n) := (hparam (T ℝ n) (degree_T ℝ n)).symm
122132

123-
theorem apply_eq_apply_T_real_iff {n : ℕ} {param : ℝ[X] → ℝ} {c : ℕ → ℝ}
124-
(hparam : (P : ℝ[X]) → P.degree = n → param P = ∑ i ≤ n, P.eval (node n i) * (c i))
133+
theorem apply_eq_apply_T_real_iff {n : ℕ} {c : ℕ → ℝ}
125134
(hcpos : ∀ i ≤ n, 0 < (-1) ^ i * (c i))
126135
{P : ℝ[X]} (hPdeg : P.degree = n) (hPbnd : ∀ x ∈ Set.Icc (-1) 1, P.eval x ∈ Set.Icc (-1) 1) :
127-
(param P = param (T ℝ n)) ↔ P = T ℝ n := by
136+
(param n c P = param n c (T ℝ n)) ↔ P = T ℝ n := by
128137
refine ⟨fun h => ?_, by intro h; rw [h]⟩
138+
rw [param, param] at h
129139
wlog! hn : n ≠ 0
130-
· rw [hparam P hPdeg, hparam (T ℝ n) (degree_T ℝ n), hn, show Finset.Iic 0 = {0} by rfl,
131-
Nat.cast_zero, T_zero, Finset.sum_singleton, Finset.sum_singleton, node_eq_one,
132-
eval_one, one_mul] at h
140+
· rw [hn, show Finset.Iic 0 = {0} by rfl, Nat.cast_zero, T_zero, Finset.sum_singleton,
141+
Finset.sum_singleton, node_eq_one, eval_one, one_mul] at h
133142
rw [hn, Nat.cast_zero] at hPdeg
134143
rw [hn, Nat.cast_zero, T_zero]
135144
have eval_P_one : P.eval 1 = 1 :=
@@ -142,7 +151,6 @@ theorem apply_eq_apply_T_real_iff {n : ℕ} {param : ℝ[X] → ℝ} {c : ℕ
142151
· rw [degree_T, Int.natAbs_natCast, Nat.cast_lt,
143152
Finset.card_image_of_injOn (strictAntiOn_node n).injOn,
144153
Finset.card_range, Nat.lt_succ_iff]
145-
rw [hparam P hPdeg, hparam (T ℝ n) (degree_T ℝ n)] at h
146154
replace h := ge_of_eq h
147155
contrapose! h
148156
obtain ⟨x, hx, hPx⟩ := h
@@ -162,31 +170,62 @@ theorem apply_eq_apply_T_real_iff {n : ℕ} {param : ℝ[X] → ℝ} {c : ℕ
162170
have := ne_of_lt (hcpos i (Finset.mem_Iic.mp hi))
163171
grind => ring
164172

165-
theorem leadingCoeff_eq_sum_node (n : ℕ) (P : ℝ[X]) (hP : P.degree = n) :
166-
P.leadingCoeff = ∑ i ≤ n, (P.eval (node n i)) *
167-
(∏ j ∈ (Finset.range (n + 1)).erase i, (node n i - node n j))⁻¹ := by
173+
/-- Coefficients use to reproduce the leading coefficient of a polynomial given its values on the
174+
Chebyshev nodes. -/
175+
private noncomputable def leadingCoeff_c (n i : ℕ) :=
176+
(∏ j ∈ (Finset.range (n + 1)).erase i, (node n i - node n j))⁻¹
177+
178+
private theorem leadingCoeff_eq_sum_node {n : ℕ} {P : ℝ[X]} (hP : P.degree = n) :
179+
param n (leadingCoeff_c n) P = P.leadingCoeff := by
180+
simp_rw [param, leadingCoeff_c]
168181
rw [Lagrange.leadingCoeff_eq_sum (strictAntiOn_node n).injOn (by simp [hP]),
169182
show Finset.range (n + 1) = Finset.Iic n by grind]
170183
rfl
171184

172-
theorem leadingCoeff_eq_sum_node_coeff_pos {n i : ℕ} (hi : i ≤ n) :
173-
0 < (-1) ^ i *
174-
(∏ j ∈ (Finset.range (n + 1)).erase i, (node n i - node n j))⁻¹ := by
185+
private theorem leadingCoeff_eq_sum_node_coeff_pos {n i : ℕ} (hi : i ≤ n) :
186+
0 < (-1) ^ i * leadingCoeff_c n i := by
175187
have := inv_pos_of_pos <| zero_lt_prod_node_sub_node hi
176188
rwa [mul_inv, ← inv_pow, inv_neg_one] at this
177189

178-
theorem leadingCoeff_le_of_bounded {n : ℕ} {P : ℝ[X]}
190+
theorem leadingCoeff_le_of_bounded' {n : ℕ} {P : ℝ[X]}
179191
(hPdeg : P.degree = n) (hPbnd : ∀ x ∈ Set.Icc (-1) 1, P.eval x ∈ Set.Icc (-1) 1) :
180192
P.leadingCoeff ≤ 2 ^ (n - 1) := by
181-
convert apply_le_apply_T_real (leadingCoeff_eq_sum_node n)
182-
(fun i hi => le_of_lt <| leadingCoeff_eq_sum_node_coeff_pos hi) hPdeg hPbnd
183-
simp
193+
rw [← leadingCoeff_eq_sum_node hPdeg]
194+
convert apply_le_apply_T_real
195+
(fun i hi => le_of_lt <| leadingCoeff_eq_sum_node_coeff_pos hi) hPbnd
196+
simp [leadingCoeff_eq_sum_node]
184197

185-
theorem leadingCoeff_eq_iff_of_bounded {n : ℕ} {P : ℝ[X]}
198+
theorem leadingCoeff_le_of_bounded {n : ℕ} {P : ℝ[X]}
199+
(hPdeg : P.degree ≤ n) (hPbnd : ∀ x ∈ Set.Icc (-1) 1, P.eval x ∈ Set.Icc (-1) 1) :
200+
P.leadingCoeff ≤ 2 ^ (n - 1) := by
201+
by_cases P = 0
202+
case pos hP => simp [hP]
203+
case neg hP =>
204+
lift P.degree to ℕ using degree_ne_bot.mpr hP with d hd
205+
replace hPdeg : d ≤ n := (WithBot.coe_le rfl).mp hPdeg
206+
calc P.leadingCoeff ≤ 2 ^ (d - 1) := leadingCoeff_le_of_bounded' hd.symm hPbnd
207+
_ ≤ 2 ^ (n - 1) := by gcongr; norm_num
208+
209+
theorem leadingCoeff_eq_iff_of_bounded' {n : ℕ} {P : ℝ[X]}
186210
(hPdeg : P.degree = n) (hPbnd : ∀ x ∈ Set.Icc (-1) 1, P.eval x ∈ Set.Icc (-1) 1) :
187211
P.leadingCoeff = 2 ^ (n - 1) ↔ P = T ℝ n := by
188-
convert apply_eq_apply_T_real_iff (leadingCoeff_eq_sum_node n)
189-
(fun i hi => leadingCoeff_eq_sum_node_coeff_pos hi) hPdeg hPbnd
190-
simp
212+
rw [← leadingCoeff_eq_sum_node hPdeg]
213+
convert apply_eq_apply_T_real_iff (fun i hi => leadingCoeff_eq_sum_node_coeff_pos hi) hPdeg hPbnd
214+
simp [leadingCoeff_eq_sum_node]
215+
216+
theorem leadingCoeff_eq_iff_of_bounded {n : ℕ} {P : ℝ[X]} (hn : 2 ≤ n)
217+
(hPdeg : P.degree ≤ n) (hPbnd : ∀ x ∈ Set.Icc (-1) 1, P.eval x ∈ Set.Icc (-1) 1) :
218+
P.leadingCoeff = 2 ^ (n - 1) ↔ P = T ℝ n := by
219+
refine ⟨fun hP => ?_, fun hP => by simp [hP]⟩
220+
lift P.degree to ℕ with d hd
221+
· contrapose! hP
222+
rw [degree_eq_bot.mp hP, leadingCoeff_zero]
223+
positivity
224+
suffices n ≤ P.degree from (leadingCoeff_eq_iff_of_bounded' (by grind) hPbnd).mp hP
225+
replace hP := ge_of_eq hP
226+
contrapose! hP
227+
have : d - 1 < n - 1 := by grind [Nat.cast_withBot, WithBot.coe_le_coe, WithBot.coe_lt_coe]
228+
calc P.leadingCoeff ≤ 2 ^ (d - 1) := leadingCoeff_le_of_bounded' hd.symm hPbnd
229+
_ < 2 ^ (n - 1) := by gcongr; norm_num
191230

192231
end Polynomial.Chebyshev

0 commit comments

Comments
 (0)