Jacobi方法求解特征值、特征向量
1. Givens变换
Jacobi 方法是用来计算实对称矩阵的全部特征值和特征向量的一种方法, 它的基本思想是: 因为任何一个实对称矩阵都与一个对角矩阵相似, 所以通过正交相似变换把实对称矩阵化为对角矩阵, 对角矩阵的对角线上的元素即为所求特征值. 由线性代数的知识 得, 若
A
∈
R
n
×
n
\mathbf{A} {\in} {\mathbf{R}}^{n {\times} n}
A∈Rn×n 为对称矩阵, 则存在一个正交矩阵
P
\mathbf{P}
P , 使得
P
A
P
−
1
=
diag
(
λ
1
,
λ
2
,
⋯
,
λ
n
)
=
D
\mathbf{PA}{\mathbf{P}}^{{-}1} = \operatorname{diag}\left( {\lambda}_{1},{\lambda}_{2},{\cdots},{\lambda}_{n} \right) = \mathbf{D}
PAP−1=diag(λ1,λ2,⋯,λn)=D
λ
1
,
λ
2
,
⋯
,
λ
n
{\lambda}_{1},{\lambda}_{2},{\cdots},{\lambda}_{n}
λ1,λ2,⋯,λn 即为矩阵
A
\mathbf{A}
A 的特征值,
P
T
{\mathbf{P}}^{\mathrm{T}}
PT 的
n
n
n 个列向量
v
1
,
v
2
,
⋯
,
v
n
v_{1},v_{2},{\cdots},v_{n}
v1,v2,⋯,vn 即为所对应的特征向量
P
=
[
1
⋱
cos
θ
sin
θ
1
⋱
1
−
sin
θ
cos
θ
1
⋱
1
]
≡
P
(
i
,
j
)
\mathbf{P} = \begin{bmatrix} 1 & & & & & & & \\ & {\ddots} & & & & & & \\ & & \cos\theta & & & & \sin\theta & \\ & & & 1 & & & & \\ & & & & {\ddots} & & & \\ & & & & & 1 & & \\ & & {-} \sin\theta & & & & \cos\theta & \\ & & & & & & & 1 \\ & & & & & & & & {\ddots} \\ & & & & & & & & & 1 \end{bmatrix} {\equiv} \mathbf{P}(i, j)
P=
1⋱cosθ−sinθ1⋱1sinθcosθ1⋱1
≡P(i,j)
称
P
\mathbf{P}
P 为平面旋转矩阵,
P
A
PA
PA 只改变
A
A
A 的第
i
i
i 行与第
j
j
j 行的元素;
A
P
T
AP^{\mathrm{T}}
APT 只改变
A
A
A 的第
i
i
i 列与第
j
j
j 列的元素;
P
A
P
T
PAP^{T}
PAPT 只改变
A
A
A 的第
i
i
i 行和第
j
j
j 行, 第
i
i
i 列与第
j
j
j 列的元素,考虑
n
=
2
n = 2
n=2 的情况, 设
A
=
[
a
11
a
12
a
21
a
22
]
\mathbf{A} = \left\lbrack \begin{array}{ll} a_{11} & a_{12} \\ a_{21} & a_{22} \end{array} \right\rbrack
A=[a11a21a12a22] 为对称矩阵, 今取
P
=
[
cos
θ
sin
θ
−
sin
θ
cos
θ
]
\mathbf{P} = \begin{bmatrix} \cos\theta & \sin\theta \\ {-} \sin\theta & \cos\theta \end{bmatrix}
P=[cosθ−sinθsinθcosθ] , 显然
P
\mathbf{P}
P 为正交矩阵, 令
P
A
P
T
=
C
=
[
c
11
c
12
c
21
c
22
]
\mathbf{PA}{\mathbf{P}}^{\mathrm{T}} = \mathbf{C} = \left\lbrack \begin{array}{ll} c_{11} & c_{12} \\ c_{21} & c_{22} \end{array} \right\rbrack
PAPT=C=[c11c21c12c22] , 由矩阵乘法得
- c 11 = a 11 cos 2 θ + a 21 sin 2 θ + a 22 sin 2 θ , c_{11} = a_{11}{\cos}^{2}\theta + a_{21}\sin 2\theta + a_{22}{\sin}^{2}\theta, c11=a11cos2θ+a21sin2θ+a22sin2θ,
- c 22 = − a 12 sin 2 θ + a 11 sin 2 θ + a 22 cos 2 θ , c_{22} = {-} a_{12}\sin 2\theta + a_{11}{\sin}^{2}\theta + a_{22}{\cos}^{2}\theta, c22=−a12sin2θ+a11sin2θ+a22cos2θ,
- c 21 = c 12 = 1 2 ( a 22 − a 11 ) sin 2 θ + a 21 cos 2 θ . c_{21} = c_{12} = \frac{1}{2}\left( a_{22} {-} a_{11} \right)\sin 2\theta + a_{21}\cos 2\theta. c21=c12=21(a22−a11)sin2θ+a21cos2θ.
为使得 P A P T = C \mathbf{P}\mathbf{A}{\mathbf{P}}^{\mathrm{T}} = \mathbf{C} PAPT=C 成为对角矩阵, 应选择 θ \theta θ 使 c 21 = c 12 = 0 c_{21} = c_{12} = 0 c21=c12=0 , 即 1 2 ( a 22 − a 11 ) sin 2 θ + a 21 cos 2 θ = 0 , \frac{1}{2}\left( a_{22} {-} a_{11} \right)\sin 2\theta + a_{21}\cos 2\theta = 0, 21(a22−a11)sin2θ+a21cos2θ=0,得 tan 2 θ = 2 a 21 a 11 − a 22 \tan 2\theta = \frac{2a_{21}}{a_{11} {-} a_{22}} tan2θ=a11−a222a21 , 由此可得 θ \theta θ 的值. 若 a 11 = a 22 a_{11} = a_{22} a11=a22 时, 取 ∣ θ ∣ = π 4 ; a 11 > 0 |\theta| = \frac{\pi}{4};a_{11} > 0 ∣θ∣=4π;a11>0 时, θ = π 4 ; a 11 < 0 \theta = \frac{\pi}{4};a_{11} < 0 θ=4π;a11<0 时, θ = − π 4 \theta = {-} \frac{\pi}{4} θ=−4π , 结果就使得 P A P T = diag ( λ 1 , λ 2 ) \mathbf{P}\mathbf{A}{\mathbf{P}}^{\mathrm{T}} = \operatorname{diag}\left( {\lambda}_{1},{\lambda}_{2} \right) PAPT=diag(λ1,λ2) ,则 C = P A P T \mathbf{C} = \mathbf{P}\mathbf{A}{\mathbf{P}}^{\mathrm{T}} C=PAPT 的元素 c i j c_{ij} cij 的计算公式为:
-
c i i = a i i cos 2 θ + a i j sin 2 θ + a j j sin 2 θ c_{ii} = a_{ii}{\cos}^{2}\theta + a_{ij}\sin 2\theta + a_{jj}{\sin}^{2}\theta cii=aiicos2θ+aijsin2θ+ajjsin2θ , c j j = − a i j sin 2 θ + a i i sin 2 θ + a j j cos 2 θ . c_{jj} = {-} a_{ij}\sin 2\theta + a_{ii}{\sin}^{2}\theta + a_{jj}{\cos}^{2}\theta. cjj=−aijsin2θ+aiisin2θ+ajjcos2θ.
-
c i j = c j i = 1 2 ( a j j − a i i ) sin 2 θ + a i j cos 2 θ c_{ij} = c_{ji} = \frac{1}{2}\left( a_{jj} {-} a_{ii} \right)\sin 2\theta + a_{ij}\cos 2\theta cij=cji=21(ajj−aii)sin2θ+aijcos2θ .
-
第 i i i 行元素 c i k = c k i = a i k cos θ + a j k sin θ , k ≠ i , j c_{ik} = c_{ki} = a_{ik}\cos\theta + a_{jk}\sin\theta,k {\neq} i,j cik=cki=aikcosθ+ajksinθ,k=i,j .
-
第 j j j 行元素 c j k = c k j = a j k cos θ − a i k sin θ , k ≠ i , j c_{jk} = c_{kj} = a_{jk}\cos\theta {-} a_{ik}\sin\theta,k {\neq} i,j cjk=ckj=ajkcosθ−aiksinθ,k=i,j .
-
第 i i i 列元素 c k i = a k i cos θ + a k j sin θ , k ≠ i , j c_{ki} = a_{ki}\cos\theta + a_{kj}\sin\theta,k {\neq} i,j cki=akicosθ+akjsinθ,k=i,j .
-
第 j j j 列元素 c k j = a k j cos θ − a k i sin θ , k ≠ i , j c_{kj} = a_{kj}\cos\theta {-} a_{ki}\sin\theta,k {\neq} i,j ckj=akjcosθ−akisinθ,k=i,j .
-
其他元素不变, c l k = a l k , l , k ≠ i , j c_{lk} = a_{lk},l,k {\neq} i,j clk=alk,l,k=i,j .
由此可见, 若矩阵 A \mathbf{A} A 的非对角元素 a i j ≠ 0 a_{ij} {\neq} 0 aij=0 , 我们就可以选择一个正交矩阵 P ( i , j ) \mathbf{P}(i,j) P(i,j) 使得 C = P A P T \mathbf{C} = \mathbf{P}\mathbf{A}{\mathbf{P}}^{\mathrm{T}} C=PAPT 的元素 c i j = c j i = 0 c_{ij} = c_{ji} = 0 cij=cji=0 , 即选择 θ \theta θ 满足
tan 2 θ = 2 a i j a i i − a j j , ∣ θ ∣ ≤ π 4 . \tan 2\theta = \frac{2a_{ij}}{a_{ii} {-} a_{jj}},|\theta| {\leq} \frac{\pi}{4}. tan2θ=aii−ajj2aij,∣θ∣≤4π.
通过不断左乘右乘旋转矩阵,就能完成对角化,对角矩阵即为特征值,旋转矩阵的乘积为特征向量。
2. 经典Jacobi
算法步骤:
- 在 A \mathbf{A} A 的非对角元素中选取一个绝对值最大的元素 (称为主元素), 设 ∣ a i 1 , j 1 ∣ = max l ≠ k \left| {\mathbf{a}}_{i_{1},j_{1}} \right| = \mathop{\max}\limits_{l {\neq} k} ∣ai1,j1∣=l=kmax ∣ a l k ∣ \left| a_{lk} \right| ∣alk∣ , 可设 a i 1 , j 1 > t o l a_{i_{1},j_{1}} >tol ai1,j1>tol 即大于精度误差, 否则, 认为 A A A 已对角化迭代结束;
- 构造旋转矩阵 P 1 ( i 1 , j 1 ) {\mathbf{P}}_{1}\left( i_{1},j_{1} \right) P1(i1,j1)使得 A 1 = P 1 A P 1 ⊤ {\mathbf{A}}_{1} = {\mathbf{P}}_{1}\mathbf{A}{\mathbf{P}}_{1}^{{\top}} A1=P1AP1⊤ 的 非对角元 a i 1 j 1 ( 1 ) = a j 1 i 1 ( 1 ) = 0 a_{i_{1}j_{1}}^{(1)} = a_{j_{1}i_{1}}^{(1)} = 0 ai1j1(1)=aj1i1(1)=0
- 更新元素 c i j c_{ij} cij 进行下一轮迭代
Matlab代码如下:
function [V,D,iter]=Jocobi_classical(A,maxIter,tol)
n = size(A, 1); % 矩阵的大小
V = eye(n); % 初始化特征向量矩阵为单位矩阵
iter = 0; % 初始化迭代次数
% 设置最大迭代次数和误差精度
if nargin < 3 || isempty(tol)
tol = 1e-9; % 默认误差精度
end
if nargin < 2 || isempty(maxIter)
maxIter = 1000; % 默认最大迭代次数
end
while(iter < maxIter)
iter=iter+1;
D=A;
n=size(D,1);
p=1;q=2;
for i=1:n
for j=i+1:n
if(abs(D(i,j))>abs(D(p,q)))%找到对称矩阵的上三角矩阵中最大的元素的下标
p=i;q=j;
end
end
end
if(abs(D(p,q))<tol)
break;
end
if(A(p,q)~=0)
d=(A(q,q)-A(p,p))/(2*A(p,q));
if(d>0)
t=1/(d+sqrt(d^2+1));
else
t=-1/(-d+sqrt(d^2+1));
end
c=1/sqrt(t^2+1);s=c*t;
else
c=1;s=0;
end
R=[c s;-s c];
A([p,q],:)=R'*A([p,q],:);
A(:,[p,q])=A(:,[p,q])*R;
V(:, [p, q]) = V(:,[p,q])*R;
end
// 计算特征值和特征向量的雅可比迭代法
// a:输入n*n的矩阵,计算后对角元素为特征值
// n:矩阵a的阶数
// v:用于存储特征向量的数组
// eps:精度
// jt:最大迭代次数
// 返回值:1表示成功,-1表示迭代次数超过最大迭代次数
int jcbi(double a[], int n, double v[], double eps, int jt) {
int i, j, p, q, u, w, t, s, l;
double fm, cn, sn, omega, x, y, d;
l = 1;
// 初始化v为单位矩阵
for (i = 0; i <= n - 1; i++) {
v[i * n + i] = 1.0;
for (j = 0; j <= n - 1; j++)
if (i != j)
v[i * n + j] = 0.0;
}
while (1) {
fm = 0.0;
// 下三角找最大值
for (i = 1; i <= n - 1; i++)
for (j = 0; j <= i - 1; j++) {
d = fabs(a[i * n + j]);
if ((i != j) && (d > fm)) {
fm = d;
p = i;
q = j;
}
}
if (fm < eps)
return (1);
if (l > jt)
return (-1);
l = l + 1; // 迭代次数
u = p * n + q; // a[p][q]
w = p * n + p; // a[p][p]
t = q * n + p; // a[q][p]
s = q * n + q; // a[q][q]
x = -a[u];
y = (a[s] - a[w]) / 2.0;
omega = x / sqrt(x * x + y * y);
if (y < 0.0)
omega = -omega;
sn = 1.0 + sqrt(1.0 - omega * omega);
sn = omega / sqrt(2.0 * sn);
cn = sqrt(1.0 - sn * sn);
fm = a[w];
// 更新a[p][p],a[q][q],a[p][q],a[q][p]
a[w] = fm * cn * cn + a[s] * sn * sn + a[u] * omega;
a[s] = fm * sn * sn + a[s] * cn * cn - a[u] * omega;
a[u] = 0.0;
a[t] = 0.0;
// 更新a[p][*],a[q][*]
for (j = 0; j <= n - 1; j++)
if ((j != p) && (j != q)) {
u = p * n + j;
w = q * n + j;
fm = a[u];
a[u] = fm * cn + a[w] * sn;
a[w] = -fm * sn + a[w] * cn;
}
// 更新a[*][p],a[*][q]
for (i = 0; i <= n - 1; i++)
if ((i != p) && (i != q)) {
u = i * n + p;
w = i * n + q;
fm = a[u];
a[u] = fm * cn + a[w] * sn;
a[w] = -fm * sn + a[w] * cn;
}
// 更新v[*][*]
for (i = 0; i <= n - 1; i++) {
u = i * n + p;
w = i * n + q;
fm = v[u];
v[u] = fm * cn + v[w] * sn;
v[w] = -fm * sn + v[w] * cn;
}
}
return (1);
}
3. 参考文献
- 王晓峰,石东伟主编. 数值分析[M]. 开封:河南大学出版社, 2019.04.
- 徐士良,马尔妮编著. 常用算法程序集 C/C++描述 第5版[M]. 北京:清华大学出版社, 2013.04.