Skip to content

Commit 5f779be

Browse files
committed
feat(LinearAlgebra/Matrix): charpoly splits into IsHermitian.eigenvalues (#29476)
Co-authored-by: @Aristotle-Harmonic
1 parent bdca5a5 commit 5f779be

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,5 +146,11 @@ lemma cfc_eq (f : ℝ → ℝ) : cfc f A = hA.cfc f := by
146146
simp only [cfcAux_apply, ContinuousMap.coe_mk, Function.comp_def, Set.restrict_apply,
147147
IsHermitian.cfc]
148148

149+
open Polynomial in
150+
lemma charpoly_cfc_eq (f : ℝ → ℝ) :
151+
(cfc f A).charpoly = ∏ i, (X - C (f (hA.eigenvalues i) : 𝕜)) := by
152+
rw [cfc_eq hA f, IsHermitian.cfc, charpoly_mul_comm, ← mul_assoc]
153+
simp [charpoly_diagonal]
154+
149155
end IsHermitian
150156
end Matrix

Mathlib/LinearAlgebra/Matrix/Spectrum.lean

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Authors: Alexander Bentkamp
55
-/
66
import Mathlib.Analysis.InnerProductSpace.Spectrum
77
import Mathlib.LinearAlgebra.Eigenspace.Matrix
8+
import Mathlib.LinearAlgebra.Matrix.Charpoly.Eigs
89
import Mathlib.LinearAlgebra.Matrix.Diagonal
910
import Mathlib.LinearAlgebra.Matrix.Hermitian
1011
import Mathlib.LinearAlgebra.Matrix.Rank
@@ -22,7 +23,7 @@ spectral theorem, diagonalization theorem -/
2223
namespace Matrix
2324

2425
variable {𝕜 : Type*} [RCLike 𝕜] {n : Type*} [Fintype n]
25-
variable {A : Matrix n n 𝕜}
26+
variable {A B : Matrix n n 𝕜}
2627

2728
lemma finite_real_spectrum [DecidableEq n] : (spectrum ℝ A).Finite := by
2829
rw [← spectrum.preimage_algebraMap 𝕜]
@@ -42,13 +43,16 @@ namespace IsHermitian
4243
section DecidableEq
4344

4445
variable [DecidableEq n]
45-
variable (hA : A.IsHermitian)
46+
variable (hA : A.IsHermitian) (hB : B.IsHermitian)
4647

4748
/-- The eigenvalues of a Hermitian matrix, indexed by `Fin (Fintype.card n)` where `n` is the index
4849
type of the matrix. -/
4950
noncomputable def eigenvalues₀ : Fin (Fintype.card n) → ℝ :=
5051
(isHermitian_iff_isSymmetric.1 hA).eigenvalues finrank_euclideanSpace
5152

53+
lemma eigenvalues₀_antitone : Antitone hA.eigenvalues₀ :=
54+
LinearMap.IsSymmetric.eigenvalues_antitone ..
55+
5256
/-- The eigenvalues of a Hermitian matrix, reusing the index `n` of the matrix entries. -/
5357
noncomputable def eigenvalues : n → ℝ := fun i =>
5458
hA.eigenvalues₀ <| (Fintype.equivOfCardEq (Fintype.card_fin _)).symm i
@@ -141,11 +145,43 @@ theorem eigenvalues_eq (i : n) :
141145
inner_self_eq_norm_sq_to_K, RCLike.smul_re, hA.eigenvectorBasis.orthonormal.1 i,
142146
mul_one, algebraMap.coe_one, one_pow, RCLike.one_re]
143147

148+
open Polynomial in
149+
lemma charpoly_eq : A.charpoly = ∏ i, (X - C (hA.eigenvalues i : 𝕜)) := by
150+
conv_lhs => rw [hA.spectral_theorem, charpoly_mul_comm, ← mul_assoc]
151+
simp [charpoly_diagonal]
152+
153+
lemma roots_charpoly_eq_eigenvalues :
154+
A.charpoly.roots = Multiset.map (RCLike.ofReal ∘ hA.eigenvalues) Finset.univ.val := by
155+
rw [hA.charpoly_eq, Polynomial.roots_prod]
156+
· simp
157+
· simp [Finset.prod_ne_zero_iff, Polynomial.X_sub_C_ne_zero]
158+
159+
lemma roots_charpoly_eq_eigenvalues₀ :
160+
A.charpoly.roots = Multiset.map (RCLike.ofReal ∘ hA.eigenvalues₀) Finset.univ.val := by
161+
rw [hA.roots_charpoly_eq_eigenvalues]
162+
simp only [← Multiset.map_map, eigenvalues, ← Function.comp_apply (f := hA.eigenvalues₀)]
163+
simp
164+
165+
lemma sort_roots_charpoly_eq_eigenvalues₀ :
166+
(A.charpoly.roots.map RCLike.re).sort (· ≥ ·) = List.ofFn hA.eigenvalues₀ := by
167+
simp_rw [hA.roots_charpoly_eq_eigenvalues₀, Fin.univ_val_map, Multiset.map_coe, List.map_ofFn,
168+
Function.comp_def, RCLike.ofReal_re, Multiset.coe_sort]
169+
rw [List.mergeSort_of_sorted]
170+
simpa [List.Sorted] using (eigenvalues₀_antitone hA).ofFn_sorted
171+
172+
lemma eigenvalues_eq_eigenvalues_iff :
173+
hA.eigenvalues = hB.eigenvalues ↔ A.charpoly = B.charpoly := by
174+
constructor <;> intro h
175+
· rw [hA.charpoly_eq, hB.charpoly_eq, h]
176+
· suffices hA.eigenvalues₀ = hB.eigenvalues₀ by unfold eigenvalues; rw [this]
177+
simp_rw [← List.ofFn_inj, ← sort_roots_charpoly_eq_eigenvalues₀, h]
178+
179+
theorem splits_charpoly (hA : A.IsHermitian) : A.charpoly.Splits (RingHom.id 𝕜) :=
180+
Polynomial.splits_iff_card_roots.mpr (by simp [hA.roots_charpoly_eq_eigenvalues])
181+
144182
/-- The determinant of a Hermitian matrix is the product of its eigenvalues. -/
145183
theorem det_eq_prod_eigenvalues : det A = ∏ i, (hA.eigenvalues i : 𝕜) := by
146-
convert congr_arg det hA.spectral_theorem
147-
rw [det_mul_right_comm]
148-
simp
184+
simp [det_eq_prod_roots_charpoly_of_splits hA.splits_charpoly, hA.roots_charpoly_eq_eigenvalues]
149185

150186
/-- rank of a Hermitian matrix is the rank of after diagonalization by the eigenvector unitary -/
151187
lemma rank_eq_rank_diagonal : A.rank = (Matrix.diagonal hA.eigenvalues).rank := by
@@ -195,8 +231,7 @@ lemma exists_eigenvector_of_ne_zero (hA : IsHermitian A) (h_ne : A ≠ 0) :
195231

196232
theorem trace_eq_sum_eigenvalues [DecidableEq n] (hA : A.IsHermitian) :
197233
A.trace = ∑ i, (hA.eigenvalues i : 𝕜) := by
198-
conv_lhs => rw [hA.spectral_theorem, trace_mul_cycle]
199-
simp
234+
simp [trace_eq_sum_roots_charpoly_of_splits hA.splits_charpoly, hA.roots_charpoly_eq_eigenvalues]
200235

201236
end IsHermitian
202237

0 commit comments

Comments
 (0)