Skip to main content
LESSON

7.3.13 Characteristic polynomial

We consider an n × n n\times n n × n matrix A A A , where n ≥ 0 ∧ n ∈ Z n\geq 0\land n\in\mathbb{Z} n ≥ 0 ∧ n ∈ Z . Its characteristic polynomial is recorded as p A ( x ) p_A(x) p A ​ ( x ) where

Definition of characteristic polynomial

Let's consider a n×nn\times n matrix AA, among which n0nZn\geq 0\land n\in\mathbb{Z}. Its characteristic polynomial is written as pA(x)p_A(x) Among them

pA(x)=det(xInA) p_A(x)=\det(xI_n-A)

Among them InI_n for one n×nn\times n the identity matrix. In some places it is defined as pA(x)=det(AxIn)p_A(x)=\det(A-xI_n) differs by only one symbol from our definition (1)n(-1)^n, but using this definition we get pA(x)p_A(x) must be a leading polynomial, and other definitions are only if nn It is a leading polynomial only when it is an even number. It should be noted that 0×00\times 0 The matrix determinant of is 11 It is well defined.

How to find characteristic polynomials

If n×nn\times n matrix AA is an upper triangular matrix such as

A=[a1,1a1,2a1,na2,2a2,nan,n] A= \begin{bmatrix} a_{1,1}&a_{1,2}&\cdots &a_{1,n}\\ &a_{2,2}&\cdots &a_{2,n}\\ &&\ddots &\vdots \\ &&&a_{n,n} \end{bmatrix}

Then

pA(x)=det(xInA)=[xa1,1a1,2a1,nxa2,2a2,nxan,n]=i=1n(xai,i) \begin{aligned} p_A(x)&=\det(xI_n-A)\\ &= \begin{bmatrix} x-a_{1,1}&-a_{1,2}&\cdots &-a_{1,n}\\ &x-a_{2,2}&\cdots &-a_{2,n}\\ &&\ddots &\vdots \\ &&&x-a_{n,n} \end{bmatrix} \\ &=\prod_{i=1}^n(x-a_{i,i}) \end{aligned}

It can be easily obtained, and the lower triangular matrix is similar. But if AA Does not belong to these two matrices, we need to use similarity transformation to make the matrix into a form that is easy to find the characteristic polynomial.

similarity transformation

for n×nn\times n matrix AA and BB, when exists n×nn\times n the invertible matrix PP satisfy

B=P1AP B=P^{-1}AP

we say AA and BB Similar, note transformation AP1APA\mapsto P^{-1}AP is a similar transformation. Let us say AA and P1APP^{-1}AP have the same characteristic polynomials.

consider

det(xInP1AP)=det(xP1InPP1AP)=det(P1xInPP1AP)=det(P1)det(P)det(xInA)=det(xInA)=pA(x) \begin{aligned} \det(xI_n-P^{-1}AP)&=\det(xP^{-1}I_nP-P^{-1}AP)\\ &=\det(P^{-1}xI_nP-P^{-1}AP)\\ &=\det(P^{-1})\cdot \det(P)\cdot \det(xI_n-A)\\ &=\det(xI_n-A)\\ &=p_A(x) \end{aligned}

proved, and we found APAP1A\mapsto PAP^{-1} Same thing. In addition pA(0)=(1)ndet(A)p_A(0)=(-1)^n\cdot \det(A), because pA(0)=det(1InA)=det(1In)det(A)p_A(0)=\det(-1\cdot I_nA)=\det(-1\cdot I_n)\cdot \det(A) Therefore det(A)=det(P1AP)\det(A)=\det(P^{-1}AP)

Similarity transformation using Gaussian elimination

Yes n×nn\times n matrix BB The three basic operations for performing Gaussian elimination row transformation are

  • will BB of the iijj Row swap:BPijBB\mapsto P_{ij}B
  • will BB of the ii travel by k0k\neq 0BDi(k)BB\mapsto D_i(k)B
  • will BB of the jj OK kk doubled to ii Line:BTij(k)BB\mapsto T_{ij}(k)B

for 1i<jn1\leq i\lt j\leq n These few n×nn\times n The elementary matrices of are respectively

Pij=[Ii101Iji110Inj] P_{ij}= \begin{bmatrix} I_{i-1}&&&&\\ &0&&1&\\ &&I_{j-i-1}&&\\ &1&&0&\\ &&&&I_{n-j} \end{bmatrix}

two of them 11 respectively in PijP_{ij} of the ii and jj OK, pay attention Pij1=PijP_{ij}^{-1}=P_{ij}

Di(k)=[Ii1kIni] D_i(k)= \begin{bmatrix} I_{i-1}&&\\ &k&\\ &&I_{n-i} \end{bmatrix}

Among them kk in Di(k)D_i(k) of the ii line of work ii column, note Di(k)1=Di(k1)D_i(k)^{-1}=D_i(k^{-1})

Tij(k)=[Ii11k1Inj] T_{ij}(k)= \begin{bmatrix} I_{i-1}&&&&\\ &1&&k&\\ &&\ddots &&\\ &&&1&\\ &&&&I_{n-j} \end{bmatrix}

Among them kk in Tij(k)T_{ij}(k) of the ii line of work jj column, note Tij(k)1=Tij(k)T_{ij}(k)^{-1}=T_{ij}(-k)

If we remember EijE_{ij} for the first ii line of work jj The elements of the column are 11, the rest is zero n×nn\times n matrix, then

  • Pij=InEiiEjj+Eij+EjiP_{ij}=I_n-E_{ii}-E_{jj}+E_{ij}+E_{ji}
  • Di(k)=In+(k1)EiiD_i(k)=I_n+(k-1)E_{ii}
  • Tij(k)=In+kEijT_{ij}(k)=I_n+kE_{ij}

It is easy to verify its inverse matrix.

After we use the above operation on the matrix (left multiplication of the elementary matrix), we then right-multiply its inverse matrix, which is the similarity transformation. The left multiplication is the row transformation, and it is easy to find that the right multiplication is the column transformation.

If we can transform the matrix into an upper triangular or lower triangular form through similarity transformation, then its characteristic polynomial can be easily obtained. But we found that if we apply a transformation to the elements on the main diagonal ATij(k)ATij(k)A\mapsto T_{ij}(k)AT_{ij}(-k) will later cause the original pass ATij(k)AA\mapsto T_{ij}(k)A General ii line of work jj The elements of the column are eliminated to zero and then multiplied by the right Tij(k)T_{ij}(-k) Coming soon AA of the ii column k-k doubled to jj The operation of column makes it possible that elements that were previously eliminated to zero may now be non-zero, and may not be transformed into upper or lower triangular form.

It will be explained later that the matrix obtained after applying transformation to the elements on the subdiagonal can still easily obtain its characteristic polynomial.

Upper Hessenberg matrix

for n>2n\gt 2 shaped like

H=[α1h12h1nβ2α2h23h(n1)nβnαn] H= \begin{bmatrix} \alpha_{1}&h_{12}&\dots&\dots&h_{1n}\\ \beta_{2}&\alpha_{2}&h_{23}&\dots &\vdots \\ &\ddots &\ddots & \ddots &\vdots \\ & &\ddots &\ddots & h_{(n-1)n}\\ &&& \beta_{n}& \alpha_{n} \end{bmatrix}

The matrix is called the upper Hessenberg matrix, where β\beta is a sub-diagonal line.

We can obtain the upper Hessenberg matrix by using a similarity transformation to eliminate the elements below the sub-diagonal to zero, and find a n×nn\times n The characteristic polynomial of the upper Hessenberg matrix can be found in O(n3)O(n^3) Time is done.

we remember HiH_i reserved for only HH before ii line and before ii column matrix, note pi(x)=det(xIiHi)p_i(x)=\det(xI_i-H_i) Then

H0=[],p0(x)=1 H_0= \begin{bmatrix} \end{bmatrix},\quad p_0(x)=1

H1=[α1],p1(x)=det(xI1H1)=xα1 H_1= \begin{bmatrix} \alpha_1 \end{bmatrix},\quad p_1(x)=\det(x I_1-H_1)=x -\alpha_1

H2=[α1h12β2α2],p2(x)=det(xI2H2)=(xα2)p1(x)β2h12p0(x) H_2= \begin{bmatrix} \alpha_1&h_{12}\\ \beta_2&\alpha_2 \end{bmatrix},\quad p_2(x)=\det(xI_2-H_2)=(x-\alpha_2)p_1(x)-\beta_2h_{12}p_0(x)

When calculating the determinant, we generally choose to expand by the cofactor of the row or column with the most zeros. The cosubform is the matrix after deleting the row and column of the currently selected element. Here we choose to expand by the last row, and there is

p3(x)=det(xI3H3)=xα1h12h13β2xα2h23β3xα3=(xα3)(1)3+3p2(x)β3(1)3+2xα1h13β2h23=(xα3)p2(x)β3(h23p1(x)+β2h13p0(x)) \begin{aligned} p_3(x)&= \det(xI_3-H_3)\\ &=\begin{vmatrix} x-\alpha_1&-h_{12}&-h_{13}\\ -\beta_2&x-\alpha_2&-h_{23}\\ &-\beta_3&x-\alpha_3 \end{vmatrix}\\ &=(x-\alpha_3)\cdot (-1)^{3+3}p_2(x)-\beta_3\cdot (-1)^{3+2} \begin{vmatrix} x-\alpha_1&-h_{13}\\ -\beta_2&-h_{23} \end{vmatrix}\\ &=(x-\alpha_3)p_2(x)-\beta_3(h_{23}p_1(x)+\beta_2h_{13}p_0(x)) \end{aligned}

Observe and summarize, yes 2in2\leq i\leq n Yes

pi(x)=(xαi)pi1(x)m=1i1him,i(j=im+1iβj)pim1(x) p_i(x)=(x-\alpha_i)p_{i-1}(x)- \sum_{m=1}^{i-1}h_{i-m,i} \left( \prod_{j=i-m+1}^{i}\beta_j \right) p_{i-m-1}(x)

This completes the entire algorithm, which is generally called the Hessenberg algorithm.

Application

In informatics we generally consider (Z/mZ)n×n(\mathbb{Z}/m\mathbb{Z})^{n\times n} matrix, usually mm is a prime number, it is simple to perform the above similarity transformation, when mm When it is a composite number, we can consider a method similar to euclidean division.

 #include <iostream> #include <random> #include <vector> typedef std::vector<std::vector<int>> Matrix; typedef long long i64; Matrix to_upper_Hessenberg(const Matrix &M, int mod) { Matrix H(M); int n = H.size(); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if ((H[i][j] %= mod) < 0) H[i][j] += mod; } } for (int i = 0; i < n - 1; ++i) { int pivot = i + 1; for (; pivot < n; ++pivot) { if (H[pivot][i] != 0) break; } if (pivot == n) continue; if (pivot != i + 1) { for (int j = i; j < n; ++j) std::swap(H[i + 1][j], H[pivot][j]); for (int j = 0; j < n; ++j) std::swap(H[j][i + 1], H[j][pivot]); } for (int j = i + 2; j < n; ++j) { for (;;) { if (H[j][i] == 0) break; if (H[i + 1][i] == 0) { for (int k = i; k < n; ++k) std::swap(H[i + 1][k], H[j][k]); for (int k = 0; k < n; ++k) std::swap(H[k][i + 1], H[k][j]); break; } if (H[j][i] >= H[i + 1][i]) { int q = H[j][i] / H[i + 1][i], mq = mod - q; for (int k = i; k < n; ++k) H[j][k] = (H[j][k] + i64(mq) * H[i + 1][k]) % mod; for (int k = 0; k < n; ++k) H[k][i + 1] = (H[k][i + 1] + i64(q) * H[k][j]) % mod; } else { int q = H[i + 1][i] / H[j][i], mq = mod - q; for (int k = i; k < n; ++k) H[i + 1][k] = (H[i + 1][k] + i64(mq) * H[j][k]) % mod; for (int k = 0; k < n; ++k) H[k][j] = (H[k][j] + i64(q) * H[k][i + 1]) % mod; } } } } return H; } std::vector<int> get_charpoly(const Matrix &M, int mod) { Matrix H(to_upper_Hessenberg(M, mod)); int n = H.size(); std::vector<std::vector<int>> p(n + 1); p[0] = {1 % mod}; for (int i = 1; i <= n; ++i) { const std::vector<int> &pi_1 = p[i - 1]; std::vector<int> &pi = p[i]; pi.resize(i + 1, 0); int v = mod - H[i - 1][i - 1]; if (v == mod) v -= mod; for (int j = 0; j < i; ++j) { pi[j] = (pi[j] + i64(v) * pi_1[j]) % mod; if ((pi[j + 1] += pi_1[j]) >= mod) pi[j + 1] -= mod; } int t = 1; for (int j = 1; j < i; ++j) { t = i64(t) * H[i - j][i - j - 1] % mod; int prod = i64(t) * H[i - j - 1][i - 1] % mod; if (prod == 0) continue; prod = mod - prod; for (int k = 0; k <= i - j - 1; ++k) pi[k] = (pi[k] + i64(prod) * p[i - j - 1][k]) % mod; } } return p[n]; } bool verify(const Matrix &M, const std::vector<int> &charpoly, int mod) { if (mod == 1) return true; int n = M.size(); std::vector<int> randvec(n), sum(n, 0); std::mt19937 gen(std::random_device{}()); std::uniform_int_distribution<int> dis(1, mod - 1); for (int i = 0; i < n; ++i) randvec[i] = dis(gen); for (int i = 0; i <= n; ++i) { int v = charpoly[i]; for (int j = 0; j < n; ++j) sum[j] = (sum[j] + i64(v) * randvec[j]) % mod; std::vector<int> prod(n, 0); for (int j = 0; j < n; ++j) { for (int k = 0; k < n; ++k) { prod[j] = (prod[j] + i64(M[j][k]) * randvec[k]) % mod; } } randvec.swap(prod); } for (int i = 0; i < n; ++i) if (sum[i] != 0) return false; return true; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); int n, mod; std::cin >> n >> mod; Matrix M(n, std::vector<int>(n)); for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) std::cin >> M[i][j]; std::vector<int> charpoly(get_charpoly(M, mod)); for (int i = 0; i <= n; ++i) std::cout << charpoly[i] << ' '; assert(verify(M, charpoly, mod)); return 0; }

The above Hessenberg algorithm is not numerically stable, so Rn×n\mathbb{R}^{n\times n} The matrix above needs to be adjusted by other algorithms or switched to other algorithms with numerical stability before use.

We can connect characteristic polynomials with homogeneous linear recursion with constant coefficients, or combine it with the Cayley-Hamilton theorem and polynomial modulo to speed up algorithms for finding matrix powers in some domains.

The Cayley-Hamilton theorem states

pA(A)=An+c1An1++cn1A+cnI=O \begin{aligned} p_A(A)&=A^n+c_1A^{n-1}+\cdots +c_{n-1}A+c_nI\\ &=O \end{aligned}

Among them OO for n×nn\times n The zero matrix ofACn×nA\in\mathbb{C}^{n\times n} And pA(x)=xn+i=1ncixniC[x]p_A(x)=x^n+\sum_{i=1}^nc_ix^{n-i}\in\mathbb{C}[x] for AA The characteristic polynomial of .

if we ask AKA^K Among them KK is larger, then we can find f(x)=xKmodpA(x)f(x)=x^K\bmod{p_A(x)} Later use f(A)=AKf(A)=A^K

And deg(f(x))<n\deg(f(x))\lt n Obviously. we order f(x)=i=0n1fixif(x)=\sum_{i=0}^{n-1}f_ix^i And n=kmn=km Then

fkm1xkm1++f1x+f0=((fkm1xk1++fk(m1))xk+fk(m1)1xk1++fk(m2))xk++fk1xk1++f1x+f0 \begin{aligned} f_{km-1}x^{km-1}+\cdots +f_1x+f_0&=(\cdots (f_{km-1}x^{k-1}+\cdots +f_{k(m-1)})x^k\\ &+f_{k(m-1)-1}x^{k-1}+\cdots +f_{k(m-2)})x^k\\ &+\cdots\\ &+f_{k-1}x^{k-1}+\cdots +f_1x+f_0 \end{aligned}

Order k=nk=\sqrt{n} Calculations can be found f(A)f(A) It takes about O(n)O(\sqrt{n}) Submatrix and matrix multiplication.