矩阵特征值及特征向量的计算(c#)

我们都知道,n阶方阵A∈R(n*n)的特征值和特征向量满足如下两方程的特征值λ∈C和非零向量x∈C(n):
|A-λI|=0 矩阵A的特征方程
Ax=λx
|A-λI|为仿真A-λI的行列式,是λ的n次代数多项式,当n较大时其零点很难求得准确解,实际应用中经常通过迭代法对矩阵特征及特征向量求解,基本思想是将特征值和特征向量作为无限序列的极限来求解,舍入误差等于此类方法影响很小,通常计算量较大。

1.幂法(PowerMethod)、反幂法

1.1介绍

对于一些对矩阵仅要求求得按模最大的特征值即主特征值和相应的特征向量,对于此类问题幂法相对合适。幂法是一种计算实矩阵A的主特征值的一种迭代算法,算法较为简单,适用于对稀疏矩阵求解。
假设矩阵A=(aij)n有完全的特征向量组,其特征值为λ1,λ2,… ,λn,则相应的特征向量分别是x1,x2,… ,xn
假设A主特征值是实根,满足下述条件:
|λ1|>|λ2|>|λ3|>…>|λn|
则任取一个非零n为列向量v(0),假设列向量v(0)可表示为:
v(0)=c1x1+c2x2+c3x3+…………+cnxn
通过迭代对矩阵A计算构造如下的向量序列:
v(1)=Av(0)
v(2)=Av(1)=(A^2)v(0)
v(3)=Av(2)=(A^3)v(0)
……… ………
v(k)=Av(k-1)=(A^k)v(0)
于是
因为 |λ1|>|λ2|>|λ3|>…>|λn|,所以
|λi/λ1|<1,i=2,3,…,n
当k→∞时,lim[(vk+1)i/(vk)i]=λ1
这种通过抑制非零n维列向量v0即矩阵A的乘幂Ak所构造的向量序列{vk}计算的主特征值λ1及与其对应的特征向量的方法称为幂法。为了防止迭代过程中出现溢出的现象,迭代期间添加临时向量uk,为vk向量的标准化后的向量:
uk=vk/max(|vk|),
反幂法及对原始数据矩阵求逆矩阵,步骤如上所述相似,只不过最终求得的值为最小特征值的倒数。
详细代码如下。

1.2代码

/// <summary>
        /// 矩阵最大、最小特征值(power-method,invpower-method)
        /// </summary>
        /// <param name="MatrixEin">非奇异矩阵</param>
        /// <param name="Eigenvector">输出特征向量</param>
        /// <param name="epsilon">迭代精度</param>
        /// <param name="Type">0:最大特征,1:最小特征</param>
        /// <returns>特征值</returns>
        public static double MatrixEigenvalue(double[,] MatrixEin, ref double[,] Eigenvector,double epsilon=1e-6,int Type=0)
        {
    
    
            MatrixEin = Type == 0 ? MatrixEin : Athwart(MatrixEin);
            double Eigenvalue = double.MaxValue;
            int Row = MatrixEin.GetLength(0);
            double[,] cVec = VectorGenerate(Row, 1, RowVec: false);
            double[,] uVec = VectorGenerate(Row, 1, RowVec: false);
            double diff = double.MaxValue;
            while (diff > epsilon)
            {
    
    
                cVec = MultiplyMatrix(MatrixEin, uVec);
                uVec = MatrixMaxMinNormalize(cVec,1);
                MatrixMinMax(cVec,out double min,out double max);
                diff = Math.Abs(max - Eigenvalue);
                Eigenvalue = max;
                Eigenvector = uVec;
            }
            return Eigenvalue;
        }

2.雅可比方法(JacobiMethod)

2.1介绍

雅可比方法用于求解实对称矩阵的全部特征值和对应的特征向量,数学原理如下:
1).n阶实对称矩阵的特征值全部为实数,其对应的特征向量线性无关且两两相交。
2).相似矩阵具有相同的特征值。
3).若n阶实矩阵A是对称的,则存在正交矩阵Q是的Q’AQ=D,其中D是一个对角矩阵,其对角元素就是矩阵A的特征值,矩阵Q的第i列向量则是与第i项特征值对应的特征向量。
选择A0=A中一对非零非对角元素aij和aji,使用平面旋转矩阵Rij,对矩阵A0做正交相似变换得A1,当前状态下A的aij和aji值均为0,以此类推,对矩阵A0不断迭代进行正交相似变换,直到Ak近似为对角矩阵,除对角元素外均为零,此时其对角元素则为原矩阵A的全部的特征值。

2.2代码

 /// <summary>
        /// 雅可比计算对称矩阵全部特征值及相关特征向量(JacobiMethod)
        /// </summary>
        /// <param name="MatrixEin">input matrix</param>
        /// <param name="EigenVector">eigenvectors</param>
        /// <param name="epsilon">precision requirement</param>
        /// <param name="iterations">iterate max times</param>
        /// <returns>TotalEigenvalues</returns>
        public static double[] SymmetricMatricEigenvalud(double[,] MatrixEin,ref double[,] EigenVector, double epsilon=1e-7,int iterations = 1000)
        {
    
    
            double[,] A = (double[,])MatrixEin.Clone();
            int Row = MatrixEin.GetLength(0);
            int Col = MatrixEin.GetLength(1);
            double[,] Q = UnitMatrix(Row);
            double[,] R = UnitMatrix(Row);
            double max = double.MaxValue;
            int mx = -1, my = -1;
            int times = 0;
            while (max > epsilon && times<iterations)
            {
    
    
                max = double.MinValue;
                for (int i = 0; i < Row; i++)
                {
    
    
                    for (int j = i+1; j < Col; j++)
                    {
    
    
                        if (Math.Abs(A[i, j]) > max)
                        {
    
    
                            max = Math.Abs(A[i, j]);
                            mx = i;
                            my = j;
                        }
                    }
                }
                times += 1;
                double d = (A[mx, mx] - A[my, my]) / (2.0 * A[mx, my]);
                double t = d > 0 ? -d + Math.Sqrt(d * d + 1) : d == 0 ? -1 : -d - Math.Sqrt(d * d + 1);
                double c = Math.Pow(1 + t * t, -0.5);
                double s = t * c;
                R = UnitMatrix(Row);
                R[mx, mx] = R[my, my] = c;
                R[mx, my] = s;
                R[my, mx] = -s;
                double[,] RT = Transpose(R);
                double[,] B = MultiplyMatrix(R, A);
                A = MultiplyMatrix(B, RT);
                Q = MultiplyMatrix(Q, RT);
            }
            EigenVector = Q;
            double[] Eigenvalue = new double[Col];
            for(int i =0;i<Row; i++)
            {
    
    
                Eigenvalue[i] = A[i, i];
            }
            return Eigenvalue;
        }

3.参考

《计算方法及其应用》

猜你喜欢

转载自blog.csdn.net/JAYLEE900/article/details/131947379