QiuQiu

Linear Algebra - Trace

迹(trace)是方阵对角线元素之和。它看起来是最简单的矩阵不变量,却是连接“矩阵”和“线性映射”两种视角的桥。这篇按 Mathlib 的组织方式过一遍:定义、基本性质、核心定理 tr(AB)=tr(BA)\operatorname{tr}(AB)=\operatorname{tr}(BA) 的完整推导、由它派生出的相似不变性,最后是与特征值的关系。所有定理名都对照 Mathlib/LinearAlgebra/Matrix/Trace.lean

定义

tr(A)=iAii\operatorname{tr}(A)=\sum_{i} A_{ii}

Mathlib 里它就是一个普通函数,输入 n×nn\times n 矩阵,输出一个标量:

def Matrix.trace (A : Matrix n n R) : R :=
  ∑ i, diag A i

diag A i 就是 AiiA_{ii}。要求 n 是有限类型(Fintype n),R 是加法交换幺半群(AddCommMonoid R),因为只用到了“有限个数相加”。注意定义里没有乘法,所以迹在任何能做加法的地方都有定义,不需要环。

同一个函数还被打包成两种带结构的形式:

名字 类型 附带的证明
Matrix.trace Matrix n n R → R 无,纯函数
Matrix.traceAddMonoidHom Matrix n n R →+ R 保 0、保加法
Matrix.traceLinearMap Matrix n n R →ₗ[α] R 保加法、保数乘

三者的 toFun 都是同一个 trace。后两个的意义是:当你需要把“迹是线性的”这个事实交给别的定理(比如 map_sum)时,直接用打包好的版本,不用每次手证。

基本性质

全部是定义加求和的性质,不涉及矩阵乘法:

性质 Mathlib 用到的求和工具
tr(0)=0\operatorname{tr}(0)=0 trace_zero Finset.sum_const_zero
tr(A+B)=trA+trB\operatorname{tr}(A+B)=\operatorname{tr}A+\operatorname{tr}B trace_add Finset.sum_add_distrib
tr(rA)=rtrA\operatorname{tr}(rA)=r\operatorname{tr}A trace_smul Finset.smul_sum
tr(AT)=trA\operatorname{tr}(A^{\mathsf T})=\operatorname{tr}A trace_transpose 无,AiiT=AiiA^{\mathsf T}_{ii}=A_{ii} 按定义
tr(In)=n\operatorname{tr}(I_n)=n trace_one Finset.card
tr(diag(d))=idi\operatorname{tr}(\operatorname{diag}(d))=\sum_i d_i trace_diagonal 按定义
tr(abcd)=a+d\operatorname{tr}\begin{pmatrix}a&b\\c&d\end{pmatrix}=a+d trace_fin_two_of Fin.sum_univ_two

trace_one 值得看一眼:结果是 Fintype.card n,也就是维数,类型是自然数被强制转换到 R

配套练习:(AB)ij(AB)_{ij} 的下标怎么读,后面每一步推导都建立在那个读法上。

核心定理:tr(AB)=tr(BA)\operatorname{tr}(AB)=\operatorname{tr}(BA)

手算

AAm×nm\times n,BBn×mn\times mABABm×mm\times m,BABAn×nn\times n,两个方阵大小不同,但迹相等:

tr(AB)=i=1m(AB)ii=i=1mk=1nAikBki\operatorname{tr}(AB)=\sum_{i=1}^{m}(AB)_{ii}=\sum_{i=1}^{m}\sum_{k=1}^{n}A_{ik}B_{ki}
tr(BA)=k=1n(BA)kk=k=1ni=1mBkiAik\operatorname{tr}(BA)=\sum_{k=1}^{n}(BA)_{kk}=\sum_{k=1}^{n}\sum_{i=1}^{m}B_{ki}A_{ik}

两式被加项 AikBkiA_{ik}B_{ki}BkiAikB_{ki}A_{ik} 差一个标量交换(mul_comm),两层求和的顺序差一个换序(Finset.sum_comm)。就这两步。

Mathlib 怎么拆

Mathlib 没有一步到位,而是拆成两个定理,恰好把 Finset.sum_commmul_comm 的分工分开了。

第一步,不需要交换律:

theorem trace_transpose_mul [AddCommMonoid R] [Mul R]
    (A : Matrix m n R) (B : Matrix n m R) :
    trace (Aᵀ * Bᵀ) = trace (A * B) :=
  Finset.sum_comm

证明就是 Finset.sum_comm 本身。展开看为什么:

tr(ATBT)=ikAikTBkiT=ikAkiBik\operatorname{tr}(A^{\mathsf T}B^{\mathsf T}) =\sum_{i}\sum_{k}A^{\mathsf T}_{ik}B^{\mathsf T}_{ki} =\sum_{i}\sum_{k}A_{ki}B_{ik}
tr(AB)=kiAkiBik\operatorname{tr}(AB) =\sum_{k}\sum_{i}A_{ki}B_{ik}

第二行只是把 tr(AB)\operatorname{tr}(AB) 的求和变量改名(iki\leftrightarrow k)。两边被加项逐字相同,是 AkiBikA_{ki}B_{ik},顺序都没换,只差外层求 ii 还是求 kk。所以这一步只用 Finset.sum_comm,标量不需要能交换,类型类假设只有 [Mul R]

第二步,才用到交换律:

theorem trace_mul_comm [AddCommMonoid R] [CommMagma R]
    (A : Matrix m n R) (B : Matrix n m R) :
    trace (A * B) = trace (B * A) := by
  rw [← trace_transpose, ← trace_transpose_mul, transpose_mul]

三次改写:

  1. ← trace_transpose:tr(AB)=tr((AB)T)\operatorname{tr}(AB)=\operatorname{tr}\big((AB)^{\mathsf T}\big)
  2. ← trace_transpose_mul:tr((AB)T)\operatorname{tr}\big((AB)^{\mathsf T}\big),把它看成 tr(XTYT)\operatorname{tr}(X^{\mathsf T}Y^{\mathsf T}) 的形式后倒推回 tr(XY)\operatorname{tr}(XY)。需要先把 (AB)T(AB)^{\mathsf T} 写成两个转置的乘积
  3. transpose_mul:(AB)T=BTAT(AB)^{\mathsf T}=B^{\mathsf T}A^{\mathsf T}

mul_comm 就藏在第 3 步。(AB)ijT=(AB)ji=kAjkBki(AB)^{\mathsf T}_{ij}=(AB)_{ji}=\sum_k A_{jk}B_{ki},而 (BTAT)ij=kBkiAjk(B^{\mathsf T}A^{\mathsf T})_{ij}=\sum_k B_{ki}A_{jk},要让 AjkBki=BkiAjkA_{jk}B_{ki}=B_{ki}A_{jk} 必须交换标量。所以 trace_mul_comm 的假设是 [CommMagma R],比上一步多了交换性。

这个拆法回答了“什么时候 ABAB 可以调换”:

推论

循环不变,而非任意置换不变

theorem trace_mul_cycle (A : Matrix m n R) (B : Matrix n p R) (C : Matrix p m R) :
    trace (A * B * C) = trace (C * A * B) := by
  rw [trace_mul_comm, Matrix.mul_assoc]

tr(ABC)=tr(CAB)=tr(BCA)\operatorname{tr}(ABC)=\operatorname{tr}(CAB)=\operatorname{tr}(BCA),把 (AB)(AB) 看成一个整体套 trace_mul_comm,再用结合律。但 tr(ABC)tr(ACB)\operatorname{tr}(ABC)\ne\operatorname{tr}(ACB),一般情况下不成立。三个矩阵有 6 种排列,只有 3 种循环排列的迹相等。

相似不变

theorem trace_units_conj (M : (Matrix m m R)ˣ) (N : Matrix m m R) :
    trace (↑M * N * ↑M⁻¹) = trace N

tr(PNP1)=tr(P1PN)=tr(N)\operatorname{tr}(PNP^{-1})=\operatorname{tr}(P^{-1}PN)=\operatorname{tr}(N),trace_mul_cycle 的直接应用。这条是迹能脱离矩阵、成为线性映射自身性质的原因:换一组基,矩阵变成 PNP1PNP^{-1},迹不变。

Mathlib 据此定义了与基无关的 LinearMap.trace,并证明它与任何一组基下的矩阵迹一致:

theorem LinearMap.trace_eq_matrix_trace (f : M →ₗ[R] M) :
    trace R M f = Matrix.trace (LinearMap.toMatrix b b f)

外积的迹是内积

theorem trace_vecMulVec (a b : n → R) :
    trace (vecMulVec a b) = a ⬝ᵥ b

tr(uvT)=iuivi=uv\operatorname{tr}(uv^{\mathsf T})=\sum_i u_iv_i=u\cdot v。推广一步:tr(ATB)=i,jAijBij\operatorname{tr}(A^{\mathsf T}B)=\sum_{i,j}A_{ij}B_{ij},这就是 Frobenius 内积,机器学习里 AF2=tr(ATA)\|A\|_F^2=\operatorname{tr}(A^{\mathsf T}A) 的来源。

与特征值的关系

迹是特征多项式次高项系数的相反数:

theorem trace_eq_neg_charpoly_coeff [Nonempty n] (M : Matrix n n R) :
    trace M = -M.charpoly.coeff (Fintype.card n - 1)

当特征多项式能完全分裂(比如域代数封闭)时,迹等于所有特征值之和(按重数计):

theorem trace_eq_sum_roots_charpoly [IsAlgClosed K] :
    A.trace = (Matrix.charpoly A).roots.sum

注意假设。实数域上 (0110)\begin{pmatrix}0&-1\\1&0\end{pmatrix} 没有实特征值,但迹是 0,所以“迹等于特征值之和”要么在复数域上说,要么加上 Splits 假设。定理名后缀 _of_splits 的版本就是带这个假设的。

迹不是什么

层级速查

本文用到的
抽象代数 mul_commmul_assoc
大算符(BigOperators) Finset.sum_commFinset.sum_add_distribFinset.smul_sum
矩阵(定义层) Matrix.traceMatrix.mul_applytranspose_mul
矩阵(定理层) trace_transpose_multrace_mul_commtrace_mul_cycletrace_units_conj
线性映射 LinearMap.traceLinearMap.trace_eq_matrix_trace
特征多项式 trace_eq_neg_charpoly_coefftrace_eq_sum_roots_charpoly