Skip to content

Commit ad68026

Browse files
committed
feat(Analysis/InnerProductSpace): generalized determinant of a rectangle matrix / linear map
1 parent c0ee2a9 commit ad68026

4 files changed

Lines changed: 408 additions & 0 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1952,6 +1952,7 @@ public import Mathlib.Analysis.InnerProductSpace.LinearMap
19521952
public import Mathlib.Analysis.InnerProductSpace.LinearPMap
19531953
public import Mathlib.Analysis.InnerProductSpace.MeanErgodic
19541954
public import Mathlib.Analysis.InnerProductSpace.MulOpposite
1955+
public import Mathlib.Analysis.InnerProductSpace.NormDet
19551956
public import Mathlib.Analysis.InnerProductSpace.NormPow
19561957
public import Mathlib.Analysis.InnerProductSpace.OfNorm
19571958
public import Mathlib.Analysis.InnerProductSpace.Orientation

Mathlib/Analysis/InnerProductSpace/GramMatrix.lean

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module
88
public import Mathlib.Analysis.InnerProductSpace.Basic
99
public import Mathlib.Analysis.InnerProductSpace.PiL2
1010
public import Mathlib.LinearAlgebra.Matrix.PosDef
11+
import Mathlib.Analysis.Matrix.Order
1112

1213
/-! # Gram Matrices
1314
@@ -95,6 +96,12 @@ theorem linearIndependent_of_posDef_gram {v : n → E} (h_gram : PosDef (gram
9596
have := h_gram.dotProduct_mulVec_pos (x := y)
9697
simp_all [star_dotProduct_gram_mulVec]
9798

99+
omit [Finite n] in
100+
theorem linearIndependent_of_det_gram_ne_zero [Fintype n] [DecidableEq n] {v : n → E}
101+
(h : (gram 𝕜 v).det ≠ 0) : LinearIndependent 𝕜 v := by
102+
apply linearIndependent_of_posDef_gram
103+
simpa [(Matrix.posSemidef_gram _ _).posDef_iff_isUnit, Matrix.isUnit_iff_isUnit_det] using h
104+
98105
end SemiInnerProductSpace
99106

100107
section NormedInnerProductSpace
Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
/-
2+
Copyright (c) 2026 Weiyi Wang. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Weiyi Wang
5+
-/
6+
module
7+
8+
public import Mathlib.Analysis.InnerProductSpace.Adjoint
9+
public import Mathlib.Analysis.InnerProductSpace.GramMatrix
10+
public import Mathlib.Analysis.InnerProductSpace.SingularValues
11+
12+
/-!
13+
# Normed determinant of a linear map
14+
15+
Given a rectangular matrix $T$, it is common to talk about $\sqrt{det(T^{H}T)}$, where $T^{H}$ is
16+
the conjugate transpose of $T$, as a generalization to the determinant of a square matrix. It is the
17+
$m$-dimensional volume factor for $\mathbb{R}^m \to \mathbb{R}^n$. It is given various names in
18+
literature:
19+
* "Jacobian" (definition 3.4 of [lawrenceronald2025]), in the context of volume factor
20+
for non-linear map. However, we choose to reserve this name for the matrix consists of
21+
derivatives.
22+
* "Gram determinant", which is already used by `Matrix.gram`, and it is often referring to the
23+
$det(T^{H}T)$ without the square root.
24+
* "Nonnegative determinant" (definition 1 of [haruoyoshiohidetoki2006]).
25+
26+
Without a standardized name, we give a descriptive name `LinearMap.normDet` to reflect its
27+
definition and show that it is a generalization of `‖(f : LinearMap 𝕜 U U).det‖`
28+
(See `LinearMap.normDet_eq_norm_det`). We also construct this on linear maps between inner product
29+
spaces instead of matrices, and allow the codomain to have infinite dimension.
30+
31+
## Main definition
32+
* `LinearMap.normDet` : the norm determinant of a linear map.
33+
34+
## Main result
35+
* `ContinuousLinearMap.normDet_sq` and `LinearMap.normDet_sq`: The square of `f.normDet`
36+
equals to the determinant of `f.adjoint ∘ₗ f`.
37+
* `LinearMap.normDet_sq_eq_det_gram`: The square of `LinearMap.normDet` equals to the determinant of
38+
the gram matrix formed by vectors mapped from an orthonormal basis.
39+
* `LinearMap.normDet_eq_prod_singularValues`: `LinearMap.normDet` equals to the product of singular
40+
values.
41+
42+
-/
43+
44+
public section
45+
46+
open Module
47+
48+
namespace LinearMap
49+
50+
variable {𝕜 U V W : Type*} [RCLike 𝕜] [NormedAddCommGroup U] [InnerProductSpace 𝕜 U]
51+
[FiniteDimensional 𝕜 U] [NormedAddCommGroup V] [InnerProductSpace 𝕜 V] [NormedAddCommGroup W]
52+
[InnerProductSpace 𝕜 W]
53+
54+
open Classical in
55+
/--
56+
The norm determinant of a linear map `f : U →ₗ[𝕜] V` is defined as the norm of the determinant of
57+
the square matrix from `U →ₗ[𝕜] f.range` using a pair of orthonormal basis of equal dimensions.
58+
(See `LinearMap.normDet_eq` for using arbitrary orthonormal basis)
59+
60+
If such basis doesn't exist (i.e. the map is not injective), the norm determinant is zero.
61+
(See `LinearMap.normDet_eq_zero_iff_ker_ne_bot`)
62+
-/
63+
noncomputable def normDet (f : U →ₗ[𝕜] V) : ℝ :=
64+
if h : Nonempty (OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range) then
65+
‖(f.rangeRestrict.toMatrix (stdOrthonormalBasis 𝕜 U).toBasis h.some.toBasis).det‖
66+
else
67+
0
68+
69+
theorem normDet_nonneg (f : U →ₗ[𝕜] V) : 0 ≤ f.normDet := by
70+
unfold normDet
71+
split <;> simp
72+
73+
/--
74+
`LinearMap.normDet` is well-defined under any pair of orthonormal basis.
75+
-/
76+
theorem normDet_eq {ι : Type*} [Fintype ι] [DecidableEq ι] (f : U →ₗ[𝕜] V)
77+
(bu : OrthonormalBasis ι 𝕜 U) (bv : OrthonormalBasis ι 𝕜 f.range) :
78+
f.normDet = ‖(f.rangeRestrict.toMatrix bu.toBasis bv.toBasis).det‖ := by
79+
have hrank : finrank 𝕜 U = finrank 𝕜 f.range := by
80+
rw [finrank_eq_nat_card_basis bu.toBasis, finrank_eq_nat_card_basis bv.toBasis]
81+
have h : Nonempty (OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range) := by
82+
rw [hrank]
83+
exact ⟨stdOrthonormalBasis 𝕜 f.range⟩
84+
simp only [normDet, h, ↓reduceDIte]
85+
rw [← basis_toMatrix_mul_linearMap_toMatrix_mul_basis_toMatrix (stdOrthonormalBasis 𝕜 U).toBasis
86+
bu.toBasis h.some.toBasis bv.toBasis]
87+
have h1 : bu.toBasis.toMatrix (stdOrthonormalBasis 𝕜 U).toBasis *
88+
(stdOrthonormalBasis 𝕜 U).toBasis.toMatrix bu.toBasis = 1 :=
89+
Basis.toMatrix_mul_toMatrix_flip _ _
90+
have h2 : (stdOrthonormalBasis 𝕜 U).toBasis.toMatrix bu.toBasis *
91+
bu.toBasis.toMatrix (stdOrthonormalBasis 𝕜 U).toBasis = 1 :=
92+
Basis.toMatrix_mul_toMatrix_flip _ _
93+
rw [← Matrix.det_comm' h1 h2, ← Matrix.mul_assoc, Matrix.det_mul, norm_mul]
94+
suffices ‖(bu.toBasis.toMatrix (stdOrthonormalBasis 𝕜 U).toBasis *
95+
h.some.toBasis.toMatrix ⇑bv.toBasis).det‖ = 1 by
96+
rw [this]
97+
simp
98+
apply CStarRing.norm_of_mem_unitary
99+
apply Matrix.det_of_mem_unitary
100+
rw [Matrix.mem_unitaryGroup_iff, Matrix.star_eq_conjTranspose, Matrix.conjTranspose_mul,
101+
← Matrix.mul_assoc, Matrix.mul_assoc (bu.toBasis.toMatrix (stdOrthonormalBasis 𝕜 U).toBasis)]
102+
simp
103+
104+
/--
105+
`LinearMap.normDet` vanishes iff the map is not injective.
106+
-/
107+
theorem normDet_eq_zero_iff_ker_ne_bot {f : U →ₗ[𝕜] V} :
108+
f.normDet = 0 ↔ f.ker ≠ ⊥ where
109+
mp h := by
110+
contrapose! h
111+
let g : U ≃ₗ[𝕜] f.range := LinearEquiv.ofBijective f.rangeRestrict
112+
by simpa using ker_eq_bot.mp h, f.surjective_rangeRestrict⟩
113+
let bu := stdOrthonormalBasis 𝕜 U
114+
let bv := g.finrank_eq.symm ▸ stdOrthonormalBasis 𝕜 f.range
115+
rw [f.normDet_eq bu bv, norm_eq_zero.ne]
116+
suffices (f.rangeRestrict.adjoint.toMatrix bv.toBasis bu.toBasis).det *
117+
(f.rangeRestrict.toMatrix bu.toBasis bv.toBasis).det ≠ 0 by
118+
simpa [toMatrix_adjoint, Matrix.det_conjTranspose] using this
119+
simpa [← Matrix.det_mul, ← LinearMap.toMatrix_comp, det_eq_zero_iff_ker_ne_bot,
120+
LinearMap.ker_adjoint_comp_self] using h
121+
mpr h := by
122+
suffices ¬ Nonempty (OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range) by
123+
simp [normDet, this]
124+
contrapose! h
125+
obtain ⟨b⟩ := h
126+
have hrank : finrank 𝕜 f.range = finrank 𝕜 U := by
127+
simpa using finrank_eq_card_basis b.toBasis
128+
simpa [hrank] using f.finrank_range_add_finrank_ker
129+
130+
/--
131+
`LinearMap.normDet` equals to the norm of `LinearMap.det` for an endomorphism.
132+
-/
133+
theorem normDet_eq_norm_det (f : U →ₗ[𝕜] U) : f.normDet = ‖f.det‖ := by
134+
by_cases h : f.range = ⊤
135+
· let bv : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range :=
136+
(stdOrthonormalBasis 𝕜 U).map (LinearIsometryEquiv.ofTop U _ h).symm
137+
rw [normDet_eq f (stdOrthonormalBasis 𝕜 U) bv]
138+
simp [bv, toMatrix_map_right]
139+
· have hb : ¬ Nonempty (OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range) := by
140+
contrapose! h
141+
obtain ⟨b⟩ := h
142+
apply Submodule.eq_top_of_finrank_eq
143+
conv_lhs => rw [finrank_eq_nat_card_basis b.toBasis]
144+
conv_rhs => rw [finrank_eq_nat_card_basis (stdOrthonormalBasis 𝕜 U).toBasis]
145+
suffices f.det = 0 by
146+
simp [this, normDet, hb]
147+
simpa [det_eq_zero_iff_ker_ne_bot] using ker_eq_bot_iff_range_eq_top.not.mpr h
148+
149+
/--
150+
`LinearMap.normDet` of a linear isometry is 1.
151+
-/
152+
theorem _root_.LinearIsometry.normDet_eq_one (f : U →ₗᵢ[𝕜] V) : f.toLinearMap.normDet = 1 := by
153+
have hrank : finrank 𝕜 U = finrank 𝕜 f.range :=
154+
f.equivRange.toLinearEquiv.finrank_eq
155+
let b := (stdOrthonormalBasis 𝕜 f.toLinearMap.range)
156+
rw [← hrank] at b
157+
rw [normDet_eq _ (stdOrthonormalBasis 𝕜 U) b]
158+
apply CStarRing.norm_of_mem_unitary
159+
exact Matrix.det_of_mem_unitary <| (f.equivRange).toMatrix_mem_unitaryGroup _ _
160+
161+
@[simp]
162+
theorem normDet_id : (id : U →ₗ[𝕜] U).normDet = 1 :=
163+
LinearIsometry.id.normDet_eq_one
164+
165+
@[simp]
166+
theorem normDet_subtype (p : Submodule 𝕜 U) : p.subtype.normDet = 1 :=
167+
p.subtypeₗᵢ.normDet_eq_one
168+
169+
@[simp]
170+
theorem normDet_of_subsingleton [Subsingleton U] (f : U →ₗ[𝕜] V) : f.normDet = 1 := by
171+
have h : finrank 𝕜 U = 0 := finrank_zero_iff.mpr ‹_›
172+
have hf : finrank 𝕜 f.range = 0 := by
173+
apply Nat.eq_zero_of_le_zero
174+
rw [← h]
175+
apply LinearMap.finrank_range_le
176+
let bu : OrthonormalBasis (Fin 0) 𝕜 U := (stdOrthonormalBasis 𝕜 U).reindex (by rw [h])
177+
let bv : OrthonormalBasis (Fin 0) 𝕜 f.range :=
178+
(stdOrthonormalBasis 𝕜 f.range).reindex (by rw [hf])
179+
rw [normDet_eq _ bu bv]
180+
simp
181+
182+
@[simp]
183+
theorem normDet_zero : (0 : U →ₗ[𝕜] V).normDet = 0 ^ finrank 𝕜 U := by
184+
nontriviality U
185+
simp [zero_pow finrank_pos.ne.symm, normDet_eq_zero_iff_ker_ne_bot]
186+
187+
@[simp]
188+
theorem normDet_smul (f : U →ₗ[𝕜] V) (c : 𝕜) :
189+
(c • f).normDet = ‖c‖ ^ finrank 𝕜 U * f.normDet := by
190+
by_cases hc : c = 0
191+
· nontriviality U
192+
simp [hc, zero_pow finrank_pos.ne.symm]
193+
by_cases h : f.ker = ⊥
194+
· have hrank : finrank 𝕜 f.range = finrank 𝕜 U := by
195+
obtain hrank := f.finrank_range_add_finrank_ker
196+
rw [h] at hrank
197+
simpa [h] using hrank
198+
let bu : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 U := stdOrthonormalBasis 𝕜 U
199+
let bv : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range :=
200+
(stdOrthonormalBasis 𝕜 f.range).reindex (by rw [hrank])
201+
let bv' : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 (c • f).range := bv.map
202+
(LinearIsometryEquiv.ofEq _ _ (LinearMap.range_smul _ _ hc).symm)
203+
rw [f.normDet_eq bu bv, (c • f).normDet_eq bu bv', ← norm_pow, ← norm_mul]
204+
have : finrank 𝕜 U = Fintype.card (Fin (finrank 𝕜 U)) := by simp
205+
conv in c ^ finrank 𝕜 U => rw [this]
206+
rw [← Matrix.det_smul, ← map_smul]
207+
rfl
208+
· have h' : (c • f).ker ≠ ⊥ := by simpa [f.ker_smul _ hc] using h
209+
simp [normDet_eq_zero_iff_ker_ne_bot.mpr h, normDet_eq_zero_iff_ker_ne_bot.mpr h']
210+
211+
@[simp]
212+
theorem normDet_neg (f : U →ₗ[𝕜] V) : (-f).normDet = f.normDet := by
213+
simpa using f.normDet_smul (-1)
214+
215+
set_option backward.isDefEq.respectTransparency false in
216+
/--
217+
The square of `f.normDet` equals to the determinant of `f.adjoint ∘L f`.
218+
-/
219+
theorem _root_.ContinuousLinearMap.normDet_sq [CompleteSpace V] (f : U →L[𝕜] V) :
220+
haveI : CompleteSpace U := FiniteDimensional.complete 𝕜 U
221+
↑(f.normDet ^ 2) = (f.adjoint ∘L f).det := by
222+
have : CompleteSpace U := FiniteDimensional.complete 𝕜 U
223+
have : CompleteSpace f.range := FiniteDimensional.complete 𝕜 f.range
224+
let bu := stdOrthonormalBasis 𝕜 U
225+
classical
226+
by_cases hrank : finrank 𝕜 U = finrank 𝕜 f.range
227+
· let b : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range :=
228+
(stdOrthonormalBasis 𝕜 f.range).reindex (by
229+
rw [← hrank, finrank_eq_card_basis bu.toBasis])
230+
have hf : f = f.range.subtypeₗᵢ.toContinuousLinearMap ∘L f.rangeRestrict := rfl
231+
conv_rhs => rw [hf]
232+
rw [ContinuousLinearMap.adjoint_comp, ← ContinuousLinearMap.comp_assoc,
233+
ContinuousLinearMap.comp_assoc (ContinuousLinearMap.adjoint _)]
234+
suffices f.range.subtypeₗᵢ.toContinuousLinearMap.adjoint ∘L
235+
f.range.subtypeₗᵢ.toContinuousLinearMap = ContinuousLinearMap.id 𝕜 _ by
236+
rw [this, ContinuousLinearMap.comp_id, ContinuousLinearMap.det, ContinuousLinearMap.coe_comp,
237+
← det_toMatrix bu.toBasis, toMatrix_comp bu.toBasis b.toBasis bu.toBasis]
238+
rw [show (ContinuousLinearMap.adjoint f.rangeRestrict).toLinearMap =
239+
f.rangeRestrict.toLinearMap.adjoint by rfl]
240+
rw [toMatrix_adjoint]
241+
simp [f.toLinearMap.normDet_eq bu b, RCLike.conj_mul]
242+
exact f.range.subtypeₗᵢ.adjoint_comp_self
243+
· have hb : ¬ Nonempty (OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range) := by
244+
contrapose! hrank with h
245+
obtain ⟨bv⟩ := h
246+
rw [finrank_eq_card_basis bu.toBasis, finrank_eq_card_basis bv.toBasis]
247+
trans 0
248+
· simp [normDet, hb]
249+
symm
250+
rw [det_eq_zero_iff_ker_ne_bot, ContinuousLinearMap.ker_adjoint_comp_self]
251+
contrapose! hrank
252+
exact (finrank_range_of_inj <| ker_eq_bot.mp hrank).symm
253+
254+
/--
255+
The square of `f.normDet` equals to the determinant of `f.adjoint ∘ₗ f` when the codomain is finite
256+
dimensional.
257+
-/
258+
theorem normDet_sq [FiniteDimensional 𝕜 V] (f : U →ₗ[𝕜] V) :
259+
↑(f.normDet ^ 2) = (f.adjoint ∘ₗ f).det := by
260+
have : CompleteSpace V := FiniteDimensional.complete 𝕜 V
261+
exact f.toContinuousLinearMap.normDet_sq
262+
263+
/--
264+
The square of `f.normDet` equals to the determinant of the gram matrix formed by vectors mapped from
265+
an orthonormal basis.
266+
-/
267+
theorem normDet_sq_eq_det_gram {ι : Type*} [Fintype ι] [DecidableEq ι] (f : U →ₗ[𝕜] V)
268+
(b : OrthonormalBasis ι 𝕜 U) :
269+
↑(f.normDet ^ 2) = (Matrix.gram 𝕜 (f <| b ·)).det := by
270+
suffices ↑(f.normDet ^ 2) = (Matrix.gram 𝕜 (f.rangeRestrict <| b ·)).det by
271+
simpa
272+
by_cases hrank : finrank 𝕜 U = finrank 𝕜 f.range
273+
· let bv : OrthonormalBasis ι 𝕜 f.range := (stdOrthonormalBasis 𝕜 f.range).reindex
274+
(Fintype.equivFinOfCardEq (by rw [← finrank_eq_card_basis b.toBasis, hrank])).symm
275+
rw [Matrix.gram_eq_conjTranspose_mul bv, Matrix.det_mul, Matrix.det_conjTranspose]
276+
rw [RCLike.star_def, RCLike.conj_mul, f.normDet_eq b bv]
277+
simp only [map_pow]
278+
congr
279+
ext i j
280+
simp [LinearMap.toMatrix_apply]
281+
· have hb : ¬ Nonempty (OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range) := by
282+
contrapose! hrank with h
283+
obtain ⟨bv⟩ := h
284+
simp [finrank_eq_card_basis bv.toBasis]
285+
symm
286+
suffices (Matrix.gram 𝕜 (f.rangeRestrict <| b ·)).det = 0 by
287+
simpa [normDet, hb]
288+
contrapose! hrank with h0
289+
obtain hindep := Matrix.linearIndependent_of_det_gram_ne_zero h0
290+
apply le_antisymm ?_ (finrank_range_le f)
291+
rw [finrank_eq_card_basis b.toBasis]
292+
exact hindep.fintype_card_le_finrank
293+
294+
theorem normDet_comp (f : U →ₗ[𝕜] V) (g : V →ₗ[𝕜] W) :
295+
(g ∘ₗ f).normDet = (g.domRestrict f.range).normDet * f.normDet := by
296+
by_cases hrank : finrank 𝕜 U = finrank 𝕜 f.range
297+
· let bu : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 U := stdOrthonormalBasis 𝕜 U
298+
let bv : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 f.range :=
299+
(stdOrthonormalBasis 𝕜 f.range).reindex (by
300+
rw [← hrank, finrank_eq_card_basis bu.toBasis])
301+
by_cases hrank' : finrank 𝕜 U = finrank 𝕜 (g ∘ₗ f).range
302+
· let bw : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 (g ∘ₗ f).range :=
303+
(stdOrthonormalBasis 𝕜 (g ∘ₗ f).range).reindex (by
304+
rw [← hrank', finrank_eq_card_basis bu.toBasis])
305+
let bw' : OrthonormalBasis (Fin (finrank 𝕜 U)) 𝕜 (g.domRestrict f.range).range :=
306+
bw.map (LinearIsometryEquiv.ofEq _ _ (by simp [LinearMap.range_comp]))
307+
rw [(g ∘ₗ f).normDet_eq bu bw, f.normDet_eq bu bv, (g.domRestrict f.range).normDet_eq bv bw']
308+
rw [← norm_mul, ← Matrix.det_mul, ← LinearMap.toMatrix_comp]
309+
rfl
310+
· have hker : (g ∘ₗ f).ker ≠ ⊥ := by
311+
contrapose! hrank' with hbot
312+
obtain h := (g ∘ₗ f).finrank_range_add_finrank_ker.symm
313+
rw [hbot] at h
314+
simpa using h
315+
have hker' : (g.domRestrict f.range).ker ≠ ⊥ := by
316+
contrapose! hrank' with hbot
317+
obtain h := (g.domRestrict f.range).finrank_range_add_finrank_ker.symm
318+
rw [hbot, range_domRestrict] at h
319+
rw [hrank, h, range_comp]
320+
simp
321+
simp [normDet_eq_zero_iff_ker_ne_bot.mpr hker, normDet_eq_zero_iff_ker_ne_bot.mpr hker']
322+
· have hker : f.ker ≠ ⊥ := by
323+
contrapose! hrank with hbot
324+
obtain h := f.finrank_range_add_finrank_ker.symm
325+
rw [hbot] at h
326+
simpa using h
327+
have hker' : (g ∘ₗ f).ker ≠ ⊥ := by
328+
contrapose! hker with hbot
329+
simpa [hbot] using ker_le_ker_comp f g
330+
simp [normDet_eq_zero_iff_ker_ne_bot.mpr hker, normDet_eq_zero_iff_ker_ne_bot.mpr hker']
331+
332+
theorem normDet_comp_of_finrank_eq [FiniteDimensional 𝕜 V] (f : U →ₗ[𝕜] V) (g : V →ₗ[𝕜] W)
333+
(h : finrank 𝕜 U = finrank 𝕜 V) :
334+
(g ∘ₗ f).normDet = g.normDet * f.normDet := by
335+
by_cases htop : f.range = ⊤
336+
· rw [normDet_comp]
337+
congrm ?_ * _
338+
suffices (g.domRestrict f.range).normDet * (id : V →ₗ[𝕜] V).normDet = g.normDet by simpa
339+
have : f.range = id.range := by simp [htop]
340+
convert (normDet_comp LinearMap.id g).symm
341+
· have hker : f.ker ≠ ⊥ := by
342+
simpa [ker_eq_bot_iff_range_eq_top_of_finrank_eq_finrank h] using htop
343+
have hker' : (g ∘ₗ f).ker ≠ ⊥ := by
344+
contrapose! hker with hbot
345+
simpa [hbot] using ker_le_ker_comp f g
346+
simp [normDet_eq_zero_iff_ker_ne_bot.mpr hker, normDet_eq_zero_iff_ker_ne_bot.mpr hker']
347+
348+
@[simp]
349+
theorem normDet_codRestrict {p : Submodule 𝕜 V} {f : U →ₗ[𝕜] V} (h : ∀ c, f c ∈ p) :
350+
(f.codRestrict p h).normDet = f.normDet := by
351+
have : f = p.subtype ∘ₗ f.codRestrict p h := rfl
352+
conv_rhs => rw [this]
353+
rw [normDet_comp]
354+
have : (p.subtype.domRestrict (codRestrict p f h).range).normDet = 1 :=
355+
(p.subtypeₗᵢ.comp (codRestrict p f h).range.subtypeₗᵢ).normDet_eq_one
356+
simp [this]
357+
358+
theorem normDet_eq_prod_singularValues [FiniteDimensional 𝕜 V] (f : U →ₗ[𝕜] V) :
359+
f.normDet = ∏ i ∈ Finset.range (finrank 𝕜 U), f.singularValues i := by
360+
rw [← sq_eq_sq₀ f.normDet_nonneg (Finset.prod_nonneg fun i _ ↦ f.singularValues_nonneg i),
361+
← RCLike.ofReal_inj (K := 𝕜), ← Finset.prod_pow, ← Fin.prod_univ_eq_prod_range, normDet_sq]
362+
simp_rw [sq_singularValues_fin]
363+
push_cast
364+
rw [← LinearMap.IsSymmetric.det_eq_prod_eigenvalues]
365+
366+
end LinearMap

0 commit comments

Comments
 (0)