-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Expand file tree
/
Copy pathOfScalars.lean
More file actions
330 lines (274 loc) · 14.3 KB
/
OfScalars.lean
File metadata and controls
330 lines (274 loc) · 14.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/-
Copyright (c) 2024 Edward Watine. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Edward Watine
-/
module
public import Mathlib.Analysis.Analytic.ConvergenceRadius
/-!
# Scalar series
This file contains API for analytic functions `∑ cᵢ • xⁱ` defined in terms of scalars
`c₀, c₁, c₂, …`.
## Main definitions / results:
* `FormalMultilinearSeries.ofScalars`: the formal power series `∑ cᵢ • xⁱ`.
* `FormalMultilinearSeries.ofScalarsSum`: the sum of such a power series, if it exists, and zero
otherwise.
* `FormalMultilinearSeries.ofScalars_radius_eq_(zero/inv/top)_of_tendsto`:
the ratio test for an analytic function defined in terms of a formal power series `∑ cᵢ • xⁱ`.
* `FormalMultilinearSeries.ofScalars_radius_eq_inv_of_tendsto_ENNReal`:
the ratio test for an analytic function using `ENNReal` division for all values `ℝ≥0∞`.
-/
@[expose] public section
namespace FormalMultilinearSeries
section Field
open ContinuousMultilinearMap
variable {𝕜 : Type*} (E : Type*) [Field 𝕜] [Ring E] [Algebra 𝕜 E] [TopologicalSpace E]
[IsTopologicalRing E] {c : ℕ → 𝕜}
/-- Formal power series of `∑ cᵢ • xⁱ` for some scalar field `𝕜` and ring algebra `E` -/
def ofScalars (c : ℕ → 𝕜) : FormalMultilinearSeries 𝕜 E E :=
fun n ↦ c n • ContinuousMultilinearMap.mkPiAlgebraFin 𝕜 n E
@[simp]
theorem ofScalars_eq_zero [Nontrivial E] (n : ℕ) : ofScalars E c n = 0 ↔ c n = 0 := by
rw [ofScalars, smul_eq_zero]
refine or_iff_left (ContinuousMultilinearMap.ext_iff.1.mt <| not_forall_of_exists_not ?_)
use fun _ ↦ 1
simp
@[simp]
theorem ofScalars_eq_zero_of_scalar_zero {n : ℕ} (hc : c n = 0) : ofScalars E c n = 0 := by
rw [ofScalars, hc, zero_smul 𝕜 (ContinuousMultilinearMap.mkPiAlgebraFin 𝕜 n E)]
@[simp]
theorem ofScalars_series_eq_zero [Nontrivial E] : ofScalars E c = 0 ↔ c = 0 := by
simp [FormalMultilinearSeries.ext_iff, funext_iff]
variable (𝕜) in
@[simp]
theorem ofScalars_series_eq_zero_of_scalar_zero : ofScalars E (0 : ℕ → 𝕜) = 0 := by
simp [FormalMultilinearSeries.ext_iff]
@[simp]
theorem ofScalars_series_of_subsingleton [Subsingleton E] : ofScalars E c = 0 := by
simp_rw [FormalMultilinearSeries.ext_iff, ofScalars, ContinuousMultilinearMap.ext_iff]
exact fun _ _ ↦ Subsingleton.allEq _ _
variable (𝕜) in
theorem ofScalars_series_injective [Nontrivial E] : Function.Injective (ofScalars E (𝕜 := 𝕜)) := by
intro c c' h
funext n
simpa [ofScalars] using congrArg (fun p => p n fun _ ↦ (1 : E)) h
variable (c)
@[simp]
theorem ofScalars_series_eq_iff [Nontrivial E] (c' : ℕ → 𝕜) :
ofScalars E c = ofScalars E c' ↔ c = c' :=
⟨fun e => ofScalars_series_injective 𝕜 E e, _root_.congrArg _⟩
theorem ofScalars_apply_zero (n : ℕ) :
ofScalars E c n (fun _ => 0) = Pi.single (M := fun _ => E) 0 (c 0 • 1) n := by
rw [ofScalars]
cases n <;> simp
@[simp]
lemma coeff_ofScalars {𝕜 : Type*} [NontriviallyNormedField 𝕜] {p : ℕ → 𝕜} {n : ℕ} :
(FormalMultilinearSeries.ofScalars 𝕜 p).coeff n = p n := by
simp [FormalMultilinearSeries.coeff, FormalMultilinearSeries.ofScalars, List.prod_ofFn]
theorem ofScalars_add (c' : ℕ → 𝕜) : ofScalars E (c + c') = ofScalars E c + ofScalars E c' := by
ext n x
simp [ofScalars, add_smul]
lemma ofScalars_sub (c' : ℕ → 𝕜) : ofScalars E (c - c') = ofScalars E c - ofScalars E c' := by
ext; simp [ofScalars, sub_smul]
theorem ofScalars_smul (x : 𝕜) : ofScalars E (x • c) = x • ofScalars E c := by
ext n y
simp [ofScalars, smul_smul]
theorem ofScalars_comp_neg_id :
(ofScalars E c).compContinuousLinearMap (-ContinuousLinearMap.id _ _) =
(ofScalars E (fun k ↦ (-1) ^ k * c k)) := by
ext n
rcases n.even_or_odd with (h | h) <;>
simp [ofScalars, show ((-ContinuousLinearMap.id 𝕜 E : _) : E → E) = Neg.neg by rfl,
← List.map_ofFn, h.neg_one_pow]
theorem ofScalars_comp_neg (f : E →L[𝕜] E) :
(ofScalars E c).compContinuousLinearMap (-f) =
(ofScalars E (fun k ↦ (-1) ^ k * c k)).compContinuousLinearMap f := by
conv => lhs; rw [← ContinuousLinearMap.id_comp f, ← ContinuousLinearMap.neg_comp]
rw [← FormalMultilinearSeries.compContinuousLinearMap_comp, ofScalars_comp_neg_id]
variable (𝕜) in
/-- The submodule generated by scalar series on `FormalMultilinearSeries 𝕜 E E`. -/
def ofScalarsSubmodule : Submodule 𝕜 (FormalMultilinearSeries 𝕜 E E) where
carrier := {ofScalars E f | f}
add_mem' := fun ⟨c, hc⟩ ⟨c', hc'⟩ ↦ ⟨c + c', hc' ▸ hc ▸ ofScalars_add E c c'⟩
zero_mem' := ⟨0, ofScalars_series_eq_zero_of_scalar_zero 𝕜 E⟩
smul_mem' := fun x _ ⟨c, hc⟩ ↦ ⟨x • c, hc ▸ ofScalars_smul E c x⟩
variable {E}
theorem ofScalars_apply_eq (x : E) (n : ℕ) :
ofScalars E c n (fun _ ↦ x) = c n • x ^ n := by
simp [ofScalars]
/-- This naming follows the convention of `NormedSpace.expSeries_apply_eq'`. -/
theorem ofScalars_apply_eq' (x : E) :
(fun n ↦ ofScalars E c n (fun _ ↦ x)) = fun n ↦ c n • x ^ n := by
simp [ofScalars]
/-- The sum of the formal power series. Takes the value `0` outside the radius of convergence. -/
noncomputable def ofScalarsSum := (ofScalars E c).sum
theorem ofScalars_sum_eq (x : E) : ofScalarsSum c x =
∑' n, c n • x ^ n := tsum_congr fun n => ofScalars_apply_eq c x n
theorem ofScalarsSum_eq_tsum : ofScalarsSum c =
fun (x : E) => ∑' n : ℕ, c n • x ^ n := funext (ofScalars_sum_eq c)
@[simp]
theorem ofScalarsSum_zero : ofScalarsSum c (0 : E) = c 0 • 1 := by
simp [ofScalarsSum_eq_tsum, ← ofScalars_apply_eq, ofScalars_apply_zero]
@[simp]
theorem ofScalarsSum_of_subsingleton [Subsingleton E] {x : E} : ofScalarsSum c x = 0 := by
simp [Subsingleton.eq_zero x, Subsingleton.eq_zero (1 : E)]
@[simp]
theorem ofScalarsSum_op [T2Space E] (x : E) :
ofScalarsSum c (MulOpposite.op x) = MulOpposite.op (ofScalarsSum c x) := by
simp [ofScalars_sum_eq, ← MulOpposite.op_pow, ← MulOpposite.op_smul, tsum_op]
@[simp]
theorem ofScalarsSum_unop [T2Space E] (x : Eᵐᵒᵖ) :
ofScalarsSum c (MulOpposite.unop x) = MulOpposite.unop (ofScalarsSum c x) := by
simp [ofScalars_sum_eq, ← MulOpposite.unop_pow, ← MulOpposite.unop_smul, tsum_unop]
end Field
section Seminormed
open Filter ENNReal
open scoped Topology NNReal
variable {𝕜 : Type*} (E : Type*) [NontriviallyNormedField 𝕜] [SeminormedRing E]
[NormedAlgebra 𝕜 E] (c : ℕ → 𝕜) (n : ℕ)
@[simp]
theorem ofScalars_norm_eq_mul :
‖ofScalars E c n‖ = ‖c n‖ * ‖ContinuousMultilinearMap.mkPiAlgebraFin 𝕜 n E‖ := by
rw [ofScalars, norm_smul]
theorem ofScalars_norm_le (hn : n > 0) : ‖ofScalars E c n‖ ≤ ‖c n‖ := by
simp only [ofScalars_norm_eq_mul]
exact (mul_le_of_le_one_right (norm_nonneg _)
(ContinuousMultilinearMap.norm_mkPiAlgebraFin_le_of_pos hn))
theorem ofScalars_norm [NormOneClass E] : ‖ofScalars E c n‖ = ‖c n‖ := by
simp
end Seminormed
section Normed
open Filter ENNReal
open scoped Topology NNReal
variable {𝕜 : Type*} (E : Type*) [NontriviallyNormedField 𝕜] [NormedRing E]
[NormedAlgebra 𝕜 E] (c : ℕ → 𝕜) (n : ℕ)
private theorem tendsto_succ_norm_div_norm {r r' : ℝ≥0} (hr' : r' ≠ 0)
(hc : Tendsto (fun n ↦ ‖c n.succ‖ / ‖c n‖) atTop (𝓝 r)) :
Tendsto (fun n ↦ ‖‖c (n + 1)‖ * r' ^ (n + 1)‖ /
‖‖c n‖ * r' ^ n‖) atTop (𝓝 ↑(r' * r)) := by
simp_rw [norm_mul, norm_norm, mul_div_mul_comm, ← norm_div, pow_succ, mul_div_right_comm,
div_self (pow_ne_zero _ (NNReal.coe_ne_zero.mpr hr')), one_mul, norm_div, NNReal.norm_eq]
exact mul_comm r' r ▸ hc.mul tendsto_const_nhds
theorem inv_le_ofScalars_radius_of_tendsto {r : ℝ≥0} (hr : r ≠ 0)
(hc : Tendsto (fun n ↦ ‖c n.succ‖ / ‖c n‖) atTop (𝓝 r)) :
ofNNReal r⁻¹ ≤ (ofScalars E c).radius := by
refine le_of_forall_nnreal_lt (fun r' hr' ↦ ?_)
rw [coe_lt_coe, NNReal.lt_inv_iff_mul_lt hr] at hr'
by_cases hrz : r' = 0
· simp [hrz]
apply FormalMultilinearSeries.le_radius_of_summable_norm
refine Summable.of_norm_bounded_eventually (g := fun n ↦ ‖‖c n‖ * r' ^ n‖) ?_ ?_
· refine summable_of_ratio_test_tendsto_lt_one hr' ?_ ?_
· refine (hc.eventually_ne (NNReal.coe_ne_zero.mpr hr)).mp (Eventually.of_forall ?_)
simp_all
· simp_rw [norm_norm]
exact tendsto_succ_norm_div_norm c hrz hc
· filter_upwards [eventually_cofinite_ne 0] with n hn
simp only [norm_mul, norm_norm, norm_pow, NNReal.norm_eq]
gcongr
exact ofScalars_norm_le E c n (Nat.pos_iff_ne_zero.mpr hn)
@[deprecated (since := "2025-11-21")]
alias ofScalars_radius_ge_inv_of_tendsto := inv_le_ofScalars_radius_of_tendsto
/-- The radius of convergence of a scalar series is the inverse of the non-zero limit
`fun n ↦ ‖c n.succ‖ / ‖c n‖`. -/
theorem ofScalars_radius_eq_inv_of_tendsto [NormOneClass E] {r : ℝ≥0} (hr : r ≠ 0)
(hc : Tendsto (fun n ↦ ‖c n.succ‖ / ‖c n‖) atTop (𝓝 r)) :
(ofScalars E c).radius = ofNNReal r⁻¹ := by
refine le_antisymm ?_ (inv_le_ofScalars_radius_of_tendsto E c hr hc)
refine le_of_forall_nnreal_lt (fun r' hr' ↦ ?_)
rw [coe_le_coe, NNReal.le_inv_iff_mul_le hr]
have := FormalMultilinearSeries.summable_norm_mul_pow _ hr'
contrapose! this
apply not_summable_of_ratio_test_tendsto_gt_one this
simp_rw [ofScalars_norm]
exact tendsto_succ_norm_div_norm c (by aesop) hc
/-- A convenience lemma restating the result of `ofScalars_radius_eq_inv_of_tendsto` under
the inverse ratio. -/
theorem ofScalars_radius_eq_of_tendsto [NormOneClass E] {r : NNReal} (hr : r ≠ 0)
(hc : Tendsto (fun n ↦ ‖c n‖ / ‖c n.succ‖) atTop (𝓝 r)) :
(ofScalars E c).radius = ofNNReal r := by
suffices Tendsto (fun n ↦ ‖c n.succ‖ / ‖c n‖) atTop (𝓝 r⁻¹) by
convert ofScalars_radius_eq_inv_of_tendsto E c (inv_ne_zero hr) this
simp
convert hc.inv₀ (NNReal.coe_ne_zero.mpr hr) using 1
simp
/-- The ratio test stating that if `‖c n.succ‖ / ‖c n‖` tends to zero, the radius is unbounded.
This requires that the coefficients are eventually non-zero as
`‖c n.succ‖ / 0 = 0` by convention. -/
theorem ofScalars_radius_eq_top_of_tendsto (hc : ∀ᶠ n in atTop, c n ≠ 0)
(hc' : Tendsto (fun n ↦ ‖c n.succ‖ / ‖c n‖) atTop (𝓝 0)) : (ofScalars E c).radius = ⊤ := by
refine radius_eq_top_of_summable_norm _ fun r' ↦ ?_
by_cases hrz : r' = 0
· apply Summable.comp_nat_add (k := 1)
simp [hrz]
· refine Summable.of_norm_bounded_eventually (g := fun n ↦ ‖‖c n‖ * r' ^ n‖) ?_ ?_
· apply summable_of_ratio_test_tendsto_lt_one zero_lt_one (hc.mp (Eventually.of_forall ?_))
· simp only [norm_norm]
exact mul_zero (_ : ℝ) ▸ tendsto_succ_norm_div_norm _ hrz (NNReal.coe_zero ▸ hc')
· simp_all
· filter_upwards [eventually_cofinite_ne 0] with n hn
simp only [norm_mul, norm_norm, norm_pow, NNReal.norm_eq]
gcongr
exact ofScalars_norm_le E c n (Nat.pos_iff_ne_zero.mpr hn)
/-- If `‖c n.succ‖ / ‖c n‖` is unbounded, then the radius of convergence is zero. -/
theorem ofScalars_radius_eq_zero_of_tendsto [NormOneClass E]
(hc : Tendsto (fun n ↦ ‖c n.succ‖ / ‖c n‖) atTop atTop) : (ofScalars E c).radius = 0 := by
suffices (ofScalars E c).radius ≤ 0 by simp_all
refine le_of_forall_nnreal_lt (fun r hr ↦ ?_)
rw [← coe_zero, coe_le_coe]
have := FormalMultilinearSeries.summable_norm_mul_pow _ hr
contrapose! this
refine not_summable_of_ratio_norm_eventually_ge (r := 2) (by simp) ?_ ?_
· contrapose! hc
apply not_tendsto_atTop_of_tendsto_nhds (a := 0)
apply Tendsto.congr' ?_ tendsto_const_nhds
filter_upwards [hc] with n hc'
rw [ofScalars_norm, norm_mul, norm_norm, mul_eq_zero] at hc'
cases hc' <;> aesop
· filter_upwards [hc.eventually_ge_atTop (2 * r⁻¹), eventually_ne_atTop 0] with n hc hn
simp only [ofScalars_norm, norm_mul, norm_norm, norm_pow, NNReal.norm_eq]
rw [mul_comm ‖c n‖, ← mul_assoc, ← div_le_div_iff₀, mul_div_assoc]
· convert hc
rw [pow_succ, div_mul_cancel_left₀, NNReal.coe_inv]
aesop
· simp_all
· refine Ne.lt_of_le (fun hr' ↦ Not.elim ?_ hc) (norm_nonneg _)
rw [← hr']
simp [this]
/-- This theorem combines the results of the special cases above, using `ENNReal` division to remove
the requirement that the ratio is eventually non-zero. -/
theorem ofScalars_radius_eq_inv_of_tendsto_ENNReal [NormOneClass E] {r : ℝ≥0∞}
(hc' : Tendsto (fun n ↦ ENNReal.ofReal ‖c n.succ‖ / ENNReal.ofReal ‖c n‖) atTop (𝓝 r)) :
(ofScalars E c).radius = r⁻¹ := by
rcases ENNReal.trichotomy r with (hr | hr | hr)
· simp_rw [hr, inv_zero] at hc' ⊢
by_cases h : (∀ᶠ (n : ℕ) in atTop, c n ≠ 0)
· apply ofScalars_radius_eq_top_of_tendsto E c h ?_
refine Tendsto.congr' ?_ <| (tendsto_toReal zero_ne_top).comp hc'
filter_upwards [h]
simp
· apply (ofScalars E c).radius_eq_top_of_eventually_eq_zero
simp only [eventually_atTop, not_exists, not_forall, not_not] at h ⊢
obtain ⟨ti, hti⟩ := eventually_atTop.mp (hc'.eventually_ne zero_ne_top)
obtain ⟨zi, hzi, z⟩ := h ti
refine ⟨zi, Nat.le_induction (ofScalars_eq_zero_of_scalar_zero E z) fun n hmn a ↦ ?_⟩
nontriviality E
simp only [ofScalars_eq_zero] at a ⊢
contrapose! hti
exact ⟨n, hzi.trans hmn, ENNReal.div_eq_top.mpr (by simp [a, hti])⟩
· simp_rw [hr, inv_top] at hc' ⊢
apply ofScalars_radius_eq_zero_of_tendsto E c ((tendsto_add_atTop_iff_nat 1).mp ?_)
refine tendsto_ofReal_nhds_top.mp (Tendsto.congr' ?_ ((tendsto_add_atTop_iff_nat 1).mpr hc'))
filter_upwards [hc'.eventually_ne top_ne_zero] with n hn
apply (ofReal_div_of_pos (Ne.lt_of_le (Ne.symm ?_) (norm_nonneg _))).symm
simp_all
· have hr' := toReal_ne_zero.mp hr.ne.symm
have hr'' := toNNReal_ne_zero.mpr hr' -- this result could go in ENNReal
convert ofScalars_radius_eq_inv_of_tendsto E c hr'' ?_
· simp [ENNReal.coe_inv hr'', ENNReal.coe_toNNReal (toReal_ne_zero.mp hr.ne.symm).2]
· simp_rw [ENNReal.coe_toNNReal_eq_toReal]
refine Tendsto.congr' ?_ <| (tendsto_toReal hr'.2).comp hc'
filter_upwards [hc'.eventually_ne hr'.1, hc'.eventually_ne hr'.2]
simp
end Normed
end FormalMultilinearSeries