Skip to content

Commit c0ee2a9

Browse files
feat(Analysis/InnerProductSpace): transfer lemmas about charpoly/eigenvalues from matrix to linear map (#37325)
These are some lemmas existing for matrix but missing for linear map. Co-authored-by: Aristotle (Harmonic) <aristotle-harmonic@harmonic.fun>
1 parent 1c98d2c commit c0ee2a9

3 files changed

Lines changed: 64 additions & 7 deletions

File tree

Mathlib/Analysis/InnerProductSpace/Spectrum.lean

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module
88
public import Mathlib.Analysis.InnerProductSpace.Rayleigh
99
public import Mathlib.Analysis.Normed.Group.Submodule
1010
public import Mathlib.Analysis.Normed.Operator.FredholmAlternative
11+
public import Mathlib.LinearAlgebra.Eigenspace.Charpoly
1112
public import Mathlib.LinearAlgebra.Eigenspace.ContinuousLinearMap
1213
public import Mathlib.LinearAlgebra.Eigenspace.Minpoly
1314
public import Mathlib.Data.Fin.Tuple.Sort
@@ -343,6 +344,53 @@ theorem eigenvectorBasis_apply_self_apply (hT : T.IsSymmetric) (hn : Module.finr
343344
intro a
344345
rw [smul_smul, mul_comm, ofLp_toLp]
345346

347+
theorem toMatrix_eigenvectorBasis (hT : T.IsSymmetric) (hn : Module.finrank 𝕜 E = n) :
348+
letI b := (hT.eigenvectorBasis hn).toBasis
349+
T.toMatrix b b = Matrix.diagonal (RCLike.ofReal ∘ hT.eigenvalues hn) := by
350+
ext i j
351+
simp [toMatrix_apply, Matrix.diagonal_apply, RCLike.real_smul_eq_coe_mul]
352+
grind
353+
354+
open Polynomial in
355+
theorem charpoly_eq (hT : T.IsSymmetric) (hn : Module.finrank 𝕜 E = n) :
356+
T.charpoly = ∏ i, (X - C (hT.eigenvalues hn i : 𝕜)) := by
357+
simp [← T.charpoly_toMatrix (hT.eigenvectorBasis hn).toBasis, toMatrix_eigenvectorBasis,
358+
Matrix.charpoly_diagonal]
359+
360+
theorem roots_charpoly_eq_eigenvalues (hT : T.IsSymmetric) (hn : Module.finrank 𝕜 E = n) :
361+
T.charpoly.roots = Multiset.map (RCLike.ofReal ∘ hT.eigenvalues hn) Finset.univ.val := by
362+
rw [← charpoly_toMatrix _ (hT.eigenvectorBasis hn).toBasis, toMatrix_eigenvectorBasis,
363+
Matrix.charpoly_diagonal, Polynomial.roots_prod _ _ (by
364+
simp [Finset.prod_ne_zero_iff, Polynomial.X_sub_C_ne_zero])]
365+
simp
366+
367+
theorem sort_roots_charpoly_eq_eigenvalues (hT : T.IsSymmetric) (hn : Module.finrank 𝕜 E = n) :
368+
(T.charpoly.roots.map RCLike.re).sort (· ≥ ·) = List.ofFn (hT.eigenvalues hn) := by
369+
simp_rw [hT.roots_charpoly_eq_eigenvalues, Fin.univ_val_map, Multiset.map_coe, List.map_ofFn,
370+
Function.comp_def, RCLike.ofReal_re, Multiset.coe_sort]
371+
have := hn.symm
372+
convert List.mergeSort_of_pairwise ?_
373+
simp_rw [decide_eq_true_eq, ← List.sortedGE_iff_pairwise]
374+
convert (hT.eigenvalues_antitone hn).sortedGE_ofFn
375+
376+
theorem eigenvalues_eq_eigenvalues_iff {E' : Type*} [NormedAddCommGroup E'] [InnerProductSpace 𝕜 E']
377+
[FiniteDimensional 𝕜 E'] {T' : E' →ₗ[𝕜] E'} (hT : T.IsSymmetric) (hn : Module.finrank 𝕜 E = n)
378+
(hT' : T'.IsSymmetric) (hn' : Module.finrank 𝕜 E' = n) :
379+
hT.eigenvalues hn = hT'.eigenvalues hn' ↔ T.charpoly = T'.charpoly where
380+
mp h := by rw [hT.charpoly_eq hn, hT'.charpoly_eq hn', h]
381+
mpr h := by
382+
rw [← List.ofFn_inj, ← sort_roots_charpoly_eq_eigenvalues, ← sort_roots_charpoly_eq_eigenvalues,
383+
h]
384+
385+
theorem splits_charpoly (hT : T.IsSymmetric) : T.charpoly.Splits := by
386+
refine Polynomial.splits_iff_card_roots.mpr ?_
387+
simp [hT.roots_charpoly_eq_eigenvalues rfl, LinearMap.charpoly_natDegree]
388+
389+
theorem det_eq_prod_eigenvalues (hT : T.IsSymmetric) (hn : Module.finrank 𝕜 E = n) :
390+
T.det = ∏ i, (hT.eigenvalues hn i : 𝕜) := by
391+
simp [det_eq_prod_roots_charpoly_of_splits hT.splits_charpoly,
392+
hT.roots_charpoly_eq_eigenvalues hn, List.prod_ofFn]
393+
346394
end Version2
347395

348396
end IsSymmetric

Mathlib/Analysis/InnerProductSpace/Trace.lean

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module
77

88
public import Mathlib.Analysis.InnerProductSpace.PiL2
99
public import Mathlib.Analysis.InnerProductSpace.Spectrum
10-
public import Mathlib.LinearAlgebra.Trace
10+
public import Mathlib.LinearAlgebra.Eigenspace.Charpoly
1111

1212
/-!
1313
# Traces in inner product spaces
@@ -38,12 +38,8 @@ variable {n : ℕ} (hn : Module.finrank 𝕜 E = n)
3838

3939
lemma IsSymmetric.trace_eq_sum_eigenvalues {T : E →ₗ[𝕜] E} (hT : T.IsSymmetric) :
4040
T.trace 𝕜 E = ∑ i, hT.eigenvalues hn i := by
41-
let b := hT.eigenvectorBasis hn
42-
rw [T.trace_eq_sum_inner b, RCLike.ofReal_sum]
43-
apply Fintype.sum_congr
44-
intro i
45-
rw [hT.apply_eigenvectorBasis, inner_smul_real_right, inner_self_eq_norm_sq_to_K, b.norm_eq_one]
46-
simp [RCLike.ofReal_alg]
41+
simp [Module.End.trace_eq_sum_roots_charpoly_of_splits hT.splits_charpoly,
42+
hT.roots_charpoly_eq_eigenvalues hn, List.sum_ofFn]
4743

4844
lemma IsSymmetric.re_trace_eq_sum_eigenvalues {T : E →ₗ[𝕜] E} (hT : T.IsSymmetric) :
4945
RCLike.re (T.trace 𝕜 E) = ∑ i, hT.eigenvalues hn i := by

Mathlib/LinearAlgebra/Eigenspace/Charpoly.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ module
88
public import Mathlib.LinearAlgebra.Charpoly.BaseChange
99
public import Mathlib.LinearAlgebra.Charpoly.ToMatrix
1010
public import Mathlib.LinearAlgebra.Eigenspace.Basic
11+
public import Mathlib.LinearAlgebra.Trace
12+
import Mathlib.LinearAlgebra.Matrix.Charpoly.Eigs
1113

1214
/-!
1315
# Eigenvalues are the roots of the characteristic polynomial.
@@ -44,6 +46,17 @@ lemma mem_spectrum_iff_isRoot_charpoly (f : End K V) (μ : K) :
4446
μ ∈ spectrum K f ↔ f.charpoly.IsRoot μ := by
4547
rw [← hasEigenvalue_iff_mem_spectrum, hasEigenvalue_iff_isRoot_charpoly]
4648

49+
lemma det_eq_prod_roots_charpoly_of_splits {f : End K V} (h : f.charpoly.Splits) :
50+
f.det = f.charpoly.roots.prod := by
51+
rw [← det_toMatrix (Module.Free.chooseBasis K V),
52+
Matrix.det_eq_prod_roots_charpoly_of_splits (by simpa using h), charpoly_toMatrix]
53+
54+
lemma trace_eq_sum_roots_charpoly_of_splits {f : End K V} (h : f.charpoly.Splits) :
55+
f.trace K V = f.charpoly.roots.sum := by
56+
let b := Module.Free.chooseBasis K V
57+
rw [trace_eq_matrix_trace K (Module.Free.chooseBasis K V),
58+
Matrix.trace_eq_sum_roots_charpoly_of_splits (by simpa using h), charpoly_toMatrix]
59+
4760
end End
4861

4962
end Module

0 commit comments

Comments
 (0)