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

[Merged by Bors] - feat(analysis/inner_product_space/gram_schmidt_ortho): Gram-Schmidt Orthogonalization and Orthonormalization #12857

Closed
wants to merge 69 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
d02693b
doc(linear_algebra): Gram-Schmidt Orthogonalization and Orthornormali…
Biiiilly Mar 21, 2022
89b0132
change from review
Biiiilly Mar 21, 2022
3c498d5
change import
Biiiilly Mar 21, 2022
bd02f66
changes from review
Biiiilly Mar 21, 2022
8769f46
changes from reviews
Biiiilly Mar 21, 2022
6f87999
changes from review
Biiiilly Mar 21, 2022
49238f0
changes from reviews
Biiiilly Mar 22, 2022
6b8e358
changes from reviews
Biiiilly Mar 22, 2022
63c3e86
changes from reviews
Biiiilly Mar 22, 2022
31af760
changes from reviews
Biiiilly Mar 22, 2022
ee95b97
changes from reviews
Biiiilly Mar 23, 2022
6c8964b
change some doc-strings
Biiiilly Mar 23, 2022
15c0b54
add proof of span
Biiiilly Mar 26, 2022
6e55b6e
change doc
Biiiilly Mar 26, 2022
5f329da
changes from reviews
Biiiilly Mar 26, 2022
ba9d844
changes from reviews
Biiiilly Mar 26, 2022
4e9899f
changes from reviews
Biiiilly Mar 26, 2022
40772c0
add doc to def of gs process
Biiiilly Mar 26, 2022
ad7fc34
change doc of inner notation
Biiiilly Mar 27, 2022
8c9e27e
changes from reviews
Biiiilly Mar 27, 2022
4ca03b5
change some
Biiiilly Mar 28, 2022
d385acb
change some small mistakes
Biiiilly Mar 28, 2022
c1d567e
change small mistake
Biiiilly Mar 28, 2022
928e45a
change from reviews
Biiiilly Mar 31, 2022
fda0a2b
change path to inner product space
Biiiilly Mar 31, 2022
d1ab7e6
add TODO
Biiiilly Apr 5, 2022
3c1f2a9
change from reviews
Biiiilly Apr 5, 2022
607af4f
change from reviews
Biiiilly Apr 5, 2022
8ff5618
change from review
Biiiilly Apr 5, 2022
280dd61
change from review
Biiiilly Apr 5, 2022
67c9d61
change Iic to range
Biiiilly Apr 6, 2022
b206c41
add gram_schmidt_orhogonal
Biiiilly Apr 6, 2022
a553ce5
change from reviews
Biiiilly Apr 10, 2022
4e176ee
suffices
Biiiilly Apr 12, 2022
be24d1b
simplify span proof
Biiiilly Apr 13, 2022
baa718a
simp span
Biiiilly Apr 14, 2022
f454a3c
change line length
Biiiilly Apr 14, 2022
19e1c52
change from review about induction and indent
Biiiilly Apr 14, 2022
bd76fb8
change some mistake
Biiiilly Apr 14, 2022
bb71c43
simp nezero proof
Biiiilly Apr 14, 2022
9caf604
simp proof
Biiiilly Apr 14, 2022
5f727c0
change doc
Biiiilly Apr 15, 2022
8319da4
simp proof
Biiiilly Apr 15, 2022
9c18e8a
simp proof
Biiiilly Apr 15, 2022
c3d0cde
changes
Biiiilly Apr 15, 2022
47c0e56
changess
Biiiilly Apr 15, 2022
26945ed
simp proof
Biiiilly Apr 15, 2022
2482b0a
simp proof again
Biiiilly Apr 15, 2022
14a3537
simp simp proof
Biiiilly Apr 15, 2022
1abfff2
simp proof
Biiiilly Apr 16, 2022
962091a
simp
Biiiilly Apr 16, 2022
b3afd14
change from review
Biiiilly Apr 17, 2022
4e3996b
Iic_succ
Biiiilly Apr 17, 2022
0360e03
add Iic_succ
Biiiilly Apr 17, 2022
7865671
simp proof
Biiiilly Apr 17, 2022
e8506b4
simp proof aaaagin
Biiiilly Apr 18, 2022
06d7d6d
iicsucc
Biiiilly Apr 19, 2022
f04f835
Merge remote-tracking branch 'origin' into GS_doc
Biiiilly Apr 19, 2022
3c5f8c5
add Iic_succ
Biiiilly Apr 19, 2022
aeeb897
small mis
Biiiilly Apr 19, 2022
c2aede2
cleanup weird induction
eric-wieser Apr 19, 2022
74d8e45
change from review
Biiiilly Apr 19, 2022
2f66e94
change from review
Biiiilly Apr 19, 2022
f6c8abe
change from review
Biiiilly Apr 19, 2022
e96ead0
change doc
Biiiilly Apr 20, 2022
ee54f41
change doc
Biiiilly Apr 20, 2022
431b352
change doc
Biiiilly Apr 20, 2022
418d5ca
change doc
Biiiilly Apr 20, 2022
736430f
change doc
Biiiilly Apr 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/undergrad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ Bilinear and Quadratic Forms Over a Vector Space:
Sylvester's law of inertia: 'https://en.wikipedia.org/wiki/Sylvester%27s_law_of_inertia'
real classification: 'https://en.wikipedia.org/wiki/Sylvester%27s_law_of_inertia'
complex classification: ''
Gram-Schmidt orthogonalisation: 'https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process'
Gram-Schmidt orthogonalisation: 'gram_schmidt_orthogonal'
Euclidean and Hermitian spaces:
Euclidean vector spaces: 'inner_product_space'
Hermitian vector spaces: 'inner_product_space'
Expand Down
205 changes: 205 additions & 0 deletions src/analysis/inner_product_space/gram_schmidt_ortho.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/-
Copyright (c) 2022 Jiale Miao. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Jiale Miao, Kevin Buzzard
-/

import analysis.inner_product_space.projection

/-!
# Gram-Schmidt Orthogonalization and Orthonormalization

In this file we introduce Gram-Schmidt Orthogonalization and Orthonormalization.

The Gram-Schmidt process takes a set of vectors as input
and outputs a set of orthogonal vectors which have the same span.

## Main results

- `gram_schmidt` : the Gram-Schmidt process
- `gram_schmidt_orthogonal` :
`gram_schmidt` produces an orthogonal system of vectors.
- `span_gram_schmidt` :
`gram_schmidt` preserves span of vectors.
- `gram_schmidt_ne_zero` :
If the input of the first `n + 1` vectors of `gram_schmidt` are linearly independent,
then the output of the first `n + 1` vectors are non-zero.
- `gram_schmidt_normed` :
the normalized `gram_schmidt` (i.e each vector in `gram_schmidt_normed` has unit length.)
- `gram_schmidt_orthornormal` :
`gram_schmidt_normed` produces an orthornormal system of vectors.

## TODO
Construct a version with an orthonormal basis from Gram-Schmidt process.
-/

open_locale big_operators

variables (𝕜 : Type*) {E : Type*} [is_R_or_C 𝕜] [inner_product_space 𝕜 E]

local notation `⟪`x`, `y`⟫` := @inner 𝕜 _ _ x y

/-- The Gram-Schmidt process takes a set of vectors as input
and outputs a set of orthogonal vectors which have the same span. -/
noncomputable def gram_schmidt (f : ℕ → E) : ℕ → E
| n := f n - ∑ i : fin n, orthogonal_projection (𝕜 ∙ gram_schmidt i) (f n)
using_well_founded {dec_tac := `[exact i.prop]}

/-- `gram_schmidt_def` turns the sum over `fin n` into a sum over `ℕ`. -/
lemma gram_schmidt_def (f : ℕ → E) (n : ℕ) :
gram_schmidt 𝕜 f n = f n - ∑ i in finset.range n,
orthogonal_projection (𝕜 ∙ gram_schmidt 𝕜 f i) (f n) :=
begin
rw gram_schmidt,
congr' 1,
exact fin.sum_univ_eq_sum_range (λ i,
(orthogonal_projection (𝕜 ∙ gram_schmidt 𝕜 f i) (f n) : E)) n,
end

lemma gram_schmidt_def' (f : ℕ → E) (n : ℕ):
f n = gram_schmidt 𝕜 f n + ∑ i in finset.range n,
orthogonal_projection (𝕜 ∙ gram_schmidt 𝕜 f i) (f n) :=
by simp only [gram_schmidt_def, sub_add_cancel]

@[simp] lemma gram_schmidt_zero (f : ℕ → E) :
gram_schmidt 𝕜 f 0 = f 0 :=
by simp only [gram_schmidt, fintype.univ_of_is_empty, finset.sum_empty, sub_zero]

/-- **Gram-Schmidt Orthogonalisation**:
`gram_schmidt` produces an orthogonal system of vectors. -/
theorem gram_schmidt_orthogonal (f : ℕ → E) {a b : ℕ} (h₀ : a ≠ b) :
⟪gram_schmidt 𝕜 f a, gram_schmidt 𝕜 f b⟫ = 0 :=
Biiiilly marked this conversation as resolved.
Show resolved Hide resolved
begin
suffices : ∀ a b : ℕ, a < b → ⟪gram_schmidt 𝕜 f a, gram_schmidt 𝕜 f b⟫ = 0,
{ cases h₀.lt_or_lt with ha hb,
{ exact this _ _ ha, },
{ rw inner_eq_zero_sym,
exact this _ _ hb, }, },
clear h₀ a b,
intros a b h₀,
induction b using nat.strong_induction_on with b ih generalizing a,
simp only [gram_schmidt_def 𝕜 f b, inner_sub_right, inner_sum,
orthogonal_projection_singleton, inner_smul_right],
rw finset.sum_eq_single_of_mem a (finset.mem_range.mpr h₀),
{ by_cases h : gram_schmidt 𝕜 f a = 0,
{ simp only [h, inner_zero_left, zero_div, zero_mul, sub_zero], },
{ rw [← inner_self_eq_norm_sq_to_K, div_mul_cancel, sub_self],
rwa [ne.def, inner_self_eq_zero], }, },
simp_intros i hi hia only [finset.mem_range],
simp only [mul_eq_zero, div_eq_zero_iff, inner_self_eq_zero],
right,
cases hia.lt_or_lt with hia₁ hia₂,
{ rw inner_eq_zero_sym,
exact ih a h₀ i hia₁, },
{ exact ih i hi a hia₂, },
end

/-- This is another version of `gram_schmidt_orthogonal` using `pairwise` instead. -/
theorem gram_schmidt_pairwise_orthogonal (f : ℕ → E) :
pairwise (λ a b, ⟪gram_schmidt 𝕜 f a, gram_schmidt 𝕜 f b⟫ = 0) :=
@gram_schmidt_orthogonal 𝕜 _ _ _ f

open submodule set order

/-- `gram_schmidt` preserves span of vectors. -/
lemma span_gram_schmidt (f : ℕ → E) (c : ℕ) :
span 𝕜 (gram_schmidt 𝕜 f '' Iic c) = span 𝕜 (f '' Iic c) :=
Biiiilly marked this conversation as resolved.
Show resolved Hide resolved
begin
induction c with c hc,
Biiiilly marked this conversation as resolved.
Show resolved Hide resolved
{ simp only [Iic, gram_schmidt_zero, le_zero_iff, set_of_eq_eq_singleton, image_singleton], },
have h₀ : ∀ b, b ∈ finset.range c.succ → gram_schmidt 𝕜 f b ∈ span 𝕜 (f '' Iic c),
{ simp_intros b hb only [finset.mem_range, nat.succ_eq_add_one],
rw ← hc,
refine subset_span _,
simp only [mem_image, mem_Iic],
refine ⟨b, by linarith, by refl⟩, },
rw [← nat.succ_eq_succ, Iic_succ],
simp only [span_insert, image_insert_eq, hc],
apply le_antisymm,
{ simp only [nat.succ_eq_succ,gram_schmidt_def 𝕜 f c.succ, orthogonal_projection_singleton,
sup_le_iff, span_singleton_le_iff_mem, le_sup_right, and_true],
apply submodule.sub_mem _ _ _,
{ exact mem_sup_left (mem_span_singleton_self (f c.succ)), },
{ exact submodule.sum_mem _ (λ b hb, mem_sup_right (smul_mem _ _ (h₀ b hb))), }, },
{ rw [nat.succ_eq_succ, gram_schmidt_def' 𝕜 f c.succ],
simp only [orthogonal_projection_singleton,
sup_le_iff, span_singleton_le_iff_mem, le_sup_right, and_true],
apply submodule.add_mem _ _ _,
{ exact mem_sup_left (mem_span_singleton_self (gram_schmidt 𝕜 f c.succ)), },
{ exact submodule.sum_mem _ (λ b hb, mem_sup_right (smul_mem _ _ (h₀ b hb))), }, },
end

/-- If the input of the first `n + 1` vectors of `gram_schmidt` are linearly independent,
then the output of the first `n + 1` vectors are non-zero. -/
lemma gram_schmidt_ne_zero (f : ℕ → E) (n : ℕ)
(h₀ : linear_independent 𝕜 (f ∘ (coe : fin n.succ → ℕ))) :
Biiiilly marked this conversation as resolved.
Show resolved Hide resolved
gram_schmidt 𝕜 f n ≠ 0 :=
begin
induction n with n hn,
{ intro h,
simp only [gram_schmidt_zero, ne.def] at h,
exact linear_independent.ne_zero 0 h₀ (by simp only [function.comp_app, fin.coe_zero, h]), },
{ by_contra h₁,
rw nat.succ_eq_add_one at hn h₀ h₁,
have h₂ := gram_schmidt_def' 𝕜 f n.succ,
simp only [nat.succ_eq_add_one, h₁, orthogonal_projection_singleton, zero_add] at h₂,
have h₃ : f (n + 1) ∈ span 𝕜 (f '' Iic n),
{ rw [h₂, ← span_gram_schmidt 𝕜 f n],
apply submodule.sum_mem _ _,
simp_intros a ha only [finset.mem_range],
apply submodule.smul_mem _ _ _,
refine subset_span _,
simp only [mem_image, mem_Iic],
exact ⟨a, by linarith, by refl⟩, },
change linear_independent 𝕜 (f ∘ (coe : fin (n + 2) → ℕ)) at h₀,
have h₄ : ((n + 1) : fin (n + 2)) ∉ (coe : fin (n + 2) → ℕ) ⁻¹' (Iic n),
{ simp only [mem_preimage, mem_Iic, not_le],
norm_cast,
rw fin.coe_coe_of_lt;
linarith, },
apply linear_independent.not_mem_span_image h₀ h₄,
rw [image_comp, image_preimage_eq_inter_range],
simp only [function.comp_app, subtype.range_coe_subtype],
convert h₃,
{ norm_cast,
refine fin.coe_coe_of_lt (by linarith), },
{ simp only [inter_eq_left_iff_subset, Iic, set_of_subset_set_of],
exact (λ a ha, by linarith), }, },
end

/-- If the input of `gram_schmidt` is linearly independent, then the output is non-zero. -/
lemma gram_schmidt_ne_zero' (f : ℕ → E) (h₀ : linear_independent 𝕜 f) (n : ℕ) :
gram_schmidt 𝕜 f n ≠ 0 :=
gram_schmidt_ne_zero 𝕜 f n (linear_independent.comp h₀ _ (fin.coe_injective))

/-- the normalized `gram_schmidt`
(i.e each vector in `gram_schmidt_normed` has unit length.) -/
noncomputable def gram_schmidt_normed (f : ℕ → E) (n : ℕ) : E :=
(∥gram_schmidt 𝕜 f n∥ : 𝕜)⁻¹ • (gram_schmidt 𝕜 f n)

lemma gram_schmidt_normed_unit_length (f : ℕ → E) (n : ℕ)
(h₀ : linear_independent 𝕜 (f ∘ (coe : fin n.succ → ℕ))) :
∥gram_schmidt_normed 𝕜 f n∥ = 1 :=
by simp only [gram_schmidt_ne_zero 𝕜 f n h₀,
gram_schmidt_normed, norm_smul_inv_norm, ne.def, not_false_iff]

lemma gram_schmidt_normed_unit_length' (f : ℕ → E) (n : ℕ)
(h₀ : linear_independent 𝕜 f) :
∥gram_schmidt_normed 𝕜 f n∥ = 1 :=
by simp only [gram_schmidt_ne_zero' 𝕜 f h₀,
gram_schmidt_normed, norm_smul_inv_norm, ne.def, not_false_iff]

/-- **Gram-Schmidt Orthonormalization**:
`gram_schmidt_normed` produces an orthornormal system of vectors. -/
theorem gram_schmidt_orthonormal (f : ℕ → E) (h₀ : linear_independent 𝕜 f) :
orthonormal 𝕜 (gram_schmidt_normed 𝕜 f) :=
begin
unfold orthonormal,
split,
{ simp only [gram_schmidt_normed_unit_length', h₀, forall_const], },
{ intros i j hij,
simp only [gram_schmidt_normed, inner_smul_left, inner_smul_right, is_R_or_C.conj_inv,
is_R_or_C.conj_of_real, mul_eq_zero, inv_eq_zero, is_R_or_C.of_real_eq_zero, norm_eq_zero],
repeat { right },
exact gram_schmidt_orthogonal 𝕜 f hij, },
end