def woodbury(X, Ainv, m, up=True): ''' Does a rank-k adjustment of Ainv using the woodbury matrix identity (A + XX^H)^(-1) = A^(-1) - (A^(-1)X ( I + X^(H)A^(-1)X )^(-1)X^(H)A^(-1)) If up == True: A rank update is performed, otherwise we do a rank degrade NB! Not finished ''' factor = 1 if up != True: factor = -1 XH = mynp.conjugatetranspose(X) XHAinv = mynp.dot(XH, Ainv) AinvX = mynp.dot(Ainv, XH) XHAinvX = mynp.dot(XHAinv, X) IXHAinvX = mynp.eye(m) + (factor * XHAinvX) # TODO: inv_IXHAinvX = we need to invert IXHAinvX!!! AinvX_IXHAinvX_XHAinv = mynp.dot(mynp.dot(AinvX, IXHAinvX), XHAinv) newAinv = Ainv + (-factor * AinvX_IXHAinvX_XHAinv) return newAinv
def woodbury(X, Ainv, m, up = True): ''' Does a rank-k adjustment of Ainv using the woodbury matrix identity (A + XX^H)^(-1) = A^(-1) - (A^(-1)X ( I + X^(H)A^(-1)X )^(-1)X^(H)A^(-1)) If up == True: A rank update is performed, otherwise we do a rank degrade NB! Not finished ''' factor = 1 if up != True: factor = -1 XH = mynp.conjugatetranspose(X) XHAinv = mynp.dot(XH, Ainv) AinvX = mynp.dot(Ainv, XH) XHAinvX = mynp.dot(XHAinv, X) IXHAinvX = mynp.eye(m) + (factor * XHAinvX) # TODO: inv_IXHAinvX = we need to invert IXHAinvX!!! AinvX_IXHAinvX_XHAinv = mynp.dot(mynp.dot(AinvX, IXHAinvX), XHAinv) newAinv = Ainv + (-factor * AinvX_IXHAinvX_XHAinv) return newAinv
def testSolvingComplexAxbWithCholeskyAndForwardBackwardSolve(self): R = md.cholesky(self.complexA, self.n) for i in range(self.n): for j in range(self.n): self.assertAlmostEqual( self.complexR[i][j].tolist(), R[i][j].tolist(), 14, "expected " + str(self.complexR[i][j]) + " was " + str(R[i][j])) RT = mynp.conjugatetranspose(R) y = ls.forwardSolve(RT, self.complexb, self.n) for i in range(self.n): self.assertAlmostEqual( self.complexy[i].tolist(), y[i].tolist(), 14, "expected " + str(self.complexy[i]) + " was " + str(y[i])) x = ls.backtrackSolve(R, y, self.n) for i in range(self.n): self.assertAlmostEqual( self.complexx[i].tolist(), x[i].tolist(), 14, "expected " + str(self.complexx[i]) + " was " + str(x[i]))
def solveCholeskyCpp(A, b, n): ''' Solves the Hermitian positive definite system Ax = b using cholesky decomposition''' U = md.cholesky(A, n) UT = np.conjugatetranspose(U) y = forwardSolve(UT, b, n) x = backtrackSolve(U, y, n)
def testRTransposedTimesRIsEqualA(self): R = md.cholesky(self.A, self.n) RT = mynp.conjugatetranspose(R) A = mynp.dot(RT, R) for i in range(self.n): for j in range(self.n): self.assertAlmostEqual(self.A[i][j].tolist(), A[i][j].tolist(), 15, "expected " + str(self.A[i][j]) + " was " + str(A[i][j]))
def solveUHDU(A, b, n): ''' Solves the Hermitian positive definite system Ax = b using U'DU decomposition''' UD = md.uhdu(A, n); UH = np.conjugatetranspose(UD[0]) y = forwardSolve(UH, b, n) z = diagonalSolve(UD[1], y, n) x = backtrackSolve(UD[0], z, n) return x
def solveUHDU(A, b, n): ''' Solves the Hermitian positive definite system Ax = b using U'DU decomposition''' UD = md.uhdu(A, n) UH = np.conjugatetranspose(UD[0]) y = forwardSolve(UH, b, n) z = diagonalSolve(UD[1], y, n) x = backtrackSolve(UD[0], z, n) return x
def testRTransposedTimesRIsEqualA(self): R = md.cholesky(self.A, self.n) RT = mynp.conjugatetranspose(R) A = mynp.dot(RT, R) for i in range(self.n): for j in range(self.n): self.assertAlmostEqual( self.A[i][j].tolist(), A[i][j].tolist(), 15, "expected " + str(self.A[i][j]) + " was " + str(A[i][j]))
def testSolvingAxbWithCholeskyAndForwardBackwardSolve(self): R = md.cholesky(self.A, self.n) RT = mynp.conjugatetranspose(R) y = ls.forwardSolve(RT, self.b1, self.n) x = ls.backtrackSolve(R, y, self.n) for i in range(self.n): self.assertAlmostEqual(self.x1[i].tolist(), x[i].tolist(), 14, "expected " + str(self.x1[i]) + " was " + str(x[i])) y = ls.forwardSolve(RT, self.b2, self.n) x = ls.backtrackSolve(R, y, self.n) for i in range(self.n): self.assertAlmostEqual(self.x2[i].tolist(), x[i].tolist(), 14, "expected " + str(self.x2[i]) + " was " + str(x[i]))
def testSolvingAxbWithCholeskyAndForwardBackwardSolve(self): R = md.cholesky(self.A, self.n) RT = mynp.conjugatetranspose(R) y = ls.forwardSolve(RT, self.b1, self.n) x = ls.backtrackSolve(R, y, self.n) for i in range(self.n): self.assertAlmostEqual( self.x1[i].tolist(), x[i].tolist(), 14, "expected " + str(self.x1[i]) + " was " + str(x[i])) y = ls.forwardSolve(RT, self.b2, self.n) x = ls.backtrackSolve(R, y, self.n) for i in range(self.n): self.assertAlmostEqual( self.x2[i].tolist(), x[i].tolist(), 14, "expected " + str(self.x2[i]) + " was " + str(x[i]))
def testSolvingComplexAxbWithCholeskyAndForwardBackwardSolve(self): R = md.cholesky(self.complexA, self.n) for i in range(self.n): for j in range(self.n): self.assertAlmostEqual(self.complexR[i][j].tolist(), R[i][j].tolist(), 14, "expected " + str(self.complexR[i][j]) + " was " + str(R[i][j])) RT = mynp.conjugatetranspose(R) y = ls.forwardSolve(RT, self.complexb, self.n) for i in range(self.n): self.assertAlmostEqual(self.complexy[i].tolist(), y[i].tolist(), 14, "expected " + str(self.complexy[i]) + " was " + str(y[i])) x = ls.backtrackSolve(R, y, self.n) for i in range(self.n): self.assertAlmostEqual(self.complexx[i].tolist(), x[i].tolist(), 14, "expected " + str(self.complexx[i]) + " was " + str(x[i]))
def testComplexConjugateTransposed(self): AT = mynp.conjugatetranspose(self.complexA) self.assertListEqual(self.complexA.tolist(), AT.tolist())
def solveBiCG(A, b, x0, tol, itr): ''' Solves the complex linear system Ax = b using the complex-biconjugate-gradient method Arguments: A -- Coefficient matrix b -- Right-side vector x0 -- Initial solution (default: 0-vector) tol -- Stop solver when error is less than tol (default: 0) itr -- Stop solver after itr iterations -- default ''' # Check arguments m,n = len(A),len(A[0]) if m != n: raise Exception('Coefficient matrix is not square') if len(b) != n: raise Exception('Dimension mismatch between A and b') x = x0 # make origin as starting point if no x is passed # Calculate initial residual r = b - Ax0 and search direction p r0 = b - np.dot(A, x) r = r0 normr0 = np.euclidnorm(r0) if (np.euclidnorm(r) / normr0) <= tol: # break if error is less-than tolerance. # TODO: Should also test bir return x p = np.array(r) # init biresidual and bidirection bir = r.conjugate() bip = p.conjugate() numerator,denominator = 0,0 alpha,betha = 0,0 AH = np.conjugatetranspose(A) # Simplification: since A is Hermitian and semi-positive definite in our case, we can avoid this step... if itr <= 0 or itr > m: itr = m for i in range(itr): # Calculate common matrix-vector products Ap = np.dot(A, p) AHbip = np.dot(AH, bip) # Calculate step-length parameter numerator = np.vdot(bir, r) denominator = np.vdot(bip, Ap) alpha = numerator / denominator # Obtain new solution x = x + (alpha * p) # Calculate new residual and biresidual # r = r - (alpha * Ap) for i in range(m): r[i] = r[i] - alpha * Ap[i] # Calculate new residual and biresidual if np.euclidnorm(r) / normr0 <= tol: # TODO: Should also test bir return x bir = bir - (alpha.conjugate() * AHbip) # Calculate the biconjugacy coefficient numerator = np.vdot(AHbip, r) denominator = np.vdot(bip, Ap) betha = -1.0 * (numerator / denominator) # Obtain new search and bi-search-direction p = r + (betha * p) bip = bir + (betha.conjugate() * bip) return x
def solveBiCG(A, b, x0, tol, itr): ''' Solves the complex linear system Ax = b using the complex-biconjugate-gradient method Arguments: A -- Coefficient matrix b -- Right-side vector x0 -- Initial solution (default: 0-vector) tol -- Stop solver when error is less than tol (default: 0) itr -- Stop solver after itr iterations -- default ''' # Check arguments m, n = len(A), len(A[0]) if m != n: raise Exception('Coefficient matrix is not square') if len(b) != n: raise Exception('Dimension mismatch between A and b') x = x0 # make origin as starting point if no x is passed # Calculate initial residual r = b - Ax0 and search direction p r0 = b - np.dot(A, x) r = r0 normr0 = np.euclidnorm(r0) if (np.euclidnorm(r) / normr0) <= tol: # break if error is less-than tolerance. # TODO: Should also test bir return x p = np.array(r) # init biresidual and bidirection bir = r.conjugate() bip = p.conjugate() numerator, denominator = 0, 0 alpha, betha = 0, 0 AH = np.conjugatetranspose( A ) # Simplification: since A is Hermitian and semi-positive definite in our case, we can avoid this step... if itr <= 0 or itr > m: itr = m for i in range(itr): # Calculate common matrix-vector products Ap = np.dot(A, p) AHbip = np.dot(AH, bip) # Calculate step-length parameter numerator = np.vdot(bir, r) denominator = np.vdot(bip, Ap) alpha = numerator / denominator # Obtain new solution x = x + (alpha * p) # Calculate new residual and biresidual # r = r - (alpha * Ap) for i in range(m): r[i] = r[i] - alpha * Ap[ i] # Calculate new residual and biresidual if np.euclidnorm(r) / normr0 <= tol: # TODO: Should also test bir return x bir = bir - (alpha.conjugate() * AHbip) # Calculate the biconjugacy coefficient numerator = np.vdot(AHbip, r) denominator = np.vdot(bip, Ap) betha = -1.0 * (numerator / denominator) # Obtain new search and bi-search-direction p = r + (betha * p) bip = bir + (betha.conjugate() * bip) return x
def testCholeskyInPlace(self): L = md.choleskyInPlace(self.complexA, self.n) R = mynp.conjugatetranspose(L) self.assertMatrixAlmosteEqual(self.complexR.tolist(), R.tolist(), 14)
def testForwardSolve(self): x = ls.forwardSolve(mynp.conjugatetranspose(self.C), self.b1c, self.n) self.assertListEqual(self.x1cT.tolist(), x.tolist(), "Error in forward solve")