forked from leanprover-community/mathlib4
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathChangeOrigin.lean
More file actions
398 lines (341 loc) · 19.7 KB
/
Copy pathChangeOrigin.lean
File metadata and controls
398 lines (341 loc) · 19.7 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
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
/-
Copyright (c) 2020 Sébastien Gouëzel. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sébastien Gouëzel, Yury Kudryashov
-/
module
public import Mathlib.Analysis.Analytic.Basic
/-!
# Changing origin in a power series
If a function is analytic in a disk `D(x, R)`, then it is analytic in any disk contained in that
one. Indeed, one can write
$$
f (x + y + z) = \sum_{n} p_n (y + z)^n = \sum_{n, k} \binom{n}{k} p_n y^{n-k} z^k
= \sum_{k} \Bigl(\sum_{n} \binom{n}{k} p_n y^{n-k}\Bigr) z^k.
$$
The corresponding power series has thus a `k`-th coefficient equal to
$\sum_{n} \binom{n}{k} p_n y^{n-k}$. In the general case where `pₙ` is a multilinear map, this has
to be interpreted suitably: instead of having a binomial coefficient, one should sum over all
possible subsets `s` of `Fin n` of cardinality `k`, and attribute `z` to the indices in `s` and
`y` to the indices outside of `s`.
In this file, we implement this. The new power series is called `p.changeOrigin y`. Then, we
check its convergence and the fact that its sum coincides with the original sum. The outcome of this
discussion is that the set of points where a function is analytic is open. All these arguments
require the target space to be complete, as otherwise the series might not converge.
### Main results
In a complete space, if a function admits a power series in a ball, then it is analytic at any
point `y` of this ball, and the power series there can be expressed in terms of the initial power
series `p` as `p.changeOrigin y`. See `HasFPowerSeriesOnBall.changeOrigin`. It follows in particular
that the set of points at which a given function is analytic is open, see `isOpen_analyticAt`.
-/
@[expose] public section
noncomputable section
open scoped NNReal ENNReal Topology
open Filter Set
variable {𝕜 E F : Type*} [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E]
[NormedAddCommGroup F] [NormedSpace 𝕜 F]
namespace FormalMultilinearSeries
section
variable (p : FormalMultilinearSeries 𝕜 E F) {x y : E} {r : ℝ≥0}
/-- A term of `FormalMultilinearSeries.changeOriginSeries`.
Given a formal multilinear series `p` and a point `x` in its ball of convergence,
`p.changeOrigin x` is a formal multilinear series such that
`p.sum (x+y) = (p.changeOrigin x).sum y` when this makes sense. Each term of `p.changeOrigin x`
is itself an analytic function of `x` given by the series `p.changeOriginSeries`. Each term in
`changeOriginSeries` is the sum of `changeOriginSeriesTerm`'s over all `s` of cardinality `l`.
The definition is such that `p.changeOriginSeriesTerm k l s hs (fun _ ↦ x) (fun _ ↦ y) =
p (k + l) (s.piecewise (fun _ ↦ x) (fun _ ↦ y))`
-/
def changeOriginSeriesTerm (k l : ℕ) (s : Finset (Fin (k + l))) (hs : s.card = l) :
E [×l]→L[𝕜] E [×k]→L[𝕜] F :=
let a := ContinuousMultilinearMap.curryFinFinset 𝕜 E F hs
(by rw [Finset.card_compl, Fintype.card_fin, hs, add_tsub_cancel_right])
a (p (k + l))
theorem changeOriginSeriesTerm_apply (k l : ℕ) (s : Finset (Fin (k + l))) (hs : s.card = l)
(x y : E) :
(p.changeOriginSeriesTerm k l s hs (fun _ => x) fun _ => y) =
p (k + l) (s.piecewise (fun _ => x) fun _ => y) :=
ContinuousMultilinearMap.curryFinFinset_apply_const _ _ _ _ _
@[simp]
theorem norm_changeOriginSeriesTerm (k l : ℕ) (s : Finset (Fin (k + l))) (hs : s.card = l) :
‖p.changeOriginSeriesTerm k l s hs‖ = ‖p (k + l)‖ := by
simp only [changeOriginSeriesTerm, LinearIsometryEquiv.norm_map]
@[simp]
theorem nnnorm_changeOriginSeriesTerm (k l : ℕ) (s : Finset (Fin (k + l))) (hs : s.card = l) :
‖p.changeOriginSeriesTerm k l s hs‖₊ = ‖p (k + l)‖₊ := by
simp only [changeOriginSeriesTerm, LinearIsometryEquiv.nnnorm_map]
theorem nnnorm_changeOriginSeriesTerm_apply_le (k l : ℕ) (s : Finset (Fin (k + l)))
(hs : s.card = l) (x y : E) :
‖p.changeOriginSeriesTerm k l s hs (fun _ => x) fun _ => y‖₊ ≤
‖p (k + l)‖₊ * ‖x‖₊ ^ l * ‖y‖₊ ^ k := by
rw [← p.nnnorm_changeOriginSeriesTerm k l s hs, ← Fin.prod_const, ← Fin.prod_const]
apply ContinuousMultilinearMap.le_of_opNNNorm_le
apply ContinuousMultilinearMap.le_opNNNorm
/-- The power series for `f.changeOrigin k`.
Given a formal multilinear series `p` and a point `x` in its ball of convergence,
`p.changeOrigin x` is a formal multilinear series such that
`p.sum (x+y) = (p.changeOrigin x).sum y` when this makes sense. Its `k`-th term is the sum of
the series `p.changeOriginSeries k`. -/
def changeOriginSeries (k : ℕ) : FormalMultilinearSeries 𝕜 E (E [×k]→L[𝕜] F) := fun l =>
∑ s : { s : Finset (Fin (k + l)) // Finset.card s = l }, p.changeOriginSeriesTerm k l s s.2
theorem nnnorm_changeOriginSeries_le_tsum (k l : ℕ) :
‖p.changeOriginSeries k l‖₊ ≤
∑' _ : { s : Finset (Fin (k + l)) // s.card = l }, ‖p (k + l)‖₊ :=
(nnnorm_sum_le _ (fun t => changeOriginSeriesTerm p k l (Subtype.val t) t.prop)).trans_eq <| by
simp_rw [tsum_fintype, nnnorm_changeOriginSeriesTerm (p := p) (k := k) (l := l)]
theorem nnnorm_changeOriginSeries_apply_le_tsum (k l : ℕ) (x : E) :
‖p.changeOriginSeries k l fun _ => x‖₊ ≤
∑' _ : { s : Finset (Fin (k + l)) // s.card = l }, ‖p (k + l)‖₊ * ‖x‖₊ ^ l := by
rw [NNReal.tsum_mul_right, ← Fin.prod_const]
exact (p.changeOriginSeries k l).le_of_opNNNorm_le (p.nnnorm_changeOriginSeries_le_tsum _ _) _
/-- Changing the origin of a formal multilinear series `p`, so that
`p.sum (x+y) = (p.changeOrigin x).sum y` when this makes sense.
-/
def changeOrigin (x : E) : FormalMultilinearSeries 𝕜 E F :=
fun k => (p.changeOriginSeries k).sum x
/-- An auxiliary equivalence useful in the proofs about
`FormalMultilinearSeries.changeOriginSeries`: the set of triples `(k, l, s)`, where `s` is a
`Finset (Fin (k + l))` of cardinality `l` is equivalent to the set of pairs `(n, s)`, where `s` is a
`Finset (Fin n)`.
The forward map sends `(k, l, s)` to `(k + l, s)` and the inverse map sends `(n, s)` to
`(n - Finset.card s, Finset.card s, s)`. The actual definition is less readable because of problems
with non-definitional equalities. -/
@[simps]
def changeOriginIndexEquiv :
(Σ k l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) ≃ Σ n : ℕ, Finset (Fin n) where
toFun s := ⟨s.1 + s.2.1, s.2.2⟩
invFun s :=
⟨s.1 - s.2.card, s.2.card,
⟨s.2.map
(finCongr <| (tsub_add_cancel_of_le <| card_finset_fin_le s.2).symm).toEmbedding,
Finset.card_map _⟩⟩
left_inv := by
rintro ⟨k, l, ⟨s : Finset (Fin <| k + l), hs : s.card = l⟩⟩
dsimp only [Subtype.coe_mk]
-- Lean can't automatically generalize `k' = k + l - s.card`, `l' = s.card`, so we explicitly
-- formulate the generalized goal
suffices ∀ k' l', k' = k → l' = l → ∀ (hkl : k + l = k' + l') (hs'),
(⟨k', l', ⟨s.map (finCongr hkl).toEmbedding, hs'⟩⟩ :
Σ k l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) = ⟨k, l, ⟨s, hs⟩⟩ by
apply this <;> simp only [hs, add_tsub_cancel_right]
simp
right_inv := by
rintro ⟨n, s⟩
simp [tsub_add_cancel_of_le (card_finset_fin_le s), finCongr_eq_equivCast]
lemma changeOriginSeriesTerm_changeOriginIndexEquiv_symm (n t) :
let s := changeOriginIndexEquiv.symm ⟨n, t⟩
p.changeOriginSeriesTerm s.1 s.2.1 s.2.2 s.2.2.2 (fun _ ↦ x) (fun _ ↦ y) =
p n (t.piecewise (fun _ ↦ x) fun _ ↦ y) := by
have : ∀ (m) (hm : n = m), p n (t.piecewise (fun _ ↦ x) fun _ ↦ y) =
p m ((t.map (finCongr hm).toEmbedding).piecewise (fun _ ↦ x) fun _ ↦ y) := by
rintro m rfl
simp +unfoldPartialApp [Finset.piecewise]
simp_rw [changeOriginSeriesTerm_apply, eq_comm]; apply this
set_option backward.isDefEq.respectTransparency false in
theorem changeOriginSeries_summable_aux₁ {r r' : ℝ≥0} (hr : (r + r' : ℝ≥0∞) < p.radius) :
Summable fun s : Σ k l : ℕ, { s : Finset (Fin (k + l)) // s.card = l } =>
‖p (s.1 + s.2.1)‖₊ * r ^ s.2.1 * r' ^ s.1 := by
rw [← changeOriginIndexEquiv.symm.summable_iff]
dsimp only [Function.comp_def, changeOriginIndexEquiv_symm_apply_fst,
changeOriginIndexEquiv_symm_apply_snd_fst]
have : ∀ n : ℕ,
HasSum (fun s : Finset (Fin n) => ‖p (n - s.card + s.card)‖₊ * r ^ s.card * r' ^ (n - s.card))
(‖p n‖₊ * (r + r') ^ n) := by
intro n
-- TODO: why `simp only [tsub_add_cancel_of_le (card_finset_fin_le _)]` fails?
convert_to HasSum (fun s : Finset (Fin n) => ‖p n‖₊ * (r ^ s.card * r' ^ (n - s.card))) _
· ext1 s
rw [tsub_add_cancel_of_le (card_finset_fin_le _), mul_assoc]
rw [← Fin.sum_pow_mul_eq_add_pow]
exact (hasSum_fintype _).mul_left _
refine NNReal.summable_sigma.2 ⟨fun n => (this n).summable, ?_⟩
simp only [(this _).tsum_eq]
exact p.summable_nnnorm_mul_pow hr
theorem changeOriginSeries_summable_aux₂ (hr : (r : ℝ≥0∞) < p.radius) (k : ℕ) :
Summable fun s : Σ l : ℕ, { s : Finset (Fin (k + l)) // s.card = l } =>
‖p (k + s.1)‖₊ * r ^ s.1 := by
rcases ENNReal.lt_iff_exists_add_pos_lt.1 hr with ⟨r', h0, hr'⟩
simpa only [mul_inv_cancel_right₀ (pow_pos h0 _).ne'] using
((NNReal.summable_sigma.1 (p.changeOriginSeries_summable_aux₁ hr')).1 k).mul_right (r' ^ k)⁻¹
theorem changeOriginSeries_summable_aux₃ {r : ℝ≥0} (hr : ↑r < p.radius) (k : ℕ) :
Summable fun l : ℕ => ‖p.changeOriginSeries k l‖₊ * r ^ l := by
refine NNReal.summable_of_le
(fun n => ?_) (NNReal.summable_sigma.1 <| p.changeOriginSeries_summable_aux₂ hr k).2
simp only [NNReal.tsum_mul_right]
gcongr
apply p.nnnorm_changeOriginSeries_le_tsum
theorem le_changeOriginSeries_radius (k : ℕ) : p.radius ≤ (p.changeOriginSeries k).radius :=
ENNReal.le_of_forall_nnreal_lt fun _r hr =>
le_radius_of_summable_nnnorm _ (p.changeOriginSeries_summable_aux₃ hr k)
theorem nnnorm_changeOrigin_le (k : ℕ) (h : (‖x‖₊ : ℝ≥0∞) < p.radius) :
‖p.changeOrigin x k‖₊ ≤
∑' s : Σ l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }, ‖p (k + s.1)‖₊ * ‖x‖₊ ^ s.1 := by
refine tsum_of_nnnorm_bounded ?_ fun l => p.nnnorm_changeOriginSeries_apply_le_tsum k l x
have := p.changeOriginSeries_summable_aux₂ h k
refine HasSum.sigma this.hasSum fun l => ?_
exact ((NNReal.summable_sigma.1 this).1 l).hasSum
/-- The radius of convergence of `p.changeOrigin x` is at least `p.radius - ‖x‖`. In other words,
`p.changeOrigin x` is well defined on the largest ball contained in the original ball of
convergence. -/
theorem changeOrigin_radius : p.radius - ‖x‖₊ ≤ (p.changeOrigin x).radius := by
refine ENNReal.le_of_forall_pos_nnreal_lt fun r _h0 hr => ?_
rw [lt_tsub_iff_right, add_comm] at hr
have hr' : (‖x‖₊ : ℝ≥0∞) < p.radius := (le_add_right le_rfl).trans_lt hr
apply le_radius_of_summable_nnnorm
have (k : ℕ) :
‖p.changeOrigin x k‖₊ * r ^ k ≤
(∑' s : Σ l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }, ‖p (k + s.1)‖₊ * ‖x‖₊ ^ s.1) *
r ^ k := by
gcongr; exact p.nnnorm_changeOrigin_le k hr'
refine NNReal.summable_of_le this ?_
simpa only [← NNReal.tsum_mul_right] using
(NNReal.summable_sigma.1 (p.changeOriginSeries_summable_aux₁ hr)).2
/-- `derivSeries p` is a power series for `fderiv 𝕜 f` if `p` is a power series for `f`,
see `HasFPowerSeriesOnBall.fderiv`. -/
def derivSeries : FormalMultilinearSeries 𝕜 E (E →L[𝕜] F) :=
(continuousMultilinearCurryFin1 𝕜 E F : (E [×1]→L[𝕜] F) →L[𝕜] E →L[𝕜] F)
|>.compFormalMultilinearSeries (p.changeOriginSeries 1)
theorem radius_le_radius_derivSeries : p.radius ≤ p.derivSeries.radius := by
apply (p.le_changeOriginSeries_radius 1).trans (radius_le_of_le (fun n ↦ ?_))
apply (ContinuousLinearMap.norm_compContinuousMultilinearMap_le _ _).trans
apply mul_le_of_le_one_left (norm_nonneg _)
exact ContinuousLinearMap.opNorm_le_bound _ zero_le_one (by simp)
theorem derivSeries_eq_zero {n : ℕ} (hp : p (n + 1) = 0) : p.derivSeries n = 0 := by
suffices p.changeOriginSeries 1 n = 0 by ext v; simp [derivSeries, this]
apply Finset.sum_eq_zero (fun s hs ↦ ?_)
have : p (1 + n) = 0 := p.congr_zero (by abel) hp
simp [changeOriginSeriesTerm, this]
end
-- From this point on, assume that the space is complete, to make sure that series that converge
-- in norm also converge in `F`.
variable [CompleteSpace F] (p : FormalMultilinearSeries 𝕜 E F) {x y : E}
theorem hasFPowerSeriesOnBall_changeOrigin (k : ℕ) (hr : 0 < p.radius) :
HasFPowerSeriesOnBall (fun x => p.changeOrigin x k) (p.changeOriginSeries k) 0 p.radius :=
have := p.le_changeOriginSeries_radius k
((p.changeOriginSeries k).hasFPowerSeriesOnBall (hr.trans_le this)).mono hr this
/-- Summing the series `p.changeOrigin x` at a point `y` gives back `p (x + y)`. -/
theorem changeOrigin_eval (h : (‖x‖₊ + ‖y‖₊ : ℝ≥0∞) < p.radius) :
(p.changeOrigin x).sum y = p.sum (x + y) := by
have radius_pos : 0 < p.radius := lt_of_le_of_lt (zero_le _) h
have x_mem_ball : x ∈ Metric.eball (0 : E) p.radius :=
mem_eball_zero_iff.2 ((le_add_right le_rfl).trans_lt h)
have y_mem_ball : y ∈ Metric.eball (0 : E) (p.changeOrigin x).radius := by
refine mem_eball_zero_iff.2 (lt_of_lt_of_le ?_ p.changeOrigin_radius)
rwa [lt_tsub_iff_right, add_comm]
have x_add_y_mem_ball : x + y ∈ Metric.eball (0 : E) p.radius := by
refine mem_eball_zero_iff.2 (lt_of_le_of_lt ?_ h)
exact mod_cast nnnorm_add_le x y
set f : (Σ k l : ℕ, { s : Finset (Fin (k + l)) // s.card = l }) → F := fun s =>
p.changeOriginSeriesTerm s.1 s.2.1 s.2.2 s.2.2.2 (fun _ => x) fun _ => y
have hsf : Summable f := by
refine .of_nnnorm_bounded (p.changeOriginSeries_summable_aux₁ h) ?_
rintro ⟨k, l, s, hs⟩
dsimp only [Subtype.coe_mk]
exact p.nnnorm_changeOriginSeriesTerm_apply_le _ _ _ _ _ _
have hf : HasSum f ((p.changeOrigin x).sum y) := by
refine HasSum.sigma_of_hasSum ((p.changeOrigin x).summable y_mem_ball).hasSum (fun k => ?_) hsf
· dsimp +instances only [f]
refine ContinuousMultilinearMap.hasSum_eval ?_ _
have := (p.hasFPowerSeriesOnBall_changeOrigin k radius_pos).hasSum x_mem_ball
rw [zero_add] at this
refine HasSum.sigma_of_hasSum this (fun l => ?_) ?_
· simp only [changeOriginSeries, ContinuousMultilinearMap.sum_apply]
apply hasSum_fintype
· refine .of_nnnorm_bounded
(p.changeOriginSeries_summable_aux₂ (mem_eball_zero_iff.1 x_mem_ball) k)
fun s => ?_
refine (ContinuousMultilinearMap.le_opNNNorm _ _).trans_eq ?_
simp
refine hf.unique (changeOriginIndexEquiv.symm.hasSum_iff.1 ?_)
refine HasSum.sigma_of_hasSum
(p.hasSum x_add_y_mem_ball) (fun n => ?_) (changeOriginIndexEquiv.symm.summable_iff.2 hsf)
rw [← Pi.add_def, (p n).map_add_univ (fun _ => x) fun _ => y]
simp_rw [← changeOriginSeriesTerm_changeOriginIndexEquiv_symm]
exact hasSum_fintype (fun c => f (changeOriginIndexEquiv.symm ⟨n, c⟩))
/-- Power series terms are analytic as we vary the origin -/
theorem analyticAt_changeOrigin (p : FormalMultilinearSeries 𝕜 E F) (rp : p.radius > 0) (n : ℕ) :
AnalyticAt 𝕜 (fun x ↦ p.changeOrigin x n) 0 :=
(FormalMultilinearSeries.hasFPowerSeriesOnBall_changeOrigin p n rp).analyticAt
end FormalMultilinearSeries
section
variable [CompleteSpace F] {f : E → F} {p : FormalMultilinearSeries 𝕜 E F} {s : Set E}
{x y : E} {r : ℝ≥0∞}
/-- If a function admits a power series expansion `p` within a set `s` on a ball `B (x, r)`, then
it also admits a power series on any subball of this ball (even with a different center provided
it belongs to `s`), given by `p.changeOrigin`. -/
theorem HasFPowerSeriesWithinOnBall.changeOrigin (hf : HasFPowerSeriesWithinOnBall f p s x r)
(h : ‖y‖ₑ < r) (hy : x + y ∈ insert x s) :
HasFPowerSeriesWithinOnBall f (p.changeOrigin y) s (x + y) (r - ‖y‖ₑ) where
r_le := by
apply le_trans _ p.changeOrigin_radius
exact tsub_le_tsub hf.r_le le_rfl
r_pos := by simp [h]
hasSum {z} h'z hz := by
have : f (x + y + z) =
FormalMultilinearSeries.sum (FormalMultilinearSeries.changeOrigin p y) z := by
rw [mem_eball_zero_iff, lt_tsub_iff_right, add_comm] at hz
rw [p.changeOrigin_eval (hz.trans_le hf.r_le), add_assoc, hf.sum]
· have : insert (x + y) s ⊆ insert (x + y) (insert x s) := by
apply insert_subset_insert (subset_insert _ _)
rw [insert_eq_of_mem hy] at this
apply this
simpa [add_assoc] using h'z
exact mem_eball_zero_iff.2 (lt_of_le_of_lt (enorm_add_le _ _) hz)
rw [this]
apply (p.changeOrigin y).hasSum
refine Metric.eball_subset_eball (le_trans ?_ p.changeOrigin_radius) hz
exact tsub_le_tsub hf.r_le le_rfl
/-- If a function admits a power series expansion `p` on a ball `B (x, r)`, then it also admits a
power series on any subball of this ball (even with a different center), given by `p.changeOrigin`.
-/
theorem HasFPowerSeriesOnBall.changeOrigin (hf : HasFPowerSeriesOnBall f p x r)
(h : (‖y‖₊ : ℝ≥0∞) < r) : HasFPowerSeriesOnBall f (p.changeOrigin y) (x + y) (r - ‖y‖₊) := by
rw [← hasFPowerSeriesWithinOnBall_univ] at hf ⊢
exact hf.changeOrigin h (by simp)
/-- If a function admits a power series expansion `p` on an open ball `B (x, r)`, then
it is analytic at every point of this ball. -/
theorem HasFPowerSeriesWithinOnBall.analyticWithinAt_of_mem
(hf : HasFPowerSeriesWithinOnBall f p s x r)
(h : y ∈ insert x s ∩ Metric.eball x r) : AnalyticWithinAt 𝕜 f s y := by
have : (‖y - x‖₊ : ℝ≥0∞) < r := by simpa [edist_eq_enorm_sub] using h.2
have := hf.changeOrigin this (by simpa using h.1)
rw [add_sub_cancel] at this
exact this.analyticWithinAt
/-- If a function admits a power series expansion `p` on an open ball `B (x, r)`, then
it is analytic at every point of this ball. -/
theorem HasFPowerSeriesOnBall.analyticAt_of_mem (hf : HasFPowerSeriesOnBall f p x r)
(h : y ∈ Metric.eball x r) : AnalyticAt 𝕜 f y := by
rw [← hasFPowerSeriesWithinOnBall_univ] at hf
rw [← analyticWithinAt_univ]
exact hf.analyticWithinAt_of_mem (by simpa using h)
theorem HasFPowerSeriesWithinOnBall.analyticOn (hf : HasFPowerSeriesWithinOnBall f p s x r) :
AnalyticOn 𝕜 f (insert x s ∩ Metric.eball x r) :=
fun _ hy ↦ ((analyticWithinAt_insert (y := x)).2 (hf.analyticWithinAt_of_mem hy)).mono
inter_subset_left
theorem HasFPowerSeriesOnBall.analyticOnNhd (hf : HasFPowerSeriesOnBall f p x r) :
AnalyticOnNhd 𝕜 f (Metric.eball x r) :=
fun _y hy => hf.analyticAt_of_mem hy
variable (𝕜 f) in
/-- For any function `f` from a normed vector space to a Banach space, the set of points `x` such
that `f` is analytic at `x` is open. -/
theorem isOpen_analyticAt : IsOpen { x | AnalyticAt 𝕜 f x } := by
rw [isOpen_iff_mem_nhds]
rintro x ⟨p, r, hr⟩
exact mem_of_superset (Metric.eball_mem_nhds _ hr.r_pos) fun y hy => hr.analyticAt_of_mem hy
theorem AnalyticAt.eventually_analyticAt (h : AnalyticAt 𝕜 f x) :
∀ᶠ y in 𝓝 x, AnalyticAt 𝕜 f y :=
(isOpen_analyticAt 𝕜 f).mem_nhds h
theorem AnalyticAt.exists_mem_nhds_analyticOnNhd (h : AnalyticAt 𝕜 f x) :
∃ s ∈ 𝓝 x, AnalyticOnNhd 𝕜 f s :=
h.eventually_analyticAt.exists_mem
/-- If we're analytic at a point, we're analytic in a nonempty ball -/
theorem AnalyticAt.exists_ball_analyticOnNhd (h : AnalyticAt 𝕜 f x) :
∃ r : ℝ, 0 < r ∧ AnalyticOnNhd 𝕜 f (Metric.ball x r) :=
Metric.isOpen_iff.mp (isOpen_analyticAt _ _) _ h
/-- Sum of series is analytic on its ball of convergence. -/
protected theorem FormalMultilinearSeries.analyticOnNhd :
AnalyticOnNhd 𝕜 p.sum (Metric.eball 0 p.radius) := by
by_cases hr : p.radius = 0
· simp [hr]
exact (FormalMultilinearSeries.hasFPowerSeriesOnBall _ (pos_of_ne_zero hr)).analyticOnNhd
end