简体   繁体   中英

LAPACKE C++ Real Matrix Inversion

I am trying to invert a real matrix in C++ LAPACKE. I have the same function for complex matrices and it works. But the real case gives the wrong answer. Here's my function:

void inv(std::vector<std::vector<double>> &ans, std::vector<std::vector<double>> MAT){

    int N = MAT.size();

    int *IPIV = new int[N];

    double * arr = new double[N*N];
    for (int i = 0; i<N; i++){
        for (int j = 0; j<N; j++){
            int idx = i*N + j;
            arr[idx] = MAT[i][j];
        }
    }

    LAPACKE_dgetrf(LAPACK_ROW_MAJOR, N, N, arr, N, IPIV);
    LAPACKE_dgetri(LAPACK_ROW_MAJOR, N, arr, N, IPIV);

     for (int i = 0; i<N; i++){
        for (int j = 0; j<N; j++){
            int idx = i*N + j;
            ans[i][j] = arr[idx];
        }
    }

    delete[] IPIV;
    delete[] arr;
}

I tried inverting a 24 by 24 matrix of doubles. While the program seems to be almost there, the inverse is not quite there yet and it differs a lot from what python linalg inverse gives me (python is right here because I multiplied the matrix with inverse and result is very close to indentity). In the LAPACKE output, I multiply the matrix by its inverse and I get the diagonals being 1 but the non diagonals go to values up to 0.17, which is huge compared to 0. Is there a way to make the LAPACKE program to give a better result? Thanks!

For matrix with large determinant you could rescale input, compute inverse and then rescale output back. Here is very simple Python example, your scale factor should be 1/25 or so in order to get total multiplier of (1/25) 24 =2.8e-34, thus making input matrix determinant about 1000.

import numpy as np

scale = 0.5

i = np.array([[1,2],[3,4]])
print(i)
print(np.linalg.det(i))
print("-----------------------------------")
x = np.multiply(i, [scale]) # rescale matrix
print(x)
print(np.linalg.det(x))     # determinant should be less
print("-----------------------------------")
y = np.linalg.inv(x)
print(y)
print(np.linalg.det(y))
print("-----------------------------------")
o = np.multiply(y, [scale]) # rescale matrix
print(o)
print(np.linalg.det(o))
print(np.dot(i, o))

You could play with the scale and verify that whatever value is code returns properly inverted input matrix.

So your code would be

double scale = 1.0/25.0;

for (int i = 0; i<N; i++){
    for (int j = 0; j<N; j++){
        int idx = i*N + j;
        arr[idx] = scale*MAT[i][j];
    }
}

....

for (int i = 0; i<N; i++){
    for (int j = 0; j<N; j++){
        int idx = i*N + j;
        ans[i][j] = scale * arr[idx];
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM