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

Commit c38d128

Browse files
jcommelinjjaassoonnrwbartonrobertylewis
committed
feat(ring_theory/polynomial/chebyshev): chebyshev polynomials of the first kind (#4267)
If T_n denotes the n-th Chebyshev polynomial of the first kind, then the polynomials 2*T_n(X/2) form a Lambda structure on Z[X]. I call these polynomials the lambdashev polynomials, because, as far as I am aware they don't have a name in the literature. We show that they commute, and that the p-th polynomial is congruent to X^p mod p. In other words: a Lambda structure. Co-authored-by: Jujian Zhang <jujian.zhang1998@outlook.com> Co-authored-by: Reid Barton <rwbarton@gmail.com> Co-authored-by: none <none> Co-authored-by: Rob Lewis <rob.y.lewis@gmail.com>
1 parent f75dbd3 commit c38d128

File tree

4 files changed

+350
-0
lines changed

4 files changed

+350
-0
lines changed

src/analysis/special_functions/trigonometric.lean

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Authors: Chris Hughes, Abhimanyu Pallavi Sudhir, Jean Lo, Calle Sönne, Benjamin
66
import analysis.special_functions.exp_log
77
import data.set.intervals.infinite
88
import algebra.quadratic_discriminant
9+
import ring_theory.polynomial.chebyshev.defs
910

1011
/-!
1112
# Trigonometric functions
@@ -24,6 +25,9 @@ Many basic inequalities on trigonometric functions are established.
2425
The continuity and differentiability of the usual trigonometric functions are proved, and their
2526
derivatives are computed.
2627
28+
* `polynomial.chebyshev₁_complex_cos`: the `n`-th Chebyshev polynomial evaluates on `complex.cos θ`
29+
to the value `n * complex.cos θ`.
30+
2731
## Tags
2832
2933
log, sin, cos, tan, arcsin, arccos, arctan, angle, argument
@@ -1926,6 +1930,32 @@ sin_surjective.range_eq
19261930

19271931
end complex
19281932

1933+
section chebyshev₁
1934+
1935+
open polynomial complex
1936+
1937+
/-- the `n`-th Chebyshev polynomial evaluates on `cos θ` to the value `cos (n * θ)`. -/
1938+
lemma chebyshev₁_complex_cos (θ : ℂ) :
1939+
∀ n, (chebyshev₁ ℂ n).eval (cos θ) = cos (n * θ)
1940+
| 0 := by simp only [chebyshev₁_zero, eval_one, nat.cast_zero, zero_mul, cos_zero]
1941+
| 1 := by simp only [eval_X, one_mul, chebyshev₁_one, nat.cast_one]
1942+
| (n + 2) :=
1943+
begin
1944+
simp only [eval_X, eval_one, chebyshev₁_add_two, eval_sub, eval_bit0, nat.cast_succ, eval_mul],
1945+
rw [chebyshev₁_complex_cos (n + 1), chebyshev₁_complex_cos n],
1946+
have aux : sin θ * sin θ = 1 - cos θ * cos θ,
1947+
{ rw ← sin_sq_add_cos_sq θ, ring, },
1948+
simp only [nat.cast_add, nat.cast_one, add_mul, cos_add, one_mul, sin_add, mul_assoc, aux],
1949+
ring,
1950+
end
1951+
1952+
/-- `cos (n * θ)` is equal to the `n`-th Chebyshev polynomial evaluated on `cos θ`. -/
1953+
lemma cos_nat_mul (n : ℕ) (θ : ℂ) :
1954+
cos (n * θ) = (chebyshev₁ ℂ n).eval (cos θ) :=
1955+
(chebyshev₁_complex_cos θ n).symm
1956+
1957+
end chebyshev₁
1958+
19291959
namespace real
19301960
open_locale real
19311961

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/-
2+
Copyright (c) 2020 Johan Commelin. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Johan Commelin
5+
-/
6+
7+
import ring_theory.polynomial.chebyshev.defs
8+
import analysis.special_functions.trigonometric
9+
import ring_theory.localization
10+
import data.zmod.basic
11+
import algebra.invertible
12+
13+
/-!
14+
# Chebyshev polynomials
15+
16+
The Chebyshev polynomials are two families of polynomials indexed by `ℕ`,
17+
with integral coefficients.
18+
In this file, we only consider Chebyshev polynomials of the first kind.
19+
20+
## Main declarations
21+
22+
* `polynomial.chebyshev₁_mul`, the `(m * n)`-th Chebyshev polynomial is the composition
23+
of the `m`-th and `n`-th Chebyshev polynomials.
24+
* `polynomial.lambdashev_mul`, the `(m * n)`-th lambdashev polynomial is the composition
25+
of the `m`-th and `n`-th lambdashev polynomials.
26+
* `polynomial.lambdashev_char_p`, for a prime number `p`, the `p`-th lambdashev polynomial
27+
is congruent to `X ^ p` modulo `p`.
28+
29+
## Implementation details
30+
31+
Since Chebyshev polynomials have interesting behaviour over the complex numbers and modulo `p`,
32+
we define them to have coefficients in an arbitrary commutative ring, even though
33+
technically `ℤ` would suffice.
34+
The benefit of allowing arbitrary coefficient rings, is that the statements afterwards are clean,
35+
and do not have `map (int.cast_ring_hom R)` interfering all the time.
36+
37+
38+
-/
39+
40+
noncomputable theory
41+
42+
namespace polynomial
43+
open complex
44+
variables (R S : Type*) [comm_ring R] [comm_ring S]
45+
46+
/-- The `(m * n)`-th Chebyshev polynomial is the composition of the `m`-th and `n`-th -/
47+
lemma chebyshev₁_mul (m n : ℕ) :
48+
chebyshev₁ R (m * n) = (chebyshev₁ R m).comp (chebyshev₁ R n) :=
49+
begin
50+
simp only [← map_comp, ← map_chebyshev₁ (int.cast_ring_hom R)],
51+
congr' 1,
52+
apply map_injective (int.cast_ring_hom ℂ) int.cast_injective,
53+
simp only [map_comp, map_chebyshev₁],
54+
apply polynomial.funext,
55+
intro z,
56+
obtain ⟨θ, rfl⟩ := cos_surjective z,
57+
simp only [chebyshev₁_complex_cos, nat.cast_mul, eval_comp, mul_assoc],
58+
end
59+
60+
section lambdashev
61+
/-!
62+
63+
### A Lambda structure on `polynomial ℤ`
64+
65+
Mathlib doesn't currently know what a Lambda ring is.
66+
But once it does, we can endow `polynomial ℤ` with a Lambda structure
67+
in terms of the `lambdashev` polynomials defined below.
68+
There is exactly one other Lambda structure on `polynomial ℤ` in terms of binomial polynomials.
69+
70+
-/
71+
72+
variables {R}
73+
74+
lemma lambdashev_eval_add_inv (x y : R) (h : x * y = 1) :
75+
∀ n, (lambdashev R n).eval (x + y) = x ^ n + y ^ n
76+
| 0 := by simp only [bit0, eval_one, eval_add, pow_zero, lambdashev_zero]
77+
| 1 := by simp only [eval_X, lambdashev_one, pow_one]
78+
| (n + 2) :=
79+
begin
80+
simp only [eval_sub, eval_mul, lambdashev_eval_add_inv, eval_X, lambdashev_add_two],
81+
conv_lhs { simp only [pow_succ, add_mul, mul_add, h, ← mul_assoc, mul_comm y x, one_mul] },
82+
ring_exp
83+
end
84+
85+
variables (R)
86+
87+
lemma lambdashev_eq_chebyshev₁ [invertible (2 : R)] :
88+
∀ n, lambdashev R n = 2 * (chebyshev₁ R n).comp (C (⅟2) * X)
89+
| 0 := by simp only [chebyshev₁_zero, mul_one, one_comp, lambdashev_zero]
90+
| 1 := by rw [lambdashev_one, chebyshev₁_one, X_comp, ← mul_assoc, ← C_1, ← C_bit0, ← C_mul,
91+
mul_inv_of_self, C_1, one_mul]
92+
| (n + 2) :=
93+
begin
94+
simp only [lambdashev_add_two, chebyshev₁_add_two, lambdashev_eq_chebyshev₁ (n + 1),
95+
lambdashev_eq_chebyshev₁ n, sub_comp, mul_comp, add_comp, X_comp, bit0_comp, one_comp],
96+
simp only [← C_1, ← C_bit0, ← mul_assoc, ← C_mul, mul_inv_of_self],
97+
rw [C_1, one_mul],
98+
ring
99+
end
100+
101+
lemma chebyshev₁_eq_lambdashev [invertible (2 : R)] (n : ℕ) :
102+
chebyshev₁ R n = C (⅟2) * (lambdashev R n).comp (2 * X) :=
103+
begin
104+
rw lambdashev_eq_chebyshev₁,
105+
simp only [comp_assoc, mul_comp, C_comp, X_comp, ← mul_assoc, ← C_1, ← C_bit0, ← C_mul],
106+
rw [inv_of_mul_self, C_1, one_mul, one_mul, comp_X]
107+
end
108+
109+
/-- the `(m * n)`-th lambdashev polynomial is the composition of the `m`-th and `n`-th -/
110+
lemma lambdashev_mul (m n : ℕ) :
111+
lambdashev R (m * n) = (lambdashev R m).comp (lambdashev R n) :=
112+
begin
113+
simp only [← map_lambdashev (int.cast_ring_hom R), ← map_comp],
114+
congr' 1,
115+
apply map_injective (int.cast_ring_hom ℚ) int.cast_injective,
116+
simp only [map_lambdashev, map_comp, lambdashev_eq_chebyshev₁, chebyshev₁_mul, two_mul,
117+
← add_comp],
118+
simp only [← two_mul, ← comp_assoc],
119+
apply eval₂_congr rfl rfl,
120+
rw [comp_assoc],
121+
apply eval₂_congr rfl _ rfl,
122+
rw [mul_comp, C_comp, X_comp, ← mul_assoc, ← C_1, ← C_bit0, ← C_mul,
123+
inv_of_mul_self, C_1, one_mul]
124+
end
125+
126+
lemma lambdashev_comp_comm (m n : ℕ) :
127+
(lambdashev R m).comp (lambdashev R n) = (lambdashev R n).comp (lambdashev R m) :=
128+
by rw [← lambdashev_mul, mul_comm, lambdashev_mul]
129+
130+
lemma lambdashev_zmod_p (p : ℕ) [fact p.prime] :
131+
lambdashev (zmod p) p = X ^ p :=
132+
begin
133+
-- Recall that `lambdashev_eval_add_inv` characterises `lambdashev R p`
134+
-- as a polynomial that maps `x + x⁻¹` to `x ^ p + (x⁻¹) ^ p`.
135+
-- Since `X ^ p` also satisfies this property in characteristic `p`,
136+
-- we can use a variant on `polynomial.funext` to conclude that these polynomials are equal.
137+
-- For this argument, we need an arbitrary infinite field of characteristic `p`.
138+
obtain ⟨K, _, _, H⟩ : ∃ (K : Type) [field K], by exactI ∃ [char_p K p], infinite K,
139+
{ let K := fraction_ring (polynomial (zmod p)),
140+
let f : zmod p →+* K := (fraction_ring.of _).to_map.comp C,
141+
haveI : char_p K p := by { rw ← f.char_p_iff_char_p, apply_instance },
142+
haveI : infinite K :=
143+
by { apply infinite.of_injective _ (fraction_ring.of _).injective, apply_instance },
144+
refine ⟨K, _, _, _⟩; apply_instance },
145+
resetI,
146+
apply map_injective (zmod.cast_hom (dvd_refl p) K) (ring_hom.injective _),
147+
rw [map_lambdashev, map_pow, map_X],
148+
apply eq_of_infinite_eval_eq,
149+
-- The two polynomials agree on all `x` of the form `x = y + y⁻¹`.
150+
apply @set.infinite_mono _ {x : K | ∃ y, x = y + y⁻¹ ∧ y ≠ 0},
151+
{ rintro _ ⟨x, rfl, hx⟩,
152+
simp only [eval_X, eval_pow, set.mem_set_of_eq, @add_pow_char K _ p,
153+
lambdashev_eval_add_inv _ _ (mul_inv_cancel hx)] },
154+
-- Now we need to show that the set of such `x` is infinite.
155+
-- If the set is finite, then we will show that `K` is also finite.
156+
{ intro h,
157+
rw ← set.infinite_univ_iff at H,
158+
apply H,
159+
-- To each `x` of the form `x = y + y⁻¹`
160+
-- we `bind` the set of `y` that solve the equation `x = y + y⁻¹`.
161+
-- For every `x`, that set is finite (since it is governed by a quadratic equation).
162+
-- For the moment, we claim that all these sets together cover `K`.
163+
suffices : (set.univ : set K) =
164+
{x : K | ∃ (y : K), x = y + y⁻¹ ∧ y ≠ 0} >>= (λ x, {y | x = y + y⁻¹ ∨ y = 0}),
165+
{ rw this, clear this,
166+
apply set.finite_bind h,
167+
rintro x hx,
168+
-- The following quadratic polynomial has as solutions the `y` for which `x = y + y⁻¹`.
169+
let φ : polynomial K := X ^ 2 - C x * X + 1,
170+
have hφ : φ ≠ 0,
171+
{ intro H,
172+
have : φ.eval 0 = 0, by rw [H, eval_zero],
173+
simpa [eval_X, eval_one, eval_pow, eval_sub, sub_zero, eval_add,
174+
eval_mul, mul_zero, pow_two, zero_add, one_ne_zero] },
175+
classical,
176+
convert (φ.roots ∪ {0}).to_finset.finite_to_set using 1,
177+
ext1 y,
178+
simp only [multiset.mem_to_finset, set.mem_set_of_eq, finset.mem_coe, multiset.mem_union,
179+
mem_roots hφ, is_root, eval_add, eval_sub, eval_pow, eval_mul, eval_X, eval_C, eval_one,
180+
multiset.mem_singleton, multiset.singleton_eq_singleton],
181+
by_cases hy : y = 0,
182+
{ simp only [hy, eq_self_iff_true, or_true] },
183+
apply or_congr _ iff.rfl,
184+
rw [← mul_left_inj' hy, eq_comm, ← sub_eq_zero, add_mul, inv_mul_cancel hy],
185+
apply eq_iff_eq_cancel_right.mpr,
186+
ring },
187+
-- Finally, we prove the claim that our finite union of finite sets covers all of `K`.
188+
{ apply (set.eq_univ_of_forall _).symm,
189+
intro x,
190+
simp only [exists_prop, set.mem_Union, set.bind_def, ne.def, set.mem_set_of_eq],
191+
by_cases hx : x = 0,
192+
{ simp only [hx, and_true, eq_self_iff_true, inv_zero, or_true],
193+
exact ⟨_, 1, rfl, one_ne_zero⟩ },
194+
{ simp only [hx, or_false, exists_eq_right],
195+
exact ⟨_, rfl, hx⟩ } } }
196+
end
197+
198+
lemma lambdashev_char_p (p : ℕ) [fact p.prime] [char_p R p] :
199+
lambdashev R p = X ^ p :=
200+
by rw [← map_lambdashev (zmod.cast_hom (dvd_refl p) R), lambdashev_zmod_p, map_pow, map_X]
201+
202+
end lambdashev
203+
204+
end polynomial
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import ring_theory.polynomial.chebyshev.basic
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/-
2+
Copyright (c) 2020 Johan Commelin. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Johan Commelin
5+
-/
6+
7+
import data.polynomial.eval
8+
9+
/-!
10+
# Chebyshev polynomials
11+
12+
The Chebyshev polynomials are two families of polynomials indexed by `ℕ`,
13+
with integral coefficients.
14+
In this file, we only consider Chebyshev polynomials of the first kind.
15+
16+
See the file `ring_theory.polynomial.chebyshev.basic` for more properties.
17+
18+
## Main declarations
19+
20+
* `polynomial.chebyshev₁`: the Chebyshev polynomials of the first kind.
21+
* `polynomial.lambdashev`: a variant on the Chebyshev polynomials that define a Lambda structure
22+
on `polynomial ℤ`.
23+
24+
## Implementation details
25+
26+
In this file we only give definitions and some very elementary simp-lemmas.
27+
This way, we can import this file in `analysis.special_functions.trigonometric`,
28+
and import that file in turn, in `ring_theory.polynomial.chebyshev.basic`.
29+
30+
## TODO
31+
32+
Add Chebyshev polynomials of the second kind.
33+
-/
34+
35+
36+
noncomputable theory
37+
38+
namespace polynomial
39+
40+
variables (R S : Type*) [comm_ring R] [comm_ring S]
41+
42+
/-- `chebyshev₁ n` is the `n`-th Chebyshev polynomial of the first kind -/
43+
noncomputable def chebyshev₁ : ℕ → polynomial R
44+
| 0 := 1
45+
| 1 := X
46+
| (n + 2) := 2 * X * chebyshev₁ (n + 1) - chebyshev₁ n
47+
48+
@[simp] lemma chebyshev₁_zero : chebyshev₁ R 0 = 1 := rfl
49+
@[simp] lemma chebyshev₁_one : chebyshev₁ R 1 = X := rfl
50+
lemma chebyshev₁_two : chebyshev₁ R 2 = 2 * X ^ 2 - 1 :=
51+
by simp only [chebyshev₁, sub_left_inj, pow_two, mul_assoc]
52+
@[simp] lemma chebyshev₁_add_two (n : ℕ) :
53+
chebyshev₁ R (n + 2) = 2 * X * chebyshev₁ R (n + 1) - chebyshev₁ R n :=
54+
by rw chebyshev₁
55+
56+
lemma chebyshev₁_of_two_le (n : ℕ) (h : 2 ≤ n) :
57+
chebyshev₁ R n = 2 * X * chebyshev₁ R (n - 1) - chebyshev₁ R (n - 2) :=
58+
begin
59+
obtain ⟨n, rfl⟩ := nat.exists_eq_add_of_le h,
60+
rw add_comm,
61+
exact chebyshev₁_add_two R n
62+
end
63+
64+
variables {R S}
65+
66+
lemma map_chebyshev₁ (f : R →+* S) :
67+
∀ (n : ℕ), map f (chebyshev₁ R n) = chebyshev₁ S n
68+
| 0 := by simp only [chebyshev₁_zero, map_one]
69+
| 1 := by simp only [chebyshev₁_one, map_X]
70+
| (n + 2) :=
71+
begin
72+
simp only [chebyshev₁_add_two, map_mul, map_sub, map_X, bit0, map_add, map_one],
73+
rw [map_chebyshev₁ (n + 1), map_chebyshev₁ n],
74+
end
75+
76+
variables (R)
77+
78+
/-- `lambdashev R n` is equal to `2 * (chebyshev₁ R n).comp (X / 2)`.
79+
It is a family of polynomials that satisfies
80+
`lambdashev (zmod p) p = X ^ p`, and therefore defines a Lambda structure on `polynomial ℤ`. -/
81+
noncomputable def lambdashev : ℕ → polynomial R
82+
| 0 := 2
83+
| 1 := X
84+
| (n + 2) := X * lambdashev (n + 1) - lambdashev n
85+
86+
@[simp] lemma lambdashev_zero : lambdashev R 0 = 2 := rfl
87+
@[simp] lemma lambdashev_one : lambdashev R 1 = X := rfl
88+
lemma lambdashev_two : lambdashev R 2 = X ^ 2 - 2 :=
89+
by simp only [lambdashev, sub_left_inj, pow_two, mul_assoc]
90+
@[simp] lemma lambdashev_add_two (n : ℕ) :
91+
lambdashev R (n + 2) = X * lambdashev R (n + 1) - lambdashev R n :=
92+
by rw lambdashev
93+
94+
lemma lambdashev_eq_two_le (n : ℕ) (h : 2 ≤ n) :
95+
lambdashev R n = X * lambdashev R (n - 1) - lambdashev R (n - 2) :=
96+
begin
97+
obtain ⟨n, rfl⟩ := nat.exists_eq_add_of_le h,
98+
rw add_comm,
99+
exact lambdashev_add_two R n
100+
end
101+
102+
variables {R S}
103+
104+
lemma map_lambdashev (f : R →+* S) :
105+
∀ (n : ℕ), map f (lambdashev R n) = lambdashev S n
106+
| 0 := by simp only [lambdashev_zero, bit0, map_add, map_one]
107+
| 1 := by simp only [lambdashev_one, map_X]
108+
| (n + 2) :=
109+
begin
110+
simp only [lambdashev_add_two, map_mul, map_sub, map_X, bit0, map_add, map_one],
111+
rw [map_lambdashev (n + 1), map_lambdashev n],
112+
end
113+
114+
115+
end polynomial

0 commit comments

Comments
 (0)