c_cpp 计算存储在一维点阵列中的矩阵的特征值和特征向量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 计算存储在一维点阵列中的矩阵的特征值和特征向量相关的知识,希望对你有一定的参考价值。

/// compute eigenvalues and eigen vectors of matrix stored in 1-D point array using Jacobi method.
/// </summary>
/// <param name="a">symmetric matrix with n*n size, and also used to return eigenvalues in diagonal place.</param>
/// <param name="n">size of matrix.</param>
/// <param name="v">eigen vector matrix, stored in column format.</param>
/// <param name="eps">precision parameter.</param>
/// <param name="jt">max iteration times.</param>
/// <returns>false: can't satisfy precision, and hit the max iteration times
///          true: success.</returns>
bool PcaFusion::eejcb( 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;
    //初始化特征向量矩阵使其全为0
    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( true ) //循环
    {
        fm = 0.0;
        for( i = 0; i <= n - 1; i++ )   // 出, 矩阵a( 特征值 ), 中除对角线外其他元素的最大绝对值
        {
            //这个最大值是位于a[p][q] ,等于fm
            for( j = 0; j <= n - 1; j++ )
            {
                d = fabs( a[i * n + j] );

                if( ( i != j ) && ( d > fm ) )
                {
                    fm = d;
                    p = i;
                    q = j;
                }
            }
        }

        if( fm < eps )   //精度复合要求
        {
            return true;    //正常返回
        }

        if( l > jt )     //迭代次数太多
        {
            return false;    //失败返回
        }

        l ++;       //   迭代计数器
        u = p * n + q;
        w = p * n + p;
        t = q * n + p;
        s = q * n + q;
        x = -a[u];
        y = ( a[s] - a[w] ) / 2.0;		//x y的求法不同
        omega = x / sqrt( x * x + y * y );	//sin2θ

        //tan2θ=x/y = -2.0*a[u]/(a[s]-a[w])
        if( y < 0.0 )
        {
            omega = -omega;
        }

        sn = 1.0 + sqrt( 1.0 - omega * omega );
        sn = omega / sqrt( 2.0 * sn );		//sinθ
        cn = sqrt( 1.0 - sn * sn );			//cosθ

        fm = a[w];   //   变换前的a[w]   a[p][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;

        //   以下是旋转矩阵,旋转了了p行,q行,p列,q列
        //   但是四个特殊点没有旋转(这四个点在上述语句中发生了变化)
        //   其他不在这些行和列的点也没变
        //   旋转矩阵,旋转p行和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] = a[w] * sn + fm * cn;
                a[w] = a[w] * cn - fm * sn;
            }
        }

        //旋转矩阵,旋转p列和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] = a[w] * sn + fm * cn;
                a[w] = a[w] * cn - fm * sn;
            }
        }

        //记录旋转矩阵特征向量
        for( i = 0; i <= n - 1; i++ )
        {
            u = i * n + p;
            w = i * n + q;
            fm = v[u];
            v[u] = v[w] * sn + fm * cn;
            v[w] = v[w] * cn - fm * sn;
        }
    }

    return true;
}

以上是关于c_cpp 计算存储在一维点阵列中的矩阵的特征值和特征向量的主要内容,如果未能解决你的问题,请参考以下文章

乘以存储在一维数组算法中的上三角矩阵

C++ 练气期之二维数组与矩阵运算

均值方差协方差协方差矩阵特征值特征向量

matlab练习程序(对应点集配准的四元数法)

matlab练习程序(对应点集配准的四元数法)

稀疏矩阵的运算