Skip to content

Commit bbc9111

Browse files
feat: introduce covarianceBilin (#30324)
The `covarianceBilin` associated to a measure on a Hilbert space is the positive semidefinite continuous bilinear form which represents its covariance. Also define the covariance operator of a measure. Co-authored-by: Rémy Degenne <4094732+RemyDegenne@users.noreply.github.com>
1 parent e957330 commit bbc9111

File tree

5 files changed

+240
-2
lines changed

5 files changed

+240
-2
lines changed

Mathlib/Analysis/InnerProductSpace/Dual.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ local postfix:1024 "♯" => continuousLinearMapOfBilin
187187

188188
variable (B : E →L⋆[𝕜] E →L[𝕜] 𝕜)
189189

190+
@[simp]
191+
theorem continuousLinearMapOfBilin_zero : (0 : E →L⋆[𝕜] E →L[𝕜] 𝕜)♯ = 0 := by
192+
simp [continuousLinearMapOfBilin]
193+
190194
@[simp]
191195
theorem continuousLinearMapOfBilin_apply (v w : E) : ⟪B♯ v, w⟫ = B v w := by
192196
rw [continuousLinearMapOfBilin, coe_comp', ContinuousLinearEquiv.coe_coe,

Mathlib/Analysis/Normed/Operator/BoundedLinearMaps.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ def IsBoundedBilinearMap.toContinuousLinearMap (hf : IsBoundedBilinearMap 𝕜 f
307307
(LinearMap.mk₂ _ f.curry hf.add_left hf.smul_left hf.add_right hf.smul_right) <|
308308
hf.bound.imp fun _ ↦ And.right
309309

310+
@[simp]
311+
lemma IsBoundedBilinearMap.toContinuousLinearMap_apply (hf : IsBoundedBilinearMap 𝕜 f)
312+
(x : E) (y : F) : hf.toContinuousLinearMap x y = f (x, y) := rfl
313+
310314
protected theorem IsBoundedBilinearMap.isBigO (h : IsBoundedBilinearMap 𝕜 f) :
311315
f =O[⊤] fun p : E × F => ‖p.1‖ * ‖p.2‖ :=
312316
let ⟨C, _, hC⟩ := h.bound
Lines changed: 216 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,218 @@
1+
/-
2+
Copyright (c) 2025 Rémy Degenne. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Rémy Degenne, Etienne Marion
5+
-/
6+
import Mathlib.Analysis.InnerProductSpace.Positive
7+
import Mathlib.MeasureTheory.SpecificCodomains.WithLp
18
import Mathlib.Probability.Moments.CovarianceBilinDual
29

3-
deprecated_module (since := "2025-10-13")
10+
/-!
11+
# Covariance in Hilbert spaces
12+
13+
Given a measure `μ` defined over a Banach space `E`, one can consider the associated covariance
14+
bilinear form which maps `L₁ L₂ : StrongDual ℝ E` to `cov[L₁, L₂; μ]`. This is called
15+
`covarianceBilinDual μ` and is defined in the `CovarianceBilinDual` file.
16+
17+
In the special case where `E` is a Hilbert space, each `L : StrongDual ℝ E` can be represented
18+
as the scalar product against some element of `E`. This motivates the definition of
19+
`covarianceBilin`, which is a continuous bilinear form mapping `x y : E` to
20+
`cov[⟪x, ·⟫, ⟪y, ·⟫; μ]`.
21+
22+
## Main definitions
23+
24+
* `covarianceBilin μ`: the continuous bilinear form over `E` representing the covariance of a
25+
measure over `E`.
26+
* `covarianceOperator μ`: the bounded operator over `E` such that
27+
`⟪covarianceOperator μ x, y⟫ = ∫ z, ⟪x, z⟫ * ⟪y, z⟫ ∂μ`.
28+
29+
## Tags
30+
31+
covariance, Hilbert space, bilinear form
32+
-/
33+
34+
open MeasureTheory InnerProductSpace NormedSpace WithLp EuclideanSpace
35+
open scoped RealInnerProductSpace
36+
37+
namespace ProbabilityTheory
38+
39+
variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E]
40+
[MeasurableSpace E] [BorelSpace E] {μ : Measure E}
41+
42+
/-- Covariance of a measure on an inner product space, as a continuous bilinear form. -/
43+
noncomputable
44+
def covarianceBilin (μ : Measure E) : E →L[ℝ] E →L[ℝ] ℝ :=
45+
ContinuousLinearMap.bilinearComp (covarianceBilinDual μ)
46+
(toDualMap ℝ E).toContinuousLinearMap (toDualMap ℝ E).toContinuousLinearMap
47+
48+
@[simp]
49+
lemma covarianceBilin_zero : covarianceBilin (0 : Measure E) = 0 := by
50+
rw [covarianceBilin]
51+
simp
52+
53+
lemma covarianceBilin_eq_covarianceBilinDual (x y : E) :
54+
covarianceBilin μ x y = covarianceBilinDual μ (toDualMap ℝ E x) (toDualMap ℝ E y) := rfl
55+
56+
@[simp]
57+
lemma covarianceBilin_of_not_memLp [IsFiniteMeasure μ] (h : ¬MemLp id 2 μ) :
58+
covarianceBilin μ = 0 := by
59+
ext
60+
simp [covarianceBilin_eq_covarianceBilinDual, h]
61+
62+
lemma covarianceBilin_apply [CompleteSpace E] [IsFiniteMeasure μ] (h : MemLp id 2 μ) (x y : E) :
63+
covarianceBilin μ x y = ∫ z, ⟪x, z - μ[id]⟫ * ⟪y, z - μ[id]⟫ ∂μ := by
64+
simp_rw [covarianceBilin, ContinuousLinearMap.bilinearComp_apply, covarianceBilinDual_apply' h]
65+
simp only [LinearIsometry.coe_toContinuousLinearMap, id_eq, toDualMap_apply]
66+
67+
lemma covarianceBilin_comm [IsFiniteMeasure μ] (x y : E) :
68+
covarianceBilin μ x y = covarianceBilin μ y x := by
69+
rw [covarianceBilin_eq_covarianceBilinDual, covarianceBilinDual_comm,
70+
covarianceBilin_eq_covarianceBilinDual]
71+
72+
lemma covarianceBilin_self [CompleteSpace E] [IsFiniteMeasure μ] (h : MemLp id 2 μ) (x : E) :
73+
covarianceBilin μ x x = Var[fun u ↦ ⟪x, u⟫; μ] := by
74+
rw [covarianceBilin_eq_covarianceBilinDual, covarianceBilinDual_self_eq_variance h]
75+
rfl
76+
77+
lemma covarianceBilin_apply_eq_cov [CompleteSpace E] [IsFiniteMeasure μ]
78+
(h : MemLp id 2 μ) (x y : E) :
79+
covarianceBilin μ x y = cov[fun u ↦ ⟪x, u⟫, fun u ↦ ⟪y, u⟫; μ] := by
80+
rw [covarianceBilin_eq_covarianceBilinDual, covarianceBilinDual_eq_covariance h]
81+
rfl
82+
83+
lemma covarianceBilin_real {μ : Measure ℝ} [IsFiniteMeasure μ] (x y : ℝ) :
84+
covarianceBilin μ x y = x * y * Var[id; μ] := by
85+
by_cases h : MemLp id 2 μ
86+
· simp only [covarianceBilin_apply_eq_cov h, RCLike.inner_apply, conj_trivial, mul_comm]
87+
rw [covariance_mul_left, covariance_mul_right, ← mul_assoc, covariance_self aemeasurable_id']
88+
rfl
89+
· simp [h, variance_of_not_memLp, aestronglyMeasurable_id]
90+
91+
lemma covarianceBilin_real_self {μ : Measure ℝ} [IsFiniteMeasure μ] (x : ℝ) :
92+
covarianceBilin μ x x = x ^ 2 * Var[id; μ] := by
93+
rw [covarianceBilin_real, pow_two]
94+
95+
@[simp]
96+
lemma covarianceBilin_self_nonneg [IsFiniteMeasure μ] (x : E) :
97+
0 ≤ covarianceBilin μ x x := by
98+
simp [covarianceBilin]
99+
100+
lemma isPosSemidef_covarianceBilin [IsFiniteMeasure μ] :
101+
(covarianceBilin μ).toBilinForm.IsPosSemidef where
102+
eq := covarianceBilin_comm
103+
nonneg := covarianceBilin_self_nonneg
104+
105+
lemma covarianceBilin_map_const_add [CompleteSpace E] [IsProbabilityMeasure μ] (c : E) :
106+
covarianceBilin (μ.map (fun x ↦ c + x)) = covarianceBilin μ := by
107+
by_cases h : MemLp id 2 μ
108+
· ext x y
109+
have h_Lp : MemLp id 2 (μ.map (fun x ↦ c + x)) :=
110+
(measurableEmbedding_addLeft _).memLp_map_measure_iff.mpr <| (memLp_const c).add h
111+
rw [covarianceBilin_apply h_Lp,
112+
covarianceBilin_apply h, integral_map (by fun_prop) (by fun_prop)]
113+
congr with z
114+
rw [integral_map (by fun_prop) h_Lp.1]
115+
simp only [id_eq]
116+
rw [integral_add (integrable_const _)]
117+
· simp
118+
· exact h.integrable (by simp)
119+
· ext
120+
rw [covarianceBilin_of_not_memLp, covarianceBilin_of_not_memLp h]
121+
rw [(measurableEmbedding_addLeft _).memLp_map_measure_iff.not]
122+
contrapose! h
123+
convert (memLp_const (-c)).add h
124+
ext; simp
125+
126+
lemma covarianceBilin_apply_basisFun {ι Ω : Type*} [Fintype ι] {mΩ : MeasurableSpace Ω}
127+
{μ : Measure Ω} [IsFiniteMeasure μ] {X : ι → Ω → ℝ} (hX : ∀ i, MemLp (X i) 2 μ) (i j : ι) :
128+
covarianceBilin (μ.map (fun ω ↦ toLp 2 (X · ω)))
129+
(basisFun ι ℝ i) (basisFun ι ℝ j) = cov[X i, X j; μ] := by
130+
have (i : ι) := (hX i).aemeasurable
131+
rw [covarianceBilin_apply_eq_cov, covariance_map]
132+
· simp [basisFun_inner]; rfl
133+
· exact Measurable.aestronglyMeasurable (by fun_prop)
134+
· exact Measurable.aestronglyMeasurable (by fun_prop)
135+
· fun_prop
136+
· exact (memLp_map_measure_iff aestronglyMeasurable_id (by fun_prop)).2 (MemLp.of_eval_piLp hX)
137+
138+
lemma covarianceBilin_apply_basisFun_self {ι Ω : Type*} [Fintype ι] {mΩ : MeasurableSpace Ω}
139+
{μ : Measure Ω} [IsFiniteMeasure μ] {X : ι → Ω → ℝ} (hX : ∀ i, MemLp (X i) 2 μ) (i : ι) :
140+
covarianceBilin (μ.map (fun ω ↦ toLp 2 (X · ω)))
141+
(basisFun ι ℝ i) (basisFun ι ℝ i) = Var[X i; μ] := by
142+
rw [covarianceBilin_apply_basisFun hX, covariance_self]
143+
have (i : ι) := (hX i).aemeasurable
144+
fun_prop
145+
146+
lemma covarianceBilin_apply_pi {ι Ω : Type*} [Fintype ι] {mΩ : MeasurableSpace Ω}
147+
{μ : Measure Ω} [IsFiniteMeasure μ] {X : ι → Ω → ℝ}
148+
(hX : ∀ i, MemLp (X i) 2 μ) (x y : EuclideanSpace ℝ ι) :
149+
covarianceBilin (μ.map (fun ω ↦ toLp 2 (X · ω))) x y =
150+
∑ i, ∑ j, x i * y j * cov[X i, X j; μ] := by
151+
have (i : ι) := (hX i).aemeasurable
152+
nth_rw 1 [covarianceBilin_apply_eq_cov, covariance_map_fun, ← (basisFun ι ℝ).sum_repr' x,
153+
← (basisFun ι ℝ).sum_repr' y]
154+
· simp_rw [sum_inner, real_inner_smul_left, basisFun_inner, PiLp.toLp_apply]
155+
rw [covariance_fun_sum_fun_sum]
156+
· refine Finset.sum_congr rfl fun i _ ↦ Finset.sum_congr rfl fun j _ ↦ ?_
157+
rw [covariance_mul_left, covariance_mul_right]
158+
ring
159+
all_goals exact fun i ↦ (hX i).const_mul _
160+
any_goals exact Measurable.aestronglyMeasurable (by fun_prop)
161+
· fun_prop
162+
· exact (memLp_map_measure_iff aestronglyMeasurable_id (by fun_prop)).2 (MemLp.of_eval_piLp hX)
163+
164+
section covarianceOperator
165+
166+
variable [CompleteSpace E]
167+
168+
/-- The covariance operator of the measure `μ`. This is the bounded operator `F : E →L[ℝ] E`
169+
associated to the continuous bilinear form `B : E →L[ℝ] E →L[ℝ] ℝ` such that
170+
`B x y = ∫ z, ⟪x, z⟫ * ⟪y, z⟫ ∂μ` (see `covarianceOperator_inner`). Namely we have
171+
`B x y = ⟪F x, y⟫`.
172+
173+
Note that the bilinear form `B` is the _uncentered_ covariance bilinear form associated to the
174+
measure `µ`, which is not to be confused with the covariance bilinear form defined earlier in this
175+
file as `covarianceBilin μ`. -/
176+
noncomputable def covarianceOperator (μ : Measure E) : E →L[ℝ] E :=
177+
continuousLinearMapOfBilin <| ContinuousLinearMap.bilinearComp (uncenteredCovarianceBilinDual μ)
178+
(toDualMap ℝ E).toContinuousLinearMap (toDualMap ℝ E).toContinuousLinearMap
179+
180+
@[simp]
181+
lemma covarianceOperator_zero : covarianceOperator (0 : Measure E) = 0 := by
182+
simp [covarianceOperator]
183+
184+
@[simp]
185+
lemma covarianceOperator_of_not_memLp (hμ : ¬MemLp id 2 μ) :
186+
covarianceOperator μ = 0 := by
187+
ext x
188+
refine (unique_continuousLinearMapOfBilin _ fun y ↦ ?_).symm
189+
simp [hμ, uncenteredCovarianceBilinDual_of_not_memLp]
190+
191+
lemma covarianceOperator_inner (hμ : MemLp id 2 μ) (x y : E) :
192+
⟪covarianceOperator μ x, y⟫ = ∫ z, ⟪x, z⟫ * ⟪y, z⟫ ∂μ := by
193+
simp only [covarianceOperator, continuousLinearMapOfBilin_apply,
194+
ContinuousLinearMap.bilinearComp_apply, LinearIsometry.coe_toContinuousLinearMap]
195+
rw [uncenteredCovarianceBilinDual_apply hμ]
196+
simp_rw [toDualMap_apply]
197+
198+
lemma covarianceOperator_apply (hμ : MemLp id 2 μ) (x : E) :
199+
covarianceOperator μ x = ∫ y, ⟪x, y⟫ • y ∂μ := by
200+
refine (unique_continuousLinearMapOfBilin _ fun y ↦ ?_).symm
201+
rw [real_inner_comm, ← integral_inner]
202+
· simp_rw [inner_smul_right, ← continuousLinearMapOfBilin_apply, ← covarianceOperator_inner hμ]
203+
rfl
204+
exact memLp_one_iff_integrable.1 <| hμ.smul (hμ.const_inner x)
205+
206+
lemma isPositive_covarianceOperator : (covarianceOperator μ).toLinearMap.IsPositive := by
207+
by_cases hμ : MemLp id 2 μ
208+
swap; · simp [hμ]
209+
refine ⟨fun x y ↦ ?_, fun x ↦ ?_⟩
210+
· simp_rw [ContinuousLinearMap.coe_coe, real_inner_comm _ x, covarianceOperator_inner hμ,
211+
mul_comm]
212+
· simp only [ContinuousLinearMap.coe_coe, covarianceOperator_inner hμ, ← pow_two,
213+
RCLike.re_to_real]
214+
positivity
215+
216+
end covarianceOperator
217+
218+
end ProbabilityTheory

Mathlib/Probability/Moments/CovarianceBilinDual.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ lemma uncenteredCovarianceBilinDual_of_not_memLp (h : ¬ MemLp id 2 μ) (L₁ L
189189
@[deprecated (since := "2025-10-10")] alias uncenteredCovarianceBilin_of_not_memLp :=
190190
uncenteredCovarianceBilinDual_of_not_memLp
191191

192+
@[simp]
192193
lemma uncenteredCovarianceBilinDual_zero : uncenteredCovarianceBilinDual (0 : Measure E) = 0 := by
193194
ext
194195
have : Subsingleton (Lp ℝ 2 (0 : Measure E)) := ⟨fun x y ↦ Lp.ext_iff.2 rfl⟩
@@ -262,6 +263,14 @@ lemma covarianceBilinDual_comm (L₁ L₂ : StrongDual ℝ E) :
262263
simp_rw [covarianceBilinDual, uncenteredCovarianceBilinDual_apply h', mul_comm (L₁ _)]
263264
· simp [h]
264265

266+
@[simp]
267+
lemma covarianceBilinDual_self_nonneg (L : StrongDual ℝ E) : 0 ≤ covarianceBilinDual μ L L := by
268+
by_cases h : MemLp id 2 μ
269+
· simp only [covarianceBilinDual, uncenteredCovarianceBilinDual,
270+
ContinuousLinearMap.bilinearComp_apply, IsBoundedBilinearMap.toContinuousLinearMap_apply]
271+
exact real_inner_self_nonneg
272+
· simp [h]
273+
265274
variable [CompleteSpace E]
266275

267276
lemma covarianceBilinDual_apply (h : MemLp id 2 μ) (L₁ L₂ : StrongDual ℝ E) :

Mathlib/Topology/Algebra/Module/StrongTopology.lean

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ variable {𝕜 𝕜₂ 𝕜₃ : Type*} [NormedField 𝕜] [NormedField 𝕜₂]
502502
[TopologicalSpace G] [IsTopologicalAddGroup G] [ContinuousConstSMul 𝕜₃ G]
503503
{σ₁₃ : 𝕜 →+* 𝕜₃} {σ₂₃ : 𝕜₂ →+* 𝕜₃}
504504

505-
/-- Send a continuous bilinear map to an abstract bilinear map (forgetting continuity). -/
505+
/-- Send a continuous sesquilinear map to an abstract sesquilinear map (forgetting continuity). -/
506506
def toLinearMap₁₂ (L : E →SL[σ₁₃] F →SL[σ₂₃] G) : E →ₛₗ[σ₁₃] F →ₛₗ[σ₂₃] G :=
507507
(coeLMₛₗ σ₂₃).comp L.toLinearMap
508508

@@ -513,6 +513,12 @@ def toLinearMap₁₂ (L : E →SL[σ₁₃] F →SL[σ₂₃] G) : E →ₛₗ[
513513

514514
@[deprecated (since := "2025-07-28")] alias toLinearMap₂_apply := toLinearMap₁₂_apply
515515

516+
/-- Send a continuous bilinear form to an abstract bilinear form (forgetting continuity). -/
517+
def toBilinForm (L : E →L[𝕜] E →L[𝕜] 𝕜) : LinearMap.BilinForm 𝕜 E := L.toLinearMap₁₂
518+
519+
@[simp] lemma toBilinForm_apply (L : E →L[𝕜] E →L[𝕜] 𝕜) (v : E) (w : E) :
520+
L.toBilinForm v w = L v w := rfl
521+
516522
end BilinearMaps
517523

518524
section RestrictScalars

0 commit comments

Comments
 (0)