Within a java project I’ve developed I need to calculate the inverse of a matrix. In order to align with other projects and other developers I’m using the Efficient Java Matrix Library (orj.ejml).
For inverting the Matrix I’m using invert from org.ejml.ops.CommonOps, and I has worked fine until now that I’m getting a unexpected result
I’ve isolated the case that doesn’t work to be:
DenseMatrix64F X = new DenseMatrix64F(3, 3); X.setData(new double[]{77.44000335693366,-24.64000011444091,-8.800000190734865, -24.640000114440916,7.839999732971196,2.799999952316285, -8.800000190734865,2.799999952316285,1.0000000000000004}); DenseMatrix64F invX = new DenseMatrix64F(3, 3); boolean completed = CommonOps.invert(X, invX); System.out.println(X); System.out.println(invX); System.out.println(completed);
The output I get from this test is:
Type = dense , numRows = 3 , numCols = 3
77.440 -24.640 -8.800
-24.640 7.840 2.800
-8.800 2.800 1.000Type = dense , numRows = 3 , numCols = 3
NaN -Infinity Infinity
NaN Infinity -Infinity
NaN -Infinity Infinitytrue
My first thought was that it could be a singular matrix and therefore not invertible, but after testing the same matrix with a different calculation tool I’ve found that it is not singular.
So I went back to the EJML documentation and found out the following information for this particular function.
If the algorithm could not invert the matrix then false is returned. If it returns true that just means the algorithm finished. The results could still be bad because the matrix is singular or nearly singular.
And, in this particular case the matrix is not singular but we could say it is near singular.
The only solution I could think off was to search the inverted matrix for NaN or Infinites after calculating it, and if I find something funny in there I just replace the inverted matrix with the original matrix, although it doesn’t seem a very clean practice it yields reasonable results.
My question is:
Could you think of any solution for this situation? Something smarter and wiser than just using the original matrix as its own inverse matrix.
In case there is no way around it, do you know of any other Java Matrix library that has some solution to this situation, I’m not looking forward to introduce a new library but it may be the only solution if this becomes a real problem.
Regards and thanks for your inputs!
Advertisement
Answer
You should try using SVD if you have to have an inverse. Also consider a pseudo inverse instead. Basically any library using LU decomposition will have serious issues. Here’s the output from Octave. Note how two of the singular values are almost zero. Octave will give you an inverse with real numbers, but it’s a poor one…
octave:7> cond(B) ans = 8.5768e+17 octave:8> svd(B) ans = 8.6280e+01 3.7146e-15 1.0060e-16 inv(B)*B warning: inverse: matrix singular to machine precision, rcond = 4.97813e-19 ans = 0.62500 0.06250 0.03125 0.00000 0.00000 0.00000 0.00000 0.00000 4.00000