Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 9abfa6f

Browse files
committed
refactor(linear_algebra/matrix/hermitian): golf and generalize (#18565)
A handful of these results can be proven trivially using results about `is_self_adjoint`. This also generalizes the typeclass arguments throughout the file, though largely in a mathematically meaningless way.
1 parent 7ec2946 commit 9abfa6f

File tree

4 files changed

+115
-61
lines changed

4 files changed

+115
-61
lines changed

src/algebra/star/pi.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ instance [Π i, has_star (f i)] : has_star (Π i, f i) :=
2929

3030
lemma star_def [Π i, has_star (f i)] (x : Π i, f i) : star x = λ i, star (x i) := rfl
3131

32+
instance [Π i, has_star (f i)] [∀ i, has_trivial_star (f i)] : has_trivial_star (Π i, f i) :=
33+
{ star_trivial := λ _, funext $ λ _, star_trivial _ }
34+
3235
instance [Π i, has_involutive_star (f i)] : has_involutive_star (Π i, f i) :=
3336
{ star_involutive := λ _, funext $ λ _, star_star _ }
3437

src/algebra/star/prod.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ instance [has_star R] [has_star S] : has_star (R × S) :=
2929

3030
lemma star_def [has_star R] [has_star S] (x : R × S) : star x = (star x.1, star x.2) := rfl
3131

32+
instance [has_star R] [has_star S] [has_trivial_star R] [has_trivial_star S] :
33+
has_trivial_star (R × S) :=
34+
{ star_trivial := λ _, prod.ext (star_trivial _) (star_trivial _) }
35+
3236
instance [has_involutive_star R] [has_involutive_star S] : has_involutive_star (R × S) :=
3337
{ star_involutive := λ _, prod.ext (star_star _) (star_star _) }
3438

src/algebra/star/self_adjoint.lean

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,17 @@ by simp only [is_self_adjoint_iff, star_sub, hx.star_eq, hy.star_eq]
111111

112112
end add_group
113113

114+
section add_comm_monoid
115+
variables [add_comm_monoid R] [star_add_monoid R]
116+
117+
lemma _root_.is_self_adjoint_add_star_self (x : R) : is_self_adjoint (x + star x) :=
118+
by simp only [is_self_adjoint_iff, add_comm, star_add, star_star]
119+
120+
lemma _root_.is_self_adjoint_star_add_self (x : R) : is_self_adjoint (star x + x) :=
121+
by simp only [is_self_adjoint_iff, add_comm, star_add, star_star]
122+
123+
end add_comm_monoid
124+
114125
section semigroup
115126
variables [semigroup R] [star_semigroup R]
116127

src/linear_algebra/matrix/hermitian.lean

Lines changed: 97 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import analysis.inner_product_space.pi_L2
99
1010
This file defines hermitian matrices and some basic results about them.
1111
12+
See also `is_self_adjoint`, which generalizes this definition to other star rings.
13+
1214
## Main definition
1315
1416
* `matrix.is_hermitian` : a matrix `A : matrix n n α` is hermitian if `Aᴴ = A`.
@@ -27,56 +29,28 @@ open_locale matrix
2729

2830
local notation `⟪`x`, `y`⟫` := @inner α _ _ x y
2931

30-
section non_unital_semiring
31-
32-
variables [non_unital_semiring α] [star_ring α] [non_unital_semiring β] [star_ring β]
32+
section has_star
33+
variables [has_star α] [has_star β]
3334

3435
/-- A matrix is hermitian if it is equal to its conjugate transpose. On the reals, this definition
3536
captures symmetric matrices. -/
3637
def is_hermitian (A : matrix n n α) : Prop := Aᴴ = A
3738

3839
lemma is_hermitian.eq {A : matrix n n α} (h : A.is_hermitian) : Aᴴ = A := h
3940

41+
protected lemma is_hermitian.is_self_adjoint {A : matrix n n α} (h : A.is_hermitian) :
42+
is_self_adjoint A := h
43+
4044
@[ext]
4145
lemma is_hermitian.ext {A : matrix n n α} : (∀ i j, star (A j i) = A i j) → A.is_hermitian :=
4246
by { intros h, ext i j, exact h i j }
4347

4448
lemma is_hermitian.apply {A : matrix n n α} (h : A.is_hermitian) (i j : n) : star (A j i) = A i j :=
45-
by { unfold is_hermitian at h, rw [← h, conj_transpose_apply, star_star, h] }
49+
congr_fun (congr_fun h _) _
4650

4751
lemma is_hermitian.ext_iff {A : matrix n n α} : A.is_hermitian ↔ ∀ i j, star (A j i) = A i j :=
4852
⟨is_hermitian.apply, is_hermitian.ext⟩
4953

50-
lemma is_hermitian_mul_conj_transpose_self [fintype n] (A : matrix n n α) :
51-
(A ⬝ Aᴴ).is_hermitian :=
52-
by rw [is_hermitian, conj_transpose_mul, conj_transpose_conj_transpose]
53-
54-
lemma is_hermitian_transpose_mul_self [fintype n] (A : matrix n n α) :
55-
(Aᴴ ⬝ A).is_hermitian :=
56-
by rw [is_hermitian, conj_transpose_mul, conj_transpose_conj_transpose]
57-
58-
lemma is_hermitian_conj_transpose_mul_mul [fintype m] {A : matrix m m α} (B : matrix m n α)
59-
(hA : A.is_hermitian) : (Bᴴ ⬝ A ⬝ B).is_hermitian :=
60-
by simp only [is_hermitian, conj_transpose_mul, conj_transpose_conj_transpose, hA.eq,
61-
matrix.mul_assoc]
62-
63-
lemma is_hermitian_mul_mul_conj_transpose [fintype m] {A : matrix m m α} (B : matrix n m α)
64-
(hA : A.is_hermitian) : (B ⬝ A ⬝ Bᴴ).is_hermitian :=
65-
by simp only [is_hermitian, conj_transpose_mul, conj_transpose_conj_transpose, hA.eq,
66-
matrix.mul_assoc]
67-
68-
lemma is_hermitian_add_transpose_self (A : matrix n n α) :
69-
(A + Aᴴ).is_hermitian :=
70-
by simp [is_hermitian, add_comm]
71-
72-
lemma is_hermitian_transpose_add_self (A : matrix n n α) :
73-
(Aᴴ + A).is_hermitian :=
74-
by simp [is_hermitian, add_comm]
75-
76-
@[simp] lemma is_hermitian_zero :
77-
(0 : matrix n n α).is_hermitian :=
78-
conj_transpose_zero
79-
8054
@[simp] lemma is_hermitian.map {A : matrix n n α} (h : A.is_hermitian) (f : α → β)
8155
(hf : function.semiconj f star star) :
8256
(A.map f).is_hermitian :=
@@ -95,15 +69,6 @@ lemma is_hermitian.conj_transpose {A : matrix n n α} (h : A.is_hermitian) :
9569
Aᴴ.is_hermitian :=
9670
h.transpose.map _ $ λ _, rfl
9771

98-
@[simp] lemma is_hermitian_conj_transpose_iff (A : matrix n n α) :
99-
Aᴴ.is_hermitian ↔ A.is_hermitian :=
100-
by { intro h, rw [← conj_transpose_conj_transpose A], exact is_hermitian.conj_transpose h },
101-
is_hermitian.conj_transpose⟩
102-
103-
@[simp] lemma is_hermitian.add {A B : matrix n n α} (hA : A.is_hermitian) (hB : B.is_hermitian) :
104-
(A + B).is_hermitian :=
105-
(conj_transpose_add _ _).trans (hA.symm ▸ hB.symm ▸ rfl)
106-
10772
@[simp] lemma is_hermitian.submatrix {A : matrix n n α} (h : A.is_hermitian) (f : m → n) :
10873
(A.submatrix f f).is_hermitian :=
10974
(conj_transpose_submatrix _ _ _).trans (h.symm ▸ rfl)
@@ -112,10 +77,14 @@ h.transpose.map _ $ λ _, rfl
11277
(A.submatrix e e).is_hermitian ↔ A.is_hermitian :=
11378
⟨λ h, by simpa using h.submatrix e.symm, λ h, h.submatrix _⟩
11479

115-
/-- The real diagonal matrix `diagonal v` is hermitian. -/
116-
@[simp] lemma is_hermitian_diagonal [decidable_eq n] (v : n → ℝ) :
117-
(diagonal v).is_hermitian :=
118-
diagonal_conj_transpose _
80+
end has_star
81+
82+
section has_involutive_star
83+
variables [has_involutive_star α]
84+
85+
@[simp] lemma is_hermitian_conj_transpose_iff (A : matrix n n α) :
86+
Aᴴ.is_hermitian ↔ A.is_hermitian :=
87+
is_self_adjoint.star_iff
11988

12089
/-- A block matrix `A.from_blocks B C D` is hermitian,
12190
if `A` and `D` are hermitian and `Bᴴ = C`. -/
@@ -124,7 +93,8 @@ lemma is_hermitian.from_blocks
12493
(hA : A.is_hermitian) (hBC : Bᴴ = C) (hD : D.is_hermitian) :
12594
(A.from_blocks B C D).is_hermitian :=
12695
begin
127-
have hCB : Cᴴ = B, {rw ← hBC, simp},
96+
have hCB : Cᴴ = B,
97+
{ rw [← hBC, conj_transpose_conj_transpose] },
12898
unfold matrix.is_hermitian,
12999
rw from_blocks_conj_transpose,
130100
congr;
@@ -139,34 +109,100 @@ lemma is_hermitian_from_blocks_iff
139109
congr_arg to_blocks₁₂ h, congr_arg to_blocks₂₂ h⟩,
140110
λ ⟨hA, hBC, hCB, hD⟩, is_hermitian.from_blocks hA hBC hD⟩
141111

142-
end non_unital_semiring
112+
end has_involutive_star
143113

144-
section semiring
114+
section add_monoid
115+
variables [add_monoid α] [star_add_monoid α] [add_monoid β] [star_add_monoid β]
145116

146-
variables [semiring α] [star_ring α] [semiring β] [star_ring β]
117+
/-- A diagonal matrix is hermitian if the entries are self-adjoint -/
118+
lemma is_hermitian_diagonal_of_self_adjoint [decidable_eq n]
119+
(v : n → α) (h : is_self_adjoint v) :
120+
(diagonal v).is_hermitian :=
121+
-- TODO: add a `pi.has_trivial_star` instance and remove the `funext`
122+
(diagonal_conj_transpose v).trans $ congr_arg _ h
147123

148-
@[simp] lemma is_hermitian_one [decidable_eq n] :
149-
(1 : matrix n n α).is_hermitian :=
150-
conj_transpose_one
124+
/-- A diagonal matrix is hermitian if the entries have the trivial `star` operation
125+
(such as on the reals). -/
126+
@[simp] lemma is_hermitian_diagonal [has_trivial_star α] [decidable_eq n] (v : n → α) :
127+
(diagonal v).is_hermitian :=
128+
is_hermitian_diagonal_of_self_adjoint _ (is_self_adjoint.all _)
151129

152-
end semiring
130+
@[simp] lemma is_hermitian_zero :
131+
(0 : matrix n n α).is_hermitian :=
132+
is_self_adjoint_zero _
133+
134+
@[simp] lemma is_hermitian.add {A B : matrix n n α} (hA : A.is_hermitian) (hB : B.is_hermitian) :
135+
(A + B).is_hermitian :=
136+
is_self_adjoint.add hA hB
137+
138+
end add_monoid
139+
140+
section add_comm_monoid
141+
variables [add_comm_monoid α] [star_add_monoid α]
142+
143+
lemma is_hermitian_add_transpose_self (A : matrix n n α) :
144+
(A + Aᴴ).is_hermitian :=
145+
is_self_adjoint_add_star_self A
153146

154-
section ring
147+
lemma is_hermitian_transpose_add_self (A : matrix n n α) :
148+
(Aᴴ + A).is_hermitian :=
149+
is_self_adjoint_star_add_self A
150+
151+
end add_comm_monoid
155152

156-
variables [ring α] [star_ring α] [ring β] [star_ring β]
153+
section add_group
154+
variables [add_group α] [star_add_monoid α]
157155

158156
@[simp] lemma is_hermitian.neg {A : matrix n n α} (h : A.is_hermitian) :
159157
(-A).is_hermitian :=
160-
(conj_transpose_neg _).trans (congr_arg _ h)
158+
is_self_adjoint.neg h
161159

162160
@[simp] lemma is_hermitian.sub {A B : matrix n n α} (hA : A.is_hermitian) (hB : B.is_hermitian) :
163161
(A - B).is_hermitian :=
164-
(conj_transpose_sub _ _).trans (hA.symm ▸ hB.symm ▸ rfl)
162+
is_self_adjoint.sub hA hB
165163

166-
end ring
164+
end add_group
167165

168-
section comm_ring
166+
section non_unital_semiring
167+
variables [non_unital_semiring α] [star_ring α] [non_unital_semiring β] [star_ring β]
168+
169+
/-- Note this is more general than `is_self_adjoint.mul_star_self` as `B` can be rectangular. -/
170+
lemma is_hermitian_mul_conj_transpose_self [fintype n] (A : matrix m n α) :
171+
(A ⬝ Aᴴ).is_hermitian :=
172+
by rw [is_hermitian, conj_transpose_mul, conj_transpose_conj_transpose]
173+
174+
/-- Note this is more general than `is_self_adjoint.star_mul_self` as `B` can be rectangular. -/
175+
lemma is_hermitian_transpose_mul_self [fintype m] (A : matrix m n α) :
176+
(Aᴴ ⬝ A).is_hermitian :=
177+
by rw [is_hermitian, conj_transpose_mul, conj_transpose_conj_transpose]
169178

179+
/-- Note this is more general than `is_self_adjoint.conjugate'` as `B` can be rectangular. -/
180+
lemma is_hermitian_conj_transpose_mul_mul [fintype m] {A : matrix m m α} (B : matrix m n α)
181+
(hA : A.is_hermitian) : (Bᴴ ⬝ A ⬝ B).is_hermitian :=
182+
by simp only [is_hermitian, conj_transpose_mul, conj_transpose_conj_transpose, hA.eq,
183+
matrix.mul_assoc]
184+
185+
/-- Note this is more general than `is_self_adjoint.conjugate` as `B` can be rectangular. -/
186+
lemma is_hermitian_mul_mul_conj_transpose [fintype m] {A : matrix m m α} (B : matrix n m α)
187+
(hA : A.is_hermitian) : (B ⬝ A ⬝ Bᴴ).is_hermitian :=
188+
by simp only [is_hermitian, conj_transpose_mul, conj_transpose_conj_transpose, hA.eq,
189+
matrix.mul_assoc]
190+
191+
end non_unital_semiring
192+
193+
section semiring
194+
195+
variables [semiring α] [star_ring α] [semiring β] [star_ring β]
196+
197+
/-- Note this is more general for matrices than `is_self_adjoint_one` as it does not
198+
require `fintype n`, which is necessary for `monoid (matrix n n R)`. -/
199+
@[simp] lemma is_hermitian_one [decidable_eq n] :
200+
(1 : matrix n n α).is_hermitian :=
201+
conj_transpose_one
202+
203+
end semiring
204+
205+
section comm_ring
170206
variables [comm_ring α] [star_ring α]
171207

172208
lemma is_hermitian.inv [fintype m] [decidable_eq m] {A : matrix m m α}

0 commit comments

Comments
 (0)