|
| 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