Skip to content

Commit 24e633e

Browse files
feat: port Analysis.NormedSpace.Dual (#4310)
1 parent f4c3dda commit 24e633e

File tree

2 files changed

+293
-0
lines changed

2 files changed

+293
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ import Mathlib.Analysis.NormedSpace.Complemented
485485
import Mathlib.Analysis.NormedSpace.Completion
486486
import Mathlib.Analysis.NormedSpace.ConformalLinearMap
487487
import Mathlib.Analysis.NormedSpace.ContinuousLinearMap
488+
import Mathlib.Analysis.NormedSpace.Dual
488489
import Mathlib.Analysis.NormedSpace.Extend
489490
import Mathlib.Analysis.NormedSpace.Extr
490491
import Mathlib.Analysis.NormedSpace.FiniteDimension
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
/-
2+
Copyright (c) 2020 Heather Macbeth. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Heather Macbeth
5+
6+
! This file was ported from Lean 3 source module analysis.normed_space.dual
7+
! leanprover-community/mathlib commit f2ce6086713c78a7f880485f7917ea547a215982
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.NormedSpace.HahnBanach.Extension
12+
import Mathlib.Analysis.NormedSpace.IsROrC
13+
import Mathlib.Analysis.LocallyConvex.Polar
14+
15+
/-!
16+
# The topological dual of a normed space
17+
18+
In this file we define the topological dual `NormedSpace.Dual` of a normed space, and the
19+
continuous linear map `NormedSpace.inclusionInDoubleDual` from a normed space into its double
20+
dual.
21+
22+
For base field `𝕜 = ℝ` or `𝕜 = ℂ`, this map is actually an isometric embedding; we provide a
23+
version `NormedSpace.inclusionInDoubleDualLi` of the map which is of type a bundled linear
24+
isometric embedding, `E →ₗᵢ[𝕜] (dual 𝕜 (dual 𝕜 E))`.
25+
26+
Since a lot of elementary properties don't require `eq_of_dist_eq_zero` we start setting up the
27+
theory for `SeminormedAddCommGroup` and we specialize to `NormedAddCommGroup` when needed.
28+
29+
## Main definitions
30+
31+
* `inclusion_in_double_dual` and `inclusion_in_double_dual_li` are the inclusion of a normed space
32+
in its double dual, considered as a bounded linear map and as a linear isometry, respectively.
33+
* `polar 𝕜 s` is the subset of `dual 𝕜 E` consisting of those functionals `x'` for which
34+
`‖x' z‖ ≤ 1` for every `z ∈ s`.
35+
36+
## Tags
37+
38+
dual
39+
-/
40+
41+
42+
noncomputable section
43+
44+
open Classical Topology
45+
46+
universe u v
47+
48+
namespace NormedSpace
49+
50+
section General
51+
52+
variable (𝕜 : Type _) [NontriviallyNormedField 𝕜]
53+
54+
variable (E : Type _) [SeminormedAddCommGroup E] [NormedSpace 𝕜 E]
55+
56+
variable (F : Type _) [NormedAddCommGroup F] [NormedSpace 𝕜 F]
57+
58+
/-- The topological dual of a seminormed space `E`. -/
59+
def Dual :=
60+
E →L[𝕜] 𝕜
61+
#align normed_space.dual NormedSpace.Dual
62+
63+
-- Porting note: added manually
64+
section DerivedInstances
65+
66+
instance : Inhabited (Dual 𝕜 E) :=
67+
inferInstanceAs (Inhabited (E →L[𝕜] 𝕜))
68+
69+
instance : SeminormedAddCommGroup (Dual 𝕜 E) :=
70+
inferInstanceAs (SeminormedAddCommGroup (E →L[𝕜] 𝕜))
71+
72+
instance : NormedSpace 𝕜 (Dual 𝕜 E) :=
73+
inferInstanceAs (NormedSpace 𝕜 (E →L[𝕜] 𝕜))
74+
75+
end DerivedInstances
76+
77+
instance : ContinuousLinearMapClass (Dual 𝕜 E) 𝕜 E 𝕜 :=
78+
ContinuousLinearMap.continuousSemilinearMapClass
79+
80+
instance : CoeFun (Dual 𝕜 E) fun _ => E → 𝕜 :=
81+
FunLike.hasCoeToFun
82+
83+
instance : NormedAddCommGroup (Dual 𝕜 F) :=
84+
ContinuousLinearMap.toNormedAddCommGroup
85+
86+
instance [FiniteDimensional 𝕜 E] : FiniteDimensional 𝕜 (Dual 𝕜 E) :=
87+
inferInstanceAs (FiniteDimensional 𝕜 (E →L[𝕜] 𝕜))
88+
89+
/-- The inclusion of a normed space in its double (topological) dual, considered
90+
as a bounded linear map. -/
91+
def inclusionInDoubleDual : E →L[𝕜] Dual 𝕜 (Dual 𝕜 E) :=
92+
ContinuousLinearMap.apply 𝕜 𝕜
93+
#align normed_space.inclusion_in_double_dual NormedSpace.inclusionInDoubleDual
94+
95+
@[simp]
96+
theorem dual_def (x : E) (f : Dual 𝕜 E) : inclusionInDoubleDual 𝕜 E x f = f x :=
97+
rfl
98+
#align normed_space.dual_def NormedSpace.dual_def
99+
100+
theorem inclusionInDoubleDual_norm_eq :
101+
‖inclusionInDoubleDual 𝕜 E‖ = ‖ContinuousLinearMap.id 𝕜 (Dual 𝕜 E)‖ :=
102+
ContinuousLinearMap.op_norm_flip _
103+
#align normed_space.inclusion_in_double_dual_norm_eq NormedSpace.inclusionInDoubleDual_norm_eq
104+
105+
theorem inclusionInDoubleDual_norm_le : ‖inclusionInDoubleDual 𝕜 E‖ ≤ 1 := by
106+
rw [inclusionInDoubleDual_norm_eq]
107+
exact ContinuousLinearMap.norm_id_le
108+
#align normed_space.inclusion_in_double_dual_norm_le NormedSpace.inclusionInDoubleDual_norm_le
109+
110+
theorem double_dual_bound (x : E) : ‖(inclusionInDoubleDual 𝕜 E) x‖ ≤ ‖x‖ := by
111+
simpa using ContinuousLinearMap.le_of_op_norm_le _ (inclusionInDoubleDual_norm_le 𝕜 E) x
112+
#align normed_space.double_dual_bound NormedSpace.double_dual_bound
113+
114+
/-- The dual pairing as a bilinear form. -/
115+
def dualPairing : Dual 𝕜 E →ₗ[𝕜] E →ₗ[𝕜] 𝕜 :=
116+
ContinuousLinearMap.coeLM 𝕜
117+
#align normed_space.dual_pairing NormedSpace.dualPairing
118+
119+
@[simp]
120+
theorem dualPairing_apply {v : Dual 𝕜 E} {x : E} : dualPairing 𝕜 E v x = v x :=
121+
rfl
122+
#align normed_space.dual_pairing_apply NormedSpace.dualPairing_apply
123+
124+
theorem dualPairing_separatingLeft : (dualPairing 𝕜 E).SeparatingLeft := by
125+
rw [LinearMap.separatingLeft_iff_ker_eq_bot, LinearMap.ker_eq_bot]
126+
exact ContinuousLinearMap.coe_injective
127+
#align normed_space.dual_pairing_separating_left NormedSpace.dualPairing_separatingLeft
128+
129+
end General
130+
131+
section BidualIsometry
132+
133+
variable (𝕜 : Type v) [IsROrC 𝕜] {E : Type u} [NormedAddCommGroup E] [NormedSpace 𝕜 E]
134+
135+
/-- If one controls the norm of every `f x`, then one controls the norm of `x`.
136+
Compare `ContinuousLinearMap.op_norm_le_bound`. -/
137+
theorem norm_le_dual_bound (x : E) {M : ℝ} (hMp : 0 ≤ M) (hM : ∀ f : Dual 𝕜 E, ‖f x‖ ≤ M * ‖f‖) :
138+
‖x‖ ≤ M := by
139+
classical
140+
by_cases h : x = 0
141+
· simp only [h, hMp, norm_zero]
142+
· obtain ⟨f, hf₁, hfx⟩ : ∃ f : E →L[𝕜] 𝕜, ‖f‖ = 1 ∧ f x = ‖x‖ := exists_dual_vector 𝕜 x h
143+
calc
144+
‖x‖ = ‖(‖x‖ : 𝕜)‖ := IsROrC.norm_coe_norm.symm
145+
_ = ‖f x‖ := by rw [hfx]
146+
_ ≤ M * ‖f‖ := (hM f)
147+
_ = M := by rw [hf₁, mul_one]
148+
#align normed_space.norm_le_dual_bound NormedSpace.norm_le_dual_bound
149+
150+
theorem eq_zero_of_forall_dual_eq_zero {x : E} (h : ∀ f : Dual 𝕜 E, f x = (0 : 𝕜)) : x = 0 :=
151+
norm_le_zero_iff.mp (norm_le_dual_bound 𝕜 x le_rfl fun f => by simp [h f])
152+
#align normed_space.eq_zero_of_forall_dual_eq_zero NormedSpace.eq_zero_of_forall_dual_eq_zero
153+
154+
theorem eq_zero_iff_forall_dual_eq_zero (x : E) : x = 0 ↔ ∀ g : Dual 𝕜 E, g x = 0 :=
155+
fun hx => by simp [hx], fun h => eq_zero_of_forall_dual_eq_zero 𝕜 h⟩
156+
#align normed_space.eq_zero_iff_forall_dual_eq_zero NormedSpace.eq_zero_iff_forall_dual_eq_zero
157+
158+
/-- See also `geometric_hahn_banach_point_point`. -/
159+
theorem eq_iff_forall_dual_eq {x y : E} : x = y ↔ ∀ g : Dual 𝕜 E, g x = g y := by
160+
rw [← sub_eq_zero, eq_zero_iff_forall_dual_eq_zero 𝕜 (x - y)]
161+
simp [sub_eq_zero]
162+
#align normed_space.eq_iff_forall_dual_eq NormedSpace.eq_iff_forall_dual_eq
163+
164+
/-- The inclusion of a normed space in its double dual is an isometry onto its image.-/
165+
def inclusionInDoubleDualLi : E →ₗᵢ[𝕜] Dual 𝕜 (Dual 𝕜 E) :=
166+
{ inclusionInDoubleDual 𝕜 E with
167+
norm_map' := by
168+
intro x
169+
apply le_antisymm
170+
· exact double_dual_bound 𝕜 E x
171+
rw [ContinuousLinearMap.norm_def]
172+
refine' le_csInf ContinuousLinearMap.bounds_nonempty _
173+
rintro c ⟨hc1, hc2⟩
174+
exact norm_le_dual_bound 𝕜 x hc1 hc2 }
175+
#align normed_space.inclusion_in_double_dual_li NormedSpace.inclusionInDoubleDualLi
176+
177+
end BidualIsometry
178+
179+
section PolarSets
180+
181+
open Metric Set NormedSpace
182+
183+
/-- Given a subset `s` in a normed space `E` (over a field `𝕜`), the polar
184+
`polar 𝕜 s` is the subset of `dual 𝕜 E` consisting of those functionals which
185+
evaluate to something of norm at most one at all points `z ∈ s`. -/
186+
def polar (𝕜 : Type _) [NontriviallyNormedField 𝕜] {E : Type _} [SeminormedAddCommGroup E]
187+
[NormedSpace 𝕜 E] : Set E → Set (Dual 𝕜 E) :=
188+
(dualPairing 𝕜 E).flip.polar
189+
#align normed_space.polar NormedSpace.polar
190+
191+
variable (𝕜 : Type _) [NontriviallyNormedField 𝕜]
192+
193+
variable {E : Type _} [SeminormedAddCommGroup E] [NormedSpace 𝕜 E]
194+
195+
theorem mem_polar_iff {x' : Dual 𝕜 E} (s : Set E) : x' ∈ polar 𝕜 s ↔ ∀ z ∈ s, ‖x' z‖ ≤ 1 :=
196+
Iff.rfl
197+
#align normed_space.mem_polar_iff NormedSpace.mem_polar_iff
198+
199+
@[simp]
200+
theorem polar_univ : polar 𝕜 (univ : Set E) = {(0 : Dual 𝕜 E)} :=
201+
(dualPairing 𝕜 E).flip.polar_univ
202+
(LinearMap.flip_separatingRight.mpr (dualPairing_separatingLeft 𝕜 E))
203+
#align normed_space.polar_univ NormedSpace.polar_univ
204+
205+
theorem isClosed_polar (s : Set E) : IsClosed (polar 𝕜 s) := by
206+
dsimp only [NormedSpace.polar]
207+
simp only [LinearMap.polar_eq_iInter, LinearMap.flip_apply]
208+
refine' isClosed_biInter fun z _ => _
209+
exact isClosed_Iic.preimage (ContinuousLinearMap.apply 𝕜 𝕜 z).continuous.norm
210+
#align normed_space.is_closed_polar NormedSpace.isClosed_polar
211+
212+
@[simp]
213+
theorem polar_closure (s : Set E) : polar 𝕜 (closure s) = polar 𝕜 s :=
214+
((dualPairing 𝕜 E).flip.polar_antitone subset_closure).antisymm <|
215+
(dualPairing 𝕜 E).flip.polar_gc.l_le <|
216+
closure_minimal ((dualPairing 𝕜 E).flip.polar_gc.le_u_l s) <| by
217+
simpa [LinearMap.flip_flip] using
218+
(isClosed_polar _ _).preimage (inclusionInDoubleDual 𝕜 E).continuous
219+
#align normed_space.polar_closure NormedSpace.polar_closure
220+
221+
variable {𝕜}
222+
223+
/-- If `x'` is a dual element such that the norms `‖x' z‖` are bounded for `z ∈ s`, then a
224+
small scalar multiple of `x'` is in `polar 𝕜 s`. -/
225+
theorem smul_mem_polar {s : Set E} {x' : Dual 𝕜 E} {c : 𝕜} (hc : ∀ z, z ∈ s → ‖x' z‖ ≤ ‖c‖) :
226+
c⁻¹ • x' ∈ polar 𝕜 s := by
227+
by_cases c_zero : c = 0
228+
· simp only [c_zero, inv_zero, zero_smul]
229+
exact (dualPairing 𝕜 E).flip.zero_mem_polar _
230+
have eq : ∀ z, ‖c⁻¹ • x' z‖ = ‖c⁻¹‖ * ‖x' z‖ := fun z => norm_smul c⁻¹ _
231+
have le : ∀ z, z ∈ s → ‖c⁻¹ • x' z‖ ≤ ‖c⁻¹‖ * ‖c‖ := by
232+
intro z hzs
233+
rw [eq z]
234+
apply mul_le_mul (le_of_eq rfl) (hc z hzs) (norm_nonneg _) (norm_nonneg _)
235+
have cancel : ‖c⁻¹‖ * ‖c‖ = 1 := by
236+
simp only [c_zero, norm_eq_zero, Ne.def, not_false_iff, inv_mul_cancel, norm_inv]
237+
rwa [cancel] at le
238+
#align normed_space.smul_mem_polar NormedSpace.smul_mem_polar
239+
240+
theorem polar_ball_subset_closedBall_div {c : 𝕜} (hc : 1 < ‖c‖) {r : ℝ} (hr : 0 < r) :
241+
polar 𝕜 (ball (0 : E) r) ⊆ closedBall (0 : Dual 𝕜 E) (‖c‖ / r) := by
242+
intro x' hx'
243+
rw [mem_polar_iff] at hx'
244+
simp only [polar, mem_setOf, mem_closedBall_zero_iff, mem_ball_zero_iff] at *
245+
have hcr : 0 < ‖c‖ / r := div_pos (zero_lt_one.trans hc) hr
246+
refine' ContinuousLinearMap.op_norm_le_of_shell hr hcr.le hc fun x h₁ h₂ => _
247+
calc
248+
‖x' x‖ ≤ 1 := hx' _ h₂
249+
_ ≤ ‖c‖ / r * ‖x‖ := (inv_pos_le_iff_one_le_mul' hcr).1 (by rwa [inv_div])
250+
251+
#align normed_space.polar_ball_subset_closed_ball_div NormedSpace.polar_ball_subset_closedBall_div
252+
253+
variable (𝕜)
254+
255+
theorem closedBall_inv_subset_polar_closedBall {r : ℝ} :
256+
closedBall (0 : Dual 𝕜 E) r⁻¹ ⊆ polar 𝕜 (closedBall (0 : E) r) := fun x' hx' x hx =>
257+
calc
258+
‖x' x‖ ≤ ‖x'‖ * ‖x‖ := x'.le_op_norm x
259+
_ ≤ r⁻¹ * r :=
260+
(mul_le_mul (mem_closedBall_zero_iff.1 hx') (mem_closedBall_zero_iff.1 hx) (norm_nonneg _)
261+
(dist_nonneg.trans hx'))
262+
_ = r / r := (inv_mul_eq_div _ _)
263+
_ ≤ 1 := div_self_le_one r
264+
265+
#align normed_space.closed_ball_inv_subset_polar_closed_ball NormedSpace.closedBall_inv_subset_polar_closedBall
266+
267+
/-- The `polar` of closed ball in a normed space `E` is the closed ball of the dual with
268+
inverse radius. -/
269+
theorem polar_closedBall {𝕜 E : Type _} [IsROrC 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] {r : ℝ}
270+
(hr : 0 < r) : polar 𝕜 (closedBall (0 : E) r) = closedBall (0 : Dual 𝕜 E) r⁻¹ := by
271+
refine' Subset.antisymm _ (closedBall_inv_subset_polar_closedBall 𝕜)
272+
intro x' h
273+
simp only [mem_closedBall_zero_iff]
274+
refine' ContinuousLinearMap.op_norm_le_of_ball hr (inv_nonneg.mpr hr.le) fun z _ => _
275+
simpa only [one_div] using LinearMap.bound_of_ball_bound' hr 1 x'.toLinearMap h z
276+
#align normed_space.polar_closed_ball NormedSpace.polar_closedBall
277+
278+
/-- Given a neighborhood `s` of the origin in a normed space `E`, the dual norms
279+
of all elements of the polar `polar 𝕜 s` are bounded by a constant. -/
280+
theorem bounded_polar_of_mem_nhds_zero {s : Set E} (s_nhd : s ∈ 𝓝 (0 : E)) :
281+
Bounded (polar 𝕜 s) := by
282+
obtain ⟨a, ha⟩ : ∃ a : 𝕜, 1 < ‖a‖ := NormedField.exists_one_lt_norm 𝕜
283+
obtain ⟨r, r_pos, r_ball⟩ : ∃ r : ℝ, 0 < r ∧ ball 0 r ⊆ s := Metric.mem_nhds_iff.1 s_nhd
284+
exact
285+
bounded_closedBall.mono
286+
(((dualPairing 𝕜 E).flip.polar_antitone r_ball).trans <|
287+
polar_ball_subset_closedBall_div ha r_pos)
288+
#align normed_space.bounded_polar_of_mem_nhds_zero NormedSpace.bounded_polar_of_mem_nhds_zero
289+
290+
end PolarSets
291+
292+
end NormedSpace

0 commit comments

Comments
 (0)