numpy.linalg.inv returns inverse for a singular matrix

4.9k views Asked by At

The matrix below is singular, and AFAIK attempting to invert it should result in

numpy.linalg.linalg.LinAlgError: Singular matrix

but instead, I do get some output matrix. Note that output matrix is a non-sensical result, because it has a row of 0's (which is impossible, since an inverse of a matrix should itself be invertible)!

Am I missing something here related to floating point precision, or the computation of a pseudoinverse as opposed to a true inverse?

$ np.__version__ 
'1.13.1'
$ np.linalg.inv(np.array([[2,7,7],[7,7,7],[8,7,7]]))
array([[  0.00000000e+00,   0.00000000e+00,   0.00000000e+00],
       [  3.43131400e+15,  -2.05878840e+16,   1.71565700e+16],
       [ -3.43131400e+15,   2.05878840e+16,  -1.71565700e+16]])```
2

There are 2 answers

1
ionox0 On

One note from the numpy team:

The de-facto convention in the field is that errors in matrix inversion are mostly silently ignored --- it is assumed that the user knows if this is something that needs to be checked for (implying that a more controlled approximate inversion method needs to be used --- the regularization is problem-dependent).

https://github.com/numpy/numpy/issues/2074

Seems to give an error on 1.13.0 however

0
percusse On

Behind the scenes, NumPy and SciPy (and many other software) fall back to LAPACK implementations (or C translations) of linear equation solvers (in this case GESV).

Since GESV first performs a LU decomposition and then checks the diagonal of U matrix for exact zeros, it is very difficult to hit perfect zeros in the decompositions. That's why you don't get a singular matrix error.

Apart from that you should never ever invert a matrix if you are multiplying with other matrices but instead solve for AX=B.

In SciPy since version 0.19, scipy.linalg.solve uses the "expert" driver GESVX of GESV which also reports back condition number and a warning is emitted. This is similar to matlab behavior in case the singularity is missed.

In [7]: sp.linalg.solve(np.array([[2,7,7],[7,7,7],[8,7,7]]), np.eye(3))
...\lib\site-packages\scipy\linalg\basic.py:223: RuntimeWarning: scipy.linalg.solve
Ill-conditioned matrix detected. Result is not guaranteed to be accurate.
Reciprocal condition number: 1.1564823173178713e-18
  ' condition number: {}'.format(rcond), RuntimeWarning)
Out[7]: 
array([[  0.00000000e+00,  -1.00000000e+00,   1.50000000e+00],
       [  3.43131400e+15,  -2.05878840e+16,   1.71565700e+16],
       [ -3.43131400e+15,   2.05878840e+16,  -1.71565700e+16]])