Jacobi方法特征分解学习笔记

Jacobi方法求解特征值、特征向量

1. Givens变换

​ Jacobi 方法是用来计算实对称矩阵的全部特征值和特征向量的一种方法, 它的基本思想是: 因为任何一个实对称矩阵都与一个对角矩阵相似, 所以通过正交相似变换把实对称矩阵化为对角矩阵, 对角矩阵的对角线上的元素即为所求特征值. 由线性代数的知识 得, 若 A ∈ R n × n \mathbf{A} {\in} {\mathbf{R}}^{n {\times} n} ARn×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} PAP1=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= 1cosθsinθ11sinθcosθ11 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(a22a11)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(a22a11)sin2θ+a21cos2θ=0, tan ⁡ 2 θ = 2 a 21 a 11 − a 22 \tan 2\theta = \frac{2a_{21}}{a_{11} {-} a_{22}} tan2θ=a11a222a21 , 由此可得 θ \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(ajjaii)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θ=aiiajj2aij,θ4π.

通过不断左乘右乘旋转矩阵,就能完成对角化,对角矩阵即为特征值,旋转矩阵的乘积为特征向量。

2. 经典Jacobi

算法步骤:

  1. 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 已对角化迭代结束;
  2. 构造旋转矩阵 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
  3. 更新元素 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

在这里插入图片描述

图1. 测试矩阵

在这里插入图片描述

图2. eig函数结果

在这里插入图片描述

图3. 经典Jacobi结果
最后将该算法移植为C语言实现
// 计算特征值和特征向量的雅可比迭代法
// 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);
}

在这里插入图片描述

图4. Matlab结果

在这里插入图片描述

图5. C语言结果

3. 参考文献

  1. 王晓峰,石东伟主编. 数值分析[M]. 开封:河南大学出版社, 2019.04.
  2. 徐士良,马尔妮编著. 常用算法程序集 C/C++描述 第5版[M]. 北京:清华大学出版社, 2013.04.
  • 26
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值