Skip to content

Commit 0cea0c9

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

4 files changed

Lines changed: 398 additions & 0 deletions

File tree

Mathlib.lean

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

0 commit comments

Comments
 (0)