text: import unittest
  
  import numpy as np
  import numpy.linalg as la
  import numpy.random as rnd
  import numpy.testing as np_testing
  
  import scipy as sp
  
  from pymanopt.manifolds import PositiveDefinite
  from pymanopt.tools.multi import *
  
  
  class TestPositiveDefiniteManifold(unittest.TestCase):
      def setUp(self):
          self.n = n = 10
          self.k = k = 3
          self.man = PositiveDefinite(n, k)
  
      def test_name(self):
          man = self.man
          k = self.k
          assert "Product manifold of " + str(k) in str(man)
  
      def test_dim(self):
          man = self.man
          n = self.n
          k = self.k
          np_testing.assert_equal(man.dim, 0.5 * k * n * (n+1))
  
      def test_typicaldist(self):
          man = self.man
          np_testing.assert_equal(man.typicaldist, np.sqrt(man.dim))
  
      def test_dist(self):
          k = self.k
          n = self.n
          man = self.man
          x = man.rand()
          y = man.rand()
  
          # Compare to the implementation in manopt
          d = la.solve(x, y)
          for i in range(k):
              d[i] = sp.linalg.logm(d[i])
  
          np_testing.assert_almost_equal(man.dist(x, y), la.norm(d))
  
      def test_inner(self):
          man = self.man
          k = self.k
          n = self.n
          x = man.rand()
          a, b = rnd.randn(2, k, n, n)
          np.testing.assert_almost_equal(np.tensordot(a, b, axes=a.ndim),
                                         man.inner(x, multiprod(x, a),
                                                   multiprod(x, b)))
  
      def test_proj(self):
          man = self.man
          x = man.rand()
          a = rnd.randn(self.k, self.n, self.n)
          np.testing.assert_allclose(man.proj(x, a), multisym(a))
  
      def test_egrad2rgrad(self):
          man = self.man
          x = man.rand()
          u = rnd.randn(self.k, self.n, self.n)
          np.testing.assert_allclose(man.egrad2rgrad(x, u),
                                     multiprod(multiprod(x, multisym(u)), x))
  
      def test_ehess2rhess(self):
          # Use manopt's slow method
          man = self.man
          n = self.n
          k = self.k
          x = man.rand()
          egrad, ehess = rnd.randn(2, k, n, n)
          u = man.randvec(x)
  
          Hess = (multiprod(multiprod(x, multisym(ehess)), x) +
                  2*multisym(multiprod(multiprod(u, multisym(egrad)), x)))
  
          # Correction factor for the non-constant metric
          Hess = Hess - multisym(multiprod(multiprod(u, multisym(egrad)), x))
          np_testing.assert_almost_equal(Hess, man.ehess2rhess(x, egrad, ehess,
                                                               u))
  
      def test_norm(self):
          man = self.man
          x = man.rand()
          a = np.random.randn(self.k, self.n, self.n)
          np_testing.assert_almost_equal(la.norm(a), man.norm(x,
                                                              multiprod(x, a)))
  
      def test_rand(self):
          # Just test that rand returns a point on the manifold and two
          # different matrices generated by rand aren't too close together
          k = self.k
          n = self.n
          man = self.man
          x = man.rand()
  
          assert np.shape(x) == (k, n, n)
  
          # Check symmetry
          np_testing.assert_allclose(x, multisym(x))
  
          # Check positivity of eigenvalues
          l = la.eigvalsh(x)
          assert (l > [[0]]).all()
  
      def test_randvec(self):
          # Just test that randvec returns an element of the tangent space
          # with norm 1 and that two randvecs are different.
          man = self.man
          x = man.rand()
          u = man.randvec(x)
          v = man.randvec(x)
          np_testing.assert_allclose(multisym(u), u)
          np_testing.assert_almost_equal(1, man.norm(x, u))
          assert la.norm(u - v) > 1e-3
  
      def test_transp(self):
          man = self.man
          x = man.rand()
          y = man.rand()
          u = man.randvec(x)
          np_testing.assert_allclose(man.transp(x, y, u), u)
  
      def test_exp(self):
          # Test against manopt implementation, test that for small vectors
          # exp(x, u) = x + u.
          man = self.man
          x = man.rand()
          u = man.randvec(x)
          e = np.zeros((self.k, self.n, self.n))
          for i in range(self.k):
              e[i] = sp.linalg.expm(la.solve(x[i], u[i]))
          np_testing.assert_allclose(multiprod(x, e), man.exp(x, u))
          u = u * 1e-6
          np_testing.assert_allclose(man.exp(x, u), x + u)
  
      def test_retr(self):
          # Check that result is on manifold and for small vectors
          # retr(x, u) = x + u.
          man = self.man
          x = man.rand()
          u = man.randvec(x)
          y = man.retr(x, u)
  
          assert np.shape(y) == (self.k, self.n, self.n)
          # Check symmetry
          np_testing.assert_allclose(y, multisym(y))
  
          # Check positivity of eigenvalues
          l = la.eigvalsh(y)
          assert (l > [[0]]).all()
  
          u = u * 1e-6
          np_testing.assert_allclose(man.retr(x, u), x + u)
  
      def test_exp_log_inverse(self):
          man = self.man
          x = man.rand()
          y = man.rand()
          u = man.log(x, y)
          np_testing.assert_allclose(man.exp(x, u), y)
  
      def test_log_exp_inverse(self):
          man = self.man
          x = man.rand()
          u = man.randvec(x)
          y = man.exp(x, u)
          np_testing.assert_allclose(man.log(x, y), u)
  
  
  class TestPositiveDefiniteManifoldSingle(unittest.TestCase):
      def setUp(self):
          self.n = n = 15
          self.man = PositiveDefinite(n)
  
      def test_name(self):
          man = self.man
          n = self.n
          assert "positive definite (" + str(n) in str(man)
  
      def test_rand(self):
          # Just test that rand returns a point on the manifold and two
          # different matrices generated by rand aren't too close together
          n = self.n
          man = self.man
          x = man.rand()
  
          assert np.shape(x) == (n, n)
  
          # Check symmetry
          np_testing.assert_allclose(x, multisym(x))
  
          # Check positivity of eigenvalues
          l = la.eigvalsh(x)
          assert (l > [0]).all()
  
      def test_exp(self):
          man = self.man
          x = man.rand()
          u = man.randvec(x)
          e = sp.linalg.expm(la.solve(x, u))
  
          np_testing.assert_allclose(multiprod(x, e), man.exp(x, u))
          u = u * 1e-6
          np_testing.assert_allclose(man.exp(x, u), x + u)
  
      def test_randvec(self):
          # Just test that randvec returns an element of the tangent space
          # with norm 1 and that two randvecs are different.
          man = self.man
          x = man.rand()
          u = man.randvec(x)
          v = man.randvec(x)
          np_testing.assert_allclose(multisym(u), u)
          np_testing.assert_almost_equal(1, man.norm(x, u))
          assert la.norm(u - v) > 1e-3
  