Skip to content

Commit 39b5ba0

Browse files
committed
Proved fundamental theorems
1 parent 5373938 commit 39b5ba0

1 file changed

Lines changed: 134 additions & 160 deletions

File tree

  • Mathlib/Analysis/SpecialFunctions/Trigonometric/Chebyshev

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

Lines changed: 134 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -15,179 +15,153 @@ public import Mathlib.Topology.Algebra.Polynomial
1515
1616
* Chebyshev polynomials minimize deviation from zero,
1717
following proof in https://math.stackexchange.com/a/978145/1277
18+
[SWITCH TO STATEMENT]
19+
* Chebyshev polynomials maximize iterated derivatives at 1 and beyond, using similar idea
1820
1921
## Main statements
2022
21-
* `le_sup_abs_eval_of_monic` provides a lower bound on the maximum of |P(x)| on [-1, 1] for monic P
22-
* `sup_abs_eval_eq_iff_of_monic` characterizes the equality case
23+
[STATEMENTS]
2324
-/
24-
25+
@[expose] public section
2526
namespace Polynomial.Chebyshev
2627

2728
open Polynomial Real
2829

29-
lemma mem_Icc {n j : ℕ} (hn : n ≠ 0) (hj : j ∈ Finset.range (n + 1)) : j * π / n ∈ Set.Icc 0 π := by
30-
refine ⟨by positivity, ?_⟩
31-
· replace hj : (j : ℝ) ≤ n := Finset.mem_range.mp hj |> Nat.le_of_lt_succ |> Nat.cast_le.mpr
32-
linear_combination (norm := (field_simp; ring_nf; rfl)) (π / n) * hj
33-
34-
lemma prod_pos {n : ℕ} {i : ℕ} (hi : i ∈ Finset.range (n + 1)) :
35-
0 < (-1) ^ i * ∏ j ∈ (Finset.range (n + 1)).erase i, (cos (i * π / n) - cos (j * π / n)) := by
36-
by_cases n = 0
37-
case pos hn => aesop
38-
case neg hn =>
39-
have h₁ : 0 < ∏ j ∈ Finset.range i, ((-1) * (cos (i * π / n) - cos (j * π / n))) := by
40-
apply Finset.prod_pos
41-
intro j hj
42-
have : cos (i * π / n) < cos (j * π / n) := by
43-
apply Real.strictAntiOn_cos (mem_Icc hn (by grind)) (mem_Icc hn hi)
44-
have : (j : ℝ) < i := by aesop
45-
linear_combination (π / n) * this
46-
linarith
30+
/-- For n ≠ 0 and i ≤ n, `chebyshevNode n i` is one of the extremal points of the Chebyhsev T
31+
polynomial over the interval [-1, 1]. -/
32+
noncomputable abbrev chebyshevNode (n i : ℕ) : ℝ := cos (i * π / n)
33+
34+
lemma chebyshevNode_eq_one {n : ℕ} : chebyshevNode n 0 = 1 := by simp [chebyshevNode]
35+
36+
lemma chebyshevNode_eq_neg_one {n : ℕ} (hn : n ≠ 0) : chebyshevNode n n = -1 := by
37+
have : n * π / n = π := by aesop
38+
simp [chebyshevNode, this]
39+
40+
lemma chebyshevNode_mem_Icc {n i : ℕ} : chebyshevNode n i ∈ Set.Icc (-1) 1 :=
41+
Set.mem_Icc.mpr ⟨neg_one_le_cos _, cos_le_one _⟩
42+
43+
lemma eval_T_real_chebyshevNode {n i : ℕ} (hn : n ≠ 0) :
44+
(T ℝ n).eval (chebyshevNode n i) = (-1) ^ i := by
45+
have : (n : ℤ) * (i * π / n) = i * π := by norm_cast; field
46+
rw [T_real_cos, this, cos_nat_mul_pi]
47+
48+
lemma strictAntiOn_chebyshevNode (n : ℕ) :
49+
StrictAntiOn (chebyshevNode n ·) (Finset.range (n + 1)) := by
50+
wlog hn : n ≠ 0
51+
· push_neg at hn
52+
simp [hn]
53+
refine strictAntiOn_cos.comp_strictMonoOn ?_ (fun x hx => Set.mem_Icc.mpr ⟨by positivity, ?_⟩)
54+
· apply StrictMono.strictMonoOn
55+
exact StrictMono.mul_const
56+
(StrictMono.mul_const Nat.strictMono_cast (by positivity)) (by positivity)
57+
rw [Finset.mem_coe, Finset.mem_range_succ_iff] at hx
58+
rw [mul_div_assoc]
59+
nth_rewrite 2 [← mul_div_cancel₀ π (Nat.cast_ne_zero.mpr hn)]
60+
exact mul_le_mul_of_nonneg_right (Nat.cast_le.mpr hx) (by positivity)
61+
62+
lemma chebyshevNode_lt {n i j : ℕ} (hi : i ≤ n) (hj : j ≤ n) (hij : i < j) :
63+
chebyshevNode n j < chebyshevNode n i :=
64+
(strictAntiOn_chebyshevNode n) (Finset.mem_coe.mpr (Finset.mem_range_succ_iff.mpr hi))
65+
(Finset.mem_coe.mpr (Finset.mem_range_succ_iff.mpr hj)) hij
66+
67+
lemma zero_lt_prod_chebyshevNode_sub_chebyshevNode {n i : ℕ} (hi : i ≤ n) :
68+
0 < (-1) ^ i * ∏ j ∈ (Finset.range (n + 1)).erase i, (chebyshevNode n i - chebyshevNode n j) :=
69+
by
70+
wlog hn : n ≠ 0
71+
· push_neg at hn
72+
replace hi : i = 0 := Nat.le_zero.mp (le_of_le_of_eq hi hn)
73+
simp [hn, hi]
74+
have h₁ : 0 < ∏ j ∈ Finset.range i, ((-1) * (chebyshevNode n i - chebyshevNode n j)) :=
75+
Finset.prod_pos (fun j hj => mul_pos_of_neg_of_neg neg_one_lt_zero <| sub_neg.mpr <|
76+
chebyshevNode_lt (le_trans (le_of_lt <| Finset.mem_range.mp hj) hi) hi
77+
(Finset.mem_range.mp hj))
4778
rw [Finset.prod_mul_distrib, Finset.prod_const, Finset.card_range] at h₁
48-
have h₂ : 0 < ∏ j ∈ Finset.Ioc i n, (cos (i * π / n) - cos (j * π / n)) := by
49-
apply Finset.prod_pos
50-
intro j hj
51-
have : cos (j * π / n) < cos (i * π / n) := by
52-
apply Real.strictAntiOn_cos (mem_Icc hn hi) (mem_Icc hn (by grind))
53-
have : (i : ℝ) < j := by aesop
54-
linear_combination (π / n) * this
55-
linarith
79+
have h₂ : 0 < ∏ j ∈ Finset.Ioc i n, (chebyshevNode n i - chebyshevNode n j) :=
80+
Finset.prod_pos (fun j hj => sub_pos.mpr <|
81+
chebyshevNode_lt hi (Finset.mem_Ioc.mp hj).2 (Finset.mem_Ioc.mp hj).1)
5682
have union : (Finset.range (n + 1)).erase i = (Finset.range i) ∪ Finset.Ioc i n := by grind
5783
have disjoint : Disjoint (Finset.range i) (Finset.Ioc i n) := by grind [Finset.disjoint_iff_ne]
5884
rw [union, Finset.prod_union disjoint, ← mul_assoc]
5985
exact mul_pos h₁ h₂
6086

61-
lemma leadingCoeff_formula {n : ℕ} (hn : n ≠ 0) {P : ℝ[X]} (hP : P.degree = n) :
62-
∃ (c : ℕ → ℝ),
63-
(∀ i ∈ Finset.range (n + 1), 0 < c i) ∧
64-
(∑ i ∈ Finset.range (n + 1), c i = 2 ^ (n - 1)) ∧
65-
(∑ i ∈ Finset.range (n + 1), (c i) * ((-1) ^ i * P.eval (cos (i * π / n))) = P.leadingCoeff) :=
66-
by
67-
have cos_inj : Set.InjOn (fun (i : ℕ) => cos (i * π / n)) (Finset.range (n + 1)) := by
68-
refine injOn_cos.comp ?_ (fun i hi => mem_Icc hn hi)
69-
intro i hi j hj hij
70-
suffices (i : ℝ) = j by norm_cast at this
71-
linear_combination (norm := field) (n / π) * hij
72-
have deg {Q : ℝ[X]} (hQ : Q.degree = n) : (Finset.range (n + 1)).card = Q.degree + 1 := by
73-
simp [Finset.card_range, hQ]
74-
use fun i =>
75-
((-1) ^ i * ∏ j ∈ (Finset.range (n + 1)).erase i, (cos (i * π / n) - cos (j * π / n)))⁻¹
76-
refine ⟨?_, ⟨?_, ?_⟩⟩
77-
· exact fun i hi => prod_pos hi |> inv_pos.mpr
78-
· have := Lagrange.leadingCoeff_eq_sum cos_inj (deg (degree_T ℝ n))
79-
rw [leadingCoeff_T, Int.natAbs_natCast] at this
80-
rw [this]
81-
congr! 1 with i hi
82-
dsimp
83-
have : ((n : ℤ) : ℝ) * (i * π / n) = (i : ℤ) * π := by norm_cast; field_simp
84-
rw [T_real_cos, this, cos_int_mul_pi, zpow_natCast, mul_inv, ← div_eq_mul_inv, ← inv_pow,
85-
inv_neg_one]
86-
· rw [Lagrange.leadingCoeff_eq_sum cos_inj (deg hP)]
87-
congr! 1 with i hi
88-
field
89-
90-
theorem bddAbove (P : ℝ[X]) : BddAbove { |P.eval x| | x ∈ Set.Icc (-1) 1 } :=
91-
have := P.continuous
92-
have hcont : ContinuousOn (fun x => |P.eval x|) (Set.Icc (-1) 1) :=
93-
Continuous.continuousOn (by continuity)
94-
IsCompact.bddAbove_image isCompact_Icc hcont
95-
96-
lemma P_eval_bound (P : ℝ[X]) (n i : ℕ) :
97-
(-1) ^ i * P.eval (cos (i * π / n)) ≤ sSup { |P.eval x| | x ∈ Set.Icc (-1) 1 } := by
98-
suffices |P.eval (cos (i * π / n))| ≤ sSup { |P.eval x| | x ∈ Set.Icc (-1) 1 } by
99-
cases neg_one_pow_eq_or ℝ i with
100-
| inl h => rw [h, one_mul]; exact (abs_le'.mp this).1
101-
| inr h => rw [h, neg_one_mul]; exact (abs_le'.mp this).2
102-
refine le_csSup (bddAbove P) (Set.mem_setOf.mpr ⟨cos (i * π / n), ⟨?_, rfl⟩⟩)
103-
exact Set.mem_Icc.mpr <| abs_le.mp <| abs_cos_le_one _
104-
105-
end Polynomial.Chebyshev
106-
107-
@[expose] public section
108-
109-
namespace Polynomial.Chebyshev
110-
111-
open Polynomial Real
112-
113-
theorem le_sup_abs_eval_of_monic {n : ℕ} (hn : n ≠ 0)
114-
{P : ℝ[X]} (Pdeg : P.degree = n) (Pmonic : P.Monic) :
115-
1 / 2 ^ (n - 1) ≤ sSup { |P.eval x| | x ∈ Set.Icc (-1) 1 } := by
116-
suffices 12 ^ (n - 1) * sSup { |P.eval x| | x ∈ Set.Icc (-1) 1 } by field_simp; assumption
117-
obtain ⟨c, hpos, hsum, hform⟩ := leadingCoeff_formula hn Pdeg
118-
calc 1 = P.leadingCoeff := Pmonic.symm
119-
_ = ∑ i ∈ Finset.range (n + 1), (c i) * ((-1)^i * P.eval (cos (i * π / n))) := hform.symm
120-
_ ≤ ∑ i ∈ Finset.range (n + 1), (c i) * sSup { |P.eval x| | x ∈ Set.Icc (-1) 1 } := by
121-
gcongr with i hi
122-
· exact le_of_lt (hpos i hi)
123-
· exact P_eval_bound P n i
124-
_ = 2 ^ (n - 1) * sSup { |P.eval x| | x ∈ Set.Icc (-1) 1 } := by
125-
rw [← Finset.sum_mul, hsum]
126-
127-
theorem sup_abs_eval_eq_iff_of_monic {n : ℕ} (hn : n ≠ 0) (P : ℝ[X])
128-
(Pdeg : P.degree = n) (Pmonic : P.Monic) :
129-
sSup { |P.eval x| | x ∈ Set.Icc (-1) 1 } = 1 / 2 ^ (n - 1) ↔
130-
P = (1 / 2 ^ (n - 1) : ℝ) • (T ℝ n) :=
131-
by
132-
constructor
133-
case mp =>
134-
intro hsSup
135-
let extrema := (Finset.range (n + 1)).image (fun (k : ℕ) => cos (k * π / n))
136-
have card_extrema : extrema.card = n + 1 := by
137-
rw [Finset.card_image_of_injOn, Finset.card_range]
138-
apply injOn_cos.comp (by aesop)
139-
intro k hk
140-
apply Set.mem_Icc.mpr
141-
constructor
142-
· positivity
143-
· field_simp
144-
norm_cast
145-
grind
146-
apply eq_of_degrees_lt_of_eval_finset_eq extrema
147-
· rw [Pdeg, card_extrema]; norm_cast; simp
148-
· rw [smul_eq_C_mul, degree_C_mul (by positivity), degree_T, card_extrema]
149-
norm_cast; simp
150-
obtain ⟨c, hpos, hsum, hform⟩ := leadingCoeff_formula hn Pdeg
151-
rw [Pmonic] at hform
152-
let T' := (1 / 2 ^ (n - 1) : ℝ) • (T ℝ n)
153-
have Tform (i : ℕ) :
154-
(-1) ^ i * T'.eval (cos (i * π / n)) = 1 / 2 ^ (n - 1) := by
155-
have : ((n : ℤ) : ℝ) * (i * π / n) = (i : ℤ) * π := by norm_cast; field_simp
156-
rw [eval_smul, smul_eq_mul, T_real_cos, this, cos_int_mul_pi]
157-
suffices ((-1) ^ i : ℝ) * (-1) ^ (i : ℤ) = 1 by grind
158-
simp [← sq, ← pow_mul']
159-
replace hform :
160-
∑ i ∈ Finset.range (n + 1), (c i) * ((-1) ^ i * P.eval (cos (i * π / n))) =
161-
∑ i ∈ Finset.range (n + 1), (c i) * ((-1) ^ i * T'.eval (cos (i * π / n))) := by
162-
simp_rw [hform, Tform, ← Finset.sum_mul, hsum]
163-
simp
164-
replace hform := ge_of_eq hform
165-
contrapose! hform
166-
obtain ⟨θ, hθ, hPθ⟩ := hform
167-
obtain ⟨i₀, hi₀, hi₀θ⟩ := Finset.mem_image.mp hθ
168-
have h_le {i : ℕ} (hi : i ∈ Finset.range (n + 1)) :
169-
c i * ((-1) ^ i * P.eval (cos (i * π / n))) ≤
170-
c i * ((-1) ^ i * T'.eval (cos (i * π / n))) := by
171-
rw [Tform i, ← hsSup]
172-
exact mul_le_mul_of_nonneg_left (P_eval_bound P n i) (le_of_lt (hpos i hi))
173-
have h_lt₀ :
174-
c i₀ * ((-1) ^ i₀ * P.eval (cos (i₀ * π / n))) <
175-
c i₀ * ((-1) ^ i₀ * T'.eval (cos (i₀ * π / n))) := by
176-
apply lt_of_le_of_ne (h_le hi₀)
177-
rw [hi₀θ]
178-
contrapose! hPθ
179-
rw [← mul_assoc, ← mul_assoc] at hPθ
180-
refine mul_left_cancel₀ ?_ hPθ
181-
have := hpos i₀ hi₀
182-
positivity
183-
exact Finset.sum_lt_sum (fun i hi => h_le hi) ⟨i₀, hi₀, h_lt₀⟩
184-
case mpr =>
185-
intro hP
186-
apply eq_of_le_of_ge
187-
· refine csSup_le (by use |P.eval 1|; grind) (fun x hx => ?_)
188-
obtain ⟨θ, hθ, hx⟩ := Set.mem_setOf.mp hx
189-
have := (abs_eval_T_real_le_one_iff (Int.ofNat_ne_zero.mpr hn) θ).mp (abs_le.mpr hθ)
190-
aesop
191-
· refine le_csSup (bddAbove P) ⟨1, ⟨by grind, by aesop⟩⟩
87+
private lemma negOnePow_mul_negOnePow_mul_cancel {α β : ℝ} {i : ℕ} :
88+
((-1) ^ i * α) * ((-1) ^ i * β) = α * β := calc
89+
_ = ((-1) ^ i * (-1) ^ i) * α * β := by ring
90+
_ = α * β := by simp [← mul_pow]
91+
92+
private lemma negOnePow_mul_le {α : ℝ} {i : ℕ} (hα : α ∈ Set.Icc (-1) 1) : (-1) ^ i * α ≤ 1 := by
93+
apply le_of_abs_le
94+
rw [abs_mul, abs_neg_one_pow, one_mul]
95+
exact abs_le.mpr hα
96+
97+
theorem apply_le_apply_T_real {n : ℕ} {param : ℝ[X] → ℝ} {c : ℕ → ℝ}
98+
(hparam : (P : ℝ[X]) → P.degree = n → param P = ∑ i ≤ n, P.eval (chebyshevNode n i) * (c i))
99+
(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
102+
wlog hn : n ≠ 0
103+
· push_neg at hn
104+
rw [hparam P hPdeg, hparam (T ℝ n) (degree_T ℝ n), hn, show Finset.Iic 0 = {0} by rfl,
105+
Nat.cast_zero, T_zero, Finset.sum_singleton, Finset.sum_singleton, chebyshevNode_eq_one,
106+
eval_one]
107+
exact mul_le_mul_of_nonneg_right (hPbnd 1 (by simp) |> Set.mem_Icc.mp).2
108+
(le_of_le_of_eq (hcnonneg 0 n.zero_le) (one_mul _))
109+
calc
110+
param P = ∑ i ≤ n, P.eval (chebyshevNode n i) * (c i) := hparam P hPdeg
111+
_ ≤ ∑ i ≤ n, (T ℝ n).eval (chebyshevNode n i) * (c i) := by
112+
refine Finset.sum_le_sum (fun i hi => ?_)
113+
calc
114+
P.eval (chebyshevNode n i) * (c i) =
115+
((-1) ^ i * P.eval (chebyshevNode n i)) * ((-1) ^ i * (c i)) :=
116+
negOnePow_mul_negOnePow_mul_cancel.symm
117+
_ ≤ 1 * ((-1) ^ i * (c i)) :=
118+
mul_le_mul_of_nonneg_right (negOnePow_mul_le (hPbnd _ chebyshevNode_mem_Icc))
119+
(hcnonneg i (Finset.mem_Iic.mp hi))
120+
_ = (T ℝ n).eval (chebyshevNode n i) * (c i) := by
121+
rw [eval_T_real_chebyshevNode hn, one_mul]
122+
_ = param (T ℝ n) := (hparam (T ℝ n) (degree_T ℝ n)).symm
123+
124+
theorem apply_eq_apply_T_real_iff {n : ℕ} {param : ℝ[X] → ℝ} {c : ℕ → ℝ}
125+
(hparam : (P : ℝ[X]) → P.degree = n → param P = ∑ i ≤ n, P.eval (chebyshevNode n i) * (c i))
126+
(hcpos : ∀ i ≤ n, 0 < (-1) ^ i * (c i))
127+
{P : ℝ[X]} (hPdeg : P.degree = n) (hPbnd : ∀ x ∈ Set.Icc (-1) 1, P.eval x ∈ Set.Icc (-1) 1) :
128+
(param P = param (T ℝ n)) ↔ P = T ℝ n := by
129+
refine ⟨fun h => ?_, by intro h; rw [h]⟩
130+
wlog hn : n ≠ 0
131+
· push_neg at hn
132+
rw [hparam P hPdeg, hparam (T ℝ n) (degree_T ℝ n), hn, show Finset.Iic 0 = {0} by rfl,
133+
Nat.cast_zero, T_zero, Finset.sum_singleton, Finset.sum_singleton, chebyshevNode_eq_one,
134+
eval_one, one_mul] at h
135+
rw [hn, Nat.cast_zero] at hPdeg
136+
rw [hn, Nat.cast_zero, T_zero]
137+
have eval_P_one : P.eval 1 = 1 :=
138+
(mul_eq_right₀ (ne_of_lt <| lt_of_lt_of_eq (hcpos 0 n.zero_le) (one_mul _)).symm).mp h
139+
rw [eq_C_of_degree_eq_zero hPdeg, eval_C] at eval_P_one
140+
rw [eq_C_of_degree_eq_zero hPdeg, eval_P_one, C_1]
141+
apply eq_of_degrees_lt_of_eval_finset_eq ((Finset.range (n + 1)).image (chebyshevNode n ·))
142+
· rw [hPdeg, Nat.cast_lt, Finset.card_image_of_injOn (strictAntiOn_chebyshevNode n).injOn,
143+
Finset.card_range, Nat.lt_succ_iff]
144+
· rw [degree_T, Int.natAbs_natCast, Nat.cast_lt,
145+
Finset.card_image_of_injOn (strictAntiOn_chebyshevNode n).injOn,
146+
Finset.card_range, Nat.lt_succ_iff]
147+
rw [hparam P hPdeg, hparam (T ℝ n) (degree_T ℝ n)] at h
148+
replace h := ge_of_eq h
149+
contrapose! h
150+
obtain ⟨x, hx, hPx⟩ := h
151+
obtain ⟨i, hi, hix⟩ := Finset.mem_image.mp hx
152+
replace hi := Finset.mem_Iic.mpr (Finset.mem_range_succ_iff.mp hi)
153+
suffices ∑ i ≤ n, ((-1) ^ i * P.eval (chebyshevNode n i)) * ((-1) ^ i * c i) <
154+
∑ i≤ n, ((-1) ^ i * (T ℝ n).eval (chebyshevNode n i)) * ((-1) ^ i * c i) by
155+
simp_rw [negOnePow_mul_negOnePow_mul_cancel] at this
156+
exact this
157+
have h_le {i : ℕ} (hi : i ∈ Finset.Iic n) :
158+
(-1) ^ i * P.eval (chebyshevNode n i) * ((-1) ^ i * c i) ≤
159+
(-1) ^ i * (T ℝ n).eval (chebyshevNode n i) * ((-1) ^ i * c i) := by
160+
refine mul_le_mul_of_nonneg_right ?_ (le_of_lt (hcpos i (Finset.mem_Iic.mp hi)))
161+
rw [eval_T_real_chebyshevNode hn, ← neg_pow', neg_neg, one_pow]
162+
exact negOnePow_mul_le (hPbnd _ chebyshevNode_mem_Icc)
163+
refine Finset.sum_lt_sum (fun i hi => h_le hi) ⟨i, hi, lt_of_le_of_ne (h_le hi) ?_⟩
164+
have := ne_of_lt (hcpos i (Finset.mem_Iic.mp hi))
165+
grind => ring
192166

193167
end Polynomial.Chebyshev

0 commit comments

Comments
 (0)