def setUp(self): self.m = m = 10 self.n = n = 5 self.k = k = 3 self.manifold = FixedRankEmbedded(m, n, k) u, s, vt = self.manifold.random_point() matrix = (u * s) @ vt @pymanopt.function.autograd(self.manifold) def cost(u, s, vt): return np.linalg.norm((u * s) @ vt - matrix) ** 2 self.cost = cost
def run(backend=SUPPORTED_BACKENDS[0], quiet=True): m, n, rank = 5, 4, 2 matrix = rnd.randn(m, n) cost, egrad = create_cost_egrad(backend, matrix, rank) manifold = FixedRankEmbedded(m, n, rank) problem = pymanopt.Problem(manifold, cost=cost, egrad=egrad) if quiet: problem.verbosity = 0 solver = ConjugateGradient() left_singular_vectors, singular_values, right_singular_vectors = \ solver.solve(problem) low_rank_approximation = (left_singular_vectors @ np.diag(singular_values) @ right_singular_vectors) if not quiet: u, s, vt = la.svd(matrix, full_matrices=False) indices = np.argsort(s)[-rank:] low_rank_solution = ( u[:, indices] @ np.diag(s[indices]) @ vt[indices, :]) print("Analytic low-rank solution:") print() print(low_rank_solution) print() print("Rank-{} approximation:".format(rank)) print() print(low_rank_approximation) print() print("Frobenius norm error:", la.norm(low_rank_approximation - low_rank_solution)) print()
def fixedrank(A, YT, r): """ Solves the AX=YT problem on the manifold of r-rank matrices with """ # Instantiate a manifold manifold = FixedRankEmbedded(N, r, r) # Define the cost function (here using autograd.numpy) def cost(X): U = X[0] cst = 0 for n in range(N): cst = cst + huber(U[n, :]) Mat = np.matmul(np.matmul(X[0], np.diag(X[1])), X[2]) fidelity = LA.norm(np.subtract(np.matmul(A, Mat), YT)) return cst + lambd * fidelity**2 problem = Problem(manifold=manifold, cost=cost) solver = ConjugateGradient(maxiter=maxiter) # Let Pymanopt do the rest Xopt = solver.solve(problem) #Solve Sol = np.dot(np.dot(Xopt[0], np.diag(Xopt[1])), Xopt[2]) return Sol
def setUp(self): self.m = m = 20 self.n = n = 10 self.rank = rank = 3 A = np.random.normal(size=(m, n)) self.manifold = Product([FixedRankEmbedded(m, n, rank), Euclidean(n)]) @pymanopt.function.autograd(self.manifold) def cost(u, s, vt, x): return np.linalg.norm(((u * s) @ vt - A) @ x) ** 2 self.cost = cost self.gradient = self.cost.get_gradient_operator() self.hessian = self.cost.get_hessian_operator() self.problem = pymanopt.Problem(self.manifold, self.cost)
def setUp(self): self.m = m = 20 self.n = n = 10 self.rank = rank = 3 A = np.random.randn(m, n) @pymanopt.function.Autograd def cost(u, s, vt, x): return np.linalg.norm(((u * s) @ vt - A) @ x)**2 self.cost = cost self.gradient = self.cost.compute_gradient() self.hvp = self.cost.compute_hessian_vector_product() self.manifold = Product([FixedRankEmbedded(m, n, rank), Euclidean(n)]) self.problem = pymanopt.Problem(self.manifold, self.cost)
def run(backend=SUPPORTED_BACKENDS[0], quiet=True): m, n, rank = 5, 4, 2 matrix = np.random.normal(size=(m, n)) manifold = FixedRankEmbedded(m, n, rank) cost, euclidean_gradient = create_cost_and_derivates( manifold, matrix, backend ) problem = pymanopt.Problem( manifold, cost, euclidean_gradient=euclidean_gradient ) optimizer = ConjugateGradient( verbosity=2 * int(not quiet), beta_rule="PolakRibiere" ) ( left_singular_vectors, singular_values, right_singular_vectors, ) = optimizer.run(problem).point low_rank_approximation = ( left_singular_vectors @ np.diag(singular_values) @ right_singular_vectors ) if not quiet: u, s, vt = np.linalg.svd(matrix, full_matrices=False) indices = np.argsort(s)[-rank:] low_rank_solution = ( u[:, indices] @ np.diag(s[indices]) @ vt[indices, :] ) print("Analytic low-rank solution:") print() print(low_rank_solution) print() print(f"Rank-{rank} approximation:") print() print(low_rank_approximation) print() print( "Frobenius norm error:", np.linalg.norm(low_rank_approximation - low_rank_solution), ) print()
import autograd.numpy as np from pymanopt import Problem from pymanopt.solvers import ConjugateGradient # Let A be a (5 x 4) matrix to be approximated A = np.random.randn(5, 4) k = 2 # (a) Instantiation of a manifold # points on the manifold are parameterized via their singular value # decomposition (u, s, vt) where # u is a 5 x 2 matrix with orthonormal columns, # s is a vector of length 2, # vt is a 2 x 4 matrix with orthonormal rows, # so that u*diag(s)*vt is a 5 x 4 matrix of rank 2. manifold = FixedRankEmbedded(A.shape[0], A.shape[1], k) # (b) Definition of a cost function (here using autograd.numpy) # Note that the cost must be defined in terms of u, s and vt, where # X = u * diag(s) * vt. def cost(usv): delta = .5 u = usv[0] s = usv[1] vt = usv[2] X = np.dot(np.dot(u, np.diag(s)), vt) return np.sum(np.sqrt((X - A)**2 + delta**2) - delta) # define the Pymanopt problem
class TestFixedRankEmbeddedManifold(unittest.TestCase): def setUp(self): self.m = m = 10 self.n = n = 5 self.k = k = 3 self.man = FixedRankEmbedded(m, n, k) def test_dim(self): assert self.man.dim == (self.m + self.n - self.k) * self.k def test_typicaldist(self): assert self.man.dim == self.man.typicaldist def test_dist(self): e = self.man a = e.rand() x = e.randvec(a) y = e.randvec(a) with self.assertRaises(NotImplementedError): e.dist(x, y) def test_inner(self): e = self.man x = e.rand() a = e.randvec(x) b = e.randvec(x) # First embed in the ambient space A = x[0].dot(a[1].dot(x[2])) + a[0].dot(x[2]) + x[0].dot(a[2].T) B = x[0].dot(b[1].dot(x[2])) + b[0].dot(x[2]) + x[0].dot(b[2].T) trueinner = np.sum(A * B) np_testing.assert_almost_equal(trueinner, e.inner(x, a, b)) def test_proj_range(self): m = self.man x = m.rand() v = np.random.randn(self.m, self.n) g = m.proj(x, v) # Check that g is a true tangent vector np_testing.assert_allclose(np.dot(g[0].T, x[0]), np.zeros((self.k, self.k)), atol=1e-6) np_testing.assert_allclose(np.dot(g[2].T, x[2].T), np.zeros((self.k, self.k)), atol=1e-6) def test_proj(self): # Verify that proj gives the closest point within the tangent space # by displacing the result slightly and checking that this increases # the distance. m = self.man x = self.man.rand() v = np.random.randn(self.m, self.n) g = m.proj(x, v) # Displace g a little g_disp = g + 0.01 * m.randvec(x) # Return to the ambient representation g = m.tangent2ambient(x, g) g_disp = m.tangent2ambient(x, g_disp) g = g[0].dot(g[1]).dot(g[2].T) g_disp = g_disp[0].dot(g_disp[1]).dot(g_disp[2].T) assert np.linalg.norm(g - v) < np.linalg.norm(g_disp - v) def test_proj_tangents(self): # Verify that proj leaves tangent vectors unchanged e = self.man x = e.rand() u = e.randvec(x) A = e.proj(x, e.tangent2ambient(x, u)) B = u # diff = [A[k]-B[k] for k in xrange(len(A))] np_testing.assert_allclose(A[0], B[0]) np_testing.assert_allclose(A[1], B[1]) np_testing.assert_allclose(A[2], B[2]) def test_norm(self): e = self.man x = e.rand() u = e.randvec(x) np_testing.assert_almost_equal(np.sqrt(e.inner(x, u, u)), e.norm(x, u)) def test_rand(self): e = self.man x = e.rand() y = e.rand() assert np.shape(x[0]) == (self.m, self.k) assert np.shape(x[1]) == (self.k, ) assert np.shape(x[2]) == (self.k, self.n) np_testing.assert_allclose(x[0].T.dot(x[0]), np.eye(self.k), atol=1e-6) np_testing.assert_allclose(x[2].dot(x[2].T), np.eye(self.k), atol=1e-6) assert la.norm(x[0] - y[0]) > 1e-6 assert la.norm(x[1] - y[1]) > 1e-6 assert la.norm(x[2] - y[2]) > 1e-6 def test_transp(self): s = self.man x = s.rand() y = s.rand() u = s.randvec(x) A = s.transp(x, y, u) B = s.proj(y, s.tangent2ambient(x, u)) diff = [A[k] - B[k] for k in range(len(A))] np_testing.assert_almost_equal(s.norm(y, diff), 0) def test_apply_ambient(self): m = self.man z = np.random.randn(self.m, self.n) # Set u, s, v so that z = u.dot(s).dot(v.T) u, s, v = np.linalg.svd(z, full_matrices=False) s = np.diag(s) v = v.T w = np.random.randn(self.n, self.n) np_testing.assert_allclose(z.dot(w), m._apply_ambient(z, w)) np_testing.assert_allclose(z.dot(w), m._apply_ambient((u, s, v), w)) def test_apply_ambient_transpose(self): m = self.man z = np.random.randn(self.n, self.m) # Set u, s, v so that z = u.dot(s).dot(v.T) u, s, v = np.linalg.svd(z, full_matrices=False) s = np.diag(s) v = v.T w = np.random.randn(self.n, self.n) np_testing.assert_allclose(z.T.dot(w), m._apply_ambient_transpose(z, w)) np_testing.assert_allclose(z.T.dot(w), m._apply_ambient_transpose((u, s, v), w)) def test_tangent2ambient(self): m = self.man x = m.rand() z = m.randvec(x) z_ambient = (x[0].dot(z[1]).dot(x[2]) + z[0].dot(x[2]) + x[0].dot(z[2].T)) u, s, v = m.tangent2ambient(x, z) np_testing.assert_allclose(z_ambient, u.dot(s).dot(v.T)) def test_ehess2rhess(self): pass def test_retr(self): # Test that the result is on the manifold and that for small # tangent vectors it has little effect. x = self.man.rand() u = self.man.randvec(x) y = self.man.retr(x, u) np_testing.assert_allclose(y[0].T.dot(y[0]), np.eye(self.k), atol=1e-6) np_testing.assert_allclose(y[2].dot(y[2].T), np.eye(self.k), atol=1e-6) u = u * 1e-6 y = self.man.retr(x, u) y = y[0].dot(np.diag(y[1])).dot(y[2]) u = self.man.tangent2ambient(x, u) u = u[0].dot(u[1]).dot(u[2].T) x = x[0].dot(np.diag(x[1])).dot(x[2]) np_testing.assert_allclose(y, x + u, atol=1e-5) def test_egrad2rgrad(self): # Verify that egrad2rgrad and proj are equivalent. m = self.man x = m.rand() u, s, vt = x i = np.eye(self.k) f = 1 / (s[..., np.newaxis, :]**2 - s[..., :, np.newaxis]**2 + i) du = np.random.randn(self.m, self.k) ds = np.random.randn(self.k) dvt = np.random.randn(self.k, self.n) Up = (np.dot(np.dot(np.eye(self.m) - np.dot(u, u.T), du), np.linalg.inv(np.diag(s)))) M = (np.dot(f * (np.dot(u.T, du) - np.dot(du.T, u)), np.diag(s)) + np.dot(np.diag(s), f * (np.dot(vt, dvt.T) - np.dot(dvt, vt.T))) + np.diag(ds)) Vp = (np.dot(np.dot(np.eye(self.n) - np.dot(vt.T, vt), dvt.T), np.linalg.inv(np.diag(s)))) up, m, vp = m.egrad2rgrad(x, (du, ds, dvt)) U, S, V = self.man.tangent2ambient(x, [Up, M, Vp]) u, s, v = self.man.tangent2ambient(x, [up, m, vp]) T = U.dot(S).dot(V.T) t = u.dot(s).dot(v.T) np_testing.assert_allclose(T, t) def test_randvec(self): e = self.man x = e.rand() u = e.randvec(x) # Check that u is a tangent vector assert np.shape(u[0]) == (self.m, self.k) assert np.shape(u[1]) == (self.k, self.k) assert np.shape(u[2]) == (self.n, self.k) np_testing.assert_allclose(np.dot(u[0].T, x[0]), np.zeros((self.k, self.k)), atol=1e-6) np_testing.assert_allclose(np.dot(u[2].T, x[2].T), np.zeros((self.k, self.k)), atol=1e-6) v = e.randvec(x) np_testing.assert_almost_equal(e.norm(x, u), 1) assert e.norm(x, u - v) > 1e-6 #if __name__ == '__main__': # test = TestFixedRankEmbeddedManifold() # test.setup() # test.test_egrad2rgrad()
def setUp(self): self.m = m = 10 self.n = n = 5 self.k = k = 3 self.man = FixedRankEmbedded(m, n, k)
m = 4 n = 2 k = 2 X = np.random.rand(m, n) U, S, Vt = np.linalg.svd(X, full_matrices=False) U = U[:, :k] S = S[:k] Vt = Vt[:k, :] grad_f = grad(f) grad_g = grad(g) man = FixedRankEmbedded(m, n, k) dU, dS, dVt = grad_g((U, S, Vt)) Up, M, Vp = man.egrad2rgrad((U, S, Vt), (dU, dS, dVt)) U_, S_, V_ = man.tangent2ambient((U, S, Vt), (Up, M, Vp)) tangent_grad = U_.dot(S_).dot(V_.T) print print print 'X:' print X print print 'U,S,Vt:' print U, S, Vt
#e_correct_prediction = tf.equal(tf.argmax(e_y, 1), tf.argmax(y_, 1)) #e_accuracy = tf.reduce_mean(tf.cast(e_correct_prediction, "float")) #e_accuracy_summary =tf.summary.scalar("e_accuracy", e_accuracy) summaries = tf.summary.merge_all() manifold_b = Euclidean(1,10) if use_parameterization: manifold_A = Euclidean(784, k) manifold_B = Euclidean(k, 10) manifold_W = Product([manifold_A,manifold_B]) arg = [A, B, b] else: manifold_W = FixedRankEmbedded(784, 10, k) #manifold_W = Product([Stiefel(784,k), Euclidean(k), Stiefel(k,10)]) arg = [A, M, B, b] manifold = Product([manifold_W, manifold_b]) e_manifold_W = Euclidean(784, 10) e_arg = [eW, b] e_manifold = Product([e_manifold_W, manifold_b]) problem = Problem(manifold=manifold, cost=loss, accuracy=accuracy, summary=summaries, arg=arg, data=[x,y_], verbosity=1) e_problem = Problem(manifold=e_manifold, cost=e_loss, accuracy=accuracy, summary=summaries, arg=e_arg, data=[x, y_], verbosity=1) solver = SGD(maxiter=10000000,logverbosity=10)
if not os.path.isdir('result'): os.makedirs('result') path = os.path.join('result', experiment_name + '.csv') m, n, rank = 10, 8, 4 p = 1 / 2 for i in range(n_exp): matrix = rnd.randn(m, n) P_omega = np.zeros_like(matrix) for j in range(m): for k in range(n): P_omega[j][k] = random.choice([0, 1]) cost = create_cost(matrix, P_omega) manifold = FixedRankEmbedded(m, n, rank) problem = pymanopt.Problem(manifold, cost=cost, egrad=None) res_list = [] for beta_type in BetaTypes: solver = ConjugateGradient(beta_type=beta_type, maxiter=10000) res = solver.solve(problem) res_list.append(res[1]) res_list.append(res[2]) with open(path, 'a') as f: writer = csv.writer(f) writer.writerow(res_list)
class TestFixedRankEmbeddedManifold(ManifoldTestCase): def setUp(self): self.m = m = 10 self.n = n = 5 self.k = k = 3 self.manifold = FixedRankEmbedded(m, n, k) u, s, vt = self.manifold.random_point() matrix = (u * s) @ vt @pymanopt.function.autograd(self.manifold) def cost(u, s, vt): return np.linalg.norm((u * s) @ vt - matrix) ** 2 self.cost = cost def test_dim(self): assert self.manifold.dim == (self.m + self.n - self.k) * self.k def test_typical_dist(self): assert self.manifold.dim == self.manifold.typical_dist def test_dist(self): e = self.manifold a = e.random_point() x = e.random_tangent_vector(a) y = e.random_tangent_vector(a) with self.assertRaises(NotImplementedError): e.dist(x, y) def test_inner_product(self): e = self.manifold x = e.random_point() a = e.random_tangent_vector(x) b = e.random_tangent_vector(x) # First embed in the ambient space A = x[0] @ a[1] @ x[2] + a[0] @ x[2] + x[0] @ a[2].T B = x[0] @ b[1] @ x[2] + b[0] @ x[2] + x[0] @ b[2].T trueinner = np.sum(A * B) np_testing.assert_almost_equal(trueinner, e.inner_product(x, a, b)) def test_proj_range(self): m = self.manifold x = m.random_point() v = np.random.normal(size=(self.m, self.n)) g = m.projection(x, v) # Check that g is a true tangent vector np_testing.assert_allclose( g[0].T @ x[0], np.zeros((self.k, self.k)), atol=1e-6 ) np_testing.assert_allclose( g[2].T @ x[2].T, np.zeros((self.k, self.k)), atol=1e-6 ) def test_projection(self): # Verify that proj gives the closest point within the tangent space # by displacing the result slightly and checking that this increases # the distance. m = self.manifold x = self.manifold.random_point() v = np.random.normal(size=(self.m, self.n)) g = m.projection(x, v) # Displace g a little g_disp = g + 0.01 * m.random_tangent_vector(x) # Return to the ambient representation g = m.embedding(x, g) g_disp = m.embedding(x, g_disp) g = g[0] @ g[1] @ g[2].T g_disp = g_disp[0] @ g_disp[1] @ g_disp[2].T assert np.linalg.norm(g - v) < np.linalg.norm(g_disp - v) def test_proj_tangents(self): # Verify that proj leaves tangent vectors unchanged e = self.manifold x = e.random_point() u = e.random_tangent_vector(x) A = e.projection(x, e.embedding(x, u)) B = u # diff = [A[k]-B[k] for k in range(len(A))] np_testing.assert_allclose(A[0], B[0]) np_testing.assert_allclose(A[1], B[1]) np_testing.assert_allclose(A[2], B[2]) def test_norm(self): e = self.manifold x = e.random_point() u = e.random_tangent_vector(x) np_testing.assert_almost_equal( np.sqrt(e.inner_product(x, u, u)), e.norm(x, u) ) def test_random_point(self): e = self.manifold x = e.random_point() y = e.random_point() assert np.shape(x[0]) == (self.m, self.k) assert np.shape(x[1]) == (self.k,) assert np.shape(x[2]) == (self.k, self.n) np_testing.assert_allclose(x[0].T @ x[0], np.eye(self.k), atol=1e-6) np_testing.assert_allclose(x[2] @ x[2].T, np.eye(self.k), atol=1e-6) assert np.linalg.norm(x[0] - y[0]) > 1e-6 assert np.linalg.norm(x[1] - y[1]) > 1e-6 assert np.linalg.norm(x[2] - y[2]) > 1e-6 def test_transport(self): s = self.manifold x = s.random_point() y = s.random_point() u = s.random_tangent_vector(x) A = s.transport(x, y, u) B = s.projection(y, s.embedding(x, u)) diff = [A[k] - B[k] for k in range(len(A))] np_testing.assert_almost_equal(s.norm(y, diff), 0) def test_apply_ambient(self): m = self.manifold z = np.random.normal(size=(self.m, self.n)) # Set u, s, v so that z = u @ s @ v.T u, s, v = np.linalg.svd(z, full_matrices=False) s = np.diag(s) v = v.T w = np.random.normal(size=(self.n, self.n)) np_testing.assert_allclose(z @ w, m._apply_ambient(z, w)) np_testing.assert_allclose(z @ w, m._apply_ambient((u, s, v), w)) def test_apply_ambient_transpose(self): m = self.manifold z = np.random.normal(size=(self.n, self.m)) # Set u, s, v so that z = u @ s @ v.T u, s, v = np.linalg.svd(z, full_matrices=False) s = np.diag(s) v = v.T w = np.random.normal(size=(self.n, self.n)) np_testing.assert_allclose(z.T @ w, m._apply_ambient_transpose(z, w)) np_testing.assert_allclose( z.T @ w, m._apply_ambient_transpose((u, s, v), w) ) def test_embedding(self): m = self.manifold x = m.random_point() z = m.random_tangent_vector(x) z_ambient = x[0] @ z[1] @ x[2] + z[0] @ x[2] + x[0] @ z[2].T u, s, v = m.embedding(x, z) np_testing.assert_allclose(z_ambient, u @ s @ v.T) def test_euclidean_to_riemannian_hessian(self): pass def test_retraction(self): # Test that the result is on the manifold and that for small # tangent vectors it has little effect. x = self.manifold.random_point() u = self.manifold.random_tangent_vector(x) y = self.manifold.retraction(x, u) np_testing.assert_allclose(y[0].T @ y[0], np.eye(self.k), atol=1e-6) np_testing.assert_allclose(y[2] @ y[2].T, np.eye(self.k), atol=1e-6) u = u * 1e-6 y = self.manifold.retraction(x, u) y = y[0] @ np.diag(y[1]) @ y[2] u = self.manifold.embedding(x, u) u = u[0] @ u[1] @ u[2].T x = x[0] @ np.diag(x[1]) @ x[2] np_testing.assert_allclose(y, x + u, atol=1e-5) def test_euclidean_to_riemannian_gradient(self): # Verify that euclidean_to_riemannian_gradient and proj are equivalent. m = self.manifold x = m.random_point() u, s, vt = x i = np.eye(self.k) f = 1 / (s[..., np.newaxis, :] ** 2 - s[..., :, np.newaxis] ** 2 + i) du = np.random.normal(size=(self.m, self.k)) ds = np.random.normal(size=self.k) dvt = np.random.normal(size=(self.k, self.n)) Up = (np.eye(self.m) - u @ u.T) @ du @ np.linalg.inv(np.diag(s)) M = ( f * (u.T @ du - du.T @ u) @ np.diag(s) + np.diag(s) @ f * (vt @ dvt.T - dvt @ vt.T) + np.diag(ds) ) Vp = (np.eye(self.n) - vt.T @ vt) @ dvt.T @ np.linalg.inv(np.diag(s)) up, m, vp = m.euclidean_to_riemannian_gradient(x, (du, ds, dvt)) np_testing.assert_allclose(Up, up) np_testing.assert_allclose(M, m) np_testing.assert_allclose(Vp, vp) def test_first_order_function_approximation(self): self.run_gradient_approximation_test() def test_random_tangent_vector(self): e = self.manifold x = e.random_point() u = e.random_tangent_vector(x) # Check that u is a tangent vector assert np.shape(u[0]) == (self.m, self.k) assert np.shape(u[1]) == (self.k, self.k) assert np.shape(u[2]) == (self.n, self.k) np_testing.assert_allclose( u[0].T @ x[0], np.zeros((self.k, self.k)), atol=1e-6 ) np_testing.assert_allclose( u[2].T @ x[2].T, np.zeros((self.k, self.k)), atol=1e-6 ) v = e.random_tangent_vector(x) np_testing.assert_almost_equal(e.norm(x, u), 1) assert e.norm(x, u - v) > 1e-6
class TestFixedRankEmbeddedManifold(unittest.TestCase): def setUp(self): self.m = m = 10 self.n = n = 5 self.k = k = 3 self.man = FixedRankEmbedded(m, n, k) def test_dim(self): assert self.man.dim == (self.m + self.n - self.k) * self.k def test_typicaldist(self): assert self.man.dim == self.man.typicaldist def test_dist(self): e = self.man a = e.rand() x = e.randvec(a) y = e.randvec(a) with self.assertRaises(NotImplementedError): e.dist(x, y) def test_inner(self): e = self.man x = e.rand() a = e.randvec(x) b = e.randvec(x) # First embed in the ambient space A = x[0].dot(a[1].dot(x[2])) + a[0].dot(x[2]) + x[0].dot(a[2].T) B = x[0].dot(b[1].dot(x[2])) + b[0].dot(x[2]) + x[0].dot(b[2].T) trueinner = np.sum(A*B) np_testing.assert_almost_equal(trueinner, e.inner(x, a, b)) def test_proj_range(self): m = self.man x = m.rand() v = np.random.randn(self.m, self.n) g = m.proj(x, v) # Check that g is a true tangent vector np_testing.assert_allclose(np.dot(g[0].T, x[0]), np.zeros((self.k, self.k)), atol=1e-6) np_testing.assert_allclose(np.dot(g[2].T, x[2].T), np.zeros((self.k, self.k)), atol=1e-6) def test_proj(self): # Verify that proj gives the closest point within the tangent space # by displacing the result slightly and checking that this increases # the distance. m = self.man x = self.man.rand() v = np.random.randn(self.m, self.n) g = m.proj(x, v) # Displace g a little g_disp = g + 0.01 * m.randvec(x) # Return to the ambient representation g = m.tangent2ambient(x, g) g_disp = m.tangent2ambient(x, g_disp) g = g[0].dot(g[1]).dot(g[2].T) g_disp = g_disp[0].dot(g_disp[1]).dot(g_disp[2].T) assert np.linalg.norm(g - v) < np.linalg.norm(g_disp - v) def test_proj_tangents(self): # Verify that proj leaves tangent vectors unchanged e = self.man x = e.rand() u = e.randvec(x) A = e.proj(x, e.tangent2ambient(x, u)) B = u # diff = [A[k]-B[k] for k in xrange(len(A))] np_testing.assert_allclose(A[0], B[0]) np_testing.assert_allclose(A[1], B[1]) np_testing.assert_allclose(A[2], B[2]) def test_norm(self): e = self.man x = e.rand() u = e.randvec(x) np_testing.assert_almost_equal(np.sqrt(e.inner(x, u, u)), e.norm(x, u)) def test_rand(self): e = self.man x = e.rand() y = e.rand() assert np.shape(x[0]) == (self.m, self.k) assert np.shape(x[1]) == (self.k,) assert np.shape(x[2]) == (self.k, self.n) np_testing.assert_allclose(x[0].T.dot(x[0]), np.eye(self.k), atol=1e-6) np_testing.assert_allclose(x[2].dot(x[2].T), np.eye(self.k), atol=1e-6) assert la.norm(x[0] - y[0]) > 1e-6 assert la.norm(x[1] - y[1]) > 1e-6 assert la.norm(x[2] - y[2]) > 1e-6 def test_transp(self): s = self.man x = s.rand() y = s.rand() u = s.randvec(x) A = s.transp(x, y, u) B = s.proj(y, s.tangent2ambient(x, u)) diff = [A[k]-B[k] for k in range(len(A))] np_testing.assert_almost_equal(s.norm(y, diff), 0) def test_apply_ambient(self): m = self.man z = np.random.randn(self.m, self.n) # Set u, s, v so that z = u.dot(s).dot(v.T) u, s, v = np.linalg.svd(z, full_matrices=False) s = np.diag(s) v = v.T w = np.random.randn(self.n, self.n) np_testing.assert_allclose(z.dot(w), m._apply_ambient(z, w)) np_testing.assert_allclose(z.dot(w), m._apply_ambient((u, s, v), w)) def test_apply_ambient_transpose(self): m = self.man z = np.random.randn(self.n, self.m) # Set u, s, v so that z = u.dot(s).dot(v.T) u, s, v = np.linalg.svd(z, full_matrices=False) s = np.diag(s) v = v.T w = np.random.randn(self.n, self.n) np_testing.assert_allclose(z.T.dot(w), m._apply_ambient_transpose(z, w)) np_testing.assert_allclose(z.T.dot(w), m._apply_ambient_transpose((u, s, v), w)) def test_tangent2ambient(self): m = self.man x = m.rand() z = m.randvec(x) z_ambient = (x[0].dot(z[1]).dot(x[2]) + z[0].dot(x[2]) + x[0].dot(z[2].T)) u, s, v = m.tangent2ambient(x, z) np_testing.assert_allclose(z_ambient, u.dot(s).dot(v.T)) def test_ehess2rhess(self): pass def test_retr(self): # Test that the result is on the manifold and that for small # tangent vectors it has little effect. x = self.man.rand() u = self.man.randvec(x) y = self.man.retr(x, u) np_testing.assert_allclose(y[0].T.dot(y[0]), np.eye(self.k), atol=1e-6) np_testing.assert_allclose(y[2].dot(y[2].T), np.eye(self.k), atol=1e-6) u = u * 1e-6 y = self.man.retr(x, u) y = y[0].dot(np.diag(y[1])).dot(y[2]) u = self.man.tangent2ambient(x, u) u = u[0].dot(u[1]).dot(u[2].T) x = x[0].dot(np.diag(x[1])).dot(x[2]) np_testing.assert_allclose(y, x + u, atol=1e-5) def test_egrad2rgrad(self): # Verify that egrad2rgrad and proj are equivalent. m = self.man x = m.rand() u, s, vt = x i = np.eye(self.k) f = 1 / (s[..., np.newaxis, :]**2 - s[..., :, np.newaxis]**2 + i) du = np.random.randn(self.m, self.k) ds = np.random.randn(self.k) dvt = np.random.randn(self.k, self.n) Up = (np.dot(np.dot(np.eye(self.m) - np.dot(u, u.T), du), np.linalg.inv(np.diag(s)))) M = (np.dot(f * (np.dot(u.T, du) - np.dot(du.T, u)), np.diag(s)) + np.dot(np.diag(s), f * (np.dot(vt, dvt.T) - np.dot(dvt, vt.T))) + np.diag(ds)) Vp = (np.dot(np.dot(np.eye(self.n) - np.dot(vt.T, vt), dvt.T), np.linalg.inv(np.diag(s)))) up, m, vp = m.egrad2rgrad(x, (du, ds, dvt)) np_testing.assert_allclose(Up, up) np_testing.assert_allclose(M, m) np_testing.assert_allclose(Vp, vp) def test_randvec(self): e = self.man x = e.rand() u = e.randvec(x) # Check that u is a tangent vector assert np.shape(u[0]) == (self.m, self.k) assert np.shape(u[1]) == (self.k, self.k) assert np.shape(u[2]) == (self.n, self.k) np_testing.assert_allclose(np.dot(u[0].T, x[0]), np.zeros((self.k, self.k)), atol=1e-6) np_testing.assert_allclose(np.dot(u[2].T, x[2].T), np.zeros((self.k, self.k)), atol=1e-6) v = e.randvec(x) np_testing.assert_almost_equal(e.norm(x, u), 1) assert e.norm(x, u - v) > 1e-6