Skip to content

Commit

Permalink
refactor: generalize PiLp to WithLp (#6409)
Browse files Browse the repository at this point in the history
The motivation is to be able to reuse this for `ProdLp` in #6136.

This matches the pattern of how the `Lex` type synonym is used.
  • Loading branch information
eric-wieser committed Aug 14, 2023
1 parent 4fa9d3d commit 484cfeb
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 91 deletions.
1 change: 1 addition & 0 deletions Mathlib.lean
Expand Up @@ -769,6 +769,7 @@ import Mathlib.Analysis.NormedSpace.Star.Unitization
import Mathlib.Analysis.NormedSpace.TrivSqZeroExt
import Mathlib.Analysis.NormedSpace.Units
import Mathlib.Analysis.NormedSpace.WeakDual
import Mathlib.Analysis.NormedSpace.WithLp
import Mathlib.Analysis.NormedSpace.lpSpace
import Mathlib.Analysis.ODE.Gronwall
import Mathlib.Analysis.ODE.PicardLindelof
Expand Down
4 changes: 2 additions & 2 deletions Mathlib/Analysis/InnerProductSpace/PiL2.lean
Expand Up @@ -158,7 +158,7 @@ instance EuclideanSpace.instInnerProductSpace : InnerProductSpace 𝕜 (Euclidea
@[simp]
theorem finrank_euclideanSpace :
FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 ι) = Fintype.card ι := by
simp [EuclideanSpace, PiLp]
simp [EuclideanSpace, PiLp, WithLp]
#align finrank_euclidean_space finrank_euclideanSpace

theorem finrank_euclideanSpace_fin {n : ℕ} :
Expand Down Expand Up @@ -358,7 +358,7 @@ instance instFunLike : FunLike (OrthonormalBasis ι 𝕜 E) ι fun _ => E where
rw [this, Pi.single_smul]
replace h := congr_fun h i
simp only [LinearEquiv.comp_coe, SMulHomClass.map_smul, LinearEquiv.coe_coe,
LinearEquiv.trans_apply, PiLp.linearEquiv_symm_apply, PiLp.equiv_symm_single,
LinearEquiv.trans_apply, WithLp.linearEquiv_symm_apply, PiLp.equiv_symm_single,
LinearIsometryEquiv.coe_toLinearEquiv] at h ⊢
rw [h]

Expand Down
99 changes: 10 additions & 89 deletions Mathlib/Analysis/NormedSpace/PiLp.lean
Expand Up @@ -6,6 +6,7 @@ Authors: Sébastien Gouëzel, Jireh Loreaux
import Mathlib.Analysis.MeanInequalities
import Mathlib.Data.Fintype.Order
import Mathlib.LinearAlgebra.Matrix.Basis
import Mathlib.Analysis.NormedSpace.WithLp

#align_import analysis.normed_space.pi_Lp from "leanprover-community/mathlib"@"9d013ad8430ddddd350cff5c3db830278ded3c79"

Expand Down Expand Up @@ -73,9 +74,8 @@ noncomputable section
already endowed with the `L^∞` distance, we need the type synonym to avoid confusing typeclass
resolution. Also, we let it depend on `p`, to get a whole family of type on which we can put
different distances. -/
@[nolint unusedArguments]
def PiLp (_p : ℝ≥0∞) {ι : Type*} (α : ι → Type*) : Type _ :=
∀ i : ι, α i
abbrev PiLp (p : ℝ≥0∞) {ι : Type*} (α : ι → Type*) : Type _ :=
WithLp p (∀ i : ι, α i)
#align pi_Lp PiLp

instance (p : ℝ≥0∞) {ι : Type*} (α : ι → Type*) [∀ i, Inhabited (α i)] : Inhabited (PiLp p α) :=
Expand All @@ -91,14 +91,12 @@ variable (p : ℝ≥0∞) (𝕜 𝕜' : Type*) {ι : Type*} (α : ι → Type*)

/-- Canonical bijection between `PiLp p α` and the original Pi type. We introduce it to be able
to compare the `L^p` and `L^∞` distances through it. -/
protected def equiv : PiLp p α ≃ ∀ i : ι, α i :=
Equiv.refl _
abbrev equiv : PiLp p α ≃ ∀ i : ι, α i := WithLp.equiv _ _
#align pi_Lp.equiv PiLp.equiv

/-! Note that the unapplied versions of these lemmas are deliberately omitted, as they break
the use of the type synonym. -/


@[simp]
theorem equiv_apply (x : PiLp p α) (i : ι) : PiLp.equiv p α x i = x i :=
rfl
Expand Down Expand Up @@ -617,16 +615,10 @@ theorem edist_eq_of_L2 {β : ι → Type*} [∀ i, SeminormedAddCommGroup (β i)

variable [NormedField 𝕜] [NormedField 𝕜']

-- Porting note: added
instance module [∀ i, SeminormedAddCommGroup (β i)] [∀ i, NormedSpace 𝕜 (β i)] :
Module 𝕜 (PiLp p β) :=
{ Pi.module ι β 𝕜 with }

/-- The product of finitely many normed spaces is a normed space, with the `L^p` norm. -/
instance normedSpace [∀ i, SeminormedAddCommGroup (β i)] [∀ i, NormedSpace 𝕜 (β i)] :
NormedSpace 𝕜 (PiLp p β) :=
{ module p 𝕜 β with
norm_smul_le := fun c f => by
{ norm_smul_le := fun c f => by
rcases p.dichotomy with (rfl | hp)
· letI : Module 𝕜 (PiLp ∞ β) := Pi.module ι β 𝕜
suffices ‖c • f‖₊ = ‖c‖₊ * ‖f‖₊ by exact_mod_cast NNReal.coe_mono this.le
Expand All @@ -643,21 +635,6 @@ instance normedSpace [∀ i, SeminormedAddCommGroup (β i)] [∀ i, NormedSpace
exact Finset.sum_nonneg fun i _ => rpow_nonneg_of_nonneg (norm_nonneg _) _ }
#align pi_Lp.normed_space PiLp.normedSpace

instance isScalarTower [∀ i, SeminormedAddCommGroup (β i)] [SMul 𝕜 𝕜'] [∀ i, NormedSpace 𝕜 (β i)]
[∀ i, NormedSpace 𝕜' (β i)] [∀ i, IsScalarTower 𝕜 𝕜' (β i)] : IsScalarTower 𝕜 𝕜' (PiLp p β) :=
Pi.isScalarTower
#align pi_Lp.is_scalar_tower PiLp.isScalarTower

instance smulCommClass [∀ i, SeminormedAddCommGroup (β i)] [∀ i, NormedSpace 𝕜 (β i)]
[∀ i, NormedSpace 𝕜' (β i)] [∀ i, SMulCommClass 𝕜 𝕜' (β i)] : SMulCommClass 𝕜 𝕜' (PiLp p β) :=
Pi.smulCommClass
#align pi_Lp.smul_comm_class PiLp.smulCommClass

instance finiteDimensional [∀ i, SeminormedAddCommGroup (β i)] [∀ i, NormedSpace 𝕜 (β i)]
[∀ i, FiniteDimensional 𝕜 (β i)] : FiniteDimensional 𝕜 (PiLp p β) :=
FiniteDimensional.finiteDimensional_pi' _ _
#align pi_Lp.finite_dimensional PiLp.finiteDimensional

/- Register simplification lemmas for the applications of `PiLp` elements, as the usual lemmas
for Pi types will not trigger. -/
variable {𝕜 𝕜' p α}
Expand Down Expand Up @@ -746,7 +723,7 @@ theorem _root_.LinearIsometryEquiv.piLpCongrLeft_symm (e : ι ≃ ι') :
LinearIsometryEquiv.ext fun z => by -- porting note: was `rfl`
simp only [LinearIsometryEquiv.piLpCongrLeft, LinearIsometryEquiv.symm,
LinearIsometryEquiv.coe_mk]
unfold PiLp
unfold PiLp WithLp
ext
simp only [LinearEquiv.piCongrLeft'_symm_apply, eq_rec_constant,
LinearEquiv.piCongrLeft'_apply, Equiv.symm_symm_apply]
Expand All @@ -762,58 +739,6 @@ theorem _root_.LinearIsometryEquiv.piLpCongrLeft_single [DecidableEq ι] [Decida
Pi.single, Function.update, Equiv.symm_apply_eq]
#align linear_isometry_equiv.pi_Lp_congr_left_single LinearIsometryEquiv.piLpCongrLeft_single

@[simp]
theorem equiv_zero : PiLp.equiv p β 0 = 0 :=
rfl
#align pi_Lp.equiv_zero PiLp.equiv_zero

@[simp]
theorem equiv_symm_zero : (PiLp.equiv p β).symm 0 = 0 :=
rfl
#align pi_Lp.equiv_symm_zero PiLp.equiv_symm_zero

@[simp]
theorem equiv_add : PiLp.equiv p β (x + y) = PiLp.equiv p β x + PiLp.equiv p β y :=
rfl
#align pi_Lp.equiv_add PiLp.equiv_add

@[simp]
theorem equiv_symm_add :
(PiLp.equiv p β).symm (x' + y') = (PiLp.equiv p β).symm x' + (PiLp.equiv p β).symm y' :=
rfl
#align pi_Lp.equiv_symm_add PiLp.equiv_symm_add

@[simp]
theorem equiv_sub : PiLp.equiv p β (x - y) = PiLp.equiv p β x - PiLp.equiv p β y :=
rfl
#align pi_Lp.equiv_sub PiLp.equiv_sub

@[simp]
theorem equiv_symm_sub :
(PiLp.equiv p β).symm (x' - y') = (PiLp.equiv p β).symm x' - (PiLp.equiv p β).symm y' :=
rfl
#align pi_Lp.equiv_symm_sub PiLp.equiv_symm_sub

@[simp]
theorem equiv_neg : PiLp.equiv p β (-x) = -PiLp.equiv p β x :=
rfl
#align pi_Lp.equiv_neg PiLp.equiv_neg

@[simp]
theorem equiv_symm_neg : (PiLp.equiv p β).symm (-x') = -(PiLp.equiv p β).symm x' :=
rfl
#align pi_Lp.equiv_symm_neg PiLp.equiv_symm_neg

@[simp]
theorem equiv_smul : PiLp.equiv p β (c • x) = c • PiLp.equiv p β x :=
rfl
#align pi_Lp.equiv_smul PiLp.equiv_smul

@[simp]
theorem equiv_symm_smul : (PiLp.equiv p β).symm (c • x') = c • (PiLp.equiv p β).symm x' :=
rfl
#align pi_Lp.equiv_symm_smul PiLp.equiv_symm_smul

section Single

variable (p)
Expand Down Expand Up @@ -854,7 +779,7 @@ theorem norm_equiv_symm_single (i : ι) (b : β i) : ‖(PiLp.equiv p β).symm (
theorem nndist_equiv_symm_single_same (i : ι) (b₁ b₂ : β i) :
nndist ((PiLp.equiv p β).symm (Pi.single i b₁)) ((PiLp.equiv p β).symm (Pi.single i b₂)) =
nndist b₁ b₂ := by
rw [nndist_eq_nnnorm, nndist_eq_nnnorm, ← equiv_symm_sub, ← Pi.single_sub,
rw [nndist_eq_nnnorm, nndist_eq_nnnorm, ← WithLp.equiv_symm_sub, ← Pi.single_sub,
nnnorm_equiv_symm_single]
#align pi_Lp.nndist_equiv_symm_single_same PiLp.nndist_equiv_symm_single_same

Expand Down Expand Up @@ -938,11 +863,7 @@ theorem norm_equiv_symm_one {β} [SeminormedAddCommGroup β] (hp : p ≠ ∞) [O
variable (𝕜 p)

/-- `PiLp.equiv` as a linear equivalence. -/
@[simps (config := { fullyApplied := false })]
protected def linearEquiv : PiLp p β ≃ₗ[𝕜] ∀ i, β i :=
{ LinearEquiv.refl _ _ with
toFun := PiLp.equiv _ _
invFun := (PiLp.equiv _ _).symm }
abbrev linearEquiv : PiLp p β ≃ₗ[𝕜] ∀ i, β i := WithLp.linearEquiv _ _ _
#align pi_Lp.linear_equiv PiLp.linearEquiv

/-- `PiLp.equiv` as a continuous linear equivalence. -/
Expand All @@ -965,7 +886,7 @@ def basisFun : Basis ι 𝕜 (PiLp p fun _ : ι => 𝕜) :=
@[simp]
theorem basisFun_apply [DecidableEq ι] (i) :
basisFun p 𝕜 ι i = (PiLp.equiv p _).symm (Pi.single i 1) := by
simp_rw [basisFun, Basis.coe_ofEquivFun, PiLp.linearEquiv_symm_apply, Pi.single]
simp_rw [basisFun, Basis.coe_ofEquivFun, WithLp.linearEquiv_symm_apply, Pi.single]
#align pi_Lp.basis_fun_apply PiLp.basisFun_apply

@[simp]
Expand Down Expand Up @@ -997,7 +918,7 @@ nonrec theorem basis_toMatrix_basisFun_mul (b : Basis ι 𝕜 (PiLp p fun _ : ι
Matrix.of fun i j => b.repr ((PiLp.equiv _ _).symm (Aᵀ j)) i := by
have := basis_toMatrix_basisFun_mul (b.map (PiLp.linearEquiv _ 𝕜 _)) A
simp_rw [← PiLp.basisFun_map p, Basis.map_repr, LinearEquiv.trans_apply,
PiLp.linearEquiv_symm_apply, Basis.toMatrix_map, Function.comp, Basis.map_apply,
WithLp.linearEquiv_symm_apply, Basis.toMatrix_map, Function.comp, Basis.map_apply,
LinearEquiv.symm_apply_apply] at this
exact this
#align pi_Lp.basis_to_matrix_basis_fun_mul PiLp.basis_toMatrix_basisFun_mul
Expand Down
143 changes: 143 additions & 0 deletions Mathlib/Analysis/NormedSpace/WithLp.lean
@@ -0,0 +1,143 @@
/-
Copyright (c) 2023 Eric Wieser. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Eric Wieser
-/
import Mathlib.Data.Real.ENNReal
import Mathlib.LinearAlgebra.FiniteDimensional

/-! # The `WithLp` type synonym
`WithLp p V` is a copy of `V` with exactly the same vector space structure, but with the Lp norm
instead of any existing norm on `V`; recall that by default `ι → R` and `R × R` are equipped with
a norm defined as the supremum of the norms of their components.
This file defines the vector space structure for all types `V`; the norm structure is built for
different specializations of `V` in downstream files.
Note that this should not be used for infinite products, as in these cases the "right" Lp spaces is
not the same as the direct product of the spaces. See the docstring in `Mathlib/Analysis/PiLp` for
more details.
## Main definitions
* `WithLp p V`: a copy of `V` to be equipped with an L`p` norm.
* `WithLp.equiv p V`: the canonical equivalence between `WithLp p V` and `V`.
* `WithLp.linearEquiv p K V`: the canonical `K`-module isomorphism between `WithLp p V` and `V`.
## Implementation notes
The pattern here is the same one as is used by `Lex` for order structures; it avoids having a
separate synonym for each type (`ProdLp`, `PiLp`, etc), and allows all the structure-copying code
to be shared.
TODO: is it safe to copy across the topology and uniform space structure too for all reasonable
choices of `V`?
-/


open scoped ENNReal
set_option linter.uppercaseLean3 false

universe uK uK' uV

/-- A type synonym for the given `V`, associated with the L`p` norm. Note that by default this just
forgets the norm structure on `V`; it is up to downstream users to implement the L`p` norm (for
instance, on `Prod` and finite `Pi` types). -/
@[nolint unusedArguments]
def WithLp (_p : ℝ≥0∞) (V : Type uV) : Type uV := V

variable (p : ℝ≥0∞) (K : Type uK) (K' : Type uK') (V : Type uV)

namespace WithLp

/-- The canonical equivalence between `WithLp p V` and `V`. This should always be used to convert
back and forth between the representations. -/
protected def equiv : WithLp p V ≃ V := Equiv.refl _

variable [Semiring K] [Semiring K'] [AddCommGroup V]

/-! `WithLp p V` inherits various module-adjacent structures from `V`. -/

instance instAddCommGroup : AddCommGroup (WithLp p V) := ‹AddCommGroup V›
instance instModule [Module K V] : Module K (WithLp p V) := ‹Module K V›

instance instIsScalarTower [SMul K K'] [Module K V] [Module K' V] [IsScalarTower K K' V] :
IsScalarTower K K' (WithLp p V) :=
‹IsScalarTower K K' V›

instance instSMulCommClass [Module K V] [Module K' V] [SMulCommClass K K' V] :
SMulCommClass K K' (WithLp p V) :=
‹SMulCommClass K K' V›

instance instModuleFinite [Module K V] [Module.Finite K V] : Module.Finite K (WithLp p V) :=
‹Module.Finite K V›

variable {K V}
variable [Module K V]
variable (c : K) (x y : WithLp p V) (x' y' : V)

/-! `WithLp.equiv` preserves the module structure. -/

@[simp]
theorem equiv_zero : WithLp.equiv p V 0 = 0 :=
rfl
#align pi_Lp.equiv_zero WithLp.equiv_zero

@[simp]
theorem equiv_symm_zero : (WithLp.equiv p V).symm 0 = 0 :=
rfl
#align pi_Lp.equiv_symm_zero WithLp.equiv_symm_zero

@[simp]
theorem equiv_add : WithLp.equiv p V (x + y) = WithLp.equiv p V x + WithLp.equiv p V y :=
rfl
#align pi_Lp.equiv_add WithLp.equiv_add

@[simp]
theorem equiv_symm_add :
(WithLp.equiv p V).symm (x' + y') = (WithLp.equiv p V).symm x' + (WithLp.equiv p V).symm y' :=
rfl
#align pi_Lp.equiv_symm_add WithLp.equiv_symm_add

@[simp]
theorem equiv_sub : WithLp.equiv p V (x - y) = WithLp.equiv p V x - WithLp.equiv p V y :=
rfl
#align pi_Lp.equiv_sub WithLp.equiv_sub

@[simp]
theorem equiv_symm_sub :
(WithLp.equiv p V).symm (x' - y') = (WithLp.equiv p V).symm x' - (WithLp.equiv p V).symm y' :=
rfl
#align pi_Lp.equiv_symm_sub WithLp.equiv_symm_sub

@[simp]
theorem equiv_neg : WithLp.equiv p V (-x) = -WithLp.equiv p V x :=
rfl
#align pi_Lp.equiv_neg WithLp.equiv_neg

@[simp]
theorem equiv_symm_neg : (WithLp.equiv p V).symm (-x') = -(WithLp.equiv p V).symm x' :=
rfl
#align pi_Lp.equiv_symm_neg WithLp.equiv_symm_neg

@[simp]
theorem equiv_smul : WithLp.equiv p V (c • x) = c • WithLp.equiv p V x :=
rfl
#align pi_Lp.equiv_smul WithLp.equiv_smul

@[simp]
theorem equiv_symm_smul : (WithLp.equiv p V).symm (c • x') = c • (WithLp.equiv p V).symm x' :=
rfl
#align pi_Lp.equiv_symm_smul WithLp.equiv_symm_smul

variable (K V)

/-- `WithLp.equiv` as a linear equivalence. -/
@[simps (config := { fullyApplied := false })]
protected def linearEquiv : WithLp p V ≃ₗ[K] V :=
{ LinearEquiv.refl _ _ with
toFun := WithLp.equiv _ _
invFun := (WithLp.equiv _ _).symm }

end WithLp

0 comments on commit 484cfeb

Please sign in to comment.