Skip to content

Commit 1c65b42

Browse files
committed
feat: port LinearAlgebra.Matrix.Trace (#3231)
Co-authored-by: Parcly Taxel <reddeloostw@gmail.com>
1 parent ec578b0 commit 1c65b42

File tree

2 files changed

+206
-0
lines changed

2 files changed

+206
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ import Mathlib.LinearAlgebra.GeneralLinearGroup
11951195
import Mathlib.LinearAlgebra.InvariantBasisNumber
11961196
import Mathlib.LinearAlgebra.LinearIndependent
11971197
import Mathlib.LinearAlgebra.LinearPMap
1198+
import Mathlib.LinearAlgebra.Matrix.Trace
11981199
import Mathlib.LinearAlgebra.Pi
11991200
import Mathlib.LinearAlgebra.Prod
12001201
import Mathlib.LinearAlgebra.Projection
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/-
2+
Copyright (c) 2019 Johannes Hölzl. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Johannes Hölzl, Patrick Massot, Casper Putz, Anne Baanen
5+
6+
! This file was ported from Lean 3 source module linear_algebra.matrix.trace
7+
! leanprover-community/mathlib commit 32b08ef840dd25ca2e47e035c5da03ce16d2dc3c
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Data.Matrix.Basic
12+
13+
/-!
14+
# Trace of a matrix
15+
16+
This file defines the trace of a matrix, the map sending a matrix to the sum of its diagonal
17+
entries.
18+
19+
See also `LinearAlgebra.Trace` for the trace of an endomorphism.
20+
21+
## Tags
22+
23+
matrix, trace, diagonal
24+
25+
-/
26+
27+
28+
open BigOperators Matrix
29+
30+
namespace Matrix
31+
32+
variable {ι m n p : Type _} {α R S : Type _}
33+
34+
variable [Fintype m] [Fintype n] [Fintype p]
35+
36+
section AddCommMonoid
37+
38+
variable [AddCommMonoid R]
39+
40+
/-- The trace of a square matrix. For more bundled versions, see:
41+
* `Matrix.traceAddMonoidHom`
42+
* `Matrix.traceLinearMap`
43+
-/
44+
def trace (A : Matrix n n R) : R :=
45+
∑ i, diag A i
46+
#align matrix.trace Matrix.trace
47+
48+
variable (n R)
49+
50+
@[simp]
51+
theorem trace_zero : trace (0 : Matrix n n R) = 0 :=
52+
(Finset.sum_const (0 : R)).trans <| smul_zero _
53+
#align matrix.trace_zero Matrix.trace_zero
54+
55+
variable {n R}
56+
57+
@[simp]
58+
theorem trace_add (A B : Matrix n n R) : trace (A + B) = trace A + trace B :=
59+
Finset.sum_add_distrib
60+
#align matrix.trace_add Matrix.trace_add
61+
62+
@[simp]
63+
theorem trace_smul [Monoid α] [DistribMulAction α R] (r : α) (A : Matrix n n R) :
64+
trace (r • A) = r • trace A :=
65+
Finset.smul_sum.symm
66+
#align matrix.trace_smul Matrix.trace_smul
67+
68+
@[simp]
69+
theorem trace_transpose (A : Matrix n n R) : trace Aᵀ = trace A :=
70+
rfl
71+
#align matrix.trace_transpose Matrix.trace_transpose
72+
73+
@[simp]
74+
theorem trace_conjTranspose [StarAddMonoid R] (A : Matrix n n R) : trace Aᴴ = star (trace A) :=
75+
(star_sum _ _).symm
76+
#align matrix.trace_conj_transpose Matrix.trace_conjTranspose
77+
78+
variable (n α R)
79+
80+
/-- `Matrix.trace` as an `AddMonoidHom` -/
81+
@[simps]
82+
def traceAddMonoidHom : Matrix n n R →+ R where
83+
toFun := trace
84+
map_zero' := trace_zero n R
85+
map_add' := trace_add
86+
#align matrix.trace_add_monoid_hom Matrix.traceAddMonoidHom
87+
88+
/-- `Matrix.trace` as a `LinearMap` -/
89+
@[simps]
90+
def traceLinearMap [Semiring α] [Module α R] : Matrix n n R →ₗ[α] R where
91+
toFun := trace
92+
map_add' := trace_add
93+
map_smul' := trace_smul
94+
#align matrix.trace_linear_map Matrix.traceLinearMap
95+
96+
variable {n α R}
97+
98+
@[simp]
99+
theorem trace_list_sum (l : List (Matrix n n R)) : trace l.sum = (l.map trace).sum :=
100+
map_list_sum (traceAddMonoidHom n R) l
101+
#align matrix.trace_list_sum Matrix.trace_list_sum
102+
103+
@[simp]
104+
theorem trace_multiset_sum (s : Multiset (Matrix n n R)) : trace s.sum = (s.map trace).sum :=
105+
map_multiset_sum (traceAddMonoidHom n R) s
106+
#align matrix.trace_multiset_sum Matrix.trace_multiset_sum
107+
108+
@[simp]
109+
theorem trace_sum (s : Finset ι) (f : ι → Matrix n n R) :
110+
trace (∑ i in s, f i) = ∑ i in s, trace (f i) :=
111+
map_sum (traceAddMonoidHom n R) f s
112+
#align matrix.trace_sum Matrix.trace_sum
113+
114+
end AddCommMonoid
115+
116+
section AddCommGroup
117+
118+
variable [AddCommGroup R]
119+
120+
@[simp]
121+
theorem trace_sub (A B : Matrix n n R) : trace (A - B) = trace A - trace B :=
122+
Finset.sum_sub_distrib
123+
#align matrix.trace_sub Matrix.trace_sub
124+
125+
@[simp]
126+
theorem trace_neg (A : Matrix n n R) : trace (-A) = -trace A :=
127+
Finset.sum_neg_distrib
128+
#align matrix.trace_neg Matrix.trace_neg
129+
130+
end AddCommGroup
131+
132+
section One
133+
134+
variable [DecidableEq n] [AddCommMonoidWithOne R]
135+
136+
@[simp]
137+
theorem trace_one : trace (1 : Matrix n n R) = Fintype.card n := by
138+
simp_rw [trace, diag_one, Pi.one_def, Finset.sum_const, nsmul_one, Finset.card_univ]
139+
#align matrix.trace_one Matrix.trace_one
140+
141+
end One
142+
143+
section Mul
144+
145+
@[simp]
146+
theorem trace_transpose_mul [AddCommMonoid R] [Mul R] (A : Matrix m n R) (B : Matrix n m R) :
147+
trace (Aᵀ ⬝ Bᵀ) = trace (A ⬝ B) :=
148+
Finset.sum_comm
149+
#align matrix.trace_transpose_mul Matrix.trace_transpose_mul
150+
151+
theorem trace_mul_comm [AddCommMonoid R] [CommSemigroup R] (A : Matrix m n R) (B : Matrix n m R) :
152+
trace (A ⬝ B) = trace (B ⬝ A) := by rw [← trace_transpose, ← trace_transpose_mul, transpose_mul]
153+
#align matrix.trace_mul_comm Matrix.trace_mul_comm
154+
155+
theorem trace_mul_cycle [NonUnitalCommSemiring R] (A : Matrix m n R) (B : Matrix n p R)
156+
(C : Matrix p m R) : trace (A ⬝ B ⬝ C) = trace (C ⬝ A ⬝ B) := by
157+
rw [trace_mul_comm, Matrix.mul_assoc]
158+
#align matrix.trace_mul_cycle Matrix.trace_mul_cycle
159+
160+
theorem trace_mul_cycle' [NonUnitalCommSemiring R] (A : Matrix m n R) (B : Matrix n p R)
161+
(C : Matrix p m R) : trace (A ⬝ (B ⬝ C)) = trace (C ⬝ (A ⬝ B)) := by
162+
rw [← Matrix.mul_assoc, trace_mul_comm]
163+
#align matrix.trace_mul_cycle' Matrix.trace_mul_cycle'
164+
165+
@[simp]
166+
theorem trace_col_mul_row [NonUnitalNonAssocSemiring R] (a b : n → R) :
167+
trace (col a ⬝ row b) = dotProduct a b := by
168+
apply Finset.sum_congr rfl
169+
simp [mul_apply]
170+
#align matrix.trace_col_mul_row Matrix.trace_col_mul_row
171+
172+
end Mul
173+
174+
section Fin
175+
176+
variable [AddCommMonoid R]
177+
178+
/-! ### Special cases for `Fin n`
179+
180+
While `simp [Fin.sum_univ_succ]` can prove these, we include them for convenience and consistency
181+
with `Matrix.det_fin_two` etc.
182+
-/
183+
184+
185+
@[simp]
186+
theorem trace_fin_zero (A : Matrix (Fin 0) (Fin 0) R) : trace A = 0 :=
187+
rfl
188+
#align matrix.trace_fin_zero Matrix.trace_fin_zero
189+
190+
theorem trace_fin_one (A : Matrix (Fin 1) (Fin 1) R) : trace A = A 0 0 :=
191+
add_zero _
192+
#align matrix.trace_fin_one Matrix.trace_fin_one
193+
194+
theorem trace_fin_two (A : Matrix (Fin 2) (Fin 2) R) : trace A = A 0 0 + A 1 1 :=
195+
congr_arg ((· + ·) _) (add_zero (A 1 1))
196+
#align matrix.trace_fin_two Matrix.trace_fin_two
197+
198+
theorem trace_fin_three (A : Matrix (Fin 3) (Fin 3) R) : trace A = A 0 0 + A 1 1 + A 2 2 := by
199+
rw [← add_zero (A 2 2), add_assoc]
200+
rfl
201+
#align matrix.trace_fin_three Matrix.trace_fin_three
202+
203+
end Fin
204+
205+
end Matrix

0 commit comments

Comments
 (0)