Find out if matrix is positive definite with numpy
You could try computing Cholesky decomposition (numpy.linalg.cholesky
). This will raise LinAlgError
if the matrix is not positive definite.
You can also check if all the eigenvalues of matrix are positive, if so the matrix is positive definite:
import numpy as np
def is_pos_def(x):
return np.all(np.linalg.eigvals(x) > 0)
There seems to be a small confusion in all of the answers above (at least concerning the question).
For real matrices, the tests for positive eigenvalues and positive-leading terms in np.linalg.cholesky only applies if the matrix is symmetric. So first one needs to test if the matrix is symmetric and then apply one of those methods (positive eigenvalues or Cholesky decomposition).
For example:
import numpy as np
#A nonsymmetric matrix
A = np.array([[9,7],[6,14]])
#check that all eigenvalues are positive:
np.all(np.linalg.eigvals(A) > 0)
#take a 'Cholesky' decomposition:
chol_A = np.linalg.cholesky(A)
The matrix A is not symmetric, but the eigenvalues are positive and Numpy returns a Cholesky decomposition that is wrong. You can check that:
chol_A.dot(chol_A.T)
is different than A.
You can also check that all the python functions above would test positive for 'positive-definiteness'. This could potentially be a serious problem if you were trying to use the Cholesky decomposition to compute the inverse, since:
>np.linalg.inv(A)
array([[ 0.16666667, -0.08333333],
[-0.07142857, 0.10714286]])
>np.linalg.inv(chol_A.T).dot(np.linalg.inv(chol_A))
array([[ 0.15555556, -0.06666667],
[-0.06666667, 0.1 ]])
are different.
In summary, I would suggest adding a line to any of the functions above to check if the matrix is symmetric, for example:
def is_pos_def(A):
if np.array_equal(A, A.T):
try:
np.linalg.cholesky(A)
return True
except np.linalg.LinAlgError:
return False
else:
return False
You may want to replace np.array_equal(A, A.T) in the function above for np.allclose(A, A.T) to avoid differences that are due to floating point errors.