forked from leanprover-community/mathlib4
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOrder.lean
More file actions
364 lines (289 loc) Β· 15.8 KB
/
Order.lean
File metadata and controls
364 lines (289 loc) Β· 15.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
/-
Copyright (c) 2025 Monica Omar. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Monica Omar
-/
module
public import Mathlib.Algebra.Order.Module.PositiveLinearMap
public import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances
public import Mathlib.Analysis.Matrix.HermitianFunctionalCalculus
public import Mathlib.Analysis.Matrix.PosDef
public import Mathlib.Analysis.RCLike.Sqrt
public import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Abs
public import Mathlib.LinearAlgebra.Matrix.Vec
/-!
# The partial order on matrices
This file constructs the partial order and star ordered instances on matrices on `π`.
This allows us to use more general results from Cβ-algebras, like `CFC.sqrt`.
## Main results
* `Matrix.instPartialOrder`: the partial order on matrices given by `x β€ y := (y - x).PosSemidef`.
* `Matrix.PosSemidef.dotProduct_mulVec_zero_iff`: for a positive semi-definite matrix `A`,
we have `xβ A x = 0` iff `A x = 0`.
* `Matrix.toMatrixInnerProductSpace`: the inner product on matrices induced by a
positive semi-definite matrix `M`: `βͺx, yβ« = (y * M * xα΄΄).trace`.
## Implementation notes
Note that the partial order instance is scoped to `MatrixOrder`.
Please `open scoped MatrixOrder` to use this.
-/
@[expose] public section
variable {π n : Type*} [RCLike π]
open scoped ComplexOrder
open Matrix
namespace Matrix
section PartialOrder
/-- The preorder on matrices given by `A β€ B := (B - A).PosSemidef`. -/
abbrev instPreOrder : Preorder (Matrix n n π) where
le A B := (B - A).PosSemidef
le_refl A := sub_self A βΈ PosSemidef.zero
le_trans A B C hβ hβ := sub_add_sub_cancel C B A βΈ hβ.add hβ
scoped[MatrixOrder] attribute [instance] Matrix.instPreOrder
open MatrixOrder
lemma le_iff {A B : Matrix n n π} : A β€ B β (B - A).PosSemidef := Iff.rfl
lemma nonneg_iff_posSemidef {A : Matrix n n π} : 0 β€ A β A.PosSemidef := by rw [le_iff, sub_zero]
protected alias β¨LE.le.posSemidef, PosSemidef.nonnegβ© := nonneg_iff_posSemidef
attribute [aesop safe forward (rule_sets := [CStarAlgebra])] PosSemidef.nonneg
private lemma le_antisymm_aux {A : Matrix n n π} (hβ : A.PosSemidef) (hβ : (-A).PosSemidef) :
A = 0 := by
classical
ext i j
have hdiag i : A i i = 0 :=
le_antisymm (by simpa using hβ.diag_nonneg) (by simpa using hβ.diag_nonneg)
have h1 := hβ.2 (.single i 1 + .single j (A j i))
have h2 := hβ.2 (.single i 1 + .single j (A j i))
simp [Finsupp.sum_add_index, mul_add, add_mul,
-neg_add_rev, hdiag, β hβ.1.apply j i, -RCLike.star_def] at *
simpa using le_antisymm h2 h1
/-- The partial order on matrices given by `A β€ B := (B - A).PosSemidef`. -/
abbrev instPartialOrder : PartialOrder (Matrix n n π) where
le_antisymm A B hβ hβ := by
simpa [sub_eq_zero, eq_comm] using le_antisymm_aux hβ
(by simpa only [β neg_sub B, le_iff] using hβ)
scoped[MatrixOrder] attribute [instance] Matrix.instPartialOrder
lemma instIsOrderedAddMonoid : IsOrderedAddMonoid (Matrix n n π) where
add_le_add_left _ _ _ _ := by rwa [le_iff, add_sub_add_right_eq_sub]
scoped[MatrixOrder] attribute [instance] Matrix.instIsOrderedAddMonoid
variable [Fintype n]
lemma instNonnegSpectrumClass : NonnegSpectrumClass β (Matrix n n π) where
quasispectrum_nonneg_of_nonneg A hA := by
classical
simp only [quasispectrum_eq_spectrum_union_zero β A, Set.union_singleton, Set.mem_insert_iff,
forall_eq_or_imp, le_refl, true_and]
intro x hx
obtain β¨i, rflβ© := Set.ext_iff.mp
hA.posSemidef.1.spectrum_real_eq_range_eigenvalues x |>.mp hx
exact hA.posSemidef.eigenvalues_nonneg _
scoped[MatrixOrder] attribute [instance] instNonnegSpectrumClass
lemma instStarOrderedRing : StarOrderedRing (Matrix n n π) :=
.of_nonneg_iff' add_le_add_right fun A β¦
β¨fun hA β¦ by
classical
obtain β¨X, hX, -, rflβ© :=
sub_zero A βΈ CFC.exists_sqrt_of_isSelfAdjoint_of_quasispectrumRestricts hA.isHermitian
(QuasispectrumRestricts.nnreal_of_nonneg hA.nonneg)
exact β¨X, hX.star_eq.symm βΈ rflβ©,
fun β¨A, hAβ© => hA βΈ (posSemidef_conjTranspose_mul_self A).nonnegβ©
scoped[MatrixOrder] attribute [instance] instStarOrderedRing
end PartialOrder
open scoped MatrixOrder
variable [Fintype n]
namespace PosSemidef
section sqrtDeprecated
variable [DecidableEq n] {A : Matrix n n π} (hA : PosSemidef A)
include hA
lemma inv_sqrt : (CFC.sqrt A)β»ΒΉ = CFC.sqrt Aβ»ΒΉ := by
rw [eq_comm, CFC.sqrt_eq_iff _ _ hA.inv.nonneg (CFC.sqrt_nonneg A).posSemidef.inv.nonneg, β sq,
inv_pow', CFC.sq_sqrt A]
end sqrtDeprecated
/-- For `A` positive semidefinite, we have `xβ A x = 0` iff `A x = 0`. -/
theorem dotProduct_mulVec_zero_iff {A : Matrix n n π} (hA : PosSemidef A) (x : n β π) :
star x β¬α΅₯ A *α΅₯ x = 0 β A *α΅₯ x = 0 := by
classical
refine β¨fun h β¦ ?_, fun h β¦ h βΈ dotProduct_zero _β©
obtain β¨B, rflβ© := CStarAlgebra.nonneg_iff_eq_star_mul_self.mp hA.nonneg
simp_rw [β Matrix.mulVec_mulVec, dotProduct_mulVec _ _ (B *α΅₯ x), star_eq_conjTranspose,
vecMul_conjTranspose, star_star, dotProduct_star_self_eq_zero] at h β’
rw [h, mulVec_zero]
/-- For `A` positive semidefinite, we have `xβ A x = 0` iff `A x = 0` (linear maps version). -/
theorem toLinearMapβ'_zero_iff [DecidableEq n]
{A : Matrix n n π} (hA : PosSemidef A) (x : n β π) :
Matrix.toLinearMapβ' π A (star x) x = 0 β A *α΅₯ x = 0 := by
simpa only [toLinearMapβ'_apply'] using hA.dotProduct_mulVec_zero_iff x
theorem det_sqrt [DecidableEq n] {A : Matrix n n π} (hA : A.PosSemidef) :
(CFC.sqrt A).det = RCLike.sqrt A.det := by
rw [CFC.sqrt_eq_cfc, cfc_nnreal_eq_real _ A, hA.1.cfc_eq, RCLike.sqrt_of_nonneg hA.det_nonneg]
simp only [IsHermitian.cfc, Real.coe_sqrt, Real.coe_toNNReal', det_map, det_diagonal,
Function.comp_apply, hA.isHermitian.det_eq_prod_eigenvalues, β RCLike.ofReal_prod,
RCLike.ofReal_re, Real.sqrt_prod _ fun _ _ β¦ hA.eigenvalues_nonneg _]
grind
end PosSemidef
theorem IsHermitian.det_abs [DecidableEq n] {A : Matrix n n π} (hA : A.IsHermitian) :
det (CFC.abs A) = βdet Aβ := by
rw [CFC.abs_eq_cfc_norm A, hA.cfc_eq]
simp [IsHermitian.cfc, -Unitary.conjStarAlgAut_apply, hA.det_eq_prod_eigenvalues]
theorem posSemidef_iff_isHermitian_and_spectrum_nonneg [DecidableEq n] {A : Matrix n n π} :
A.PosSemidef β A.IsHermitian β§ spectrum π A β {a : π | 0 β€ a} := by
refine β¨fun h => β¨h.isHermitian, fun a => ?_β©, fun β¨h1, h2β© => ?_β©
Β· simp only [h.isHermitian.spectrum_eq_image_range, Set.mem_image, Set.mem_range,
exists_exists_eq_and, Set.mem_setOf_eq, forall_exists_index]
rintro i rfl
exact_mod_cast h.eigenvalues_nonneg _
Β· rw [h1.posSemidef_iff_eigenvalues_nonneg]
intro i
simpa [h1.spectrum_eq_image_range] using @h2 (h1.eigenvalues i)
/-- A positive semi-definite matrix is positive definite if and only if it is invertible. -/
@[grind =]
theorem PosSemidef.posDef_iff_isUnit [DecidableEq n] {x : Matrix n n π}
(hx : x.PosSemidef) : x.PosDef β IsUnit x := by
refine β¨fun h => h.isUnit, fun h => .of_dotProduct_mulVec_pos hx.1 fun v hv => ?_β©
obtain β¨y, rflβ© := CStarAlgebra.nonneg_iff_eq_star_mul_self.mp hx.nonneg
simp_rw [dotProduct_mulVec, β vecMul_vecMul, star_eq_conjTranspose, β star_mulVec,
β dotProduct_mulVec, dotProduct_star_self_pos_iff]
contrapose! hv
rw [β map_eq_zero_iff (f := (yα΄΄ * y).mulVecLin) (mulVec_injective_iff_isUnit.mpr h),
mulVecLin_apply, β mulVec_mulVec, hv, mulVec_zero]
theorem isStrictlyPositive_iff_posDef [DecidableEq n] {x : Matrix n n π} :
IsStrictlyPositive x β x.PosDef :=
β¨fun h => h.nonneg.posSemidef.posDef_iff_isUnit.mpr h.isUnit,
fun h => h.isUnit.isStrictlyPositive h.posSemidef.nonnegβ©
alias β¨IsStrictlyPositive.posDef, PosDef.isStrictlyPositiveβ© := isStrictlyPositive_iff_posDef
attribute [aesop safe forward (rule_sets := [CStarAlgebra])] PosDef.isStrictlyPositive
lemma PosSemidef.posDef_iff_det_ne_zero [DecidableEq n] {A : Matrix n n π} (hA : A.PosSemidef) :
A.PosDef β A.det β 0 := by
simp [hA.posDef_iff_isUnit, isUnit_iff_isUnit_det]
@[deprecated IsStrictlyPositive.commute_iff (since := "2025-09-26")]
theorem PosDef.commute_iff {A B : Matrix n n π} (hA : A.PosDef) (hB : B.PosDef) :
Commute A B β (A * B).PosDef := by
classical
rw [hA.isStrictlyPositive.commute_iff hB.isStrictlyPositive, isStrictlyPositive_iff_posDef]
set_option linter.unusedDecidableInType false in
@[deprecated IsStrictlyPositive.sqrt (since := "2025-09-26")]
lemma PosDef.posDef_sqrt [DecidableEq n] {M : Matrix n n π} (hM : M.PosDef) :
PosDef (CFC.sqrt M) := hM.isStrictlyPositive.sqrt.posDef
section kronecker
omit [Fintype n]
variable [Finite n] {m : Type*} [Finite m]
open scoped Kronecker
/-- The kronecker product of two positive semi-definite matrices is positive semi-definite. -/
theorem PosSemidef.kronecker {x : Matrix n n π} {y : Matrix m m π}
(hx : x.PosSemidef) (hy : y.PosSemidef) : (x ββ y).PosSemidef := by
classical
have := Fintype.ofFinite n; have := Fintype.ofFinite m
obtain β¨a, rflβ© := CStarAlgebra.nonneg_iff_eq_star_mul_self.mp hx.nonneg
obtain β¨b, rflβ© := CStarAlgebra.nonneg_iff_eq_star_mul_self.mp hy.nonneg
simpa [mul_kronecker_mul, β conjTranspose_kronecker, star_eq_conjTranspose] using
posSemidef_conjTranspose_mul_self _
open Matrix in
/-- The kronecker of two positive definite matrices is positive definite. -/
theorem PosDef.kronecker {x : Matrix n n π} {y : Matrix m m π}
(hx : x.PosDef) (hy : y.PosDef) : (x ββ y).PosDef := by
classical
have := Fintype.ofFinite n; have := Fintype.ofFinite m
exact hx.posSemidef.kronecker hy.posSemidef |>.posDef_iff_isUnit.mpr <|
hx.isUnit.kronecker hy.isUnit
end kronecker
section hadamard
variable {ΞΉ : Type*}
/-- [**Schur product theorem**][schur1911] (positive semidefinite version): the Hadamard (entrywise)
product of positive semidefinite matrices is positive semidefinite. -/
theorem PosSemidef.hadamard {A B : Matrix ΞΉ ΞΉ π}
(hA : A.PosSemidef) (hB : B.PosSemidef) : (A β B).PosSemidef := by
classical
refine β¨hA.isHermitian.hadamard hB.isHermitian, fun x β¦ ?_β©
have hAB : ((A β B).submatrix (β) (β) : Matrix x.support _ _).PosSemidef := by
have hAs := hA.submatrix ((β) : x.support β ΞΉ)
have hBs := hB.submatrix ((β) : x.support β ΞΉ)
rw [submatrix_hadamard, posSemidef_iff_dotProduct_mulVec]
refine β¨hAs.isHermitian.hadamard hBs.isHermitian, fun y β¦ ?_β©
rw [star_dotProduct_hadamard_mulVec_eq_kronecker]
exact (hAs.kronecker hBs).dotProduct_mulVec_nonneg _
simpa [Finsupp.sum, β Finset.sum_attach x.support, β Finset.subtype_mem_eq_attach,
β Finsupp.subtypeDomain_apply, β Finsupp.support_subtypeDomain] using hAB.2 _
/-- **Schur product theorem**: the Hadamard (entrywise) product of positive definite
matrices is positive definite. -/
theorem PosDef.hadamard {A B : Matrix ΞΉ ΞΉ π}
(hA : A.PosDef) (hB : B.PosDef) : (A β B).PosDef := by
classical
refine β¨hA.isHermitian.hadamard hB.isHermitian, fun x hx β¦ ?_β©
have hAB : ((A β B).submatrix (β) (β) : Matrix x.support _ _).PosDef := by
have hAs : (A.submatrix (β) (β) : Matrix x.support _ _).PosDef :=
hA.submatrix Subtype.coe_injective
have hBs : (B.submatrix (β) (β) : Matrix x.support _ _).PosDef :=
hB.submatrix Subtype.coe_injective
rw [submatrix_hadamard, posDef_iff_dotProduct_mulVec]
refine β¨hAs.isHermitian.hadamard hBs.isHermitian, fun y hy β¦ ?_β©
rw [star_dotProduct_hadamard_mulVec_eq_kronecker]
exact (hAs.kronecker hBs).dotProduct_mulVec_pos <| by simpa
simp_rw [RCLike.star_def, hadamard_apply, Finsupp.sum,
β Finset.sum_attach x.support, β Finset.subtype_mem_eq_attach,
β Finsupp.subtypeDomain_apply, β Finsupp.support_subtypeDomain]
refine hAB.2 ?_
simpa [β Finsupp.support_nonempty_iff] using Finsupp.support_nonempty_iff.mpr hx
end hadamard
/--
A matrix is positive definite if and only if it has the form `Bα΄΄ * B` for some invertible `B`.
-/
@[deprecated CStarAlgebra.isStrictlyPositive_iff_eq_star_mul_self (since := "2025-09-28")]
lemma posDef_iff_eq_conjTranspose_mul_self [DecidableEq n] {A : Matrix n n π} :
PosDef A β β B : Matrix n n π, IsUnit B β§ A = Bα΄΄ * B :=
isStrictlyPositive_iff_posDef.symm.trans CStarAlgebra.isStrictlyPositive_iff_eq_star_mul_self
section tracePositiveLinearMap
variable (n Ξ± π : Type*) [Fintype n] [Semiring Ξ±] [RCLike π] [Module Ξ± π]
/-- `Matrix.trace` as a positive linear map. -/
def tracePositiveLinearMap : Matrix n n π ββ[Ξ±] π :=
.mkβ (traceLinearMap n Ξ± π) fun _ h β¦ h.posSemidef.trace_nonneg
@[simp] lemma toLinearMap_tracePositiveLinearMap :
(tracePositiveLinearMap n Ξ± π).toLinearMap = traceLinearMap n Ξ± π := rfl
@[simp] lemma tracePositiveLinearMap_apply (x) : tracePositiveLinearMap n Ξ± π x = trace x := rfl
end tracePositiveLinearMap
set_option backward.privateInPublic true in
/-- The pre-inner product space structure implementation. Only an auxiliary for
`Matrix.toMatrixSeminormedAddCommGroup`, `Matrix.toMatrixNormedAddCommGroup`,
and `Matrix.toMatrixInnerProductSpace`. -/
private abbrev PosSemidef.matrixPreInnerProductSpace {M : Matrix n n π} (hM : M.PosSemidef) :
PreInnerProductSpace.Core π (Matrix n n π) where
inner x y := (y * M * xα΄΄).trace
conj_inner_symm _ _ := by
simp only [mul_assoc, starRingEnd_apply, β trace_conjTranspose, conjTranspose_mul,
conjTranspose_conjTranspose, hM.isHermitian.eq]
re_inner_nonneg x := RCLike.nonneg_iff.mp (hM.mul_mul_conjTranspose_same x).trace_nonneg |>.1
add_left := by simp [mul_add]
smul_left := by simp
set_option backward.privateInPublic true in
set_option backward.privateInPublic.warn false in
/-- A positive definite matrix `M` induces a norm on `Matrix n n π`
`βxβ = sqrt (x * M * xα΄΄).trace`. -/
@[implicit_reducible]
noncomputable def toMatrixSeminormedAddCommGroup (M : Matrix n n π) (hM : M.PosSemidef) :
SeminormedAddCommGroup (Matrix n n π) :=
@InnerProductSpace.Core.toSeminormedAddCommGroup _ _ _ _ _ hM.matrixPreInnerProductSpace
set_option backward.privateInPublic true in
set_option backward.privateInPublic.warn false in
/-- A positive definite matrix `M` induces a norm on `Matrix n n π`:
`βxβ = sqrt (x * M * xα΄΄).trace`. -/
@[implicit_reducible]
noncomputable def toMatrixNormedAddCommGroup (M : Matrix n n π) (hM : M.PosDef) :
NormedAddCommGroup (Matrix n n π) :=
letI : InnerProductSpace.Core π (Matrix n n π) :=
{ __ := hM.posSemidef.matrixPreInnerProductSpace
definite x hx := by
classical
obtain β¨y, hy, rflβ© := CStarAlgebra.isStrictlyPositive_iff_eq_star_mul_self.mp
hM.isStrictlyPositive
simp +instances only at hx
rw [β mul_assoc, β conjTranspose_conjTranspose x, star_eq_conjTranspose, β conjTranspose_mul,
conjTranspose_conjTranspose, mul_assoc, trace_conjTranspose_mul_self_eq_zero_iff] at hx
lift y to (Matrix n n π)Λ£ using hy
simpa [β mul_assoc] using congr(yβ»ΒΉ * $hx) }
this.toNormedAddCommGroup
/-- A positive semi-definite matrix `M` induces an inner product on `Matrix n n π`:
`βͺx, yβ« = (y * M * xα΄΄).trace`. -/
@[implicit_reducible]
def toMatrixInnerProductSpace (M : Matrix n n π) (hM : M.PosSemidef) :
letI : SeminormedAddCommGroup (Matrix n n π) := M.toMatrixSeminormedAddCommGroup hM
InnerProductSpace π (Matrix n n π) :=
InnerProductSpace.ofCore _
@[deprecated (since := "2025-11-18")] alias PosDef.matrixNormedAddCommGroup :=
toMatrixNormedAddCommGroup
@[deprecated (since := "2025-11-12")] alias PosDef.matrixInnerProductSpace :=
toMatrixInnerProductSpace
end Matrix