Skip to content

Commit 82fd896

Browse files
committed
feat(LinearAlgebra/Matrix): expand IsSymm/IsHermitian API (leanprover-community#36349)
1 parent 82670e8 commit 82fd896

12 files changed

Lines changed: 164 additions & 14 deletions

File tree

Mathlib/Algebra/Lie/Classical.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ theorem jd_transform [Fintype l] : (PD l R)ᵀ * JD l R * PD l R = (2 : R) • S
276276
rw [h, PD, s_as_blocks, Matrix.fromBlocks_multiply, Matrix.fromBlocks_smul]
277277
simp [two_smul]
278278

279+
set_option backward.isDefEq.respectTransparency false in
279280
theorem pd_inv [Fintype l] [Invertible (2 : R)] : PD l R * ⅟(2 : R) • (PD l R)ᵀ = 1 := by
280281
rw [PD, Matrix.fromBlocks_transpose, Matrix.fromBlocks_smul,
281282
Matrix.fromBlocks_multiply]

Mathlib/Data/Matrix/Composition.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ theorem comp_map_transpose (M : Matrix I J (Matrix K L R)) :
104104
theorem comp_symm_transpose (M : Matrix (I × K) (J × L) R) :
105105
(comp J I L K R).symm Mᵀ = (((comp I J K L R).symm M).map (·ᵀ))ᵀ := rfl
106106

107+
theorem transpose_comp (M : Matrix I J (Matrix K L R)) :
108+
(comp I J K L R M)ᵀ = comp J I L K R (Mᵀ.map (·ᵀ)) :=
109+
rfl
110+
107111
end Basic
108112

109113
section Add

Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ theorem trace_eq_neg_charpoly_nextCoeff (M : Matrix n n R) : M.trace = -M.charpo
145145
nontriviality
146146
simp [trace_eq_neg_charpoly_coeff, nextCoeff]
147147

148+
set_option backward.isDefEq.respectTransparency false in
148149
theorem det_eq_sign_charpoly_coeff (M : Matrix n n R) :
149150
M.det = (-1) ^ Fintype.card n * M.charpoly.coeff 0 := by
150151
rw [coeff_zero_eq_eval_zero, charpoly, eval_det, matPolyEquiv_charmatrix, ← det_smul]

Mathlib/LinearAlgebra/Matrix/ConjTranspose.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ theorem conjTranspose_apply [Star α] (M : Matrix m n α) (i j) :
134134
theorem conjTranspose_conjTranspose [InvolutiveStar α] (M : Matrix m n α) : Mᴴᴴ = M :=
135135
Matrix.ext <| by simp
136136

137+
variable (n α) in
138+
theorem conjTranspose_involutive [InvolutiveStar α] :
139+
(conjTranspose : Matrix n n α → Matrix n n α).Involutive :=
140+
conjTranspose_conjTranspose
141+
137142
theorem conjTranspose_transpose [Star α] (M : Matrix m n α) :
138143
Mᴴᵀ = M.map star :=
139144
rfl

Mathlib/LinearAlgebra/Matrix/Defs.lean

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ instance addCommMonoid [AddCommMonoid α] : AddCommMonoid (Matrix m n α) :=
169169
instance neg [Neg α] : Neg (Matrix m n α) :=
170170
fast_instance% Pi.instNeg
171171

172+
instance involutiveNeg [InvolutiveNeg α] : InvolutiveNeg (Matrix m n α) :=
173+
Pi.involutiveNeg
174+
172175
instance sub [Sub α] : Sub (Matrix m n α) :=
173176
fast_instance% Pi.instSub
174177

@@ -351,6 +354,10 @@ theorem transpose_transpose (M : Matrix m n α) : Mᵀᵀ = M := by
351354
ext
352355
rfl
353356

357+
variable (n α) in
358+
theorem transpose_involutive : (transpose : Matrix n n α → Matrix n n α).Involutive :=
359+
transpose_transpose
360+
354361
theorem transpose_injective : Function.Injective (transpose : Matrix m n α → Matrix n m α) :=
355362
fun _ _ h => ext fun i j => ext_iff.2 h j i
356363

@@ -373,17 +380,14 @@ theorem transpose_sub [Sub α] (M : Matrix m n α) (N : Matrix m n α) : (M - N)
373380
simp
374381

375382
@[simp]
376-
theorem transpose_smul {R : Type*} [SMul R α] (c : R) (M : Matrix m n α) : (c • M)ᵀ = c • Mᵀ := by
377-
ext
383+
theorem transpose_smul {R : Type*} [SMul R α] (c : R) (M : Matrix m n α) : (c • M)ᵀ = c • Mᵀ :=
378384
rfl
379385

380386
@[simp]
381-
theorem transpose_neg [Neg α] (M : Matrix m n α) : (-M)ᵀ = -Mᵀ := by
382-
ext
387+
theorem transpose_neg [Neg α] (M : Matrix m n α) : (-M)ᵀ = -Mᵀ :=
383388
rfl
384389

385-
theorem transpose_map {f : α → β} {M : Matrix m n α} : Mᵀ.map f = (M.map f)ᵀ := by
386-
ext
390+
theorem transpose_map {f : α → β} {M : Matrix m n α} : Mᵀ.map f = (M.map f)ᵀ :=
387391
rfl
388392

389393
end Transpose

Mathlib/LinearAlgebra/Matrix/FixedDetMatrices.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ noncomputable instance repsFintype (k : ℤ) : Fintype (reps k) := by
164164
ext i j
165165
simpa only [Subtype.mk.injEq] using congrFun₂ h i j
166166

167+
set_option backward.isDefEq.respectTransparency false in
167168
@[simp]
168169
lemma S_smul_four (A : Δ m) : S • S • S • S • A = A := by
169170
simp only [smul_def, ← mul_assoc, S_mul_S_eq, neg_mul, one_mul, mul_neg, neg_neg, Subtype.coe_eta]

Mathlib/LinearAlgebra/Matrix/Hermitian.lean

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,13 @@ theorem IsHermitian.ext_iff {A : Matrix n n α} : A.IsHermitian ↔ ∀ i j, sta
6464

6565
@[simp]
6666
theorem IsHermitian.map {A : Matrix n n α} (h : A.IsHermitian) (f : α → β)
67-
(hf : Function.Semiconj f star star) : (A.map f).IsHermitian :=
68-
(conjTranspose_map f hf).symm.trans <| h.eq.symm ▸ rfl
67+
(hf : Function.Semiconj f star star) : (A.map f).IsHermitian := by
68+
rw [IsHermitian, ← conjTranspose_map f hf, h.eq]
69+
70+
@[simp]
71+
theorem isHermitian_map_iff {A : Matrix n n α} {f : α → β} (hf : Function.Semiconj f star star)
72+
(hinj : f.Injective) : (A.map f).IsHermitian ↔ A.IsHermitian := by
73+
rw [IsHermitian, IsHermitian, ← conjTranspose_map f hf, map_injective hinj |>.eq_iff]
6974

7075
@[simp, nontriviality]
7176
theorem IsHermitian.of_subsingleton {A : Matrix n n α} [Subsingleton α] : A.IsHermitian :=
@@ -76,7 +81,7 @@ theorem IsHermitian.transpose {A : Matrix n n α} (h : A.IsHermitian) : Aᵀ.IsH
7681
exact congr_arg Matrix.transpose h
7782

7883
@[simp]
79-
theorem isHermitian_transpose_iff (A : Matrix n n α) : Aᵀ.IsHermitian ↔ A.IsHermitian :=
84+
theorem isHermitian_transpose_iff {A : Matrix n n α} : Aᵀ.IsHermitian ↔ A.IsHermitian :=
8085
by intro h; rw [← transpose_transpose A]; exact IsHermitian.transpose h, IsHermitian.transpose⟩
8186

8287
theorem IsHermitian.conjTranspose {A : Matrix n n α} (h : A.IsHermitian) : Aᴴ.IsHermitian :=
@@ -91,14 +96,42 @@ theorem isHermitian_submatrix_equiv {A : Matrix n n α} (e : m ≃ n) :
9196
(A.submatrix e e).IsHermitian ↔ A.IsHermitian :=
9297
fun h => by simpa using h.submatrix e.symm, fun h => h.submatrix _⟩
9398

99+
theorem IsHermitian.reindex {A : Matrix n n α} (h : A.IsHermitian) (f : n ≃ m) :
100+
(A.reindex f f).IsHermitian := by
101+
rw [reindex_apply]
102+
apply submatrix h
103+
104+
theorem isHermitian_reindex_iff {A : Matrix n n α} (f : n ≃ m) :
105+
(A.reindex f f).IsHermitian ↔ A.IsHermitian := by
106+
refine ⟨fun h ↦ ?_, (·.reindex f)⟩
107+
simpa using h.reindex f.symm
108+
109+
theorem conjTranspose_comp {I J K L : Type*} (M : Matrix I J (Matrix K L α)) :
110+
(comp I J K L α M)ᴴ = comp J I L K α (Mᵀ.map (·ᴴ)) :=
111+
rfl
112+
113+
/-- When the inner matrices are square we can use the induced star operation -/
114+
theorem conjTranspose_comp' {I J K : Type*} (M : Matrix I J (Matrix K K α)) :
115+
(comp I J K K α M)ᴴ = comp J I K K α Mᴴ :=
116+
rfl
117+
118+
theorem isHermitian_comp_iff {A : Matrix m m (Matrix n n α)} :
119+
(A.comp m m n n α).IsHermitian ↔ A.IsHermitian := by
120+
rw [IsHermitian, IsHermitian, conjTranspose_comp', comp .. |>.injective.eq_iff]
121+
122+
theorem isHermitian_comp_iff_forall {A : Matrix m m (Matrix n n α)} :
123+
(A.comp m m n n α).IsHermitian ↔ ∀ i j i' j', star (A j i j' i') = A i j i' j' := by
124+
simp [IsHermitian.ext_iff]
125+
grind
126+
94127
end Star
95128

96129
section InvolutiveStar
97130

98131
variable [InvolutiveStar α]
99132

100133
@[simp]
101-
theorem isHermitian_conjTranspose_iff (A : Matrix n n α) : Aᴴ.IsHermitian ↔ A.IsHermitian :=
134+
theorem isHermitian_conjTranspose_iff {A : Matrix n n α} : Aᴴ.IsHermitian ↔ A.IsHermitian :=
102135
IsSelfAdjoint.star_iff
103136

104137
/-- A block matrix `A.from_blocks B C D` is Hermitian,
@@ -174,13 +207,52 @@ variable [AddGroup α] [StarAddMonoid α]
174207
theorem IsHermitian.neg {A : Matrix n n α} (h : A.IsHermitian) : (-A).IsHermitian :=
175208
IsSelfAdjoint.neg h
176209

210+
@[simp]
211+
theorem isHermitian_neg_iff {A : Matrix n n α} : (-A).IsHermitian ↔ A.IsHermitian := by
212+
refine ⟨fun h ↦ ?_, (·.neg)⟩
213+
rw [← neg_neg A]
214+
exact h.neg
215+
177216
@[simp]
178217
theorem IsHermitian.sub {A B : Matrix n n α} (hA : A.IsHermitian) (hB : B.IsHermitian) :
179218
(A - B).IsHermitian :=
180219
IsSelfAdjoint.sub hA hB
181220

182221
end AddGroup
183222

223+
section StarModule
224+
225+
variable {R : Type*} [Star R] [Star α] [SMul R α] [StarModule R α]
226+
227+
theorem IsHermitian.smul {A : Matrix n n α} (h : A.IsHermitian) {k : R} (hk : IsSelfAdjoint k) :
228+
(k • A).IsHermitian := by
229+
rw [IsHermitian, conjTranspose_smul, hk.star_eq, h.eq]
230+
231+
end StarModule
232+
233+
section MulAction_StarModule
234+
235+
variable {R : Type*} [Monoid R] [Star R] [Star α] [MulAction R α] [StarModule R α]
236+
237+
theorem IsHermitian.of_smul {A : Matrix n n α} {k : R} [Invertible k] (h : (k • A).IsHermitian)
238+
(hk : IsSelfAdjoint k) : A.IsHermitian := by
239+
rw [IsHermitian, conjTranspose_smul, hk.star_eq] at h
240+
simpa using congr(⅟k • $h)
241+
242+
/-- Assumes `IsSelfAdjoint ⅟k` instead of `IsSelfAdjoint k`.
243+
These are equivalent given `StarMul R` -/
244+
theorem IsHermitian.of_smul' {A : Matrix n n α} {k : R} [Invertible k] (h : (k • A).IsHermitian)
245+
(hk : IsSelfAdjoint ⅟k) : A.IsHermitian := by
246+
rw [← invOf_smul_smul k A]
247+
exact h.smul hk
248+
249+
@[simp]
250+
theorem isHermitian_smul_iff {A : Matrix n n α} {k : R} [Invertible k] (hk : IsSelfAdjoint k) :
251+
(k • A).IsHermitian ↔ A.IsHermitian :=
252+
⟨(·.of_smul hk), (·.smul hk)⟩
253+
254+
end MulAction_StarModule
255+
184256
section NonUnitalSemiring
185257

186258
variable [NonUnitalSemiring α] [StarRing α]
@@ -213,16 +285,22 @@ lemma IsHermitian.commute_iff [Fintype n] {A B : Matrix n n α}
213285

214286
end NonUnitalSemiring
215287

216-
section Semiring
288+
section NonAssocSemiring
217289

218-
variable [Semiring α] [StarRing α]
290+
variable [NonAssocSemiring α] [StarRing α]
219291

220292
/-- Note this is more general for matrices than `isSelfAdjoint_one` as it does not
221293
require `Fintype n`, which is necessary for `Monoid (Matrix n n R)`. -/
222294
@[simp]
223295
theorem isHermitian_one [DecidableEq n] : (1 : Matrix n n α).IsHermitian :=
224296
conjTranspose_one
225297

298+
end NonAssocSemiring
299+
300+
section Semiring
301+
302+
variable [Semiring α] [StarRing α]
303+
226304
@[simp]
227305
theorem isHermitian_natCast [DecidableEq n] (d : ℕ) : (d : Matrix n n α).IsHermitian :=
228306
conjTranspose_natCast _

Mathlib/LinearAlgebra/Matrix/SchurComplement.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ section Block
227227
/-! #### General 2×2 block matrices -/
228228

229229

230+
set_option backward.isDefEq.respectTransparency false in
230231
/-- A block matrix is invertible if the bottom right corner and the corresponding Schur complement
231232
is. -/
232233
@[implicit_reducible]

Mathlib/LinearAlgebra/Matrix/Swap.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ lemma swap_comm (i j : n) :
4646
lemma transpose_swap (i j : n) : (swap R i j).transpose = swap R i j := by
4747
simp [swap]
4848

49+
theorem isSymm_swap (i j : n) : (swap R i j).IsSymm :=
50+
transpose_swap i j
51+
4952
@[simp]
5053
lemma conjTranspose_swap {R : Type*} [NonAssocSemiring R] [StarRing R] (i j : n) :
5154
(swap R i j).conjTranspose = swap R i j := by

Mathlib/LinearAlgebra/Matrix/Symmetric.lean

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,21 +78,43 @@ theorem IsSymm.pow [CommSemiring α] [Fintype n] [DecidableEq n] {A : Matrix n n
7878
rw [IsSymm, transpose_pow, h]
7979

8080
@[simp]
81-
theorem IsSymm.map {A : Matrix n n α} (h : A.IsSymm) (f : α → β) : (A.map f).IsSymm :=
82-
transpose_map.symm.trans (h.symm ▸ rfl)
81+
theorem IsSymm.map {A : Matrix n n α} (h : A.IsSymm) (f : α → β) : (A.map f).IsSymm := by
82+
rw [IsSymm, ← transpose_map, h.eq]
8383

8484
@[simp]
85+
theorem isSymm_map_iff {A : Matrix n n α} {f : α → β} (hf : f.Injective) :
86+
(A.map f).IsSymm ↔ A.IsSymm := by
87+
rw [IsSymm, IsSymm, ← transpose_map, map_injective hf |>.eq_iff]
88+
8589
theorem IsSymm.transpose {A : Matrix n n α} (h : A.IsSymm) : Aᵀ.IsSymm :=
8690
congr_arg _ h
8791

92+
@[simp]
93+
theorem isSymm_transpose_iff {A : Matrix n n α} : Aᵀ.IsSymm ↔ A.IsSymm := by
94+
refine ⟨fun h ↦ ?_, (·.transpose)⟩
95+
rw [← A.transpose_transpose]
96+
exact h.transpose
97+
8898
@[simp]
8999
theorem IsSymm.conjTranspose [Star α] {A : Matrix n n α} (h : A.IsSymm) : Aᴴ.IsSymm :=
90100
h.transpose.map _
91101

102+
@[simp]
103+
theorem isSymm_conjTranspose_iff [InvolutiveStar α] {A : Matrix n n α} : Aᴴ.IsSymm ↔ A.IsSymm := by
104+
refine ⟨fun h ↦ ?_, (·.conjTranspose)⟩
105+
rw [← A.conjTranspose_conjTranspose]
106+
exact h.conjTranspose
107+
92108
@[simp]
93109
theorem IsSymm.neg [Neg α] {A : Matrix n n α} (h : A.IsSymm) : (-A).IsSymm :=
94110
(transpose_neg _).trans (congr_arg _ h)
95111

112+
@[simp]
113+
theorem isSymm_neg_iff [InvolutiveNeg α] {A : Matrix n n α} : (-A).IsSymm ↔ A.IsSymm := by
114+
refine ⟨fun h ↦ ?_, (·.neg)⟩
115+
rw [← neg_neg A]
116+
exact h.neg
117+
96118
@[simp]
97119
theorem IsSymm.add {A B : Matrix n n α} [Add α] (hA : A.IsSymm) (hB : B.IsSymm) : (A + B).IsSymm :=
98120
(transpose_add _ _).trans (hA.symm ▸ hB.symm ▸ rfl)
@@ -105,10 +127,25 @@ theorem IsSymm.sub {A B : Matrix n n α} [Sub α] (hA : A.IsSymm) (hB : B.IsSymm
105127
theorem IsSymm.smul [SMul R α] {A : Matrix n n α} (h : A.IsSymm) (k : R) : (k • A).IsSymm :=
106128
(transpose_smul _ _).trans (congr_arg _ h)
107129

130+
@[simp]
131+
theorem isSymm_smul_iff [Monoid R] [MulAction R α] {A : Matrix n n α} (k : R) [Invertible k] :
132+
(k • A).IsSymm ↔ A.IsSymm := by
133+
refine ⟨fun h ↦ ?_, (·.smul k)⟩
134+
rw [← invOf_smul_smul k A]
135+
exact h.smul ⅟k
136+
108137
@[simp]
109138
theorem IsSymm.submatrix {A : Matrix n n α} (h : A.IsSymm) (f : m → n) : (A.submatrix f f).IsSymm :=
110139
(transpose_submatrix _ _ _).trans (h.symm ▸ rfl)
111140

141+
theorem IsSymm.reindex {A : Matrix n n α} (h : A.IsSymm) (f : n ≃ m) : (A.reindex f f).IsSymm := by
142+
rw [reindex_apply]
143+
apply submatrix h
144+
145+
theorem isSymm_reindex_iff {A : Matrix n n α} (f : n ≃ m) : (A.reindex f f).IsSymm ↔ A.IsSymm := by
146+
refine ⟨fun h ↦ ?_, (·.reindex f)⟩
147+
simpa using h.reindex f.symm
148+
112149
/-- The diagonal matrix `diagonal v` is symmetric. -/
113150
@[simp]
114151
theorem isSymm_diagonal [DecidableEq n] [Zero α] (v : n → α) : (diagonal v).IsSymm :=
@@ -133,4 +170,14 @@ theorem isSymm_fromBlocks_iff {A : Matrix m m α} {B : Matrix m n α} {C : Matri
133170
(congr_arg toBlocks₂₂ h :)⟩,
134171
fun ⟨hA, hBC, _, hD⟩ => IsSymm.fromBlocks hA hBC hD⟩
135172

173+
theorem isSymm_comp_iff {A : Matrix m m (Matrix n n α)} :
174+
(A.comp m m n n α).IsSymm ↔ Aᵀ = A.map (·ᵀ) := by
175+
rw [IsSymm, transpose_comp, transpose_map, comp .. |>.injective.eq_iff, eq_comm,
176+
transpose_involutive _ _ |>.eq_iff]
177+
178+
theorem isSymm_comp_iff_forall {A : Matrix m m (Matrix n n α)} :
179+
(A.comp m m n n α).IsSymm ↔ ∀ i j i' j', A j i j' i' = A i j i' j' := by
180+
simp [IsSymm.ext_iff]
181+
grind
182+
136183
end Matrix

0 commit comments

Comments
 (0)