示例#1
0
 def setUp(self):
     self.k = 50
     self.man = PoincareBall(self.k)
示例#2
0
class TestSinglePoincareBallManifold(TestCase):
    def setUp(self):
        self.k = 50
        self.man = PoincareBall(self.k)

    def test_dim(self):
        assert self.man.dim == self.k

    # def test_typicaldist(self):
    #     pass

    def test_conformal_factor(self):
        x = self.man.rand() / 2
        np_testing.assert_allclose(1 - 2 / self.man.conformal_factor(x),
                                   la.norm(x)**2)

    def test_inner(self):
        x = self.man.rand() / 2
        u = self.man.randvec(x)
        v = self.man.randvec(x)
        np_testing.assert_allclose(
            (2 / (1 - la.norm(x)**2))**2 * np.inner(u, v),
            self.man.inner(x, u, v),
        )

        # test that angles are preserved
        x = self.man.rand() / 2
        u = self.man.randvec(x)
        v = self.man.randvec(x)
        cos_eangle = np.sum(u * v) / la.norm(u) / la.norm(v)
        cos_rangle = (self.man.inner(x, u, v) / self.man.norm(x, u) /
                      self.man.norm(x, v))
        np_testing.assert_allclose(cos_rangle, cos_eangle)

    def test_proj(self):
        x = self.man.rand()
        u = self.man.randvec(x)
        np_testing.assert_allclose(u, self.man.proj(x, u))

    def test_norm(self):
        x = self.man.rand() / 2
        u = self.man.randvec(x)

        np_testing.assert_allclose(2 / (1 - la.norm(x)**2) * la.norm(u),
                                   self.man.norm(x, u))

    def test_rand(self):
        # Just make sure that things generated are on the manifold and that
        # if you generate two they are not equal.
        x = self.man.rand()
        np_testing.assert_array_less(la.norm(x), 1)
        y = self.man.rand()
        assert not np.array_equal(x, y)

    def test_randvec(self):
        # Just make sure that things generated are in the tangent space and
        # that if you generate two they are not equal.
        x = self.man.rand()
        u = self.man.randvec(x)
        v = self.man.randvec(x)

        assert not np.array_equal(u, v)

    def test_zerovec(self):
        x = self.man.rand()
        u = self.man.zerovec(x)
        np_testing.assert_allclose(la.norm(u), 0)

    def test_dist(self):
        x = self.man.rand() / 2
        y = self.man.rand() / 2
        correct_dist = np.arccosh(1 + 2 * la.norm(x - y)**2 /
                                  (1 - la.norm(x)**2) / (1 - la.norm(y)**2))
        np_testing.assert_allclose(correct_dist, self.man.dist(x, y))

    # def test_egrad2rgrad(self):
    #     pass

    # def test_ehess2rhess(self):
    #     pass

    def test_retr(self):
        x = self.man.rand() / 2
        u = self.man.randvec(x)
        y = self.man.retr(x, u)
        assert la.norm(y) <= 1 + 1e-10

    def test_mobius_addition(self):
        # test if Mobius addition is closed in the Poincare ball
        x = self.man.rand() / 2
        y = self.man.rand() / 2
        z = self.man.mobius_addition(x, y)
        # The norm of z may be slightly more than one because of
        # round-off errors.
        assert la.norm(z) <= 1 + 1e-10

    def test_exp_log_inverse(self):
        x = self.man.rand() / 2
        y = self.man.rand() / 2
        explog = self.man.exp(x, self.man.log(x, y))
        np_testing.assert_allclose(y, explog)

    def test_log_exp_inverse(self):
        x = self.man.rand() / 2
        # If u is too big its exponential will have norm 1 because of
        # numerical approximations
        u = self.man.randvec(x) / self.man.dim
        logexp = self.man.log(x, self.man.exp(x, u))
        np_testing.assert_allclose(u, logexp)

    # def test_transp(self):
    #     pass

    def test_pairmean(self):
        x = self.man.rand() / 2
        y = self.man.rand() / 2
        z = self.man.pairmean(x, y)
        np_testing.assert_allclose(self.man.dist(x, z), self.man.dist(y, z))
示例#3
0
class TestSinglePoincareBallManifold(ManifoldTestCase):
    def setUp(self):
        self.n = 50
        self.manifold = PoincareBall(self.n)

        super().setUp()

    def test_dim(self):
        assert self.manifold.dim == self.n

    def test_conformal_factor(self):
        x = self.manifold.random_point() / 2
        np_testing.assert_allclose(
            1 - 2 / self.manifold.conformal_factor(x), np.linalg.norm(x) ** 2
        )

    def test_inner_product(self):
        x = self.manifold.random_point() / 2
        u = self.manifold.random_tangent_vector(x)
        v = self.manifold.random_tangent_vector(x)
        np_testing.assert_allclose(
            (2 / (1 - np.linalg.norm(x) ** 2)) ** 2 * np.inner(u, v),
            self.manifold.inner_product(x, u, v),
        )

        # Test that angles are preserved.
        x = self.manifold.random_point() / 2
        u = self.manifold.random_tangent_vector(x)
        v = self.manifold.random_tangent_vector(x)
        cos_eangle = np.sum(u * v) / np.linalg.norm(u) / np.linalg.norm(v)
        cos_rangle = (
            self.manifold.inner_product(x, u, v)
            / self.manifold.norm(x, u)
            / self.manifold.norm(x, v)
        )
        np_testing.assert_allclose(cos_rangle, cos_eangle)

        # Test symmetry.
        np_testing.assert_allclose(
            self.manifold.inner_product(x, u, v),
            self.manifold.inner_product(x, v, u),
        )

    def test_proj(self):
        x = self.manifold.random_point()
        u = self.manifold.random_tangent_vector(x)
        np_testing.assert_allclose(u, self.manifold.projection(x, u))

    def test_norm(self):
        x = self.manifold.random_point() / 2
        u = self.manifold.random_tangent_vector(x)

        np_testing.assert_allclose(
            2 / (1 - np.linalg.norm(x) ** 2) * np.linalg.norm(u),
            self.manifold.norm(x, u),
        )

    def test_random_point(self):
        # Just make sure that things generated are on the manifold and that
        # if you generate two they are not equal.
        x = self.manifold.random_point()
        np_testing.assert_array_less(np.linalg.norm(x), 1)
        y = self.manifold.random_point()
        assert not np.array_equal(x, y)

    def test_random_tangent_vector(self):
        # Just make sure that things generated are in the tangent space and
        # that if you generate two they are not equal.
        x = self.manifold.random_point()
        u = self.manifold.random_tangent_vector(x)
        v = self.manifold.random_tangent_vector(x)

        assert not np.array_equal(u, v)

    def test_zero_vector(self):
        x = self.manifold.random_point()
        u = self.manifold.zero_vector(x)
        np_testing.assert_allclose(np.linalg.norm(u), 0)

    def test_dist(self):
        x = self.manifold.random_point() / 2
        y = self.manifold.random_point() / 2
        correct_dist = np.arccosh(
            1
            + 2
            * np.linalg.norm(x - y) ** 2
            / (1 - np.linalg.norm(x) ** 2)
            / (1 - np.linalg.norm(y) ** 2)
        )
        np_testing.assert_allclose(correct_dist, self.manifold.dist(x, y))

    def test_euclidean_to_riemannian_gradient(self):
        # For now just test whether the method returns an array of the correct
        # shape.
        point = self.manifold.random_point()
        euclidean_gradient = np.random.normal(size=point.shape)
        riemannian_gradient = self.manifold.euclidean_to_riemannian_gradient(
            point, euclidean_gradient
        )
        assert euclidean_gradient.shape == riemannian_gradient.shape

    def test_first_order_function_approximation(self):
        self.run_gradient_approximation_test()

    def test_second_order_function_approximation(self):
        self.run_hessian_approximation_test()

    def test_euclidean_to_riemannian_hessian(self):
        # For now just test whether the method returns an array of the correct
        # shape.
        point = self.manifold.random_point()
        euclidean_gradient = np.random.normal(size=point.shape)
        euclidean_hessian = np.random.normal(size=point.shape)
        tangent_vector = self.manifold.random_tangent_vector(point)
        riemannian_hessian = self.manifold.euclidean_to_riemannian_hessian(
            point, euclidean_gradient, euclidean_hessian, tangent_vector
        )
        assert euclidean_hessian.shape == riemannian_hessian.shape

    def test_retraction(self):
        x = self.manifold.random_point() / 2
        u = self.manifold.random_tangent_vector(x)
        y = self.manifold.retraction(x, u)
        assert np.linalg.norm(y) <= 1 + 1e-10

    def test_mobius_addition(self):
        # test if Mobius addition is closed in the Poincare ball
        x = self.manifold.random_point() / 2
        y = self.manifold.random_point() / 2
        z = self.manifold.mobius_addition(x, y)
        # The norm of z may be slightly more than one because of
        # round-off errors.
        assert np.linalg.norm(z) <= 1 + 1e-10

    def test_exp_log_inverse(self):
        x = self.manifold.random_point() / 2
        y = self.manifold.random_point() / 2
        explog = self.manifold.exp(x, self.manifold.log(x, y))
        np_testing.assert_allclose(y, explog)

    def test_log_exp_inverse(self):
        x = self.manifold.random_point() / 2
        # If u is too big its exponential will have norm 1 because of
        # numerical approximations
        u = self.manifold.random_tangent_vector(x) / self.manifold.dim
        logexp = self.manifold.log(x, self.manifold.exp(x, u))
        np_testing.assert_allclose(u, logexp)

    def test_pair_mean(self):
        x = self.manifold.random_point() / 2
        y = self.manifold.random_point() / 2
        z = self.manifold.pair_mean(x, y)
        np_testing.assert_allclose(
            self.manifold.dist(x, z), self.manifold.dist(y, z)
        )
示例#4
0
    def setUp(self):
        self.n = 50
        self.manifold = PoincareBall(self.n)

        super().setUp()
示例#5
0
 def setUp(self):
     self.n = 50
     self.k = 20
     self.manifold = PoincareBall(self.n, k=self.k)
     super().setUp()