2025-01-12 19:40:15 +08:00
|
|
|
|
/-
|
|
|
|
|
Copyright (c) 2025 Gordon Hsu. All rights reserved.
|
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
Authors: Gordon Hsu
|
|
|
|
|
-/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
import Mathlib.LinearAlgebra.Eigenspace.Triangularizable
|
|
|
|
|
import Mathlib.LinearAlgebra.Matrix.Spectrum
|
2025-01-12 19:40:15 +08:00
|
|
|
|
/-! # Schur triangulation
|
|
|
|
|
|
|
|
|
|
Schur triangulation is more commonly known as Schur decomposition or Schur triangularization, but
|
|
|
|
|
"triangulation" makes the API more readable. It states that a square matrix over an algebraically
|
|
|
|
|
closed field, e.g., `ℂ`, is unitarily similar to an upper triangular matrix.
|
|
|
|
|
|
|
|
|
|
## Main definitions
|
|
|
|
|
|
|
|
|
|
- `Matrix.schur_triangulation` : a matrix `A : Matrix n n 𝕜` with `𝕜` being algebraically closed can
|
|
|
|
|
be decomposed as `A = U * T * star U` where `U` is unitary and `T` is upper triangular.
|
|
|
|
|
- `Matrix.schurTriangulationUnitary` : the unitary matrix `U` as previously stated.
|
|
|
|
|
- `Matrix.schurTriangulation` : the upper triangular matrix `T` as previously stated.
|
2025-01-14 00:11:17 +01:00
|
|
|
|
- Some auxiliary definitions are not meant to be used directly, but
|
2025-01-12 19:40:15 +08:00
|
|
|
|
`LinearMap.SchurTriangulationAux.of` contains the main algorithm for the triangulation procedure.
|
|
|
|
|
|
|
|
|
|
-/
|
|
|
|
|
|
2025-01-12 17:11:04 +00:00
|
|
|
|
open scoped InnerProductSpace
|
|
|
|
|
|
2025-01-11 20:06:58 +08:00
|
|
|
|
/-- `subNat' i h` subtracts `m` from `i`. This is an alternative form of `Fin.subNat`. -/
|
|
|
|
|
@[inline] def Fin.subNat' (i : Fin (m + n)) (h : ¬ i < m) : Fin n :=
|
|
|
|
|
subNat m (Fin.cast (m.add_comm n) i) (Nat.ge_of_not_lt h)
|
|
|
|
|
|
|
|
|
|
namespace Equiv
|
|
|
|
|
|
|
|
|
|
/-- An alternative form of `Equiv.sumEquivSigmaBool` where `Bool.casesOn` is replaced by `cond`. -/
|
|
|
|
|
def sumEquivSigmalCond : Fin m ⊕ Fin n ≃ Σ b, cond b (Fin m) (Fin n) :=
|
|
|
|
|
calc Fin m ⊕ Fin n
|
|
|
|
|
_ ≃ Fin n ⊕ Fin m := sumComm ..
|
|
|
|
|
_ ≃ Σ b, Bool.casesOn b (Fin n) (Fin m) := sumEquivSigmaBool ..
|
|
|
|
|
_ ≃ Σ b, cond b (Fin m) (Fin n) := sigmaCongrRight fun | true | false => Equiv.refl _
|
|
|
|
|
|
|
|
|
|
/-- The composition of `finSumFinEquiv` and `Equiv.sumEquivSigmalCond` used by
|
|
|
|
|
`LinearMap.SchurTriangulationAux.of`. -/
|
|
|
|
|
def finAddEquivSigmaCond : Fin (m + n) ≃ Σ b, cond b (Fin m) (Fin n) :=
|
|
|
|
|
finSumFinEquiv.symm.trans sumEquivSigmalCond
|
|
|
|
|
|
2025-01-10 01:37:14 +08:00
|
|
|
|
variable {i : Fin (m + n)}
|
|
|
|
|
|
2025-01-11 17:11:38 +00:00
|
|
|
|
lemma finAddEquivSigmaCond_true (h : i < m) : finAddEquivSigmaCond i = ⟨true, i, h⟩ :=
|
2025-01-11 20:06:58 +08:00
|
|
|
|
congrArg sumEquivSigmalCond <| finSumFinEquiv_symm_apply_castAdd ⟨i, h⟩
|
|
|
|
|
|
2025-01-11 17:11:38 +00:00
|
|
|
|
lemma finAddEquivSigmaCond_false (h : ¬ i < m) : finAddEquivSigmaCond i = ⟨false, i.subNat' h⟩ :=
|
2025-01-11 20:06:58 +08:00
|
|
|
|
let j : Fin n := i.subNat' h
|
|
|
|
|
calc finAddEquivSigmaCond i
|
|
|
|
|
_ = finAddEquivSigmaCond (Fin.natAdd m j) :=
|
|
|
|
|
suffices m + (i - m) = i from congrArg _ (Fin.ext this.symm)
|
|
|
|
|
Nat.add_sub_of_le (Nat.le_of_not_gt h)
|
|
|
|
|
_ = ⟨false, i.subNat' h⟩ := congrArg sumEquivSigmalCond <| finSumFinEquiv_symm_apply_natAdd j
|
|
|
|
|
|
|
|
|
|
end Equiv
|
2025-01-10 01:37:14 +08:00
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- The type family parameterized by `Bool` is finite if each type variant is finite. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
instance [M : Fintype m] [N : Fintype n] (b : Bool) : Fintype (cond b m n) := b.rec N M
|
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- The type family parameterized by `Bool` has decidable equality if each type variant is
|
|
|
|
|
decidable. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
instance [DecidableEq m] [DecidableEq n] : DecidableEq (Σ b, cond b m n)
|
|
|
|
|
| ⟨true, _⟩, ⟨false, _⟩
|
|
|
|
|
| ⟨false, _⟩, ⟨true, _⟩ => isFalse nofun
|
|
|
|
|
| ⟨false, i⟩, ⟨false, j⟩
|
2025-01-11 20:09:29 +08:00
|
|
|
|
| ⟨true, i⟩, ⟨true, j⟩ =>
|
|
|
|
|
if h : i = j then isTrue (Sigma.eq rfl h) else isFalse fun | rfl => h rfl
|
2025-01-10 01:37:14 +08:00
|
|
|
|
|
|
|
|
|
namespace Matrix
|
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- The property of a matrix being upper triangular. See also `Matrix.det_of_upperTriangular`. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
abbrev IsUpperTriangular [LT n] [CommRing R] (A : Matrix n n R) := A.BlockTriangular id
|
2025-01-11 20:09:29 +08:00
|
|
|
|
|
|
|
|
|
/-- The subtype of upper triangular matrices. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
abbrev UpperTriangular (n R) [LT n] [CommRing R] := { A : Matrix n n R // A.IsUpperTriangular }
|
|
|
|
|
|
|
|
|
|
end Matrix
|
|
|
|
|
|
|
|
|
|
namespace LinearMap
|
|
|
|
|
variable [RCLike 𝕜]
|
|
|
|
|
|
|
|
|
|
section
|
|
|
|
|
variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E]
|
|
|
|
|
|
|
|
|
|
section
|
|
|
|
|
variable [FiniteDimensional 𝕜 E] [Fintype n] [DecidableEq n]
|
|
|
|
|
|
2025-01-11 17:11:38 +00:00
|
|
|
|
lemma toMatrixOrthonormal_apply_apply (b : OrthonormalBasis n 𝕜 E) (f : Module.End 𝕜 E)
|
|
|
|
|
(i j : n) :
|
|
|
|
|
toMatrixOrthonormal b f i j = ⟪b i, f (b j)⟫_𝕜 :=
|
2025-01-10 01:37:14 +08:00
|
|
|
|
calc
|
|
|
|
|
_ = b.repr (f (b j)) i := f.toMatrix_apply ..
|
|
|
|
|
_ = ⟪b i, f (b j)⟫_𝕜 := b.repr_apply_apply ..
|
|
|
|
|
|
2025-01-11 17:11:38 +00:00
|
|
|
|
lemma toMatrixOrthonormal_reindex [Fintype m] [DecidableEq m]
|
|
|
|
|
(b : OrthonormalBasis m 𝕜 E) (e : m ≃ n) (f : Module.End 𝕜 E) :
|
|
|
|
|
toMatrixOrthonormal (b.reindex e) f = Matrix.reindex e e (toMatrixOrthonormal b f) :=
|
2025-01-11 20:09:29 +08:00
|
|
|
|
Matrix.ext fun i j =>
|
|
|
|
|
calc toMatrixOrthonormal (b.reindex e) f i j
|
|
|
|
|
_ = (b.reindex e).repr (f (b.reindex e j)) i := f.toMatrix_apply ..
|
|
|
|
|
_ = b.repr (f (b (e.symm j))) (e.symm i) := by simp
|
|
|
|
|
_ = toMatrixOrthonormal b f (e.symm i) (e.symm j) := Eq.symm <| f.toMatrix_apply ..
|
2025-01-10 01:37:14 +08:00
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- **Don't use this definition directly.** Instead, use `Matrix.schurTriangulationBasis`,
|
|
|
|
|
`Matrix.schurTriangulationUnitary`, and `Matrix.schurTriangulation`. See also
|
|
|
|
|
`LinearMap.SchurTriangulationAux.of` and `Matrix.schurTriangulationAux`. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
structure SchurTriangulationAux (f : Module.End 𝕜 E) where
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- The dimension of the inner product space `E`. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
dim : ℕ
|
|
|
|
|
hdim : Module.finrank 𝕜 E = dim
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- An orthonormal basis of `E` that induces an upper triangular form for `f`. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
basis : OrthonormalBasis (Fin dim) 𝕜 E
|
|
|
|
|
upperTriangular : (toMatrix basis.toBasis basis.toBasis f).IsUpperTriangular
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2025-01-12 19:40:15 +08:00
|
|
|
|
/-! ## Schur's recursive triangulation procedure
|
|
|
|
|
|
|
|
|
|
Given a linear endomorphism `f` on a non-trivial finite-dimensional vector space `E` over an
|
|
|
|
|
algebraically closed field `𝕜`, one can always pick an eigenvalue `μ` of `f` whose corresponding
|
|
|
|
|
eigenspace `V` is non-trivial. Given that `E` is also an inner product space, let `bV` and `bW` be
|
2025-01-14 00:11:17 +01:00
|
|
|
|
orthonormal bases for `V` and `Vᗮ` respectively. Then, the collection of vectors in `bV` and `bW`
|
|
|
|
|
forms an orthonormal basis `bE` for `E`, as the direct sum of `V` and `Vᗮ` is an internal
|
2025-01-12 19:40:15 +08:00
|
|
|
|
decomposition of `E`. The matrix representation of `f` with respect to `bE` satisfies
|
|
|
|
|
$$
|
|
|
|
|
\sideset{_\mathrm{bE}}{_\mathrm{bE}}{[f]} =
|
|
|
|
|
\begin{bmatrix}
|
|
|
|
|
\sideset{_\mathrm{bV}}{_\mathrm{bV}}{[f]} &
|
|
|
|
|
\sideset{_\mathrm{bW}}{_\mathrm{bV}}{[f]} \\
|
|
|
|
|
\sideset{_\mathrm{bV}}{_\mathrm{bW}}{[f]} &
|
|
|
|
|
\sideset{_\mathrm{bW}}{_\mathrm{bW}}{[f]}
|
|
|
|
|
\end{bmatrix} =
|
|
|
|
|
\begin{bmatrix} \mu I & □ \\ 0 & \sideset{_\mathrm{bW}}{_\mathrm{bW}}{[f]} \end{bmatrix},
|
|
|
|
|
$$
|
|
|
|
|
which is upper triangular as long as $\sideset{_\mathrm{bW}}{_\mathrm{bW}}{[f]}$ is. Finally, one
|
|
|
|
|
observes that the recursion from $\sideset{_\mathrm{bE}}{_\mathrm{bE}}{[f]}$ to
|
|
|
|
|
$\sideset{_\mathrm{bW}}{_\mathrm{bW}}{[f]}$ is well-founded, as the dimension of `bW` is smaller
|
|
|
|
|
than that of `bE` because `bV` is non-trivial.
|
|
|
|
|
|
|
|
|
|
However, in order to leverage `DirectSum.IsInternal.collectedOrthonormalBasis`, the type
|
|
|
|
|
`Σ b, cond b (Fin m) (Fin n)` has to be used instead of the more natural `Fin m ⊕ Fin n` while their
|
|
|
|
|
equivalence is propositionally established by `Equiv.sumEquivSigmalCond`.
|
|
|
|
|
|
|
|
|
|
-/
|
|
|
|
|
|
2025-01-10 01:37:14 +08:00
|
|
|
|
variable [IsAlgClosed 𝕜]
|
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- **Don't use this definition directly.** This is the key algorithm behind
|
|
|
|
|
`Matrix.schur_triangulation`. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
protected noncomputable def SchurTriangulationAux.of
|
2025-01-11 17:11:38 +00:00
|
|
|
|
[NormedAddCommGroup E] [InnerProductSpace 𝕜 E] [FiniteDimensional 𝕜 E] (f : Module.End 𝕜 E) :
|
|
|
|
|
SchurTriangulationAux f :=
|
2025-01-10 01:37:14 +08:00
|
|
|
|
haveI : Decidable (Nontrivial E) := Classical.propDecidable _
|
|
|
|
|
if hE : Nontrivial E then
|
|
|
|
|
let μ : f.Eigenvalues := default
|
|
|
|
|
let V : Submodule 𝕜 E := f.eigenspace μ
|
|
|
|
|
let W : Submodule 𝕜 E := Vᗮ
|
|
|
|
|
let m := Module.finrank 𝕜 V
|
|
|
|
|
have hdim : m + Module.finrank 𝕜 W = Module.finrank 𝕜 E := V.finrank_add_finrank_orthogonal
|
|
|
|
|
let g : Module.End 𝕜 W := orthogonalProjection W ∘ₗ f.domRestrict W
|
|
|
|
|
let ⟨n, hn, bW, hg⟩ := SchurTriangulationAux.of g
|
|
|
|
|
|
|
|
|
|
have bV : OrthonormalBasis (Fin m) 𝕜 V := stdOrthonormalBasis 𝕜 V
|
|
|
|
|
have hV := V.orthogonalFamily_self
|
|
|
|
|
have int : DirectSum.IsInternal (cond · V W) :=
|
|
|
|
|
suffices ⨆ b, cond b V W = ⊤ from (hV.decomposition this).isInternal _
|
|
|
|
|
(sup_eq_iSup V W).symm.trans Submodule.sup_orthogonal_of_completeSpace
|
|
|
|
|
let B (b : Bool) : OrthonormalBasis (cond b (Fin m) (Fin n)) 𝕜 ↥(cond b V W) := b.rec bW bV
|
2025-01-11 20:09:29 +08:00
|
|
|
|
let bE : OrthonormalBasis (Σ b, cond b (Fin m) (Fin n)) 𝕜 E :=
|
|
|
|
|
int.collectedOrthonormalBasis hV B
|
2025-01-11 20:06:58 +08:00
|
|
|
|
let e := Equiv.finAddEquivSigmaCond
|
|
|
|
|
let basis := bE.reindex e.symm
|
2025-01-10 01:37:14 +08:00
|
|
|
|
{
|
|
|
|
|
basis
|
|
|
|
|
dim := m + n
|
|
|
|
|
hdim := hn ▸ hdim.symm
|
|
|
|
|
upperTriangular := fun i j (hji : j < i) => show toMatrixOrthonormal basis f i j = 0 from
|
|
|
|
|
have hB : ∀ s, bE s = B s.1 s.2
|
|
|
|
|
| ⟨true, i⟩ => show bE ⟨true, i⟩ = bV i from
|
2025-01-11 20:09:29 +08:00
|
|
|
|
show (int.collectedBasis fun b => (B b).toBasis).toOrthonormalBasis _ ⟨true, i⟩ = bV i
|
|
|
|
|
by simp
|
2025-01-10 01:37:14 +08:00
|
|
|
|
| ⟨false, j⟩ => show bE ⟨false, j⟩ = bW j from
|
2025-01-11 20:09:29 +08:00
|
|
|
|
show (int.collectedBasis fun b => (B b).toBasis).toOrthonormalBasis _ ⟨false, j⟩ = bW j
|
|
|
|
|
by simp
|
2025-01-11 20:06:58 +08:00
|
|
|
|
have hf {bi i' bj j'} (hi : e i = ⟨bi, i'⟩) (hj : e j = ⟨bj, j'⟩) :=
|
2025-01-11 20:09:29 +08:00
|
|
|
|
calc toMatrixOrthonormal basis f i j
|
2025-01-11 17:11:38 +00:00
|
|
|
|
_ = toMatrixOrthonormal bE f (e i) (e j) := by
|
|
|
|
|
rw [f.toMatrixOrthonormal_reindex]
|
|
|
|
|
rfl
|
2025-01-11 20:06:58 +08:00
|
|
|
|
_ = ⟪bE (e i), f (bE (e j))⟫_𝕜 := f.toMatrixOrthonormal_apply_apply ..
|
2025-01-10 01:37:14 +08:00
|
|
|
|
_ = ⟪(B bi i' : E), f (B bj j')⟫_𝕜 := by rw [hB, hB, hi, hj]
|
|
|
|
|
|
|
|
|
|
if hj : j < m then
|
|
|
|
|
let j' : Fin m := ⟨j, hj⟩
|
2025-01-11 20:06:58 +08:00
|
|
|
|
have hf' {bi i'} (hi : e i = ⟨bi, i'⟩) (h0 : ⟪(B bi i' : E), bV j'⟫_𝕜 = 0) :=
|
2025-01-11 20:09:29 +08:00
|
|
|
|
calc toMatrixOrthonormal basis f i j
|
2025-01-11 20:06:58 +08:00
|
|
|
|
_ = ⟪(B bi i' : E), f _⟫_𝕜 := hf hi (Equiv.finAddEquivSigmaCond_true hj)
|
2025-01-10 01:37:14 +08:00
|
|
|
|
_ = ⟪_, f (bV j')⟫_𝕜 := rfl
|
|
|
|
|
_ = 0 :=
|
|
|
|
|
suffices f (bV j') = μ.val • bV j' by rw [this, inner_smul_right, h0, mul_zero]
|
|
|
|
|
suffices f.HasEigenvector μ (bV j') from this.apply_eq_smul
|
|
|
|
|
⟨(bV j').property, fun h => bV.toBasis.ne_zero j' (Subtype.ext h)⟩
|
|
|
|
|
|
|
|
|
|
if hi : i < m then
|
|
|
|
|
let i' : Fin m := ⟨i, hi⟩
|
2025-01-11 20:06:58 +08:00
|
|
|
|
suffices ⟪(bV i' : E), bV j'⟫_𝕜 = 0 from hf' (Equiv.finAddEquivSigmaCond_true hi) this
|
2025-01-10 01:37:14 +08:00
|
|
|
|
bV.orthonormal.right (Fin.ne_of_gt hji)
|
|
|
|
|
else
|
2025-01-11 20:06:58 +08:00
|
|
|
|
let i' : Fin n := i.subNat' hi
|
|
|
|
|
suffices ⟪(bW i' : E), bV j'⟫_𝕜 = 0 from hf' (Equiv.finAddEquivSigmaCond_false hi) this
|
2025-01-10 01:37:14 +08:00
|
|
|
|
V.inner_left_of_mem_orthogonal (bV j').property (bW i').property
|
|
|
|
|
else
|
|
|
|
|
have hi (h : i < m) : False := hj (Nat.lt_trans hji h)
|
2025-01-11 20:06:58 +08:00
|
|
|
|
let i' : Fin n := i.subNat' hi
|
|
|
|
|
let j' : Fin n := j.subNat' hj
|
2025-01-11 20:09:29 +08:00
|
|
|
|
calc toMatrixOrthonormal basis f i j
|
2025-01-11 20:06:58 +08:00
|
|
|
|
_ = ⟪(bW i' : E), f (bW j')⟫_𝕜 :=
|
|
|
|
|
hf (Equiv.finAddEquivSigmaCond_false hi) (Equiv.finAddEquivSigmaCond_false hj)
|
2025-01-10 01:37:14 +08:00
|
|
|
|
_ = ⟪bW i', g (bW j')⟫_𝕜 := by simp [g]
|
|
|
|
|
_ = toMatrixOrthonormal bW g i' j' := (g.toMatrixOrthonormal_apply_apply ..).symm
|
|
|
|
|
_ = 0 := hg (Nat.sub_lt_sub_right (Nat.le_of_not_lt hj) hji)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
haveI : Subsingleton E := not_nontrivial_iff_subsingleton.mp hE
|
|
|
|
|
{
|
|
|
|
|
dim := 0
|
|
|
|
|
hdim := Module.finrank_zero_of_subsingleton
|
|
|
|
|
basis := (Basis.empty E).toOrthonormalBasis ⟨nofun, nofun⟩
|
|
|
|
|
upperTriangular := nofun
|
|
|
|
|
}
|
|
|
|
|
termination_by Module.finrank 𝕜 E
|
|
|
|
|
decreasing_by exact
|
2025-01-11 20:09:29 +08:00
|
|
|
|
calc Module.finrank 𝕜 W
|
|
|
|
|
_ < m + Module.finrank 𝕜 W :=
|
|
|
|
|
suffices 0 < m from Nat.lt_add_of_pos_left this
|
|
|
|
|
Submodule.one_le_finrank_iff.mpr μ.property
|
2025-01-10 01:37:14 +08:00
|
|
|
|
_ = Module.finrank 𝕜 E := hdim
|
|
|
|
|
|
|
|
|
|
end LinearMap
|
|
|
|
|
|
|
|
|
|
namespace Matrix
|
|
|
|
|
/- IMPORTANT: existing `DecidableEq n` should take precedence over `LinearOrder.decidableEq`,
|
|
|
|
|
a.k.a., `instDecidableEq_mathlib`. -/
|
|
|
|
|
variable [RCLike 𝕜] [IsAlgClosed 𝕜] [Fintype n] [DecidableEq n] [LinearOrder n] (A : Matrix n n 𝕜)
|
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- **Don't use this definition directly.** Instead, use `Matrix.schurTriangulationBasis`,
|
|
|
|
|
`Matrix.schurTriangulationUnitary`, and `Matrix.schurTriangulation` for which this is their
|
|
|
|
|
simultaneous definition. This is `LinearMap.SchurTriangulationAux` adapted for matrices in the
|
|
|
|
|
Euclidean space. -/
|
2025-01-11 17:11:38 +00:00
|
|
|
|
noncomputable def schurTriangulationAux :
|
|
|
|
|
OrthonormalBasis n 𝕜 (EuclideanSpace 𝕜 n) × UpperTriangular n 𝕜 :=
|
2025-01-10 01:37:14 +08:00
|
|
|
|
let f := toEuclideanLin A
|
|
|
|
|
let ⟨d, hd, b, hut⟩ := LinearMap.SchurTriangulationAux.of f
|
|
|
|
|
let e : Fin d ≃o n := Fintype.orderIsoFinOfCardEq n (finrank_euclideanSpace.symm.trans hd)
|
|
|
|
|
let b' := b.reindex e
|
|
|
|
|
let B := LinearMap.toMatrixOrthonormal b' f
|
|
|
|
|
suffices B.IsUpperTriangular from ⟨b', B, this⟩
|
|
|
|
|
fun i j (hji : j < i) =>
|
2025-01-11 20:09:29 +08:00
|
|
|
|
calc LinearMap.toMatrixOrthonormal b' f i j
|
2025-01-11 17:11:38 +00:00
|
|
|
|
_ = LinearMap.toMatrixOrthonormal b f (e.symm i) (e.symm j) := by
|
|
|
|
|
rw [f.toMatrixOrthonormal_reindex]
|
|
|
|
|
rfl
|
2025-01-10 01:37:14 +08:00
|
|
|
|
_ = 0 := hut (e.symm.lt_iff_lt.mpr hji)
|
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- The change of basis that induces the upper triangular form `A.schurTriangulation` of a matrix
|
|
|
|
|
`A` over an algebraically closed field. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
noncomputable def schurTriangulationBasis : OrthonormalBasis n 𝕜 (EuclideanSpace 𝕜 n) :=
|
|
|
|
|
A.schurTriangulationAux.1
|
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- The unitary matrix that induces the upper triangular form `A.schurTriangulation` to which a
|
|
|
|
|
matrix `A` over an algebraically closed field is unitarily similar. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
noncomputable def schurTriangulationUnitary : unitaryGroup n 𝕜 where
|
|
|
|
|
val := (EuclideanSpace.basisFun n 𝕜).toBasis.toMatrix A.schurTriangulationBasis
|
|
|
|
|
property := OrthonormalBasis.toMatrix_orthonormalBasis_mem_unitary ..
|
|
|
|
|
|
2025-01-11 20:09:29 +08:00
|
|
|
|
/-- The upper triangular form induced by `A.schurTriangulationUnitary` to which a matrix `A` over an
|
|
|
|
|
algebraically closed field is unitarily similar. -/
|
2025-01-10 01:37:14 +08:00
|
|
|
|
noncomputable def schurTriangulation : UpperTriangular n 𝕜 :=
|
|
|
|
|
A.schurTriangulationAux.2
|
|
|
|
|
|
|
|
|
|
/-- **Schur triangulation**, **Schur decomposition** for matrices over an algebraically closed
|
|
|
|
|
field. In particular, a complex matrix can be converted to upper-triangular form by a change of
|
|
|
|
|
basis. In other words, any complex matrix is unitarily similar to an upper triangular matrix. -/
|
2025-01-11 17:11:38 +00:00
|
|
|
|
lemma schur_triangulation :
|
|
|
|
|
A = A.schurTriangulationUnitary * A.schurTriangulation * star A.schurTriangulationUnitary :=
|
2025-01-10 01:37:14 +08:00
|
|
|
|
let U := A.schurTriangulationUnitary
|
|
|
|
|
have h : U * A.schurTriangulation.val = A * U :=
|
|
|
|
|
let b := A.schurTriangulationBasis.toBasis
|
|
|
|
|
let c := (EuclideanSpace.basisFun n 𝕜).toBasis
|
2025-01-11 20:09:29 +08:00
|
|
|
|
calc c.toMatrix b * LinearMap.toMatrix b b (toEuclideanLin A)
|
2025-01-10 01:37:14 +08:00
|
|
|
|
_ = LinearMap.toMatrix c c (toEuclideanLin A) * c.toMatrix b := by simp
|
|
|
|
|
_ = LinearMap.toMatrix c c (toLin c c A) * U := rfl
|
|
|
|
|
_ = A * U := by simp
|
2025-01-11 20:09:29 +08:00
|
|
|
|
calc A
|
2025-01-10 01:37:14 +08:00
|
|
|
|
_ = A * U * star U := by simp [mul_assoc]
|
2025-01-11 17:11:38 +00:00
|
|
|
|
_ = U * A.schurTriangulation * star U := by rw [← h]
|
2025-01-10 01:37:14 +08:00
|
|
|
|
|
|
|
|
|
end Matrix
|