← Verification

.lake/packages/mathlib/Mathlib/Analysis/Normed/Lp/PiLp.lean

Download original source

Read-only source copy. Line numbers are navigation aids.

1/-
2Copyright (c) 2020 Sébastien Gouëzel. All rights reserved.
3Released under Apache 2.0 license as described in the file LICENSE.
4Authors: Sébastien Gouëzel, Jireh Loreaux
5-/
6module
7
8public import Mathlib.Analysis.MeanInequalities
9public import Mathlib.Data.Fintype.Order
10public import Mathlib.LinearAlgebra.Matrix.Basis
11public import Mathlib.Analysis.Normed.Lp.ProdLp
12
13/-!
14# `L^p` distance on finite products of metric spaces
15
16Given finitely many metric spaces, one can put the max distance on their product, but there is also
17a whole family of natural distances, indexed by a parameter `p : ℝ≥0∞`, that also induce
18the product topology. We define them in this file. For `0 < p < ∞`, the distance on `Π i, α i`
19is given by
20$$
21d(x, y) = \left(\sum d(x_i, y_i)^p\right)^{1/p}.
22$$,
23whereas for `p = 0` it is the cardinality of the set ${i | d (x_i, y_i) ≠ 0}$. For `p = ∞` the
24distance is the supremum of the distances.
25
26We give instances of this construction for emetric spaces, metric spaces, normed groups and normed
27spaces.
28
29To avoid conflicting instances, all these are defined on a copy of the original Π-type, named
30`PiLp p α`. The assumption `[Fact (1 ≤ p)]` is required for the metric and normed space instances.
31
32We ensure that the topology, bornology and uniform structure on `PiLp p α` are (defeq to) the
33product topology, product bornology and product uniformity, to be able to use freely continuity
34statements for the coordinate functions, for instance.
35
36If you wish to endow a type synonym of `Π i, α i` with the `L^p` distance, you can use
37`pseudoMetricSpaceToPi` and the declarations below that one.
38
39## Implementation notes
40
41We only deal with the `L^p` distance on a product of finitely many metric spaces, which may be
42distinct. A closely related construction is `lp`, the `L^p` norm on a product of (possibly
43infinitely many) normed spaces, where the norm is
44$$
45\left(\sum ‖f (x)‖^p \right)^{1/p}.
46$$
47However, the topology induced by this construction is not the product topology, and some functions
48have infinite `L^p` norm. These subtleties are not present in the case of finitely many metric
49spaces, hence it is worth devoting a file to this specific case which is particularly well behaved.
50
51Another related construction is `MeasureTheory.Lp`, the `L^p` norm on the space of functions from
52a measure space to a normed space, where the norm is
53$$
54\left(\int ‖f (x)‖^p dμ\right)^{1/p}.
55$$
56This has all the same subtleties as `lp`, and the further subtlety that this only
57defines a seminorm (as almost everywhere zero functions have zero `L^p` norm).
58The construction `PiLp` corresponds to the special case of `MeasureTheory.Lp` in which the basis
59is a finite space equipped with the counting measure.
60
61To prove that the topology (and the uniform structure) on a finite product with the `L^p` distance
62are the same as those coming from the `L^∞` distance, we could argue that the `L^p` and `L^∞` norms
63are equivalent on `ℝ^n` for abstract (norm equivalence) reasons. Instead, we give a more explicit
64(easy) proof which provides a comparison between these two norms with explicit constants.
65
66We also set up the theory for `PseudoEMetricSpace` and `PseudoMetricSpace`.
67
68## TODO
69
70TODO: the results about uniformity and bornology in the `Aux` section should be using the tools in
71`Mathlib.Topology.MetricSpace.Bilipschitz`, so that they can be inlined in the next section and
72the only remaining results are about `Lipschitz` and `Antilipschitz`.
73-/
74
75@[expose] public section
76
77open Module Real Set Filter Bornology NNReal ENNReal WithLp
78
79open scoped Uniformity
80
81noncomputable section
82
83/-- A copy of a Pi type, on which we will put the `L^p` distance. Since the Pi type itself is
84already endowed with the `L^∞` distance, we need the type synonym to avoid confusing typeclass
85resolution. Also, we let it depend on `p`, to get a whole family of type on which we can put
86different distances. -/
87abbrev PiLp (p : ℝ≥0∞) {ι : Type*} (α : ι → Type*) : Type _ :=
88 WithLp p (∀ i : ι, α i)
89
90/-The following should not be a `FunLike` instance because then the coercion `⇑` would get
91unfolded to `FunLike.coe` instead of `WithLp.equiv`. -/
92instance (p : ℝ≥0∞) {ι : Type*} (α : ι → Type*) : CoeFun (PiLp p α) (fun _ ↦ (i : ι) → α i) where
93 coe := ofLp
94
95instance (p : ℝ≥0∞) {ι : Type*} (α : ι → Type*) [∀ i, Inhabited (α i)] : Inhabited (PiLp p α) :=
96 ⟨toLp p fun _ => default⟩
97
98@[ext]
99protected theorem PiLp.ext {p : ℝ≥0∞} {ι : Type*} {α : ι → Type*} {x y : PiLp p α}
100 (h : ∀ i, x i = y i) : x = y := ofLp_injective p <| funext h
101
102namespace PiLp
103
104variable (p : ℝ≥0∞) (𝕜 : Type*) {ι : Type*} (α : ι → Type*) (β : ι → Type*)
105section
106/- Register simplification lemmas for the applications of `PiLp` elements, as the usual lemmas
107for Pi types will not trigger. -/
108variable {𝕜 p α}
109variable [Semiring 𝕜] [∀ i, SeminormedAddCommGroup (β i)]
110variable [∀ i, Module 𝕜 (β i)] (c : 𝕜)
111variable (x y : PiLp p β) (i : ι)
112
113@[simp]
114theorem zero_apply : (0 : PiLp p β) i = 0 :=
115 rfl
116
117@[simp]
118theorem add_apply : (x + y) i = x i + y i :=
119 rfl
120
121@[simp]
122theorem sub_apply : (x - y) i = x i - y i :=
123 rfl
124
125@[simp]
126theorem smul_apply : (c • x) i = c • x i :=
127 rfl
128
129@[simp]
130theorem neg_apply : (-x) i = -x i :=
131 rfl
132
133variable (p) in
134/-- The projection on the `i`-th coordinate of `WithLp p (∀ i, α i)`, as a linear map. -/
135@[simps!]
136def projₗ (i : ι) : PiLp p β →ₗ[𝕜] β i :=
137 (LinearMap.proj i : (∀ i, β i) →ₗ[𝕜] β i) ∘ₗ (WithLp.linearEquiv p 𝕜 (∀ i, β i)).toLinearMap
138
139end
140
141lemma toLp_apply (x : ∀ i, α i) (i : ι) : toLp p x i = x i := rfl
142
143section Single
144variable [DecidableEq ι]
145variable {β}
146
147section Zero
148variable [∀ i, Zero (β i)]
149
150/-- The vector given in `PiLp` by being `a : β i` at coordinate `i : ι` and `0 : β j` at
151all other coordinates `j`. -/
152def single (i : ι) (a : β i) : PiLp p β := toLp p (Pi.single i a)
153
154@[simp]
155lemma ofLp_single (i : ι) (a : β i) : ofLp (single p i a) = Pi.single i a := rfl
156
157@[simp]
158lemma toLp_single (i : ι) (a : β i) : toLp p (Pi.single i a) = single p i a := rfl
159
160@[simp]
161lemma single_eq_same (i : ι) (a : β i) : single p i a i = a := by
162 rw [ofLp_single, Pi.single_eq_same]
163
164@[simp]
165lemma single_eq_of_ne {i i' : ι} (h : i' ≠ i) (a : β i) : single p i a i' = 0 := by
166 rw [ofLp_single, Pi.single_eq_of_ne h]
167
168/-- Changing the hypothesis direction in `PiLp.single_eq_of_ne` for for ease of use by simp. -/
169@[simp]
170lemma single_eq_of_ne' {i i' : ι} (h : i ≠ i') (a : β i) : single p i a i' = 0 := by
171 rw [ofLp_single, Pi.single_eq_of_ne' h]
172
173end Zero
174
175@[simp]
176lemma single_apply [Zero 𝕜] (i : ι) (a : 𝕜) (j : ι) :
177 (single p i a : PiLp p (fun _ ↦ 𝕜)) j = ite (j = i) a 0 := by
178 rw [← toLp_single, PiLp.toLp_apply, ← Pi.single_apply i a j]
179
180section AddCommGroup
181variable [∀ i, AddCommGroup (β i)]
182
183@[simp]
184theorem single_eq_zero_iff (p : ℝ≥0∞) (i : ι) {a : β i} :
185 single p i a = 0 ↔ a = 0 :=
186 (toLp_eq_zero p).trans Pi.single_eq_zero_iff
187
188lemma single_add (p : ℝ≥0∞) (i : ι) {a b : β i} :
189 single p i (a + b) = single p i a + single p i b := by
190 simp_rw [← toLp_single, Pi.single_add, toLp_add]
191
192lemma single_sub (p : ℝ≥0∞) (i : ι) {a b : β i} :
193 single p i (a - b) = single p i a - single p i b := by
194 simp_rw [← toLp_single, Pi.single_sub, toLp_sub]
195
196lemma single_neg (p : ℝ≥0∞) (i : ι) {a : β i} :
197 single p i (-a) = -single p i a := by
198 simp_rw [← toLp_single, Pi.single_neg, toLp_neg]
199
200end AddCommGroup
201
202section LinearIndependent
203
204theorem linearIndependent_single [Semiring 𝕜] {η : Type*} {ιs : η → Type*}
205 {Ms : η → Type*} [∀ i, AddCommGroup (Ms i)] [∀ i, Module 𝕜 (Ms i)] [DecidableEq η]
206 (v : ∀ j, ιs j → Ms j) (hs : ∀ i, LinearIndependent 𝕜 (v i)) :
207 LinearIndependent 𝕜 fun ji : Σ j, ιs j ↦ single p ji.1 (v ji.1 ji.2) := by
208 suffices LinearIndependent 𝕜 ((WithLp.linearEquiv p 𝕜 _).symm.toLinearMap ∘
209 fun ji : Σ j, ιs j ↦ Pi.single ji.1 (v ji.1 ji.2)) by
210 simpa
211 rw [LinearMap.linearIndependent_iff_of_injOn _ (by simp)]
212 exact Pi.linearIndependent_single v hs
213
214theorem linearIndependent_single_one [Ring 𝕜] :
215 LinearIndependent 𝕜 (fun i : ι ↦ single p i (1 : 𝕜)) := by
216 suffices LinearIndependent 𝕜 ((WithLp.linearEquiv p 𝕜 _).symm.toLinearMap ∘
217 fun i : ι ↦ Pi.single i (1 : 𝕜)) by
218 simpa
219 rw [LinearMap.linearIndependent_iff_of_injOn _ (by simp)]
220 exact Pi.linearIndependent_single_one ι 𝕜
221
222theorem linearIndependent_single_of_ne_zero [Ring 𝕜] [IsDomain 𝕜] {M : Type*}
223 [AddCommGroup M] [Module 𝕜 M] [IsTorsionFree 𝕜 M] {v : ι → M} (hv : ∀ i, v i ≠ 0) :
224 LinearIndependent 𝕜 fun i : ι ↦ single p i (v i) := by
225 suffices LinearIndependent 𝕜 ((WithLp.linearEquiv p 𝕜 _).symm.toLinearMap ∘
226 fun i : ι ↦ Pi.single i (v i)) by
227 simpa
228 rw [LinearMap.linearIndependent_iff_of_injOn _ (by simp)]
229 exact Pi.linearIndependent_single_of_ne_zero hv
230
231end LinearIndependent
232
233end Single
234
235section DistNorm
236
237variable [Fintype ι]
238
239/-!
240### Definition of `edist`, `dist` and `norm` on `PiLp`
241
242In this section we define the `edist`, `dist` and `norm` functions on `PiLp p α` without assuming
243`[Fact (1 ≤ p)]` or metric properties of the spaces `α i`. This allows us to provide the rewrite
244lemmas for each of three cases `p = 0`, `p = ∞` and `0 < p.to_real`.
245-/
246
247
248section EDist
249
250variable [∀ i, EDist (β i)]
251
252/-- Endowing the space `PiLp p β` with the `L^p` edistance. We register this instance
253separate from `pi_Lp.pseudo_emetric` since the latter requires the type class hypothesis
254`[Fact (1 ≤ p)]` in order to prove the triangle inequality.
255
256Registering this separately allows for a future emetric-like structure on `PiLp p β` for `p < 1`
257satisfying a relaxed triangle inequality. The terminology for this varies throughout the
258literature, but it is sometimes called a *quasi-metric* or *semi-metric*. -/
259instance : EDist (PiLp p β) where
260 edist f g :=
261 if p = 0 then {i | edist (f i) (g i) ≠ 0}.toFinite.toFinset.card
262 else
263 if p = ∞ then ⨆ i, edist (f i) (g i) else (∑ i, edist (f i) (g i) ^ p.toReal) ^ (1 / p.toReal)
264
265variable {β}
266
267theorem edist_eq_card (f g : PiLp 0 β) :
268 edist f g = {i | edist (f i) (g i) ≠ 0}.toFinite.toFinset.card :=
269 ite_eq_left rfl
270
271theorem edist_eq_sum {p : ℝ≥0∞} (hp : 0 < p.toReal) (f g : PiLp p β) :
272 edist f g = (∑ i, edist (f i) (g i) ^ p.toReal) ^ (1 / p.toReal) :=
273 let hp' := ENNReal.toReal_pos_iff.mp hp
274 (ite_eq_right hp'.1.ne').trans (ite_eq_right hp'.2.ne)
275
276theorem edist_eq_iSup (f g : PiLp ∞ β) : edist f g = ⨆ i, edist (f i) (g i) := rfl
277
278end EDist
279
280section EDistProp
281
282variable {β}
283variable [∀ i, PseudoEMetricSpace (β i)]
284
285/-- This holds independent of `p` and does not require `[Fact (1 ≤ p)]`. We keep it separate
286from `pi_Lp.pseudo_emetric_space` so it can be used also for `p < 1`. -/
287protected theorem edist_self (f : PiLp p β) : edist f f = 0 := by
288 rcases p.trichotomy with (rfl | rfl | h)
289 · simp [edist_eq_card]
290 · simp [edist_eq_iSup]
291 · simp [edist_eq_sum h, ENNReal.zero_rpow_of_pos h, ENNReal.zero_rpow_of_pos (inv_pos.2 <| h)]
292
293/-- This holds independent of `p` and does not require `[Fact (1 ≤ p)]`. We keep it separate
294from `pi_Lp.pseudo_emetric_space` so it can be used also for `p < 1`. -/
295protected theorem edist_comm (f g : PiLp p β) : edist f g = edist g f := by
296 rcases p.trichotomy with (rfl | rfl | h)
297 · simp only [edist_eq_card, edist_comm]
298 · simp only [edist_eq_iSup, edist_comm]
299 · simp only [edist_eq_sum h, edist_comm]
300
301end EDistProp
302
303section Dist
304
305variable [∀ i, Dist (α i)]
306
307/-- Endowing the space `PiLp p β` with the `L^p` distance. We register this instance
308separate from `pi_Lp.pseudo_metric` since the latter requires the type class hypothesis
309`[Fact (1 ≤ p)]` in order to prove the triangle inequality.
310
311Registering this separately allows for a future metric-like structure on `PiLp p β` for `p < 1`
312satisfying a relaxed triangle inequality. The terminology for this varies throughout the
313literature, but it is sometimes called a *quasi-metric* or *semi-metric*. -/
314instance : Dist (PiLp p α) where
315 dist f g :=
316 if p = 0 then {i | dist (f i) (g i) ≠ 0}.toFinite.toFinset.card
317 else
318 if p = ∞ then ⨆ i, dist (f i) (g i) else (∑ i, dist (f i) (g i) ^ p.toReal) ^ (1 / p.toReal)
319
320variable {α}
321
322theorem dist_eq_card (f g : PiLp 0 α) :
323 dist f g = {i | dist (f i) (g i) ≠ 0}.toFinite.toFinset.card :=
324 ite_eq_left rfl
325
326theorem dist_eq_sum {p : ℝ≥0∞} (hp : 0 < p.toReal) (f g : PiLp p α) :
327 dist f g = (∑ i, dist (f i) (g i) ^ p.toReal) ^ (1 / p.toReal) :=
328 let hp' := ENNReal.toReal_pos_iff.mp hp
329 (ite_eq_right hp'.1.ne').trans (ite_eq_right hp'.2.ne)
330
331theorem dist_eq_iSup (f g : PiLp ∞ α) : dist f g = ⨆ i, dist (f i) (g i) := rfl
332
333end Dist
334
335section Norm
336
337variable [∀ i, Norm (β i)]
338
339/-- Endowing the space `PiLp p β` with the `L^p` norm. We register this instance
340separate from `PiLp.seminormedAddCommGroup` since the latter requires the type class hypothesis
341`[Fact (1 ≤ p)]` in order to prove the triangle inequality.
342
343Registering this separately allows for a future norm-like structure on `PiLp p β` for `p < 1`
344satisfying a relaxed triangle inequality. These are called *quasi-norms*. -/
345instance instNorm : Norm (PiLp p β) where
346 norm f :=
347 if p = 0 then {i | ‖f i‖ ≠ 0}.toFinite.toFinset.card
348 else if p = ∞ then ⨆ i, ‖f i‖ else (∑ i, ‖f i‖ ^ p.toReal) ^ (1 / p.toReal)
349
350variable {p β}
351
352theorem norm_eq_card (f : PiLp 0 β) : ‖f‖ = {i | ‖f i‖ ≠ 0}.toFinite.toFinset.card :=
353 ite_eq_left rfl
354
355theorem norm_eq_ciSup (f : PiLp ∞ β) : ‖f‖ = ⨆ i, ‖f i‖ := rfl
356
357theorem norm_eq_sum (hp : 0 < p.toReal) (f : PiLp p β) :
358 ‖f‖ = (∑ i, ‖f i‖ ^ p.toReal) ^ (1 / p.toReal) :=
359 let hp' := ENNReal.toReal_pos_iff.mp hp
360 (ite_eq_right hp'.1.ne').trans (ite_eq_right hp'.2.ne)
361
362end Norm
363
364end DistNorm
365
366section Aux
367
368/-!
369### The uniformity on finite `L^p` products is the product uniformity
370
371In this section, we put the `L^p` edistance on `PiLp p α`, and we check that the uniformity
372coming from this edistance coincides with the product uniformity, by showing that the canonical
373map to the Pi type (with the `L^∞` distance) is a uniform embedding, as it is both Lipschitz and
374antiLipschitz.
375
376We only register this emetric space structure as a temporary instance, as the true instance (to be
377registered later) will have as uniformity exactly the product uniformity, instead of the one coming
378from the edistance (which is equal to it, but not defeq). See Note [forgetful inheritance]
379explaining why having definitionally the right uniformity is often important.
380
381TODO: the results about uniformity and bornology should be using the tools in
382`Mathlib.Topology.MetricSpace.Bilipschitz`, so that they can be inlined in the next section and
383the only remaining results are about `Lipschitz` and `Antilipschitz`.
384-/
385
386
387variable [Fact (1 ≤ p)] [∀ i, PseudoMetricSpace (α i)] [∀ i, PseudoEMetricSpace (β i)]
388variable [Fintype ι]
389
390/-- Endowing the space `PiLp p β` with the `L^p` pseudoemetric structure. This definition is not
391satisfactory, as it does not register the fact that the topology and the uniform structure coincide
392with the product one. Therefore, we do not register it as an instance. Using this as a temporary
393pseudoemetric space instance, we will show that the uniform structure is equal (but not defeq) to
394the product one, and then register an instance in which we replace the uniform structure by the
395product one using this pseudoemetric space and `PseudoEMetricSpace.replaceUniformity`. -/
396@[instance_reducible]
397def pseudoEmetricAux : PseudoEMetricSpace (PiLp p β) where
398 edist_self := PiLp.edist_self p
399 edist_comm := PiLp.edist_comm p
400 edist_triangle f g h := by
401 rcases p.dichotomy with (rfl | hp)
402 · simp only [edist_eq_iSup]
403 cases isEmpty_or_nonempty ι
404 · simp only [ciSup_of_empty, ENNReal.bot_eq_zero, add_zero, nonpos_iff_eq_zero]
405 -- Porting note: `le_iSup` needed some help
406 refine
407 iSup_le fun i => (edist_triangle _ (g i) _).trans <| add_le_add
408 (le_iSup (fun k => edist (f k) (g k)) i) (le_iSup (fun k => edist (g k) (h k)) i)
409 · simp only [edist_eq_sum (zero_lt_one.trans_le hp)]
410 calc
411 (∑ i, edist (f i) (h i) ^ p.toReal) ^ (1 / p.toReal) ≤
412 (∑ i, (edist (f i) (g i) + edist (g i) (h i)) ^ p.toReal) ^ (1 / p.toReal) := by
413 gcongr
414 apply edist_triangle
415 _ ≤
416 (∑ i, edist (f i) (g i) ^ p.toReal) ^ (1 / p.toReal) +
417 (∑ i, edist (g i) (h i) ^ p.toReal) ^ (1 / p.toReal) :=
418 ENNReal.Lp_add_le _ _ _ hp
419
420attribute [local instance] PiLp.pseudoEmetricAux
421
422set_option backward.isDefEq.respectTransparency false in
423/-- An auxiliary lemma used twice in the proof of `PiLp.pseudoMetricAux` below. Not intended for
424use outside this file. -/
425theorem iSup_edist_ne_top_aux {ι : Type*} [Finite ι] {α : ι → Type*}
426 [∀ i, PseudoMetricSpace (α i)] (f g : PiLp ∞ α) : (⨆ i, edist (f i) (g i)) ≠ ⊤ := by
427 cases nonempty_fintype ι
428 obtain ⟨M, hM⟩ := Finite.exists_le fun i => (⟨dist (f i) (g i), dist_nonneg⟩ : ℝ≥0)
429 refine ne_of_lt ((iSup_le fun i => ?_).trans_lt (@ENNReal.coe_lt_top M))
430 simp only [edist, PseudoMetricSpace.edist_dist, ENNReal.ofReal_eq_coe_nnreal dist_nonneg]
431 exact mod_cast hM i
432
433/-- Endowing the space `PiLp p α` with the `L^p` pseudometric structure. This definition is not
434satisfactory, as it does not register the fact that the topology, the uniform structure, and the
435bornology coincide with the product ones. Therefore, we do not register it as an instance. Using
436this as a temporary pseudoemetric space instance, we will show that the uniform structure is equal
437(but not defeq) to the product one, and then register an instance in which we replace the uniform
438structure and the bornology by the product ones using this pseudometric space,
439`PseudoMetricSpace.replaceUniformity`, and `PseudoMetricSpace.replaceBornology`.
440
441See note [reducible non-instances] -/
442abbrev pseudoMetricAux : PseudoMetricSpace (PiLp p α) :=
443 PseudoEMetricSpace.toPseudoMetricSpaceOfDist dist
444 (fun f g => by
445 rcases p.dichotomy with (rfl | h)
446 · simp only [dist, top_ne_zero, ↓reduceIte]
447 exact Real.iSup_nonneg fun i ↦ dist_nonneg
448 · simp only [dist]
449 split_ifs with hp
450 · linarith
451 · exact Real.iSup_nonneg fun i ↦ dist_nonneg
452 · exact rpow_nonneg (Fintype.sum_nonneg fun i ↦ by positivity) (1 / p.toReal))
453 fun f g => by
454 rcases p.dichotomy with (rfl | h)
455 · rw [edist_eq_iSup, dist_eq_iSup]
456 cases isEmpty_or_nonempty ι
457 · simp
458 · refine ENNReal.eq_of_forall_le_nnreal_iff fun r ↦ ?_
459 have : BddAbove <| .range fun i ↦ dist (f i) (g i) := Finite.bddAbove_range _
460 simp [ciSup_le_iff this]
461 · have : 0 < p.toReal := by rw [ENNReal.toReal_pos_iff_ne_top]; rintro rfl; norm_num at h
462 simp only [edist_eq_sum, edist_dist, dist_eq_sum, this]
463 rw [← ENNReal.ofReal_rpow_of_nonneg (by simp [Finset.sum_nonneg, Real.rpow_nonneg]) (by simp)]
464 simp [Real.rpow_nonneg, ENNReal.ofReal_sum_of_nonneg, ← ENNReal.ofReal_rpow_of_nonneg]
465
466attribute [local instance] PiLp.pseudoMetricAux
467
468variable {p β} in
469private theorem edist_apply_le_edist_aux (x y : PiLp p β) (i : ι) :
470 edist (x i) (y i) ≤ edist x y := by
471 rcases p.dichotomy with (rfl | h)
472 · simpa only [edist_eq_iSup] using le_iSup (fun i => edist (x i) (y i)) i
473 · have cancel : p.toReal * (1 / p.toReal) = 1 := mul_div_cancel₀ 1 (zero_lt_one.trans_le h).ne'
474 rw [edist_eq_sum (zero_lt_one.trans_le h)]
475 calc
476 edist (x i) (y i) = (edist (x i) (y i) ^ p.toReal) ^ (1 / p.toReal) := by
477 simp [← ENNReal.rpow_mul, cancel, -one_div]
478 _ ≤ (∑ i, edist (x i) (y i) ^ p.toReal) ^ (1 / p.toReal) := by
479 grw [← Finset.single_le_sum (fun i _ => (bot_le : (0 : ℝ≥0∞) ≤ _)) (Finset.mem_univ i)]
480
481private lemma lipschitzWith_ofLp_aux : LipschitzWith 1 (@ofLp p (∀ i, β i)) :=
482 .of_edist_le fun x y => by
483 simp_rw [edist_pi_def, Finset.sup_le_iff, Finset.mem_univ, forall_true_left]
484 exact edist_apply_le_edist_aux _ _
485
486private lemma antilipschitzWith_ofLp_aux :
487 AntilipschitzWith ((Fintype.card ι : ℝ≥0) ^ (1 / p).toReal) (@ofLp p (∀ i, β i)) := by
488 intro x y
489 rcases p.dichotomy with (rfl | h)
490 · simp only [edist_eq_iSup, ENNReal.div_top, ENNReal.toReal_zero, NNReal.rpow_zero,
491 ENNReal.coe_one, one_mul, iSup_le_iff]
492 -- Porting note: `Finset.le_sup` needed some help
493 exact fun i => Finset.le_sup (f := fun i => edist (x i) (y i)) (Finset.mem_univ i)
494 · have pos : 0 < p.toReal := zero_lt_one.trans_le h
495 have nonneg : 0 ≤ 1 / p.toReal := one_div_nonneg.2 (le_of_lt pos)
496 have cancel : p.toReal * (1 / p.toReal) = 1 := mul_div_cancel₀ 1 (ne_of_gt pos)
497 rw [edist_eq_sum pos, ENNReal.toReal_div 1 p]
498 simp only [edist, ENNReal.toReal_one]
499 calc
500 (∑ i, edist (x i) (y i) ^ p.toReal) ^ (1 / p.toReal) ≤
501 (∑ _i, edist (ofLp x) (ofLp y) ^ p.toReal) ^ (1 / p.toReal) := by
502 gcongr with i
503 exact Finset.le_sup (f := fun i => edist (x i) (y i)) (Finset.mem_univ i)
504 _ =
505 ((Fintype.card ι : ℝ≥0) ^ (1 / p.toReal) : ℝ≥0) *
506 edist (ofLp x) (ofLp y) := by
507 simp only [nsmul_eq_mul, Finset.card_univ, ENNReal.rpow_one, Finset.sum_const,
508 ENNReal.mul_rpow_of_nonneg _ _ nonneg, ← ENNReal.rpow_mul, cancel]
509 have : (Fintype.card ι : ℝ≥0∞) = (Fintype.card ι : ℝ≥0) :=
510 (ENNReal.coe_natCast (Fintype.card ι)).symm
511 rw [this, ENNReal.coe_rpow_of_nonneg _ nonneg]
512
513private lemma isUniformInducing_ofLp_aux : IsUniformInducing (@ofLp p (∀ i, β i)) :=
514 (antilipschitzWith_ofLp_aux p β).isUniformInducing
515 (lipschitzWith_ofLp_aux p β).uniformContinuous
516
517set_option backward.privateInPublic true in
518private lemma uniformity_aux : 𝓤 (PiLp p β) = 𝓤[UniformSpace.comap ofLp inferInstance] := by
519 rw [← (isUniformInducing_ofLp_aux p β).comap_uniformity]
520 rfl
521
522instance bornology (p : ℝ≥0∞) (β : ι → Type*) [∀ i, Bornology (β i)] :
523 Bornology (PiLp p β) := Bornology.induced ofLp
524
525set_option backward.privateInPublic true in
526private lemma cobounded_aux : @cobounded _ PseudoMetricSpace.toBornology = cobounded (PiLp p α) :=
527 le_antisymm (antilipschitzWith_ofLp_aux p α).tendsto_cobounded.le_comap
528 (lipschitzWith_ofLp_aux p α).comap_cobounded_le
529
530end Aux
531
532/-! ### Instances on finite `L^p` products -/
533
534instance topologicalSpace [∀ i, TopologicalSpace (β i)] : TopologicalSpace (PiLp p β) :=
535 Pi.topologicalSpace.induced ofLp
536
537@[fun_prop, continuity]
538theorem continuous_ofLp [∀ i, TopologicalSpace (β i)] : Continuous (@ofLp p (∀ i, β i)) :=
539 continuous_induced_dom
540
541@[fun_prop, continuity]
542protected lemma continuous_apply [∀ i, TopologicalSpace (β i)] (i : ι) :
543 Continuous (fun f : PiLp p β ↦ f i) := (continuous_apply i).comp (continuous_ofLp p β)
544
545@[fun_prop, continuity]
546theorem continuous_toLp [∀ i, TopologicalSpace (β i)] : Continuous (@toLp p (∀ i, β i)) :=
547 continuous_induced_rng.2 continuous_id
548
549/-- `WithLp.equiv` as a homeomorphism. -/
550def homeomorph [∀ i, TopologicalSpace (β i)] : PiLp p β ≃ₜ (Π i, β i) where
551 toEquiv := WithLp.equiv p (Π i, β i)
552
553@[simp]
554lemma toEquiv_homeomorph [∀ i, TopologicalSpace (β i)] :
555 (homeomorph p β).toEquiv = WithLp.equiv p (Π i, β i) := rfl
556
557lemma isOpenMap_apply [∀ i, TopologicalSpace (β i)] (i : ι) :
558 IsOpenMap (fun f : PiLp p β ↦ f i) := (isOpenMap_eval i).comp (homeomorph p β).isOpenMap
559
560instance instProdT0Space [∀ i, TopologicalSpace (β i)] [∀ i, T0Space (β i)] :
561 T0Space (PiLp p β) :=
562 (homeomorph p β).symm.t0Space
563
564instance secondCountableTopology [Countable ι] [∀ i, TopologicalSpace (β i)]
565 [∀ i, SecondCountableTopology (β i)] : SecondCountableTopology (PiLp p β) :=
566 (homeomorph p β).secondCountableTopology
567
568instance uniformSpace [∀ i, UniformSpace (β i)] : UniformSpace (PiLp p β) :=
569 (Pi.uniformSpace β).comap ofLp
570
571@[fun_prop]
572lemma uniformContinuous_ofLp [∀ i, UniformSpace (β i)] :
573 UniformContinuous (@ofLp p (∀ i, β i)) :=
574 uniformContinuous_comap
575
576@[fun_prop]
577lemma uniformContinuous_toLp [∀ i, UniformSpace (β i)] :
578 UniformContinuous (@toLp p (∀ i, β i)) :=
579 uniformContinuous_comap' uniformContinuous_id
580
581/-- `WithLp.equiv` as a uniform isomorphism. -/
582def uniformEquiv [∀ i, UniformSpace (β i)] : PiLp p β ≃ᵤ (Π i, β i) where
583 toEquiv := WithLp.equiv p (Π i, β i)
584 uniformContinuous_toFun := uniformContinuous_ofLp p β
585 uniformContinuous_invFun := uniformContinuous_toLp p β
586
587@[simp]
588lemma toHomeomorph_uniformEquiv [∀ i, UniformSpace (β i)] :
589 (uniformEquiv p β).toHomeomorph = homeomorph p β := rfl
590
591@[simp]
592lemma toEquiv_uniformEquiv [∀ i, UniformSpace (β i)] :
593 (uniformEquiv p β).toEquiv = WithLp.equiv p (Π i, β i) := rfl
594
595instance completeSpace [∀ i, UniformSpace (β i)] [∀ i, CompleteSpace (β i)] :
596 CompleteSpace (PiLp p β) :=
597 (uniformEquiv p β).completeSpace_iff.2 inferInstance
598
599section Fintype
600variable [hp : Fact (1 ≤ p)]
601variable [Fintype ι]
602
603set_option backward.privateInPublic true in
604set_option backward.privateInPublic.warn false in
605/-- pseudoemetric space instance on the product of finitely many pseudoemetric spaces, using the
606`L^p` pseudoedistance, and having as uniformity the product uniformity. -/
607instance [∀ i, PseudoEMetricSpace (β i)] : PseudoEMetricSpace (PiLp p β) :=
608 (pseudoEmetricAux p β).replaceUniformity (uniformity_aux p β).symm
609
610/-- emetric space instance on the product of finitely many emetric spaces, using the `L^p`
611edistance, and having as uniformity the product uniformity. -/
612instance [∀ i, EMetricSpace (α i)] : EMetricSpace (PiLp p α) :=
613 EMetricSpace.ofT0PseudoEMetricSpace (PiLp p α)
614
615set_option backward.privateInPublic true in
616set_option backward.privateInPublic.warn false in
617/-- pseudometric space instance on the product of finitely many pseudometric spaces, using the
618`L^p` distance, and having as uniformity the product uniformity. -/
619instance [∀ i, PseudoMetricSpace (β i)] : PseudoMetricSpace (PiLp p β) :=
620 ((pseudoMetricAux p β).replaceUniformity (uniformity_aux p β).symm).replaceBornology fun s =>
621 Filter.ext_iff.1 (cobounded_aux p β).symm sᶜ
622
623/-- metric space instance on the product of finitely many metric spaces, using the `L^p` distance,
624and having as uniformity the product uniformity. -/
625instance [∀ i, MetricSpace (α i)] : MetricSpace (PiLp p α) :=
626 MetricSpace.ofT0PseudoMetricSpace _
627
628theorem nndist_eq_sum {p : ℝ≥0∞} [Fact (1 ≤ p)] {β : ι → Type*} [∀ i, PseudoMetricSpace (β i)]
629 (hp : p ≠ ∞) (x y : PiLp p β) :
630 nndist x y = (∑ i : ι, nndist (x i) (y i) ^ p.toReal) ^ (1 / p.toReal) :=
631 NNReal.eq <| by
632 push_cast
633 exact dist_eq_sum (p.toReal_pos_iff_ne_top.mpr hp) _ _
634
635theorem nndist_eq_iSup {β : ι → Type*} [∀ i, PseudoMetricSpace (β i)] (x y : PiLp ∞ β) :
636 nndist x y = ⨆ i, nndist (x i) (y i) :=
637 NNReal.eq <| by
638 push_cast
639 exact dist_eq_iSup _ _
640
641section
642variable {β p}
643
644theorem edist_apply_le [∀ i, PseudoEMetricSpace (β i)] (x y : PiLp p β) (i : ι) :
645 edist (x i) (y i) ≤ edist x y :=
646 edist_apply_le_edist_aux x y i
647
648theorem nndist_apply_le [∀ i, PseudoMetricSpace (β i)] (x y : PiLp p β) (i : ι) :
649 nndist (x i) (y i) ≤ nndist x y := by
650 simpa [← coe_nnreal_ennreal_nndist] using edist_apply_le x y i
651
652theorem dist_apply_le [∀ i, PseudoMetricSpace (β i)] (x y : PiLp p β) (i : ι) :
653 dist (x i) (y i) ≤ dist x y :=
654 nndist_apply_le x y i
655
656end
657
658lemma lipschitzWith_ofLp [∀ i, PseudoEMetricSpace (β i)] :
659 LipschitzWith 1 (@ofLp p (∀ i, β i)) :=
660 lipschitzWith_ofLp_aux p β
661
662lemma antilipschitzWith_toLp [∀ i, PseudoEMetricSpace (β i)] :
663 AntilipschitzWith 1 (@toLp p (∀ i, β i)) :=
664 (lipschitzWith_ofLp p β).to_rightInverse (ofLp_toLp p)
665
666theorem antilipschitzWith_ofLp [∀ i, PseudoEMetricSpace (β i)] :
667 AntilipschitzWith ((Fintype.card ι : ℝ≥0) ^ (1 / p).toReal) (@ofLp p (∀ i, β i)) :=
668 antilipschitzWith_ofLp_aux p β
669
670lemma lipschitzWith_toLp [∀ i, PseudoEMetricSpace (β i)] :
671 LipschitzWith ((Fintype.card ι : ℝ≥0) ^ (1 / p).toReal) (@toLp p (∀ i, β i)) :=
672 (antilipschitzWith_ofLp p β).to_rightInverse (ofLp_toLp p)
673
674lemma isometry_ofLp_infty [∀ i, PseudoEMetricSpace (β i)] :
675 Isometry (@ofLp ∞ (∀ i, β i)) :=
676 fun x y =>
677 le_antisymm (by simpa only [ENNReal.coe_one, one_mul] using lipschitzWith_ofLp ∞ β x y)
678 (by simpa only [ENNReal.div_top, ENNReal.toReal_zero, NNReal.rpow_zero, ENNReal.coe_one,
679 one_mul] using antilipschitzWith_ofLp ∞ β x y)
680
681/-- seminormed group instance on the product of finitely many normed groups, using the `L^p`
682norm. -/
683instance seminormedAddCommGroup [∀ i, SeminormedAddCommGroup (β i)] :
684 SeminormedAddCommGroup (PiLp p β) where
685 dist_eq := fun x y => by
686 rcases p.dichotomy with (rfl | h)
687 · simp only [dist_eq_iSup, norm_eq_ciSup, dist_eq_norm, add_apply, neg_apply, norm_neg_add]
688 · have : p ≠ ∞ := by
689 intro hp
690 rw [hp, ENNReal.toReal_top] at h
691 linarith
692 simp only [dist_eq_sum (zero_lt_one.trans_le h), norm_eq_sum (zero_lt_one.trans_le h),
693 dist_eq_norm, add_apply, neg_apply, norm_neg_add]
694
695omit [Fintype ι] in
696lemma isUniformInducing_toLp [Finite ι] [∀ i, PseudoEMetricSpace (β i)] :
697 IsUniformInducing (@toLp p (Π i, β i)) :=
698 have := Fintype.ofFinite ι
699 (antilipschitzWith_toLp p β).isUniformInducing
700 (lipschitzWith_toLp p β).uniformContinuous
701
702section
703variable {β p}
704
705theorem enorm_apply_le [∀ i, SeminormedAddCommGroup (β i)] (x : PiLp p β) (i : ι) :
706 ‖x i‖ₑ ≤ ‖x‖ₑ := by
707 simpa using edist_apply_le x 0 i
708
709theorem nnnorm_apply_le [∀ i, SeminormedAddCommGroup (β i)] (x : PiLp p β) (i : ι) :
710 ‖x i‖₊ ≤ ‖x‖₊ := by
711 simpa using nndist_apply_le x 0 i
712
713theorem norm_apply_le [∀ i, SeminormedAddCommGroup (β i)] (x : PiLp p β) (i : ι) :
714 ‖x i‖ ≤ ‖x‖ := by
715 simpa using dist_apply_le x 0 i
716
717end
718
719/-- normed group instance on the product of finitely many normed groups, using the `L^p` norm. -/
720instance normedAddCommGroup [∀ i, NormedAddCommGroup (α i)] : NormedAddCommGroup (PiLp p α) :=
721 { PiLp.seminormedAddCommGroup p α with
722 eq_of_dist_eq_zero := eq_of_dist_eq_zero }
723
724theorem nnnorm_eq_sum {p : ℝ≥0∞} [Fact (1 ≤ p)] {β : ι → Type*} (hp : p ≠ ∞)
725 [∀ i, SeminormedAddCommGroup (β i)] (f : PiLp p β) :
726 ‖f‖₊ = (∑ i, ‖f i‖₊ ^ p.toReal) ^ (1 / p.toReal) := by
727 ext
728 simp [NNReal.coe_sum, norm_eq_sum (p.toReal_pos_iff_ne_top.mpr hp)]
729
730section Linfty
731variable {β}
732variable [∀ i, SeminormedAddCommGroup (β i)]
733
734theorem nnnorm_eq_ciSup (f : PiLp ∞ β) : ‖f‖₊ = ⨆ i, ‖f i‖₊ := by
735 ext
736 simp [NNReal.coe_iSup, norm_eq_ciSup]
737
738@[simp] lemma nnnorm_ofLp (f : PiLp ∞ β) : ‖ofLp f‖₊ = ‖f‖₊ := by
739 rw [nnnorm_eq_ciSup, Pi.nnnorm_def, Finset.sup_univ_eq_ciSup]
740
741@[simp] lemma nnnorm_toLp (f : ∀ i, β i) : ‖toLp ∞ f‖₊ = ‖f‖₊ := (nnnorm_ofLp _).symm
742
743@[simp] lemma norm_ofLp (f : PiLp ∞ β) : ‖ofLp f‖ = ‖f‖ := congr_arg NNReal.toReal <| nnnorm_ofLp f
744@[simp] lemma norm_toLp (f : ∀ i, β i) : ‖toLp ∞ f‖ = ‖f‖ := (norm_ofLp _).symm
745
746end Linfty
747
748theorem norm_eq_of_nat {p : ℝ≥0∞} [Fact (1 ≤ p)] {β : ι → Type*}
749 [∀ i, SeminormedAddCommGroup (β i)] (n : ℕ) (h : p = n) (f : PiLp p β) :
750 ‖f‖ = (∑ i, ‖f i‖ ^ n) ^ (1 / (n : ℝ)) := by
751 have := p.toReal_pos_iff_ne_top.mpr (ne_of_eq_of_ne h <| ENNReal.natCast_ne_top n)
752 simp only [one_div, h, Real.rpow_natCast, ENNReal.toReal_natCast,
753 norm_eq_sum this]
754
755section L1
756variable {β} [∀ i, SeminormedAddCommGroup (β i)]
757
758set_option backward.isDefEq.respectTransparency false in
759theorem norm_eq_of_L1 (x : PiLp 1 β) : ‖x‖ = ∑ i : ι, ‖x i‖ := by
760 simp [norm_eq_sum]
761
762theorem nnnorm_eq_of_L1 (x : PiLp 1 β) : ‖x‖₊ = ∑ i : ι, ‖x i‖₊ :=
763 NNReal.eq <| by push_cast; exact norm_eq_of_L1 x
764
765theorem dist_eq_of_L1 (x y : PiLp 1 β) : dist x y = ∑ i, dist (x i) (y i) := by
766 simp_rw [dist_eq_norm, norm_eq_of_L1, sub_apply]
767
768theorem nndist_eq_of_L1 (x y : PiLp 1 β) : nndist x y = ∑ i, nndist (x i) (y i) :=
769 NNReal.eq <| by push_cast; exact dist_eq_of_L1 _ _
770
771set_option backward.isDefEq.respectTransparency false in
772theorem edist_eq_of_L1 (x y : PiLp 1 β) : edist x y = ∑ i, edist (x i) (y i) := by
773 simp [PiLp.edist_eq_sum]
774
775end L1
776
777section L2
778variable {β} [∀ i, SeminormedAddCommGroup (β i)]
779
780theorem norm_eq_of_L2 (x : PiLp 2 β) :
781 ‖x‖ = √(∑ i : ι, ‖x i‖ ^ 2) := by
782 rw [norm_eq_of_nat 2 (by norm_cast) _]
783 rw [Real.sqrt_eq_rpow]
784 norm_cast
785
786theorem nnnorm_eq_of_L2 (x : PiLp 2 β) :
787 ‖x‖₊ = NNReal.sqrt (∑ i : ι, ‖x i‖₊ ^ 2) :=
788 NNReal.eq <| by
789 push_cast
790 exact norm_eq_of_L2 x
791
792theorem norm_sq_eq_of_L2 (β : ι → Type*) [∀ i, SeminormedAddCommGroup (β i)] (x : PiLp 2 β) :
793 ‖x‖ ^ 2 = ∑ i : ι, ‖x i‖ ^ 2 := by
794 suffices ‖x‖₊ ^ 2 = ∑ i : ι, ‖x i‖₊ ^ 2 by
795 simpa only [NNReal.coe_sum] using! congr_arg ((↑) : ℝ≥0 → ℝ) this
796 rw [nnnorm_eq_of_L2, NNReal.sq_sqrt]
797
798theorem dist_eq_of_L2 (x y : PiLp 2 β) :
799 dist x y = √(∑ i, dist (x i) (y i) ^ 2) := by
800 simp_rw [dist_eq_norm, norm_eq_of_L2, sub_apply]
801
802theorem dist_sq_eq_of_L2 (x y : PiLp 2 β) :
803 dist x y ^ 2 = ∑ i, dist (x i) (y i) ^ 2 := by
804 simp_rw [dist_eq_norm, norm_sq_eq_of_L2, sub_apply]
805
806theorem nndist_eq_of_L2 (x y : PiLp 2 β) :
807 nndist x y = NNReal.sqrt (∑ i, nndist (x i) (y i) ^ 2) :=
808 NNReal.eq <| by
809 push_cast
810 exact dist_eq_of_L2 _ _
811
812theorem edist_eq_of_L2 (x y : PiLp 2 β) :
813 edist x y = (∑ i, edist (x i) (y i) ^ 2) ^ (1 / 2 : ℝ) := by simp [PiLp.edist_eq_sum]
814
815end L2
816
817instance instIsBoundedSMul [SeminormedRing 𝕜] [∀ i, SeminormedAddCommGroup (β i)]
818 [∀ i, Module 𝕜 (β i)] [∀ i, IsBoundedSMul 𝕜 (β i)] :
819 IsBoundedSMul 𝕜 (PiLp p β) :=
820 .of_nnnorm_smul_le fun c f => by
821 rcases p.dichotomy with (rfl | hp)
822 · rw [← nnnorm_ofLp, ← nnnorm_ofLp, ofLp_smul]
823 exact nnnorm_smul_le c (ofLp f)
824 · have hp0 : 0 < p.toReal := zero_lt_one.trans_le hp
825 have hpt : p ≠ ⊤ := p.toReal_pos_iff_ne_top.mp hp0
826 rw [nnnorm_eq_sum hpt, nnnorm_eq_sum hpt, one_div, NNReal.rpow_inv_le_iff hp0,
827 NNReal.mul_rpow, ← NNReal.rpow_mul, inv_mul_cancel₀ hp0.ne', NNReal.rpow_one,
828 Finset.mul_sum]
829 simp_rw [← NNReal.mul_rpow, smul_apply]
830 gcongr
831 apply nnnorm_smul_le
832
833instance instNormSMulClass [SeminormedRing 𝕜] [∀ i, SeminormedAddCommGroup (β i)]
834 [∀ i, Module 𝕜 (β i)] [∀ i, NormSMulClass 𝕜 (β i)] :
835 NormSMulClass 𝕜 (PiLp p β) :=
836 .of_nnnorm_smul fun c f => by
837 rcases p.dichotomy with (rfl | hp)
838 · rw [← nnnorm_ofLp, ← nnnorm_ofLp, WithLp.ofLp_smul, nnnorm_smul]
839 · have hp0 : 0 < p.toReal := zero_lt_one.trans_le hp
840 have hpt : p ≠ ⊤ := p.toReal_pos_iff_ne_top.mp hp0
841 rw [nnnorm_eq_sum hpt, nnnorm_eq_sum hpt, one_div, NNReal.rpow_inv_eq_iff hp0.ne',
842 NNReal.mul_rpow, ← NNReal.rpow_mul, inv_mul_cancel₀ hp0.ne', NNReal.rpow_one,
843 Finset.mul_sum]
844 simp_rw [← NNReal.mul_rpow, smul_apply, nnnorm_smul]
845
846/-- The product of finitely many normed spaces is a normed space, with the `L^p` norm. -/
847instance normedSpace [NormedField 𝕜] [∀ i, SeminormedAddCommGroup (β i)]
848 [∀ i, NormedSpace 𝕜 (β i)] : NormedSpace 𝕜 (PiLp p β) where
849 norm_smul_le := norm_smul_le
850
851variable {𝕜 p α}
852variable [Semiring 𝕜] [∀ i, SeminormedAddCommGroup (α i)] [∀ i, SeminormedAddCommGroup (β i)]
853variable [∀ i, Module 𝕜 (α i)] [∀ i, Module 𝕜 (β i)]
854
855/-- The canonical map `WithLp.equiv` between `PiLp ∞ β` and `Π i, β i` as a linear isometric
856equivalence. -/
857def equivₗᵢ : PiLp ∞ β ≃ₗᵢ[𝕜] (∀ i, β i) where
858 __ := WithLp.linearEquiv ∞ 𝕜 _
859 norm_map' := norm_ofLp
860
861section piLpCongrLeft
862variable {ι' : Type*}
863variable [Fintype ι']
864variable (p 𝕜)
865variable (E : Type*) [SeminormedAddCommGroup E] [Module 𝕜 E]
866
867/-- An equivalence of finite domains induces a linearly isometric equivalence of finitely supported
868functions. -/
869def _root_.LinearIsometryEquiv.piLpCongrLeft (e : ι ≃ ι') :
870 (PiLp p fun _ : ι => E) ≃ₗᵢ[𝕜] PiLp p fun _ : ι' => E where
871 toLinearEquiv := (WithLp.linearEquiv p 𝕜 (ι → E)).trans
872 ((LinearEquiv.piCongrLeft' 𝕜 (fun _ : ι => E) e).trans (WithLp.linearEquiv p 𝕜 (ι' → E)).symm)
873 norm_map' x' := by
874 rcases p.dichotomy with (rfl | h)
875 · simp_rw [norm_eq_ciSup]
876 exact e.symm.iSup_congr fun _ => rfl
877 · simp only [norm_eq_sum (zero_lt_one.trans_le h)]
878 congr 1
879 exact Fintype.sum_equiv e.symm _ _ fun _ => rfl
880
881variable {p 𝕜 E}
882
883@[simp]
884theorem _root_.LinearIsometryEquiv.piLpCongrLeft_apply (e : ι ≃ ι') (v : PiLp p fun _ : ι => E) :
885 LinearIsometryEquiv.piLpCongrLeft p 𝕜 E e v = Equiv.piCongrLeft' (fun _ : ι => E) e v :=
886 rfl
887
888@[simp]
889theorem _root_.LinearIsometryEquiv.piLpCongrLeft_symm (e : ι ≃ ι') :
890 (LinearIsometryEquiv.piLpCongrLeft p 𝕜 E e).symm =
891 LinearIsometryEquiv.piLpCongrLeft p 𝕜 E e.symm := by
892 ext
893 simp [LinearIsometryEquiv.piLpCongrLeft, LinearIsometryEquiv.symm]
894
895@[simp high]
896theorem _root_.LinearIsometryEquiv.piLpCongrLeft_single [DecidableEq ι] [DecidableEq ι']
897 (e : ι ≃ ι') (i : ι) (v : E) :
898 LinearIsometryEquiv.piLpCongrLeft p 𝕜 E e (single p i v) = single p (e i) v := by
899 ext x
900 simp [LinearIsometryEquiv.piLpCongrLeft_apply, Equiv.piCongrLeft',
901 Pi.single, Function.update, Equiv.symm_apply_eq]
902
903end piLpCongrLeft
904
905section piLpCongrRight
906variable {β}
907
908variable (p) in
909/-- A family of linearly isometric equivalences in the codomain induces an isometric equivalence
910between Pi types with the Lp norm.
911
912This is the isometry version of `LinearEquiv.piCongrRight`. -/
913protected def _root_.LinearIsometryEquiv.piLpCongrRight (e : ∀ i, α i ≃ₗᵢ[𝕜] β i) :
914 PiLp p α ≃ₗᵢ[𝕜] PiLp p β where
915 toLinearEquiv :=
916 WithLp.linearEquiv _ _ _
917 ≪≫ₗ (LinearEquiv.piCongrRight fun i => (e i).toLinearEquiv)
918 ≪≫ₗ (WithLp.linearEquiv _ _ _).symm
919 norm_map' := (WithLp.linearEquiv p 𝕜 _).symm.surjective.forall.2 fun x => by
920 simp only [coe_symm_linearEquiv, LinearEquiv.trans_apply, coe_linearEquiv]
921 obtain rfl | hp := p.dichotomy
922 · simp_rw [PiLp.norm_toLp, Pi.norm_def, LinearEquiv.piCongrRight_apply,
923 LinearIsometryEquiv.coe_toLinearEquiv, LinearIsometryEquiv.nnnorm_map]
924 · have : 0 < p.toReal := zero_lt_one.trans_le <| by norm_cast
925 simp only [PiLp.norm_eq_sum this, LinearEquiv.piCongrRight_apply,
926 LinearIsometryEquiv.coe_toLinearEquiv, LinearIsometryEquiv.norm_map, one_div]
927
928@[simp]
929theorem _root_.LinearIsometryEquiv.piLpCongrRight_apply (e : ∀ i, α i ≃ₗᵢ[𝕜] β i) (x : PiLp p α) :
930 LinearIsometryEquiv.piLpCongrRight p e x = toLp p fun i => e i (x i) := rfl
931
932@[simp]
933theorem _root_.LinearIsometryEquiv.piLpCongrRight_refl :
934 LinearIsometryEquiv.piLpCongrRight p (fun i => .refl 𝕜 (α i)) = .refl _ _ :=
935 rfl
936
937@[simp]
938theorem _root_.LinearIsometryEquiv.piLpCongrRight_symm (e : ∀ i, α i ≃ₗᵢ[𝕜] β i) :
939 (LinearIsometryEquiv.piLpCongrRight p e).symm =
940 LinearIsometryEquiv.piLpCongrRight p (fun i => (e i).symm) :=
941 rfl
942
943@[simp high]
944theorem _root_.LinearIsometryEquiv.piLpCongrRight_single (e : ∀ i, α i ≃ₗᵢ[𝕜] β i) [DecidableEq ι]
945 (i : ι) (v : α i) :
946 LinearIsometryEquiv.piLpCongrRight p e (single p i v) = single p i (e _ v) :=
947 PiLp.ext <| Pi.apply_single (e ·) (fun _ => map_zero _) _ _
948
949end piLpCongrRight
950
951section piLpCurry
952
953variable {ι : Type*} {κ : ι → Type*} (p : ℝ≥0∞) [Fact (1 ≤ p)]
954 [Fintype ι] [∀ i, Fintype (κ i)]
955 (α : ∀ i, κ i → Type*) [∀ i k, SeminormedAddCommGroup (α i k)] [∀ i k, Module 𝕜 (α i k)]
956
957variable (𝕜) in
958/-- `LinearEquiv.piCurry` for `PiLp`, as an isometry. -/
959def _root_.LinearIsometryEquiv.piLpCurry :
960 PiLp p (fun i : Sigma _ => α i.1 i.2) ≃ₗᵢ[𝕜] PiLp p (fun i => PiLp p (α i)) where
961 toLinearEquiv :=
962 WithLp.linearEquiv _ _ _
963 ≪≫ₗ LinearEquiv.piCurry 𝕜 α
964 ≪≫ₗ (LinearEquiv.piCongrRight fun _ => (WithLp.linearEquiv _ _ _).symm)
965 ≪≫ₗ (WithLp.linearEquiv _ _ _).symm
966 norm_map' := (WithLp.linearEquiv p 𝕜 _).symm.surjective.forall.2 fun x => by
967 simp_rw [← coe_nnnorm, NNReal.coe_inj, WithLp.linearEquiv_symm_apply]
968 obtain rfl | hp := eq_or_ne p ⊤
969 · simp [Pi.nnnorm_def, ← Finset.univ_sigma_univ, Finset.sup_sigma, Sigma.curry]
970 · have : 0 < p.toReal := (toReal_pos_iff_ne_top _).mpr hp
971 simp [nnnorm_eq_sum hp, this.ne', ← Finset.univ_sigma_univ, Finset.sum_sigma, Sigma.curry]
972
973@[simp] theorem _root_.LinearIsometryEquiv.piLpCurry_apply
974 (f : PiLp p (fun i : Sigma κ => α i.1 i.2)) :
975 _root_.LinearIsometryEquiv.piLpCurry 𝕜 p α f =
976 toLp p (fun i => (toLp p) <| Sigma.curry (ofLp f) i) :=
977 rfl
978
979@[simp] theorem _root_.LinearIsometryEquiv.piLpCurry_symm_apply
980 (f : PiLp p (fun i => PiLp p (α i))) :
981 (_root_.LinearIsometryEquiv.piLpCurry 𝕜 p α).symm f =
982 toLp p (Sigma.uncurry fun i j => f i j) :=
983 rfl
984
985end piLpCurry
986
987section sumPiLpEquivProdLpPiLp
988
989variable {ι κ : Type*} (p : ℝ≥0∞) (α : ι ⊕ κ → Type*) [Fintype ι] [Fintype κ] [Fact (1 ≤ p)]
990variable [∀ i, SeminormedAddCommGroup (α i)] [∀ i, Module 𝕜 (α i)]
991
992/-- `LinearEquiv.sumPiEquivProdPi` for `PiLp`, as an isometry. -/
993@[simps! +simpRhs]
994def sumPiLpEquivProdLpPiLp :
995 WithLp p (Π i, α i) ≃ₗᵢ[𝕜]
996 WithLp p (WithLp p (Π i, α (.inl i)) × WithLp p (Π i, α (.inr i))) where
997 toLinearEquiv :=
998 WithLp.linearEquiv p _ _
999 ≪≫ₗ LinearEquiv.sumPiEquivProdPi _ _ _ α
1000 ≪≫ₗ LinearEquiv.prodCongr (WithLp.linearEquiv p _ _).symm
1001 (WithLp.linearEquiv _ _ _).symm
1002 ≪≫ₗ (WithLp.linearEquiv p _ _).symm
1003 norm_map' := (WithLp.linearEquiv p 𝕜 _).symm.surjective.forall.2 fun x => by
1004 obtain rfl | hp := p.dichotomy
1005 · simp [← Finset.univ_disjSum_univ, Finset.sup_disjSum, Pi.norm_def]
1006 · have : 0 < p.toReal := by positivity
1007 have hpt : p ≠ ⊤ := (toReal_pos_iff_ne_top p).mp this
1008 simp_rw [← coe_nnnorm]; congr 1 -- convert to nnnorm to avoid needing positivity arguments
1009 simp [nnnorm_eq_sum hpt, WithLp.prod_nnnorm_eq_add hpt, NNReal.rpow_inv_rpow this.ne']
1010
1011end sumPiLpEquivProdLpPiLp
1012
1013section Single
1014
1015variable (p)
1016variable [DecidableEq ι]
1017
1018@[simp]
1019theorem nnnorm_single (i : ι) (b : β i) : ‖single p i b‖₊ = ‖b‖₊ := by
1020 have : Nonempty ι := ⟨i⟩
1021 induction p generalizing hp with
1022 | top =>
1023 simp_rw [nnnorm_eq_ciSup]
1024 refine
1025 ciSup_eq_of_forall_le_of_forall_lt_exists_gt (fun j => ?_) fun n hn => ⟨i, hn.trans_eq ?_⟩
1026 · obtain rfl | hij := Decidable.eq_or_ne i j
1027 · rw [single_eq_same]
1028 · simp [hij]
1029 · rw [single_eq_same]
1030 | coe p =>
1031 have hp0 : (p : ℝ) ≠ 0 :=
1032 mod_cast (zero_lt_one.trans_le <| Fact.out (p := 1 ≤ (p : ℝ≥0∞))).ne'
1033 rw [nnnorm_eq_sum ENNReal.coe_ne_top, ENNReal.coe_toReal, Fintype.sum_eq_single i,
1034 toLp_apply, single_eq_same, ← NNReal.rpow_mul, one_div,
1035 mul_inv_cancel₀ hp0, NNReal.rpow_one]
1036 intro j hij
1037 rw [toLp_apply, single_eq_of_ne _ hij, nnnorm_zero, NNReal.zero_rpow hp0]
1038
1039@[deprecated nnnorm_single (since := "2026-03-15")]
1040theorem nnnorm_toLp_single (i : ι) (b : β i) : ‖toLp p (Pi.single i b)‖₊ = ‖b‖₊ :=
1041 nnnorm_single p β i b
1042
1043@[simp]
1044lemma norm_single (i : ι) (b : β i) : ‖single p i b‖ = ‖b‖ :=
1045 congr_arg ((↑) : ℝ≥0 → ℝ) <| nnnorm_single p β i b
1046
1047@[deprecated norm_single (since := "2026-03-15")]
1048lemma norm_toLp_single (i : ι) (b : β i) : ‖toLp p (Pi.single i b)‖ = ‖b‖ :=
1049 norm_single p β i b
1050
1051@[simp]
1052lemma nndist_single_same (i : ι) (b₁ b₂ : β i) :
1053 nndist (single p i b₁) (single p i b₂) = nndist b₁ b₂ := by
1054 rw [nndist_eq_nnnorm, nndist_eq_nnnorm, ← single_sub, nnnorm_single]
1055
1056@[deprecated nndist_single_same (since := "2026-03-15")]
1057lemma nndist_toLp_single_same (i : ι) (b₁ b₂ : β i) :
1058 nndist (toLp p (Pi.single i b₁)) (toLp p (Pi.single i b₂)) = nndist b₁ b₂ :=
1059 nndist_single_same p β i b₁ b₂
1060
1061@[simp]
1062lemma dist_single_same (i : ι) (b₁ b₂ : β i) :
1063 dist (single p i b₁) (single p i b₂) = dist b₁ b₂ :=
1064 congr_arg ((↑) : ℝ≥0 → ℝ) <| nndist_single_same p β i b₁ b₂
1065
1066@[deprecated dist_single_same (since := "2026-03-15")]
1067lemma dist_toLp_single_same (i : ι) (b₁ b₂ : β i) :
1068 dist (toLp p (Pi.single i b₁)) (toLp p (Pi.single i b₂)) = dist b₁ b₂ :=
1069 dist_single_same p β i b₁ b₂
1070
1071@[simp]
1072lemma edist_single_same (i : ι) (b₁ b₂ : β i) :
1073 edist (single p i b₁) (single p i b₂) = edist b₁ b₂ := by
1074 simp only [edist_nndist, nndist_single_same p β i b₁ b₂]
1075
1076@[deprecated edist_single_same (since := "2026-03-15")]
1077lemma edist_toLp_single_same (i : ι) (b₁ b₂ : β i) :
1078 edist (toLp p (Pi.single i b₁)) (toLp p (Pi.single i b₂)) = edist b₁ b₂ :=
1079 edist_single_same p β i b₁ b₂
1080
1081end Single
1082
1083/-- When `p = ∞`, this lemma does not hold without the additional assumption `Nonempty ι` because
1084the left-hand side simplifies to `0`, while the right-hand side simplifies to `‖b‖₊`. See
1085`PiLp.nnnorm_equiv_symm_const'` for a version which exchanges the hypothesis `p ≠ ∞` for
1086`Nonempty ι`. -/
1087lemma nnnorm_toLp_const {β} [SeminormedAddCommGroup β] (hp : p ≠ ∞) (b : β) :
1088 ‖toLp p (Function.const ι b)‖₊ =
1089 (Fintype.card ι : ℝ≥0) ^ (1 / p).toReal * ‖b‖₊ := by
1090 rcases p.dichotomy with (h | h)
1091 · exact False.elim (hp h)
1092 · have ne_zero : p.toReal ≠ 0 := (zero_lt_one.trans_le h).ne'
1093 simp_rw [nnnorm_eq_sum hp, Function.const_apply, Finset.sum_const,
1094 Finset.card_univ, nsmul_eq_mul, NNReal.mul_rpow, ← NNReal.rpow_mul,
1095 mul_one_div_cancel ne_zero, NNReal.rpow_one, ENNReal.toReal_div, ENNReal.toReal_one]
1096
1097/-- When `IsEmpty ι`, this lemma does not hold without the additional assumption `p ≠ ∞` because
1098the left-hand side simplifies to `0`, while the right-hand side simplifies to `‖b‖₊`. See
1099`PiLp.nnnorm_toLp_const` for a version which exchanges the hypothesis `Nonempty ι`.
1100for `p ≠ ∞`. -/
1101lemma nnnorm_toLp_const' {β} [SeminormedAddCommGroup β] [Nonempty ι] (b : β) :
1102 ‖toLp p (Function.const ι b)‖₊ =
1103 (Fintype.card ι : ℝ≥0) ^ (1 / p).toReal * ‖b‖₊ := by
1104 rcases em <| p = ∞ with (rfl | hp)
1105 · simp only [ENNReal.div_top, ENNReal.toReal_zero, NNReal.rpow_zero,
1106 one_mul, nnnorm_eq_ciSup, Function.const_apply, ciSup_const]
1107 · exact nnnorm_toLp_const hp b
1108
1109/-- When `p = ∞`, this lemma does not hold without the additional assumption `Nonempty ι` because
1110the left-hand side simplifies to `0`, while the right-hand side simplifies to `‖b‖₊`. See
1111`PiLp.norm_toLp_const'` for a version which exchanges the hypothesis `p ≠ ∞` for
1112`Nonempty ι`. -/
1113lemma norm_toLp_const {β} [SeminormedAddCommGroup β] (hp : p ≠ ∞) (b : β) :
1114 ‖toLp p (Function.const ι b)‖ =
1115 (Fintype.card ι : ℝ≥0) ^ (1 / p).toReal * ‖b‖ :=
1116 (congr_arg ((↑) : ℝ≥0 → ℝ) <| nnnorm_toLp_const hp b).trans <| by simp
1117
1118/-- When `IsEmpty ι`, this lemma does not hold without the additional assumption `p ≠ ∞` because
1119the left-hand side simplifies to `0`, while the right-hand side simplifies to `‖b‖₊`. See
1120`PiLp.norm_equiv_symm_const` for a version which exchanges the hypothesis `Nonempty ι`.
1121for `p ≠ ∞`. -/
1122lemma norm_toLp_const' {β} [SeminormedAddCommGroup β] [Nonempty ι] (b : β) :
1123 ‖toLp p (Function.const ι b)‖ =
1124 (Fintype.card ι : ℝ≥0) ^ (1 / p).toReal * ‖b‖ :=
1125 (congr_arg ((↑) : ℝ≥0 → ℝ) <| nnnorm_toLp_const' b).trans <| by simp
1126
1127lemma nnnorm_toLp_one {β} [SeminormedAddCommGroup β] (hp : p ≠ ∞) [One β] :
1128 ‖toLp p (1 : ι → β)‖₊ = (Fintype.card ι : ℝ≥0) ^ (1 / p).toReal * ‖(1 : β)‖₊ :=
1129 (nnnorm_toLp_const hp (1 : β)).trans rfl
1130
1131lemma norm_toLp_one {β} [SeminormedAddCommGroup β] (hp : p ≠ ∞) [One β] :
1132 ‖toLp p (1 : ι → β)‖ = (Fintype.card ι : ℝ≥0) ^ (1 / p).toReal * ‖(1 : β)‖ :=
1133 (norm_toLp_const hp (1 : β)).trans rfl
1134
1135end Fintype
1136
1137section
1138
1139variable [Semiring 𝕜] [∀ i, AddCommGroup (β i)] [∀ i, Module 𝕜 (β i)] [∀ i, TopologicalSpace (β i)]
1140
1141/-- `WithLp.linearEquiv` as a continuous linear equivalence. -/
1142@[simps! apply symm_apply]
1143def continuousLinearEquiv : PiLp p β ≃L[𝕜] ∀ i, β i where
1144 toLinearEquiv := WithLp.linearEquiv _ _ _
1145 continuous_invFun := (by fun_prop : Continuous fun (a : Π i, β i) ↦ toLp p a)
1146
1147lemma coe_continuousLinearEquiv :
1148 ⇑(PiLp.continuousLinearEquiv p 𝕜 β) = ofLp := rfl
1149
1150lemma coe_symm_continuousLinearEquiv :
1151 ⇑(PiLp.continuousLinearEquiv p 𝕜 β).symm = toLp p := rfl
1152
1153/-- The natural equivalence between `PiLp p β` and `β default`,
1154for any index type `ι` with a unique element. -/
1155@[simps! apply symm_apply]
1156def equivOfUnique [Unique ι] : PiLp p β ≃L[𝕜] β default :=
1157 (continuousLinearEquiv p 𝕜 β).trans <| .piUnique 𝕜 β
1158
1159end
1160
1161section
1162
1163variable [Semiring 𝕜] [∀ i, NormedAddCommGroup (β i)] [∀ i, Module 𝕜 (β i)]
1164
1165variable {𝕜} in
1166/-- The projection on the `i`-th coordinate of `PiLp p β`, as a continuous linear map. -/
1167@[simps!]
1168def proj (i : ι) : PiLp p β →L[𝕜] β i where
1169 __ := projₗ p β i
1170 cont := (by fun_prop : Continuous fun a : PiLp p β ↦ a.ofLp i)
1171
1172end
1173
1174section Basis
1175
1176variable [Finite ι] [Ring 𝕜]
1177variable (ι)
1178
1179/-- A version of `Pi.basisFun` for `PiLp`. -/
1180def basisFun : Basis ι 𝕜 (PiLp p fun _ : ι => 𝕜) :=
1181 Basis.ofEquivFun (WithLp.linearEquiv p 𝕜 (ι → 𝕜))
1182
1183@[simp]
1184theorem basisFun_apply [DecidableEq ι] (i) :
1185 basisFun p 𝕜 ι i = single p i 1 := by
1186 simp_rw [basisFun, Basis.coe_ofEquivFun, WithLp.coe_symm_linearEquiv, toLp_single]
1187
1188@[simp]
1189theorem basisFun_repr (x : PiLp p fun _ : ι => 𝕜) (i : ι) : (basisFun p 𝕜 ι).repr x i = x i :=
1190 rfl
1191
1192@[simp]
1193theorem basisFun_equivFun : (basisFun p 𝕜 ι).equivFun = WithLp.linearEquiv p 𝕜 (ι → 𝕜) :=
1194 Basis.equivFun_ofEquivFun _
1195
1196theorem basisFun_eq_pi_basisFun :
1197 basisFun p 𝕜 ι = (Pi.basisFun 𝕜 ι).map (WithLp.linearEquiv p 𝕜 (ι → 𝕜)).symm :=
1198 rfl
1199
1200@[simp]
1201theorem basisFun_map :
1202 (basisFun p 𝕜 ι).map (WithLp.linearEquiv p 𝕜 (ι → 𝕜)) = Pi.basisFun 𝕜 ι := rfl
1203
1204end Basis
1205
1206open Matrix
1207
1208nonrec theorem basis_toMatrix_basisFun_mul [Fintype ι]
1209 {𝕜} [SeminormedCommRing 𝕜] (b : Basis ι 𝕜 (PiLp p fun _ : ι => 𝕜))
1210 (A : Matrix ι ι 𝕜) :
1211 b.toMatrix (PiLp.basisFun _ _ _) * A =
1212 Matrix.of fun i j => b.repr (toLp p (Aᵀ j)) i := by
1213 have := basis_toMatrix_basisFun_mul (b.map (WithLp.linearEquiv _ 𝕜 _)) A
1214 simp_rw [← PiLp.basisFun_map p, Basis.map_repr, LinearEquiv.trans_apply,
1215 WithLp.linearEquiv_symm_apply, Basis.toMatrix_map, Function.comp_def, Basis.map_apply,
1216 LinearEquiv.symm_apply_apply] at this
1217 exact this
1218
1219section toPi
1220
1221/-!
1222### `L^p` distance on a product space
1223
1224In this section we define a pseudometric space structure on `Π i, α i`, as well as a seminormed
1225group structure. These are meant to be used to put the desired instances on type synonyms
1226of `Π i, α i`. See for instance `Matrix.frobeniusSeminormedAddCommGroup`.
1227-/
1228
1229-- This prevents Lean from elaborating terms of `Π i, α i` with an unintended norm.
1230attribute [-instance] Pi.seminormedAddGroup
1231
1232variable [Fact (1 ≤ p)] [Fintype ι]
1233
1234/-- This definition allows to endow `Π i, α i` with the Lp distance with the uniformity and
1235bornology being defeq to the product ones. It is useful to endow a type synonym of `Π i, α i` with
1236the Lp distance. -/
1237abbrev pseudoMetricSpaceToPi [∀ i, PseudoMetricSpace (α i)] :
1238 PseudoMetricSpace (Π i, α i) :=
1239 (isUniformInducing_toLp p α).comapPseudoMetricSpace.replaceBornology
1240 fun s => Filter.ext_iff.1
1241 (le_antisymm (antilipschitzWith_toLp p α).tendsto_cobounded.le_comap
1242 (lipschitzWith_toLp p α).comap_cobounded_le) sᶜ
1243
1244lemma dist_pseudoMetricSpaceToPi [∀ i, PseudoMetricSpace (α i)] (x y : Π i, α i) :
1245 @dist _ (pseudoMetricSpaceToPi p α).toDist x y = dist (toLp p x) (toLp p y) := rfl
1246
1247/-- This definition allows to endow `Π i, α i` with the Lp norm with the uniformity and bornology
1248being defeq to the product ones. It is useful to endow a type synonym of `Π i, α i` with the
1249Lp norm. -/
1250abbrev seminormedAddCommGroupToPi [∀ i, SeminormedAddCommGroup (α i)] :
1251 SeminormedAddCommGroup (Π i, α i) where
1252 norm x := ‖toLp p x‖
1253 toPseudoMetricSpace := pseudoMetricSpaceToPi p α
1254 dist_eq x y := by
1255 rw [dist_pseudoMetricSpaceToPi, SeminormedAddCommGroup.dist_eq, toLp_add, toLp_neg]
1256
1257lemma norm_seminormedAddCommGroupToPi [∀ i, SeminormedAddCommGroup (α i)] (x : Π i, α i) :
1258 @Norm.norm _ (seminormedAddCommGroupToPi p α).toNorm x = ‖toLp p x‖ := rfl
1259
1260lemma nnnorm_seminormedAddCommGroupToPi [∀ i, SeminormedAddCommGroup (α i)] (x : Π i, α i) :
1261 @NNNorm.nnnorm _ (seminormedAddCommGroupToPi p α).toSeminormedAddGroup.toNNNorm x =
1262 ‖toLp p x‖₊ := rfl
1263
1264lemma isBoundedSMulSeminormedAddCommGroupToPi
1265 [∀ i, SeminormedAddCommGroup (α i)] {R : Type*} [SeminormedRing R]
1266 [∀ i, Module R (α i)] [∀ i, IsBoundedSMul R (α i)] :
1267 letI := pseudoMetricSpaceToPi p α
1268 IsBoundedSMul R (Π i, α i) := by
1269 let := pseudoMetricSpaceToPi p α
1270 refine ⟨fun x y z ↦ ?_, fun x y z ↦ ?_⟩
1271 · simpa [dist_pseudoMetricSpaceToPi] using dist_smul_pair x (toLp p y) (toLp p z)
1272 · simpa [dist_pseudoMetricSpaceToPi] using dist_pair_smul x y (toLp p z)
1273
1274lemma normSMulClassSeminormedAddCommGroupToPi
1275 [∀ i, SeminormedAddCommGroup (α i)] {R : Type*} [SeminormedRing R]
1276 [∀ i, Module R (α i)] [∀ i, NormSMulClass R (α i)] :
1277 letI := seminormedAddCommGroupToPi p α
1278 NormSMulClass R (Π i, α i) := by
1279 let := seminormedAddCommGroupToPi p α
1280 refine ⟨fun x y ↦ ?_⟩
1281 simp [norm_seminormedAddCommGroupToPi, norm_smul]
1282
1283/-- This definition allows to endow `Π i, α i` with a normed space structure corresponding to
1284the Lp norm. It is useful for type synonyms of `Π i, α i`. -/
1285abbrev normedSpaceSeminormedAddCommGroupToPi
1286 [∀ i, SeminormedAddCommGroup (α i)] {R : Type*} [NormedField R]
1287 [∀ i, NormedSpace R (α i)] :
1288 letI := seminormedAddCommGroupToPi p α
1289 NormedSpace R (Π i, α i) := by
1290 letI := seminormedAddCommGroupToPi p α
1291 refine ⟨fun x y ↦ ?_⟩
1292 simp [norm_seminormedAddCommGroupToPi, norm_smul]
1293
1294/-- This definition allows to endow `Π i, α i` with the Lp norm with the uniformity and bornology
1295being defeq to the product ones. It is useful to endow a type synonym of `Π i, α i` with the
1296Lp norm. -/
1297abbrev normedAddCommGroupToPi [∀ i, NormedAddCommGroup (α i)] :
1298 NormedAddCommGroup (Π i, α i) where
1299 norm x := ‖toLp p x‖
1300 toPseudoMetricSpace := pseudoMetricSpaceToPi p α
1301 dist_eq x y := by
1302 rw [dist_pseudoMetricSpaceToPi, SeminormedAddCommGroup.dist_eq, toLp_add, toLp_neg]
1303 eq_of_dist_eq_zero {x y} h := by
1304 rw [dist_pseudoMetricSpaceToPi] at h
1305 apply eq_of_dist_eq_zero at h
1306 exact WithLp.toLp_injective p h
1307
1308end toPi
1309
1310end PiLp