Skip to content

Commit 7df6728

Browse files
chore: make CLM.extend total and define LM.leftInverse (#31799)
- Make `ContinuousLinearMap.extend` a total function - Define `LinearMap.leftInverse` as a total function with junk value if the input is not invertible. Required for #31074 Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 0d20243 commit 7df6728

File tree

8 files changed

+144
-99
lines changed

8 files changed

+144
-99
lines changed

Mathlib/Analysis/InnerProductSpace/LinearPMap.lean

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,39 +106,40 @@ theorem adjointDomainMkCLM_apply (y : T.adjointDomain) (x : T.domain) :
106106
adjointDomainMkCLM T y x = ⟪(y : F), T x⟫ :=
107107
rfl
108108

109-
variable {T}
110-
variable (hT : Dense (T.domain : Set E))
111-
112109
/-- The unique continuous extension of the operator `adjointDomainMkCLM` to `E`. -/
113110
def adjointDomainMkCLMExtend (y : T.adjointDomain) : StrongDual 𝕜 E :=
114-
(T.adjointDomainMkCLM y).extend (Submodule.subtypeL T.domain) hT.denseRange_val
115-
isUniformEmbedding_subtype_val.isUniformInducing
111+
(T.adjointDomainMkCLM y).extend (Submodule.subtypeL T.domain)
112+
113+
variable {T}
116114

117115
@[simp]
118-
theorem adjointDomainMkCLMExtend_apply (y : T.adjointDomain) (x : T.domain) :
119-
adjointDomainMkCLMExtend hT y (x : E) = ⟪(y : F), T x⟫ :=
120-
ContinuousLinearMap.extend_eq _ _ _ _ _
116+
theorem adjointDomainMkCLMExtend_apply (hT : Dense (T.domain : Set E)) (y : T.adjointDomain)
117+
(x : T.domain) : adjointDomainMkCLMExtend T y (x : E) = ⟪(y : F), T x⟫ :=
118+
ContinuousLinearMap.extend_eq _ hT.denseRange_val
119+
isUniformEmbedding_subtype_val.isUniformInducing _
121120

122121
variable [CompleteSpace E]
123122

123+
variable (hT : Dense (T.domain : Set E))
124+
124125
/-- The adjoint as a linear map from its domain to `E`.
125126
126127
This is an auxiliary definition needed to define the adjoint operator as a `LinearPMap` without
127128
the assumption that `T.domain` is dense. -/
128129
def adjointAux : T.adjointDomain →ₗ[𝕜] E where
129-
toFun y := (InnerProductSpace.toDual 𝕜 E).symm (adjointDomainMkCLMExtend hT y)
130+
toFun y := (InnerProductSpace.toDual 𝕜 E).symm (adjointDomainMkCLMExtend T y)
130131
map_add' x y :=
131132
hT.eq_of_inner_left fun _ => by
132133
simp only [inner_add_left, Submodule.coe_add, InnerProductSpace.toDual_symm_apply,
133-
adjointDomainMkCLMExtend_apply]
134+
adjointDomainMkCLMExtend_apply hT]
134135
map_smul' _ _ :=
135136
hT.eq_of_inner_left fun _ => by
136137
simp only [inner_smul_left, Submodule.coe_smul_of_tower, RingHom.id_apply,
137-
InnerProductSpace.toDual_symm_apply, adjointDomainMkCLMExtend_apply]
138+
InnerProductSpace.toDual_symm_apply, adjointDomainMkCLMExtend_apply hT]
138139

139140
theorem adjointAux_inner (y : T.adjointDomain) (x : T.domain) :
140141
⟪adjointAux hT y, x⟫ = ⟪(y : F), T x⟫ := by
141-
simp [adjointAux]
142+
simp [adjointAux, hT]
142143

143144
theorem adjointAux_unique (y : T.adjointDomain) {x₀ : E}
144145
(hx₀ : ∀ x : T.domain, ⟪x₀, x⟫ = ⟪(y : F), T x⟫) : adjointAux hT y = x₀ :=

Mathlib/Analysis/Normed/Operator/Extend.lean

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,44 +41,52 @@ variable [AddCommGroup E] [UniformSpace E] [IsUniformAddGroup E]
4141
[ContinuousConstSMul 𝕜 Eₗ] [ContinuousConstSMul 𝕜₂ F]
4242
{σ₁₂ : 𝕜 →+* 𝕜₂} (f g : E →SL[σ₁₂] F) [CompleteSpace F] (e : E →L[𝕜] Eₗ)
4343

44-
variable (h_dense : DenseRange e) (h_e : IsUniformInducing e)
45-
44+
open scoped Classical in
4645
/-- Extension of a continuous linear map `f : E →SL[σ₁₂] F`, with `E` a normed space and `F` a
4746
complete normed space, along a uniform and dense embedding `e : E →L[𝕜] Eₗ`. -/
4847
def extend : Eₗ →SL[σ₁₂] F :=
48+
if h : DenseRange e ∧ IsUniformInducing e then
4949
-- extension of `f` is continuous
50-
have cont := (uniformContinuous_uniformly_extend h_e h_dense f.uniformContinuous).continuous
50+
have cont := (uniformContinuous_uniformly_extend h.2 h.1 f.uniformContinuous).continuous
5151
-- extension of `f` agrees with `f` on the domain of the embedding `e`
52-
have eq := uniformly_extend_of_ind h_e h_dense f.uniformContinuous
53-
{ toFun := (h_e.isDenseInducing h_dense).extend f
52+
have eq := uniformly_extend_of_ind h.2 h.1 f.uniformContinuous
53+
{ toFun := (h.2.isDenseInducing h.1).extend f
5454
map_add' := by
55-
refine h_dense.induction_on₂ ?_ ?_
55+
refine h.1.induction_on₂ ?_ ?_
5656
· exact isClosed_eq (cont.comp continuous_add)
5757
((cont.comp continuous_fst).add (cont.comp continuous_snd))
5858
· intro x y
5959
simp only [eq, ← e.map_add]
6060
exact f.map_add _ _
6161
map_smul' := fun k => by
62-
refine fun b => h_dense.induction_on b ?_ ?_
62+
refine fun b => h.1.induction_on b ?_ ?_
6363
· exact isClosed_eq (cont.comp (continuous_const_smul _))
6464
((continuous_const_smul _).comp cont)
6565
· intro x
6666
rw [← map_smul]
6767
simp only [eq]
6868
exact ContinuousLinearMap.map_smulₛₗ _ _ _
6969
cont }
70+
else 0
7071

71-
@[simp]
72-
theorem extend_eq (x : E) : extend f e h_dense h_e (e x) = f x :=
73-
IsDenseInducing.extend_eq (h_e.isDenseInducing h_dense) f.cont _
72+
variable {e}
7473

75-
theorem extend_unique (g : Eₗ →SL[σ₁₂] F) (H : g.comp e = f) : extend f e h_dense h_e = g :=
76-
ContinuousLinearMap.coeFn_injective <|
74+
@[simp]
75+
theorem extend_eq (h_dense : DenseRange e) (h_e : IsUniformInducing e) (x : E) :
76+
extend f e (e x) = f x := by
77+
simp only [extend, h_dense, h_e, and_self, ↓reduceDIte, coe_mk', LinearMap.coe_mk, AddHom.coe_mk]
78+
exact IsDenseInducing.extend_eq (h_e.isDenseInducing h_dense) f.cont _
79+
80+
theorem extend_unique (h_dense : DenseRange e) (h_e : IsUniformInducing e) (g : Eₗ →SL[σ₁₂] F)
81+
(H : g.comp e = f) : extend f e = g := by
82+
simp only [extend, h_dense, h_e, and_self, ↓reduceDIte]
83+
exact ContinuousLinearMap.coeFn_injective <|
7784
uniformly_extend_unique h_e h_dense (ContinuousLinearMap.ext_iff.1 H) g.continuous
7885

7986
@[simp]
80-
theorem extend_zero : extend (0 : E →SL[σ₁₂] F) e h_dense h_e = 0 :=
81-
extend_unique _ _ _ _ _ (zero_comp _)
87+
theorem extend_zero (h_dense : DenseRange e) (h_e : IsUniformInducing e) :
88+
extend (0 : E →SL[σ₁₂] F) e = 0 :=
89+
extend_unique _ h_dense h_e _ (zero_comp _)
8290

8391
end Ring
8492

@@ -87,16 +95,16 @@ section NormedField
8795
variable [NontriviallyNormedField 𝕜] [NontriviallyNormedField 𝕜₂] {σ₁₂ : 𝕜 →+* 𝕜₂}
8896
[NormedAddCommGroup E] [NormedAddCommGroup Eₗ] [NormedAddCommGroup F] [NormedAddCommGroup Fₗ]
8997
[NormedSpace 𝕜 E] [NormedSpace 𝕜 Eₗ] [NormedSpace 𝕜₂ F] [NormedSpace 𝕜₂ Fₗ] [CompleteSpace F]
90-
(f g : E →SL[σ₁₂] F) (e : E →L[𝕜] Eₗ)
98+
(f g : E →SL[σ₁₂] F) {e : E →L[𝕜] Eₗ}
9199

92100
variable (h_dense : DenseRange e) (h_e : IsUniformInducing e)
93101

94-
variable {N : ℝ≥0} (h_e : ∀ x, ‖x‖ ≤ N * ‖e x‖) [RingHomIsometric σ₁₂]
102+
variable {N : ℝ≥0} [RingHomIsometric σ₁₂]
95103

96104
/-- If a dense embedding `e : E →L[𝕜] G` expands the norm by a constant factor `N⁻¹`, then the
97105
norm of the extension of `f` along `e` is bounded by `N * ‖f‖`. -/
98-
theorem opNorm_extend_le :
99-
‖f.extend e h_dense (isUniformEmbedding_of_bound _ h_e).isUniformInducing‖ ≤ N * ‖f‖ := by
106+
theorem opNorm_extend_le (h_dense : DenseRange e) (h_e : ∀ x, ‖x‖ ≤ N * ‖e x‖) :
107+
‖f.extend e‖ ≤ N * ‖f‖ := by
100108
-- Add `opNorm_le_of_dense`?
101109
refine opNorm_le_bound _ ?_ (isClosed_property h_dense (isClosed_le ?_ ?_) fun x ↦ ?_)
102110
· cases le_total 0 N with
@@ -108,7 +116,7 @@ theorem opNorm_extend_le :
108116
simp
109117
· exact (cont _).norm
110118
· exact continuous_const.mul continuous_norm
111-
· rw [extend_eq]
119+
· rw [extend_eq _ h_dense (isUniformEmbedding_of_bound _ h_e).isUniformInducing]
112120
calc
113121
‖f x‖ ≤ ‖f‖ * ‖x‖ := le_opNorm _ _
114122
_ ≤ ‖f‖ * (N * ‖e x‖) := mul_le_mul_of_nonneg_left (h_e x) (norm_nonneg _)

Mathlib/LinearAlgebra/Basis/VectorSpace.lean

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,28 @@ theorem LinearMap.exists_leftInverse_of_injective (f : V →ₗ[K] V') (hf_inj :
256256
rw [Basis.ofVectorSpace_apply_self, fb_eq, hC.constr_basis]
257257
exact leftInverse_invFun (LinearMap.ker_eq_bot.1 hf_inj) _
258258

259+
open scoped Classical in
260+
/-- The left inverse of `f : E →ₗ[𝕜] F`.
261+
262+
If `f` is not injective, then we use the junk value `0`. -/
263+
noncomputable
264+
def LinearMap.leftInverse (f : V →ₗ[K] V') : V' →ₗ[K] V :=
265+
if h_inj : LinearMap.ker f = ⊥ then
266+
(f.exists_leftInverse_of_injective h_inj).choose
267+
else 0
268+
269+
theorem LinearMap.leftInverse_comp_of_inj {f : V →ₗ[K] V'} (h_inj : LinearMap.ker f = ⊥) :
270+
f.leftInverse ∘ₗ f = LinearMap.id := by
271+
simpa [leftInverse, h_inj] using (f.exists_leftInverse_of_injective h_inj).choose_spec
272+
273+
/-- If `f` is injective, then the left inverse composed with `f` is the identity. -/
274+
theorem LinearMap.leftInverse_apply_of_inj {f : V →ₗ[K] V'} (h_inj : LinearMap.ker f = ⊥) (x : V) :
275+
f.leftInverse (f x) = x :=
276+
LinearMap.ext_iff.mp (f.leftInverse_comp_of_inj h_inj) x
277+
259278
theorem Submodule.exists_isCompl (p : Submodule K V) : ∃ q : Submodule K V, IsCompl p q :=
260-
let ⟨f, hf⟩ := p.subtype.exists_leftInverse_of_injective p.ker_subtype
261-
⟨LinearMap.ker f, LinearMap.isCompl_of_proj <| LinearMap.ext_iff.1 hf
279+
⟨LinearMap.ker p.subtype.leftInverse,
280+
LinearMap.isCompl_of_proj <| LinearMap.leftInverse_apply_of_inj p.ker_subtype
262281

263282
instance Submodule.complementedLattice : ComplementedLattice (Submodule K V) :=
264283
⟨Submodule.exists_isCompl⟩

Mathlib/LinearAlgebra/Dual/Lemmas.lean

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,14 +422,13 @@ theorem dualAnnihilator_inj {W W' : Subspace K V} :
422422
an arbitrary extension of `φ` to an element of the dual of `V`.
423423
That is, `dualLift W φ` sends `w ∈ W` to `φ x` and `x` in a chosen complement of `W` to `0`. -/
424424
noncomputable def dualLift (W : Subspace K V) : Module.Dual K W →ₗ[K] Module.Dual K V :=
425-
(Classical.choose <| W.subtype.exists_leftInverse_of_injective W.ker_subtype).dualMap
425+
W.subtype.leftInverse.dualMap
426426

427427
variable {W : Subspace K V}
428428

429429
@[simp]
430430
theorem dualLift_of_subtype {φ : Module.Dual K W} (w : W) : W.dualLift φ (w : V) = φ w :=
431-
congr_arg φ <| DFunLike.congr_fun
432-
(Classical.choose_spec <| W.subtype.exists_leftInverse_of_injective W.ker_subtype) w
431+
congr_arg φ <| LinearMap.leftInverse_apply_of_inj W.ker_subtype _
433432

434433
theorem dualLift_of_mem {φ : Module.Dual K W} {w : V} (hw : w ∈ W) : W.dualLift φ w = φ ⟨w, hw⟩ :=
435434
dualLift_of_subtype ⟨w, hw⟩

Mathlib/MeasureTheory/Function/Holder.lean

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,8 @@ def lpPairing (B : E →L[𝕜] F →L[𝕜] G) : Lp E p μ →L[𝕜] Lp F q μ
133133

134134
lemma lpPairing_eq_integral (f : Lp E p μ) (g : Lp F q μ) :
135135
B.lpPairing μ p q f g = ∫ x, B (f x) (g x) ∂μ := by
136-
change L1.integralCLM _ = _
137-
rw [← L1.integral_def, L1.integral_eq_integral]
138-
exact integral_congr_ae <| B.coeFn_holder _ _
136+
simpa [lpPairing, ← L1.integral_eq', L1.integral_eq_integral] using
137+
integral_congr_ae <| B.coeFn_holder _ _
139138

140139
end ContinuousLinearMap
141140

Mathlib/MeasureTheory/Integral/Bochner/L1.lean

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -530,8 +530,7 @@ open ContinuousLinearMap
530530
variable (𝕜) in
531531
/-- The Bochner integral in L1 space as a continuous linear map. -/
532532
nonrec def integralCLM' : (α →₁[μ] E) →L[𝕜] E :=
533-
(integralCLM' α E 𝕜 μ).extend (coeToLp α E 𝕜) (simpleFunc.denseRange one_ne_top)
534-
simpleFunc.isUniformInducing
533+
(integralCLM' α E 𝕜 μ).extend (coeToLp α E 𝕜)
535534

536535
/-- The Bochner integral in L1 space as a continuous linear map over ℝ. -/
537536
def integralCLM : (α →₁[μ] E) →L[ℝ] E :=
@@ -554,6 +553,21 @@ theorem SimpleFunc.integral_L1_eq_integral (f : α →₁ₛ[μ] E) :
554553
simp only [integral, L1.integral]
555554
exact setToL1_eq_setToL1SCLM (dominatedFinMeasAdditive_weightedSMul μ) f
556555

556+
@[norm_cast]
557+
theorem SimpleFunc.integralCLM'_L1_eq_integral (f : α →₁ₛ[μ] E) :
558+
L1.integralCLM' 𝕜 (f : α →₁[μ] E) = SimpleFunc.integral f := by
559+
apply ContinuousLinearMap.extend_eq _ _ simpleFunc.isUniformInducing
560+
exact simpleFunc.denseRange one_ne_top
561+
562+
variable (𝕜) in
563+
theorem integral_eq' (f : α →₁[μ] E) : integral f = integralCLM' 𝕜 f := by
564+
apply isClosed_property (simpleFunc.denseRange one_ne_top)
565+
(isClosed_eq _ (integralCLM' 𝕜).continuous) _ f
566+
· simp_rw [integral_def]
567+
exact (integralCLM (E := E)).continuous
568+
intro f
569+
norm_cast
570+
557571
variable (α E)
558572

559573
@[simp]
@@ -580,9 +594,7 @@ theorem integral_sub (f g : α →₁[μ] E) : integral (f - g) = integral f - i
580594

581595
@[integral_simps]
582596
theorem integral_smul (c : 𝕜) (f : α →₁[μ] E) : integral (c • f) = c • integral f := by
583-
simp only [integral]
584-
change (integralCLM' 𝕜) (c • f) = c • (integralCLM' 𝕜) f
585-
exact map_smul (integralCLM' 𝕜) c f
597+
rw [integral_eq' 𝕜 f, integral_eq' 𝕜 (c • f), map_smul (integralCLM' 𝕜) c f]
586598

587599
theorem norm_Integral_le_one : ‖integralCLM (α := α) (E := E) (μ := μ)‖ ≤ 1 :=
588600
norm_setToL1_le (dominatedFinMeasAdditive_weightedSMul μ) zero_le_one

0 commit comments

Comments
 (0)