def approxUpdateEig(self, subW, ABBA, omega, Q): """ Update the eigenvalue decomposition of ABBA """ # --- remove rows/columns --- if self.n > ABBA.shape[0]: omega, Q = EigenUpdater.eigenRemove(omega, Q, ABBA.shape[0], min(self.k2, ABBA.shape[0])) # --- update existing nodes --- currentN = min(self.n, ABBA.shape[0]) deltaDegrees = numpy.array( subW.sum(0)).ravel()[0:currentN] - self.degrees[:currentN] inds = numpy.arange(currentN)[deltaDegrees != 0] if len(inds) > 0: Y1 = ABBA[:currentN, inds] - self.ABBALast[:currentN, inds] Y1 = numpy.array(Y1.todense()) Y1[inds, :] = Y1[inds, :] / 2 Y2 = numpy.zeros((currentN, inds.shape[0])) Y2[(inds, numpy.arange(inds.shape[0]))] = 1 omega, Q = EigenUpdater.eigenAdd2(omega, Q, Y1, Y2, min(self.k2, currentN)) # --- add rows/columns --- if self.n < ABBA.shape[0]: AB = numpy.array(ABBA[0:self.n, self.n:].todense()) BB = numpy.array(ABBA[self.n:, self.n:].todense()) omega, Q = EigenUpdater.lazyEigenConcatAsUpdate( omega, Q, AB, BB, min(self.k2, ABBA.shape[0])) return omega, Q
def testEigenRemove(self): tol = 10**-6 for i in range(10): m = numpy.random.randint(5, 10) n = numpy.random.randint(5, 10) #How many rows/cols to remove p = numpy.random.randint(1, 5) A = numpy.random.randn(m, n) C = A.conj().T.dot(A) lastError = 100 omega, Q = numpy.linalg.eigh(C) self.assertTrue(numpy.linalg.norm(C-(Q*omega).dot(Q.conj().T)) < tol ) # Cprime = C[0:n-p, 0:n-p] for k in range(1,9): pi, V, K, Y1, Y2, omega2 = EigenUpdater.eigenRemove(omega, Q, n-p, k, debug=True) # V is "orthogonal" self.assertTrue(numpy.linalg.norm(V.conj().T.dot(V) - numpy.eye(V.shape[1])) < tol ) # The approximation converges to the exact decomposition C_k = (V*pi).dot(V.conj().T) error = numpy.linalg.norm(Cprime-C_k) if Util.rank(C)<k: self.assertTrue(error <= tol) lastError = error
def approxUpdateEig(self, subW, ABBA, omega, Q): """ Update the eigenvalue decomposition of ABBA """ # --- remove rows/columns --- if self.n > ABBA.shape[0]: omega, Q = EigenUpdater.eigenRemove(omega, Q, ABBA.shape[0], min(self.k2, ABBA.shape[0])) # --- update existing nodes --- currentN = min(self.n, ABBA.shape[0]) deltaDegrees = numpy.array(subW.sum(0)).ravel()[0:currentN]- self.degrees[:currentN] inds = numpy.arange(currentN)[deltaDegrees!=0] if len(inds) > 0: Y1 = ABBA[:currentN, inds] - self.ABBALast[:currentN, inds] Y1 = numpy.array(Y1.todense()) Y1[inds, :] = Y1[inds, :]/2 Y2 = numpy.zeros((currentN, inds.shape[0])) Y2[(inds, numpy.arange(inds.shape[0]))] = 1 omega, Q = EigenUpdater.eigenAdd2(omega, Q, Y1, Y2, min(self.k2, currentN)) # --- add rows/columns --- if self.n < ABBA.shape[0]: AB = numpy.array(ABBA[0:self.n, self.n:].todense()) BB = numpy.array(ABBA[self.n:, self.n:].todense()) omega, Q = EigenUpdater.lazyEigenConcatAsUpdate(omega, Q, AB, BB, min(self.k2, ABBA.shape[0])) return omega, Q
def testEigenRemove2(self): tol = 10**-6 m = 10 n = 8 A = numpy.random.randn(m, n) C = A.conj().T.dot(A) p = 5 k = 8 omega, Q = numpy.linalg.eig(C) Cprime = C[0:n - p, 0:n - p] pi, V = EigenUpdater.eigenRemove(omega, Q, n - p, k, debug=False) C_k = (V * pi).dot(V.conj().T) error = numpy.linalg.norm(Cprime - C_k) self.assertTrue(error <= tol)
def testEigenRemove2(self): tol = 10**-6 m = 10 n = 8 A = numpy.random.randn(m, n) C = A.conj().T.dot(A) p = 5 k = 8 omega, Q = numpy.linalg.eig(C) Cprime = C[0:n-p, 0:n-p] pi, V = EigenUpdater.eigenRemove(omega, Q, n-p, k, debug=False) C_k = (V*pi).dot(V.conj().T) error = numpy.linalg.norm(Cprime-C_k) self.assertTrue(error <= tol)
def testEigenRemove(self): tol = 10**-6 for i in range(10): m = numpy.random.randint(5, 10) n = numpy.random.randint(5, 10) #How many rows/cols to remove p = numpy.random.randint(1, 5) A = numpy.random.randn(m, n) C = A.conj().T.dot(A) lastError = 100 omega, Q = numpy.linalg.eigh(C) self.assertTrue( numpy.linalg.norm(C - (Q * omega).dot(Q.conj().T)) < tol) # Cprime = C[0:n - p, 0:n - p] for k in range(1, 9): pi, V, K, Y1, Y2, omega2 = EigenUpdater.eigenRemove(omega, Q, n - p, k, debug=True) # V is "orthogonal" self.assertTrue( numpy.linalg.norm(V.conj().T.dot(V) - numpy.eye(V.shape[1])) < tol) # The approximation converges to the exact decomposition C_k = (V * pi).dot(V.conj().T) error = numpy.linalg.norm(Cprime - C_k) if Util.rank(C) < k: self.assertTrue(error <= tol) lastError = error