Skip to content

Instantly share code, notes, and snippets.

@lorenzoriano
Created March 6, 2013 01:59
Show Gist options
  • Save lorenzoriano/5096138 to your computer and use it in GitHub Desktop.
Save lorenzoriano/5096138 to your computer and use it in GitHub Desktop.
neareast positive semi-definite matrix algorithm from Higham (2000) (http://stackoverflow.com/questions/10939213/how-can-i-calculate-the-nearest-positive-semi-definite-matrix)
import numpy as np,numpy.linalg
def _getAplus(A):
eigval, eigvec = np.linalg.eig(A)
Q = np.matrix(eigvec)
xdiag = np.matrix(np.diag(np.maximum(eigval, 0)))
return Q*xdiag*Q.T
def _getPs(A, W=None):
W05 = np.matrix(W**.5)
return W05.I * _getAplus(W05 * A * W05) * W05.I
def _getPu(A, W=None):
Aret = np.array(A.copy())
Aret[W > 0] = np.array(W)[W > 0]
return np.matrix(Aret)
def nearPD(A, nit=10):
n = A.shape[0]
W = np.identity(n)
# W is the matrix used for the norm (assumed to be Identity matrix here)
# the algorithm should work for any diagonal W
deltaS = 0
Yk = A.copy()
for k in range(nit):
Rk = Yk - deltaS
Xk = _getPs(Rk, W=W)
deltaS = Xk - Rk
Yk = _getPu(Xk, W=W)
return Yk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment