Skip to content

Commit 9629646

Browse files
feat: port Analysis.InnerProductSpace.LinearPMap (#5523)
Co-authored-by: Moritz Doll <moritz.doll@googlemail.com>
1 parent cda66a7 commit 9629646

File tree

2 files changed

+249
-0
lines changed

2 files changed

+249
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ import Mathlib.Analysis.InnerProductSpace.Dual
609609
import Mathlib.Analysis.InnerProductSpace.EuclideanDist
610610
import Mathlib.Analysis.InnerProductSpace.GramSchmidtOrtho
611611
import Mathlib.Analysis.InnerProductSpace.LaxMilgram
612+
import Mathlib.Analysis.InnerProductSpace.LinearPMap
612613
import Mathlib.Analysis.InnerProductSpace.Orientation
613614
import Mathlib.Analysis.InnerProductSpace.Orthogonal
614615
import Mathlib.Analysis.InnerProductSpace.PiL2
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
/-
2+
Copyright (c) 2022 Moritz Doll. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Moritz Doll
5+
6+
! This file was ported from Lean 3 source module analysis.inner_product_space.linear_pmap
7+
! leanprover-community/mathlib commit 8b981918a93bc45a8600de608cde7944a80d92b9
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Analysis.InnerProductSpace.Adjoint
12+
import Mathlib.Topology.Algebra.Module.LinearPMap
13+
import Mathlib.Topology.Algebra.Module.Basic
14+
15+
/-!
16+
17+
# Partially defined linear operators on Hilbert spaces
18+
19+
We will develop the basics of the theory of unbounded operators on Hilbert spaces.
20+
21+
## Main definitions
22+
23+
* `LinearPMap.IsFormalAdjoint`: An operator `T` is a formal adjoint of `S` if for all `x` in the
24+
domain of `T` and `y` in the domain of `S`, we have that `⟪T x, y⟫ = ⟪x, S y⟫`.
25+
* `LinearPMap.adjoint`: The adjoint of a map `E →ₗ.[𝕜] F` as a map `F →ₗ.[𝕜] E`.
26+
27+
## Main statements
28+
29+
* `LinearPMap.adjoint_isFormalAdjoint`: The adjoint is a formal adjoint
30+
* `LinearPMap.IsFormalAdjoint.le_adjoint`: Every formal adjoint is contained in the adjoint
31+
* `ContinuousLinearMap.toPMap_adjoint_eq_adjoint_toPMap_of_dense`: The adjoint on
32+
`ContinuousLinearMap` and `LinearPMap` coincide.
33+
34+
## Notation
35+
36+
* For `T : E →ₗ.[𝕜] F` the adjoint can be written as `T†`.
37+
This notation is localized in `LinearPMap`.
38+
39+
## Implementation notes
40+
41+
We use the junk value pattern to define the adjoint for all `LinearPMap`s. In the case that
42+
`T : E →ₗ.[𝕜] F` is not densely defined the adjoint `T†` is the zero map from `T.adjoint.domain` to
43+
`E`.
44+
45+
## References
46+
47+
* [J. Weidmann, *Linear Operators in Hilbert Spaces*][weidmann_linear]
48+
49+
## Tags
50+
51+
Unbounded operators, closed operators
52+
-/
53+
54+
55+
noncomputable section
56+
57+
open IsROrC
58+
59+
open scoped ComplexConjugate Classical
60+
61+
variable {𝕜 E F G : Type _} [IsROrC 𝕜]
62+
63+
variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E]
64+
65+
variable [NormedAddCommGroup F] [InnerProductSpace 𝕜 F]
66+
67+
local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y
68+
69+
namespace LinearPMap
70+
71+
/-- An operator `T` is a formal adjoint of `S` if for all `x` in the domain of `T` and `y` in the
72+
domain of `S`, we have that `⟪T x, y⟫ = ⟪x, S y⟫`. -/
73+
def IsFormalAdjoint (T : E →ₗ.[𝕜] F) (S : F →ₗ.[𝕜] E) : Prop :=
74+
∀ (x : T.domain) (y : S.domain), ⟪T x, y⟫ = ⟪(x : E), S y⟫
75+
#align linear_pmap.is_formal_adjoint LinearPMap.IsFormalAdjoint
76+
77+
variable {T : E →ₗ.[𝕜] F} {S : F →ₗ.[𝕜] E}
78+
79+
protected theorem IsFormalAdjoint.symm (h : T.IsFormalAdjoint S) :
80+
S.IsFormalAdjoint T := fun y _ => by
81+
rw [← inner_conj_symm, ← inner_conj_symm (y : F), h]
82+
#align linear_pmap.is_formal_adjoint.symm LinearPMap.IsFormalAdjoint.symm
83+
84+
variable (T)
85+
86+
/-- The domain of the adjoint operator.
87+
88+
This definition is needed to construct the adjoint operator and the preferred version to use is
89+
`T.adjoint.domain` instead of `T.adjointDomain`. -/
90+
def adjointDomain : Submodule 𝕜 F where
91+
carrier := {y | Continuous ((innerₛₗ 𝕜 y).comp T.toFun)}
92+
zero_mem' := by
93+
rw [Set.mem_setOf_eq, LinearMap.map_zero, LinearMap.zero_comp]
94+
exact continuous_zero
95+
add_mem' hx hy := by rw [Set.mem_setOf_eq, LinearMap.map_add] at *; exact hx.add hy
96+
smul_mem' a x hx := by
97+
rw [Set.mem_setOf_eq, LinearMap.map_smulₛₗ] at *
98+
exact hx.const_smul (conj a)
99+
#align linear_pmap.adjoint_domain LinearPMap.adjointDomain
100+
101+
/-- The operator `λ x, ⟪y, T x⟫` considered as a continuous linear operator from `T.adjointDomain`
102+
to `𝕜`. -/
103+
def adjointDomainMkClm (y : T.adjointDomain) : T.domain →L[𝕜] 𝕜 :=
104+
⟨(innerₛₗ 𝕜 (y : F)).comp T.toFun, y.prop⟩
105+
#align linear_pmap.adjoint_domain_mk_clm LinearPMap.adjointDomainMkClm
106+
107+
theorem adjointDomainMkClm_apply (y : T.adjointDomain) (x : T.domain) :
108+
adjointDomainMkClm T y x = ⟪(y : F), T x⟫ :=
109+
rfl
110+
#align linear_pmap.adjoint_domain_mk_clm_apply LinearPMap.adjointDomainMkClm_apply
111+
112+
variable {T}
113+
114+
variable (hT : Dense (T.domain : Set E))
115+
116+
/-- The unique continuous extension of the operator `adjointDomainMkClm` to `E`. -/
117+
def adjointDomainMkClmExtend (y : T.adjointDomain) : E →L[𝕜] 𝕜 :=
118+
(T.adjointDomainMkClm y).extend (Submodule.subtypeL T.domain) hT.denseRange_val
119+
uniformEmbedding_subtype_val.toUniformInducing
120+
#align linear_pmap.adjoint_domain_mk_clm_extend LinearPMap.adjointDomainMkClmExtend
121+
122+
@[simp]
123+
theorem adjointDomainMkClmExtend_apply (y : T.adjointDomain) (x : T.domain) :
124+
adjointDomainMkClmExtend hT y (x : E) = ⟪(y : F), T x⟫ :=
125+
ContinuousLinearMap.extend_eq _ _ _ _ _
126+
#align linear_pmap.adjoint_domain_mk_clm_extend_apply LinearPMap.adjointDomainMkClmExtend_apply
127+
128+
variable [CompleteSpace E]
129+
130+
/-- The adjoint as a linear map from its domain to `E`.
131+
132+
This is an auxiliary definition needed to define the adjoint operator as a `LinearPMap` without
133+
the assumption that `T.domain` is dense. -/
134+
def adjointAux : T.adjointDomain →ₗ[𝕜] E where
135+
toFun y := (InnerProductSpace.toDual 𝕜 E).symm (adjointDomainMkClmExtend hT y)
136+
map_add' x y :=
137+
hT.eq_of_inner_left fun _ => by
138+
simp only [inner_add_left, Submodule.coe_add, InnerProductSpace.toDual_symm_apply,
139+
adjointDomainMkClmExtend_apply]
140+
-- Porting note(https://github.com/leanprover-community/mathlib4/issues/5026):
141+
-- mathlib3 was finished here
142+
rw [adjointDomainMkClmExtend_apply, adjointDomainMkClmExtend_apply,
143+
adjointDomainMkClmExtend_apply]
144+
simp only [AddSubmonoid.coe_add, Submodule.coe_toAddSubmonoid, inner_add_left]
145+
map_smul' _ _ :=
146+
hT.eq_of_inner_left fun _ => by
147+
simp only [inner_smul_left, Submodule.coe_smul_of_tower, RingHom.id_apply,
148+
InnerProductSpace.toDual_symm_apply, adjointDomainMkClmExtend_apply]
149+
-- Porting note(https://github.com/leanprover-community/mathlib4/issues/5026):
150+
-- mathlib3 was finished here
151+
rw [adjointDomainMkClmExtend_apply, adjointDomainMkClmExtend_apply]
152+
simp only [Submodule.coe_smul_of_tower, inner_smul_left]
153+
#align linear_pmap.adjoint_aux LinearPMap.adjointAux
154+
155+
theorem adjointAux_inner (y : T.adjointDomain) (x : T.domain) :
156+
⟪adjointAux hT y, x⟫ = ⟪(y : F), T x⟫ := by
157+
simp only [adjointAux, LinearMap.coe_mk, InnerProductSpace.toDual_symm_apply,
158+
adjointDomainMkClmExtend_apply]
159+
-- Porting note(https://github.com/leanprover-community/mathlib4/issues/5026):
160+
-- mathlib3 was finished here
161+
simp only [AddHom.coe_mk, InnerProductSpace.toDual_symm_apply]
162+
rw [adjointDomainMkClmExtend_apply]
163+
#align linear_pmap.adjoint_aux_inner LinearPMap.adjointAux_inner
164+
165+
theorem adjointAux_unique (y : T.adjointDomain) {x₀ : E}
166+
(hx₀ : ∀ x : T.domain, ⟪x₀, x⟫ = ⟪(y : F), T x⟫) : adjointAux hT y = x₀ :=
167+
hT.eq_of_inner_left fun v => (adjointAux_inner hT _ _).trans (hx₀ v).symm
168+
#align linear_pmap.adjoint_aux_unique LinearPMap.adjointAux_unique
169+
170+
variable (T)
171+
172+
/-- The adjoint operator as a partially defined linear operator. -/
173+
def adjoint : F →ₗ.[𝕜] E where
174+
domain := T.adjointDomain
175+
toFun := if hT : Dense (T.domain : Set E) then adjointAux hT else 0
176+
#align linear_pmap.adjoint LinearPMap.adjoint
177+
178+
scoped postfix:1024 "†" => LinearPMap.adjoint
179+
180+
theorem mem_adjoint_domain_iff (y : F) : y ∈ T†.domain ↔ Continuous ((innerₛₗ 𝕜 y).comp T.toFun) :=
181+
Iff.rfl
182+
#align linear_pmap.mem_adjoint_domain_iff LinearPMap.mem_adjoint_domain_iff
183+
184+
variable {T}
185+
186+
theorem mem_adjoint_domain_of_exists (y : F) (h : ∃ w : E, ∀ x : T.domain, ⟪w, x⟫ = ⟪y, T x⟫) :
187+
y ∈ T†.domain := by
188+
cases' h with w hw
189+
rw [T.mem_adjoint_domain_iff]
190+
-- Porting note: was `by continuity`
191+
have : Continuous ((innerSL 𝕜 w).comp T.domain.subtypeL) := ContinuousLinearMap.continuous _
192+
convert this using 1
193+
exact funext fun x => (hw x).symm
194+
#align linear_pmap.mem_adjoint_domain_of_exists LinearPMap.mem_adjoint_domain_of_exists
195+
196+
theorem adjoint_apply_of_not_dense (hT : ¬Dense (T.domain : Set E)) (y : T†.domain) : T† y = 0 := by
197+
change (if hT : Dense (T.domain : Set E) then adjointAux hT else 0) y = _
198+
simp only [hT, not_false_iff, dif_neg, LinearMap.zero_apply]
199+
#align linear_pmap.adjoint_apply_of_not_dense LinearPMap.adjoint_apply_of_not_dense
200+
201+
theorem adjoint_apply_of_dense (y : T†.domain) : T† y = adjointAux hT y := by
202+
change (if hT : Dense (T.domain : Set E) then adjointAux hT else 0) y = _
203+
simp only [hT, dif_pos, LinearMap.coe_mk]
204+
#align linear_pmap.adjoint_apply_of_dense LinearPMap.adjoint_apply_of_dense
205+
206+
theorem adjoint_apply_eq (y : T†.domain) {x₀ : E} (hx₀ : ∀ x : T.domain, ⟪x₀, x⟫ = ⟪(y : F), T x⟫) :
207+
T† y = x₀ :=
208+
(adjoint_apply_of_dense hT y).symm ▸ adjointAux_unique hT _ hx₀
209+
#align linear_pmap.adjoint_apply_eq LinearPMap.adjoint_apply_eq
210+
211+
/-- The fundamental property of the adjoint. -/
212+
theorem adjoint_isFormalAdjoint : T†.IsFormalAdjoint T := fun x =>
213+
(adjoint_apply_of_dense hT x).symm ▸ adjointAux_inner hT x
214+
#align linear_pmap.adjoint_is_formal_adjoint LinearPMap.adjoint_isFormalAdjoint
215+
216+
/-- The adjoint is maximal in the sense that it contains every formal adjoint. -/
217+
theorem IsFormalAdjoint.le_adjoint (h : T.IsFormalAdjoint S) : S ≤ T† :=
218+
-- Trivially, every `x : S.domain` is in `T.adjoint.domain`
219+
fun x hx =>
220+
mem_adjoint_domain_of_exists _
221+
⟨S ⟨x, hx⟩, h.symm ⟨x, hx⟩⟩,-- Equality on `S.domain` follows from equality
222+
-- `⟪v, S x⟫ = ⟪v, T.adjoint y⟫` for all `v : T.domain`:
223+
fun _ _ hxy => (adjoint_apply_eq hT _ fun _ => by rw [h.symm, hxy]).symm⟩
224+
#align linear_pmap.is_formal_adjoint.le_adjoint LinearPMap.IsFormalAdjoint.le_adjoint
225+
226+
end LinearPMap
227+
228+
namespace ContinuousLinearMap
229+
230+
variable [CompleteSpace E] [CompleteSpace F]
231+
232+
variable (A : E →L[𝕜] F) {p : Submodule 𝕜 E}
233+
234+
/-- Restricting `A` to a dense submodule and taking the `LinearPMap.adjoint` is the same
235+
as taking the `continuous_linear_map.adjoint` interpreted as a `linear_pmap`. -/
236+
theorem toPMap_adjoint_eq_adjoint_toPMap_of_dense (hp : Dense (p : Set E)) :
237+
(A.toPMap p).adjoint = A.adjoint.toPMap ⊤ := by
238+
ext x y hxy
239+
· simp only [LinearMap.toPMap_domain, Submodule.mem_top, iff_true_iff,
240+
LinearPMap.mem_adjoint_domain_iff, LinearMap.coe_comp, innerₛₗ_apply_coe]
241+
exact ((innerSL 𝕜 x).comp <| A.comp <| Submodule.subtypeL _).cont
242+
refine' LinearPMap.adjoint_apply_eq _ _ fun v => _
243+
· -- Porting note: was simply `hp` as an argument above
244+
simpa using hp
245+
· simp only [adjoint_inner_left, hxy, LinearMap.toPMap_apply, coe_coe]
246+
#align continuous_linear_map.to_pmap_adjoint_eq_adjoint_to_pmap_of_dense ContinuousLinearMap.toPMap_adjoint_eq_adjoint_toPMap_of_dense
247+
248+
end ContinuousLinearMap

0 commit comments

Comments
 (0)