Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 1a4df69

Browse files
committed
feat(analysis/inner_product_space/basic): orthogonal submodules (#18705)
This adds `submodule.is_ortho U V`, with notation `U ⟂ V`, as a shorthand for `U ≤ Vᗮ`. To make this useful, this also adds about 30 lemmas of basic API. Some downstream proofs are golfed using the new API.
1 parent d524d0a commit 1a4df69

File tree

6 files changed

+193
-23
lines changed

6 files changed

+193
-23
lines changed

src/analysis/inner_product_space/basic.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,6 +1885,7 @@ open_locale direct_sum
18851885
The simple way to express this concept would be as a condition on `V : ι → submodule 𝕜 E`. We
18861886
We instead implement it as a condition on a family of inner product spaces each equipped with an
18871887
isometric embedding into `E`, thus making it a property of morphisms rather than subobjects.
1888+
The connection to the subobject spelling is shown in `orthogonal_family_iff_pairwise`.
18881889
18891890
This definition is less lightweight, but allows for better definitional properties when the inner
18901891
product space structure on each of the submodules is important -- for example, when considering

src/analysis/inner_product_space/gram_schmidt_ortho.lean

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,15 @@ begin
181181
apply finset.sum_eq_zero,
182182
intros j hj,
183183
rw coe_eq_zero,
184-
suffices : span 𝕜 (f '' set.Iic j) ≤ (𝕜 ∙ f i)ᗮ,
184+
suffices : span 𝕜 (f '' set.Iic j) 𝕜 ∙ f i,
185185
{ apply orthogonal_projection_mem_subspace_orthogonal_complement_eq_zero,
186186
rw mem_orthogonal_singleton_iff_inner_left,
187187
rw ←mem_orthogonal_singleton_iff_inner_right,
188188
exact this (gram_schmidt_mem_span 𝕜 f (le_refl j)) },
189-
rw span_le,
190-
rintros - ⟨k, hk, rfl⟩,
191-
rw [set_like.mem_coe, mem_orthogonal_singleton_iff_inner_left],
189+
rw is_ortho_span,
190+
rintros u ⟨k, hk, rfl⟩ v (rfl : v = f i),
192191
apply hf,
193-
refine (lt_of_le_of_lt hk _).ne,
194-
simpa using hj },
192+
exact (lt_of_le_of_lt hk (finset.mem_Iio.mp hj)).ne },
195193
{ simp },
196194
end
197195

@@ -358,16 +356,14 @@ lemma inner_gram_schmidt_orthonormal_basis_eq_zero {f : ι → E} {i : ι}
358356
⟪gram_schmidt_orthonormal_basis h f i, f j⟫ = 0 :=
359357
begin
360358
rw ←mem_orthogonal_singleton_iff_inner_right,
361-
suffices : span 𝕜 (gram_schmidt_normed 𝕜 f '' Iic j)
362-
≤ (𝕜 ∙ gram_schmidt_orthonormal_basis h f i)ᗮ,
359+
suffices : span 𝕜 (gram_schmidt_normed 𝕜 f '' Iic j) ⟂ 𝕜 ∙ gram_schmidt_orthonormal_basis h f i,
363360
{ apply this,
364361
rw span_gram_schmidt_normed,
365-
simpa using mem_span_gram_schmidt 𝕜 f (le_refl j) },
366-
rw span_le,
367-
rintros - ⟨k, -, rfl⟩,
368-
rw [set_like.mem_coe, mem_orthogonal_singleton_iff_inner_left],
362+
exact mem_span_gram_schmidt 𝕜 f le_rfl },
363+
rw is_ortho_span,
364+
rintros u ⟨k, hk, rfl⟩ v (rfl : v = _),
369365
by_cases hk : gram_schmidt_normed 𝕜 f k = 0,
370-
{ simp [hk] },
366+
{ rw [hk, inner_zero_left] },
371367
rw ← gram_schmidt_orthonormal_basis_apply h hk,
372368
have : k ≠ i,
373369
{ rintros rfl,

src/analysis/inner_product_space/orthogonal.lean

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,19 @@ In this file, the `orthogonal` complement of a submodule `K` is defined, and bas
1919
Some of the more subtle results about the orthogonal complement are delayed to
2020
`analysis.inner_product_space.projection`.
2121
22+
See also `bilin_form.orthogonal` for orthogonality with respect to a general bilinear form.
23+
2224
## Notation
2325
2426
The orthogonal complement of a submodule `K` is denoted by `Kᗮ`.
27+
28+
The proposition that two submodules are orthogonal, `submodule.is_ortho`, is denoted by `U ⟂ V`.
29+
Note this is not the same unicode symbol as `⊥` (`has_bot`).
2530
-/
2631

2732
variables {𝕜 E F : Type*} [is_R_or_C 𝕜]
2833
variables [normed_add_comm_group E] [inner_product_space 𝕜 E]
29-
variables [normed_add_comm_group F] [inner_product_space F]
34+
variables [normed_add_comm_group F] [inner_product_space 𝕜 F]
3035
local notation `⟪`x`, `y`⟫` := @inner 𝕜 _ _ x y
3136

3237
namespace submodule
@@ -200,3 +205,157 @@ lemma orthogonal_family_self :
200205
| ff ff := absurd rfl
201206

202207
end submodule
208+
209+
@[simp]
210+
lemma bilin_form_of_real_inner_orthogonal {E} [normed_add_comm_group E] [inner_product_space ℝ E]
211+
(K : submodule ℝ E) :
212+
bilin_form_of_real_inner.orthogonal K = Kᗮ := rfl
213+
214+
/-!
215+
### Orthogonality of submodules
216+
217+
In this section we define `submodule.is_ortho U V`, with notation `U ⟂ V`.
218+
219+
The API roughly matches that of `disjoint`.
220+
-/
221+
namespace submodule
222+
223+
/-- The proposition that two submodules are orthogonal. Has notation `U ⟂ V`. -/
224+
def is_ortho (U V : submodule 𝕜 E) : Prop :=
225+
U ≤ Vᗮ
226+
227+
infix ` ⟂ `:50 := submodule.is_ortho
228+
229+
lemma is_ortho_iff_le {U V : submodule 𝕜 E} : U ⟂ V ↔ U ≤ Vᗮ := iff.rfl
230+
231+
@[symm]
232+
lemma is_ortho.symm {U V : submodule 𝕜 E} (h : U ⟂ V) : V ⟂ U :=
233+
(le_orthogonal_orthogonal _).trans (orthogonal_le h)
234+
lemma is_ortho_comm {U V : submodule 𝕜 E} : U ⟂ V ↔ V ⟂ U := ⟨is_ortho.symm, is_ortho.symm⟩
235+
lemma symmetric_is_ortho : symmetric (is_ortho : submodule 𝕜 E → submodule 𝕜 E → Prop) :=
236+
λ _ _, is_ortho.symm
237+
238+
lemma is_ortho.inner_eq {U V : submodule 𝕜 E} (h : U ⟂ V) {u v : E} (hu : u ∈ U) (hv : v ∈ V) :
239+
⟪u, v⟫ = 0 :=
240+
h.symm hv _ hu
241+
242+
lemma is_ortho_iff_inner_eq {U V : submodule 𝕜 E} : U ⟂ V ↔ ∀ (u ∈ U) (v ∈ V), ⟪u, v⟫ = 0 :=
243+
forall₄_congr $ λ u hu v hv, inner_eq_zero_symm
244+
245+
/- TODO: generalize `submodule.map₂` to semilinear maps, so that we can state
246+
`U ⟂ V ↔ submodule.map₂ (innerₛₗ 𝕜) U V ≤ ⊥`. -/
247+
248+
@[simp] lemma is_ortho_bot_left {V : submodule 𝕜 E} : ⊥ ⟂ V := bot_le
249+
@[simp] lemma is_ortho_bot_right {U : submodule 𝕜 E} : U ⟂ ⊥ := is_ortho_bot_left.symm
250+
251+
lemma is_ortho.mono_left {U₁ U₂ V : submodule 𝕜 E} (hU : U₂ ≤ U₁) (h : U₁ ⟂ V) : U₂ ⟂ V :=
252+
hU.trans h
253+
254+
lemma is_ortho.mono_right {U V₁ V₂ : submodule 𝕜 E} (hV : V₂ ≤ V₁) (h : U ⟂ V₁) : U ⟂ V₂ :=
255+
(h.symm.mono_left hV).symm
256+
257+
lemma is_ortho.mono {U₁ V₁ U₂ V₂ : submodule 𝕜 E} (hU : U₂ ≤ U₁) (hV : V₂ ≤ V₁) (h : U₁ ⟂ V₁) :
258+
U₂ ⟂ V₂ :=
259+
(h.mono_right hV).mono_left hU
260+
261+
@[simp]
262+
lemma is_ortho_self {U : submodule 𝕜 E} : U ⟂ U ↔ U = ⊥ :=
263+
⟨λ h, eq_bot_iff.mpr $ λ x hx, inner_self_eq_zero.mp (h hx x hx), λ h, h.symm ▸ is_ortho_bot_left⟩
264+
265+
@[simp] lemma is_ortho_orthogonal_right (U : submodule 𝕜 E) : U ⟂ Uᗮ :=
266+
le_orthogonal_orthogonal _
267+
268+
@[simp] lemma is_ortho_orthogonal_left (U : submodule 𝕜 E) : Uᗮ ⟂ U :=
269+
(is_ortho_orthogonal_right U).symm
270+
271+
lemma is_ortho.le {U V : submodule 𝕜 E} (h : U ⟂ V) : U ≤ Vᗮ := h
272+
lemma is_ortho.ge {U V : submodule 𝕜 E} (h : U ⟂ V) : V ≤ Uᗮ := h.symm
273+
@[simp]
274+
lemma is_ortho_top_right {U : submodule 𝕜 E} : U ⟂ ⊤ ↔ U = ⊥ :=
275+
⟨λ h, eq_bot_iff.mpr $ λ x hx, inner_self_eq_zero.mp (h hx _ mem_top),
276+
λ h, h.symm ▸ is_ortho_bot_left⟩
277+
278+
@[simp]
279+
lemma is_ortho_top_left {V : submodule 𝕜 E} : ⊤ ⟂ V ↔ V = ⊥ :=
280+
is_ortho_comm.trans is_ortho_top_right
281+
282+
/-- Orthogonal submodules are disjoint. -/
283+
lemma is_ortho.disjoint {U V : submodule 𝕜 E} (h : U ⟂ V) : disjoint U V :=
284+
(submodule.orthogonal_disjoint _).mono_right h.symm
285+
286+
@[simp] lemma is_ortho_sup_left {U₁ U₂ V : submodule 𝕜 E} : U₁ ⊔ U₂ ⟂ V ↔ U₁ ⟂ V ∧ U₂ ⟂ V :=
287+
sup_le_iff
288+
289+
@[simp] lemma is_ortho_sup_right {U V₁ V₂ : submodule 𝕜 E} : U ⟂ V₁ ⊔ V₂ ↔ U ⟂ V₁ ∧ U ⟂ V₂ :=
290+
is_ortho_comm.trans $ is_ortho_sup_left.trans $ is_ortho_comm.and is_ortho_comm
291+
292+
@[simp] lemma is_ortho_Sup_left {U : set (submodule 𝕜 E)} {V : submodule 𝕜 E} :
293+
Sup U ⟂ V ↔ ∀ Uᵢ ∈ U, Uᵢ ⟂ V :=
294+
Sup_le_iff
295+
296+
@[simp] lemma is_ortho_Sup_right {U : submodule 𝕜 E} {V : set (submodule 𝕜 E)} :
297+
U ⟂ Sup V ↔ ∀ Vᵢ ∈ V, U ⟂ Vᵢ :=
298+
is_ortho_comm.trans $ is_ortho_Sup_left.trans $ by simp_rw is_ortho_comm
299+
300+
@[simp] lemma is_ortho_supr_left {ι : Sort*} {U : ι → submodule 𝕜 E} {V : submodule 𝕜 E} :
301+
supr U ⟂ V ↔ ∀ i, U i ⟂ V :=
302+
supr_le_iff
303+
304+
@[simp] lemma is_ortho_supr_right {ι : Sort*} {U : submodule 𝕜 E} {V : ι → submodule 𝕜 E} :
305+
U ⟂ supr V ↔ ∀ i, U ⟂ V i :=
306+
is_ortho_comm.trans $ is_ortho_supr_left.trans $ by simp_rw is_ortho_comm
307+
308+
@[simp] lemma is_ortho_span {s t : set E} :
309+
span 𝕜 s ⟂ span 𝕜 t ↔ ∀ ⦃u⦄, u ∈ s → ∀ ⦃v⦄, v ∈ t → ⟪u, v⟫ = 0 :=
310+
begin
311+
simp_rw [span_eq_supr_of_singleton_spans s, span_eq_supr_of_singleton_spans t,
312+
is_ortho_supr_left, is_ortho_supr_right, is_ortho_iff_le, span_le, set.subset_def,
313+
set_like.mem_coe, mem_orthogonal_singleton_iff_inner_left, set.mem_singleton_iff, forall_eq],
314+
end
315+
316+
lemma is_ortho.map (f : E →ₗᵢ[𝕜] F) {U V : submodule 𝕜 E} (h : U ⟂ V) : U.map f ⟂ V.map f :=
317+
begin
318+
rw is_ortho_iff_inner_eq at *,
319+
simp_rw [mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂,
320+
linear_isometry.inner_map_map],
321+
exact h,
322+
end
323+
324+
lemma is_ortho.comap (f : E →ₗᵢ[𝕜] F) {U V : submodule 𝕜 F} (h : U ⟂ V) : U.comap f ⟂ V.comap f :=
325+
begin
326+
rw is_ortho_iff_inner_eq at *,
327+
simp_rw [mem_comap, ←f.inner_map_map],
328+
intros u hu v hv,
329+
exact h _ hu _ hv,
330+
end
331+
332+
@[simp] lemma is_ortho.map_iff (f : E ≃ₗᵢ[𝕜] F) {U V : submodule 𝕜 E} : U.map f ⟂ V.map f ↔ U ⟂ V :=
333+
⟨λ h, begin
334+
have hf : ∀ p : submodule 𝕜 E, (p.map f).comap f.to_linear_isometry = p :=
335+
comap_map_eq_of_injective f.injective,
336+
simpa only [hf] using h.comap f.to_linear_isometry,
337+
end, is_ortho.map f.to_linear_isometry⟩
338+
339+
@[simp] lemma is_ortho.comap_iff (f : E ≃ₗᵢ[𝕜] F) {U V : submodule 𝕜 F} :
340+
U.comap f ⟂ V.comap f ↔ U ⟂ V :=
341+
⟨λ h, begin
342+
have hf : ∀ p : submodule 𝕜 F, (p.comap f).map f.to_linear_isometry = p :=
343+
map_comap_eq_of_surjective f.surjective,
344+
simpa only [hf] using h.map f.to_linear_isometry,
345+
end, is_ortho.comap f.to_linear_isometry⟩
346+
347+
end submodule
348+
349+
lemma orthogonal_family_iff_pairwise {ι} {V : ι → submodule 𝕜 E} :
350+
orthogonal_family 𝕜 (λ i, V i) (λ i, (V i).subtypeₗᵢ) ↔ pairwise ((⟂) on V) :=
351+
forall₃_congr $ λ i j hij,
352+
subtype.forall.trans $ forall₂_congr $ λ x hx, subtype.forall.trans $ forall₂_congr $ λ y hy,
353+
inner_eq_zero_symm
354+
355+
alias orthogonal_family_iff_pairwise ↔ orthogonal_family.pairwise orthogonal_family.of_pairwise
356+
357+
/-- Two submodules in an orthogonal family with different indices are orthogonal. -/
358+
lemma orthogonal_family.is_ortho {ι} {V : ι → submodule 𝕜 E}
359+
(hV : orthogonal_family 𝕜 (λ i, V i) (λ i, (V i).subtypeₗᵢ)) {i j : ι} (hij : i ≠ j) :
360+
V i ⟂ V j :=
361+
hV.pairwise hij

src/analysis/inner_product_space/projection.lean

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,23 @@ lemma orthogonal_projection_mem_subspace_orthogonal_complement_eq_zero
785785
orthogonal_projection K v = 0 :=
786786
by { ext, convert eq_orthogonal_projection_of_mem_orthogonal _ _; simp [hv] }
787787

788+
/-- The projection into `U` from an orthogonal submodule `V` is the zero map. -/
789+
lemma submodule.is_ortho.orthogonal_projection_comp_subtypeL {U V : submodule 𝕜 E}
790+
[complete_space U] (h : U ⟂ V) :
791+
orthogonal_projection U ∘L V.subtypeL = 0 :=
792+
continuous_linear_map.ext $ λ v,
793+
orthogonal_projection_mem_subspace_orthogonal_complement_eq_zero $ h.symm v.prop
794+
795+
/-- The projection into `U` from `V` is the zero map if and only if `U` and `V` are orthogonal. -/
796+
lemma orthogonal_projection_comp_subtypeL_eq_zero_iff {U V : submodule 𝕜 E}
797+
[complete_space U] :
798+
orthogonal_projection U ∘L V.subtypeL = 0 ↔ U ⟂ V :=
799+
⟨λ h u hu v hv, begin
800+
convert orthogonal_projection_inner_eq_zero v u hu using 2,
801+
have : orthogonal_projection U v = 0 := fun_like.congr_fun h ⟨_, hv⟩,
802+
rw [this, submodule.coe_zero, sub_zero]
803+
end, submodule.is_ortho.orthogonal_projection_comp_subtypeL⟩
804+
788805
lemma orthogonal_projection_eq_linear_proj [complete_space K] (x : E) :
789806
orthogonal_projection K x =
790807
K.linear_proj_of_is_compl _ submodule.is_compl_orthogonal_of_complete_space x :=

src/analysis/inner_product_space/spectrum.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ lemma orthogonal_supr_eigenspaces (μ : 𝕜) :
107107
begin
108108
set p : submodule 𝕜 E := (⨆ μ, eigenspace T μ)ᗮ,
109109
refine eigenspace_restrict_eq_bot hT.orthogonal_supr_eigenspaces_invariant _,
110-
have H₂ : p ≤ (eigenspace T μ)ᗮ := submodule.orthogonal_le (le_supr _ _),
111-
exact (eigenspace T μ).orthogonal_disjoint.mono_right H₂
110+
have H₂ : eigenspace T μ ⟂ p := (submodule.is_ortho_orthogonal_right _).mono_left (le_supr _ _),
111+
exact H₂.disjoint
112112
end
113113

114114
/-! ### Finite-dimensional theory -/

src/geometry/euclidean/monge_point.lean

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,11 @@ by rw [altitude_def,
367367

368368
/-- The vector span of the opposite face lies in the direction
369369
orthogonal to an altitude. -/
370-
lemma vector_span_le_altitude_direction_orthogonal {n : ℕ} (s : simplex ℝ P (n + 1))
371-
(i : fin (n + 2)) :
372-
vector_span ℝ (s.points '' ↑(finset.univ.erase i)) ≤ (s.altitude i).directionᗮ :=
370+
lemma vector_span_is_ortho_altitude_direction {n : ℕ} (s : simplex ℝ P (n + 1)) (i : fin (n + 2)) :
371+
vector_span ℝ (s.points '' ↑(finset.univ.erase i)) ⟂ (s.altitude i).direction :=
373372
begin
374373
rw direction_altitude,
375-
exact le_trans
376-
(vector_span ℝ (s.points '' ↑(finset.univ.erase i))).le_orthogonal_orthogonal
377-
(submodule.orthogonal_le inf_le_left)
374+
exact (submodule.is_ortho_orthogonal_right _).mono_right inf_le_left,
378375
end
379376

380377
open finite_dimensional
@@ -594,7 +591,7 @@ begin
594591
have hle : (t₁.altitude i₃).directionᗮ ≤
595592
line[ℝ, t₁.orthocenter, t₁.points i₃].directionᗮ :=
596593
submodule.orthogonal_le (direction_le (affine_span_orthocenter_point_le_altitude _ _)),
597-
refine hle ((t₁.vector_span_le_altitude_direction_orthogonal i₃) _),
594+
refine hle ((t₁.vector_span_is_ortho_altitude_direction i₃) _),
598595
have hui : finset.univ.erase i₃ = {i₁, i₂}, { clear hle h₂ h₃, dec_trivial! },
599596
rw [hui, finset.coe_insert, finset.coe_singleton, set.image_insert_eq, set.image_singleton],
600597
refine vsub_mem_vector_span ℝ (set.mem_insert _ _)

0 commit comments

Comments
 (0)