对称矩阵求逆使用CBLAS / LAPACKÇ(Symmetric Matrix Inversion

2019-07-29 12:36发布

我使用C编写的算法,需要矩阵与向量乘法。 我有一个矩阵Q(W×宽),这是由矢量Ĵ(1×W)与自身的转置相乘并添加单位矩阵I创建的,缩放的用标量一个

Q = [(j ^ T)* J + Al]。

然后,我要乘Q的倒数矢量G来获得向量M。

M =(Q ^( - 1))* G.

我使用cblasCLAPACK发展我的算法。 当矩阵Q被使用的随机数(float类型)填充和倒置使用例程sgetrf_sgetri_,所计算出的逆是正确的

但是,当矩阵Q是对称的 ,这是当你乘法(j ^ T)×j中的情况下,所计算出的逆是错误!

我知道阵列,同时在C中调用LAPACK例程的行主(C语言)和列为主(以FORTRAN)格式的,但对于一个对称矩阵这不应该是为A ^ T = A的问题

我附上下面矩阵求逆我的C函数的代码。

我相信有一个更好的办法来解决这个问题。 谁能帮我这个?

使用cblas一个解决方案将是巨大的...

谢谢。

void InverseMatrix_R(float *Matrix, int W)
{   
    int     LDA = W;
    int     IPIV[W];
    int     ERR_INFO;
    int     LWORK = W * W;
    float   Workspace[LWORK];

    // - Compute the LU factorization of a M by N matrix A
    sgetrf_(&W, &W, Matrix, &LDA, IPIV, &ERR_INFO);

    // - Generate inverse of the matrix given its LU decompsotion
    sgetri_(&W, Matrix, &LDA, IPIV, Workspace, &LWORK, &ERR_INFO);

    // - Display the Inverted matrix
    PrintMatrix(Matrix, W, W);

}

void PrintMatrix(float* Matrix, int row, int colm)
{
    int i,k;

    for (i =0; i < row; i++) 
    {
        for (k = 0; k < colm; k++) 
        {
            printf("%g, ",Matrix[i*colm + k]);
        }

        printf("\n");
    }
}

Answer 1:

I don't know BLAS or LAPACK, so I have no idea what may cause this behaviour.

But, for matrices of the given form, calculating the inverse is quite easy. The important fact for this is

(J^T*J)^2 = (J^T*J)*(J^T*J) = J^T*(J*J^T)*J = <J|J> * (J^T*J)

where <u|v> denotes the inner product (if the components are real - the canonical bilinear form for complex components, but then you'd probably consider not the transpose but the conjugate transpose, and you'd be back at the inner product).

Generalising,

(J^T*J)^n = (<J|J>)^(n-1) * (J^T*J), for n >= 1.

Let us denote the symmetric square matrix (J^T*J) by S and the scalar <J|J> by q. Then, for general a != 0 of sufficiently large absolute value (|a| > q):

(a*I + S)^(-1) = 1/a * (I + a^(-1)*S)^(-1)
               = 1/a * (I + ∑ (-1)^k * a^(-k) * S^k)
                           k>0
               = 1/a * (I + (∑ (-1)^k * a^(-k) * q^(k-1)) * S)
                            k>0
               = 1/a * (I - 1/(a+q)*S)
               = 1/a*I - 1/(a*(a+q))*S

That formula holds (by analyticity) for all a except a = 0 and a = -q, as can be verified by calculating

(a*I + S) * (1/a*I - 1/(a*(a+q))*S) = I + 1/a*S - 1/(a+q)*S - 1/(a*(a+q))*S^2
                                    = I + 1/a*S - 1/(a+q)*S - q/(a*(a+q))*S
                                    = I + ((a+q) - a - q)/(a*(a+q))*S
                                    = I

using S^2 = q*S.

That calculation is also much simpler and more efficient than first finding the LU decomposition.



Answer 2:

你可能想尝试犰狳 ,这是一个易于使用的C ++包装的LAPACK。 它提供了一些逆相关的功能:

  • INV() ,一般逆,具有对称正定矩阵的可选加速
  • PINV() ,伪逆
  • 解决() ,求解线性方程系统(可以是过表达或低测定),而不进行实际的逆


Answer 3:

例如,对于3×3的矩阵求逆,访问sgetri.f更多

//__CLPK_integer is typedef of int
//__CLPK_real is typedef of float


__CLPK_integer ipiv[3];
{
    //Compute LU lower upper factorization of matrix
    __CLPK_integer m=3;
    __CLPK_integer n=3;
    __CLPK_real *a=(float *)this->m1;
    __CLPK_integer lda=3;
    __CLPK_integer info;
    sgetrf_(&m, &n, a, &lda, ipiv, &info);
}

{
    //compute inverse of a matrix
    __CLPK_integer n=3;
    __CLPK_real *a=(float *)this->m1;
    __CLPK_integer lda=3;
    __CLPK_real work[3];
    __CLPK_integer lwork=3;
    __CLPK_integer info;
    sgetri_(&n, a, &lda, ipiv, work, &lwork, &info);
}


文章来源: Symmetric Matrix Inversion in C using CBLAS/LAPACK