Beispiel #1
0
class TestVisualization(geomstats.tests.TestCase):
    def setUp(self):
        self.n_samples = 10
        self.SO3_GROUP = SpecialOrthogonal(n=3, point_type='vector')
        self.SE3_GROUP = SpecialEuclidean(n=3, point_type='vector')
        self.S1 = Hypersphere(dim=1)
        self.S2 = Hypersphere(dim=2)
        self.H2 = Hyperbolic(dim=2)
        self.H2_half_plane = PoincareHalfSpace(dim=2)

        plt.figure()

    @staticmethod
    def test_tutorial_matplotlib():
        visualization.tutorial_matplotlib()

    def test_plot_points_so3(self):
        points = self.SO3_GROUP.random_uniform(self.n_samples)
        visualization.plot(points, space='SO3_GROUP')

    def test_plot_points_se3(self):
        points = self.SE3_GROUP.random_uniform(self.n_samples)
        visualization.plot(points, space='SE3_GROUP')

    @geomstats.tests.np_and_pytorch_only
    def test_plot_points_s1(self):
        points = self.S1.random_uniform(self.n_samples)
        visualization.plot(points, space='S1')

    def test_plot_points_s2(self):
        points = self.S2.random_uniform(self.n_samples)
        visualization.plot(points, space='S2')

    def test_plot_points_h2_poincare_disk(self):
        points = self.H2.random_uniform(self.n_samples)
        visualization.plot(points, space='H2_poincare_disk')

    def test_plot_points_h2_poincare_half_plane_ext(self):
        points = self.H2.random_uniform(self.n_samples)
        visualization.plot(points,
                           space='H2_poincare_half_plane',
                           point_type='extrinsic')

    def test_plot_points_h2_poincare_half_plane_none(self):
        points = self.H2_half_plane.random_uniform(self.n_samples)
        visualization.plot(points, space='H2_poincare_half_plane')

    def test_plot_points_h2_poincare_half_plane_hs(self):
        points = self.H2_half_plane.random_uniform(self.n_samples)
        visualization.plot(points,
                           space='H2_poincare_half_plane',
                           point_type='half_space')

    def test_plot_points_h2_klein_disk(self):
        points = self.H2.random_uniform(self.n_samples)
        visualization.plot(points, space='H2_klein_disk')
Beispiel #2
0
 def test_fit_matrix_se(self):
     se_mat = SpecialEuclidean(n=3, default_point_type='matrix')
     X = se_mat.random_uniform(self.n_samples)
     estimator = ExponentialBarycenter(se_mat)
     estimator.fit(X)
     mean = estimator.estimate_
     tpca = TangentPCA(metric=se_mat, point_type='matrix')
     tangent_projected_data = tpca.fit_transform(X, base_point=mean)
     result = tpca.inverse_transform(tangent_projected_data)
     expected = X
     self.assertAllClose(result, expected)
Beispiel #3
0
class TestVisualizationMethods(geomstats.tests.TestCase):
    def setUp(self):
        self.n_samples = 10
        self.SO3_GROUP = SpecialOrthogonal(n=3)
        self.SE3_GROUP = SpecialEuclidean(n=3)
        self.S1 = Hypersphere(dim=1)
        self.S2 = Hypersphere(dim=2)
        self.H2 = Hyperbolic(dim=2)

        plt.figure()

    @geomstats.tests.np_only
    def test_plot_points_so3(self):
        points = self.SO3_GROUP.random_uniform(self.n_samples)
        visualization.plot(points, space='SO3_GROUP')

    @geomstats.tests.np_only
    def test_plot_points_se3(self):
        points = self.SE3_GROUP.random_uniform(self.n_samples)
        visualization.plot(points, space='SE3_GROUP')

    @geomstats.tests.np_only
    def test_plot_points_s1(self):
        points = self.S1.random_uniform(self.n_samples)
        visualization.plot(points, space='S1')

    @geomstats.tests.np_only
    def test_plot_points_s2(self):
        points = self.S2.random_uniform(self.n_samples)
        visualization.plot(points, space='S2')

    @geomstats.tests.np_only
    def test_plot_points_h2_poincare_disk(self):
        points = self.H2.random_uniform(self.n_samples)
        visualization.plot(points, space='H2_poincare_disk')

    @geomstats.tests.np_only
    def test_plot_points_h2_poincare_half_plane(self):
        points = self.H2.random_uniform(self.n_samples)
        visualization.plot(points, space='H2_poincare_half_plane')

    @geomstats.tests.np_only
    def test_plot_points_h2_klein_disk(self):
        points = self.H2.random_uniform(self.n_samples)
        visualization.plot(points, space='H2_klein_disk')
Beispiel #4
0
class TestExponentialBarycenter(geomstats.tests.TestCase):
    def setUp(self):
        logger = logging.getLogger()
        logger.disabled = True
        self.se_mat = SpecialEuclidean(n=3)
        self.so_vec = SpecialOrthogonal(n=3, point_type='vector')
        self.so = SpecialOrthogonal(n=3)
        self.n_samples = 4

    @geomstats.tests.np_only
    def test_estimate_and_belongs_se(self):
        point = self.se_mat.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.se_mat)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.se_mat.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

    def test_estimate_one_sample_se(self):
        point = self.se_mat.random_uniform()
        estimator = ExponentialBarycenter(self.se_mat)
        estimator.fit(point)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(1)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_and_reach_max_iter_se(self):
        point = self.se_mat.random_uniform(1)
        estimator = ExponentialBarycenter(self.se_mat, max_iter=2)
        points = gs.array([point, point])
        estimator.fit(points)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(1)
        estimator = ExponentialBarycenter(self.so_vec, max_iter=2)
        points = gs.array([point, point])
        estimator.fit(points)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_so_matrix(self):
        points = self.so.random_uniform(2)

        mean_vec = ExponentialBarycenter(group=self.so)
        mean_vec.fit(points)

        logs = self.so.log(points, mean_vec.estimate_)
        result = gs.sum(logs, axis=0)
        expected = gs.zeros_like(points[0])
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_and_belongs_so(self):
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_one_sample_so(self):
        point = self.so.random_uniform(1)
        estimator = ExponentialBarycenter(self.so)
        estimator.fit(point)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(1)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_and_reach_max_iter_so(self):
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so, max_iter=2)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec, max_iter=2)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_coincides_with_frechet_so(self):
        gs.random.seed(0)
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so, max_iter=40, epsilon=1e-10)
        estimator.fit(point)
        result = estimator.estimate_
        frechet_estimator = FrechetMean(self.so.bi_invariant_metric,
                                        max_iter=40,
                                        epsilon=1e-10)
        frechet_estimator.fit(point)
        expected = frechet_estimator.estimate_
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_weights(self):
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so, verbose=True)
        weights = gs.arange(self.n_samples)
        estimator.fit(point, weights=weights)
        barexp = estimator.estimate_
        result = self.so.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point, weights=weights)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

    def test_linear_mean(self):
        euclidean = Euclidean(3)
        point = euclidean.random_uniform(self.n_samples)

        estimator = ExponentialBarycenter(euclidean)

        estimator.fit(point)
        result = estimator.estimate_

        expected = gs.mean(point, axis=0)

        self.assertAllClose(result, expected)
class TestSpecialEuclidean(geomstats.tests.TestCase):
    def setUp(self):
        self.n = 2
        self.group = SpecialEuclidean(n=self.n)
        self.n_samples = 4
        self.point = self.group.random_uniform(self.n_samples)
        self.tangent_vec = self.group.to_tangent(
            gs.random.rand(self.n_samples, self.group.n + 1, self.group.n + 1),
            self.point)

    def test_belongs(self):
        theta = gs.pi / 3
        point_1 = gs.array([[gs.cos(theta), -gs.sin(theta), 2.],
                            [gs.sin(theta), gs.cos(theta), 3.], [0., 0., 1.]])
        result = self.group.belongs(point_1)
        expected = True
        self.assertAllClose(result, expected)

        point_2 = gs.array([[gs.cos(theta), -gs.sin(theta), 2.],
                            [gs.sin(theta), gs.cos(theta), 3.], [0., 0., 0.]])
        result = self.group.belongs(point_2)
        expected = False
        self.assertAllClose(result, expected)

        point = gs.array([point_1, point_2])
        expected = gs.array([True, False])
        result = self.group.belongs(point)
        self.assertAllClose(result, expected)

    def test_random_uniform_and_belongs(self):
        point = self.group.random_uniform()
        result = self.group.belongs(point)
        expected = True
        self.assertAllClose(result, expected)

        point = self.group.random_uniform(self.n_samples)
        result = self.group.belongs(point)
        expected = gs.array([True] * self.n_samples)
        self.assertAllClose(result, expected)

    def test_identity(self):
        result = self.group.identity
        expected = gs.eye(self.n + 1)
        self.assertAllClose(result, expected)

    def test_is_tangent(self):
        theta = gs.pi / 3
        vec_1 = gs.array([[0., -theta, 2.], [theta, 0., 3.], [0., 0., 0.]])
        point = self.group.random_uniform()
        tangent_vec = self.group.compose(point, vec_1)
        result = self.group.is_tangent(tangent_vec, point)
        expected = True
        self.assertAllClose(result, expected)

        vec_2 = gs.array([[0., -theta, 2.], [theta, 0., 3.], [0., 0., 1.]])
        tangent_vec = self.group.compose(point, vec_2)
        result = self.group.is_tangent(tangent_vec, point)
        expected = False
        self.assertAllClose(result, expected)

        vec = gs.array([vec_1, vec_2])
        expected = gs.array([True, False])
        result = self.group.is_tangent(vec)
        self.assertAllClose(result, expected)

    def test_to_tangent_vec_vectorization(self):
        n = self.group.n
        tangent_vecs = gs.arange(self.n_samples * (n + 1)**2)
        tangent_vecs = gs.cast(tangent_vecs, gs.float32)
        tangent_vecs = gs.reshape(tangent_vecs,
                                  (self.n_samples, ) + (n + 1, ) * 2)
        point = self.group.random_uniform(self.n_samples)
        tangent_vecs = self.group.compose(point, tangent_vecs)
        regularized = self.group.to_tangent(tangent_vecs, point)
        result = self.group.compose(
            self.group.transpose(point), regularized) + \
            self.group.compose(self.group.transpose(regularized), point)
        result = result[:, :n, :n]
        expected = gs.zeros_like(result)
        self.assertAllClose(result, expected)

    def test_compose_and_inverse_matrix_form(self):
        point = self.group.random_uniform()
        inv_point = self.group.inverse(point)
        result = self.group.compose(point, inv_point)
        expected = self.group.identity
        self.assertAllClose(result, expected)

        if not geomstats.tests.tf_backend():
            result = self.group.compose(inv_point, point)
            expected = self.group.identity
            self.assertAllClose(result, expected)

    def test_compose_vectorization(self):
        n_samples = self.n_samples
        n_points_a = self.group.random_uniform(n_samples=n_samples)
        n_points_b = self.group.random_uniform(n_samples=n_samples)
        one_point = self.group.random_uniform(n_samples=1)

        result = self.group.compose(one_point, n_points_a)
        self.assertAllClose(gs.shape(result),
                            (n_samples, ) + (self.group.n + 1, ) * 2)

        result = self.group.compose(n_points_a, one_point)

        if not geomstats.tests.tf_backend():
            self.assertAllClose(gs.shape(result),
                                (n_samples, ) + (self.group.n + 1, ) * 2)

            result = self.group.compose(n_points_a, n_points_b)
            self.assertAllClose(gs.shape(result),
                                (n_samples, ) + (self.group.n + 1, ) * 2)

    def test_inverse_vectorization(self):
        n_samples = self.n_samples
        points = self.group.random_uniform(n_samples=n_samples)
        result = self.group.inverse(points)
        self.assertAllClose(gs.shape(result),
                            (n_samples, ) + (self.group.n + 1, ) * 2)

    def test_compose_matrix_form(self):
        point = self.group.random_uniform()
        result = self.group.compose(point, self.group.identity)
        expected = point
        self.assertAllClose(result, expected)

        if not geomstats.tests.tf_backend():
            # Composition by identity, on the left
            # Expect the original transformation
            result = self.group.compose(self.group.identity, point)
            expected = point
            self.assertAllClose(result, expected)

            # Composition of translations (no rotational part)
            # Expect the sum of the translations
            point_a = gs.array([[1., 0., 1.], [0., 1., 1.5], [0., 0., 1.]])
            point_b = gs.array([[1., 0., 2.], [0., 1., 2.5], [0., 0., 1.]])

            result = self.group.compose(point_a, point_b)
            last_line_0 = gs.array_from_sparse([(0, 2), (1, 2)], [1., 1.],
                                               (3, 3))
            expected = point_a + point_b * last_line_0
            self.assertAllClose(result, expected)

    def test_left_exp_coincides(self):
        vector_group = SpecialEuclidean(n=2, point_type='vector')
        theta = gs.pi / 3
        initial_vec = gs.array([theta, 2., 2.])
        initial_matrix_vec = self.group.lie_algebra.matrix_representation(
            initial_vec)
        vector_exp = vector_group.left_canonical_metric.exp(initial_vec)
        result = self.group.left_canonical_metric.exp(initial_matrix_vec)
        expected = vector_group.matrix_from_vector(vector_exp)
        self.assertAllClose(result, expected)

    def test_right_exp_coincides(self):
        vector_group = SpecialEuclidean(n=2, point_type='vector')
        theta = gs.pi / 2
        initial_vec = gs.array([theta, 1., 1.])
        initial_matrix_vec = self.group.lie_algebra.matrix_representation(
            initial_vec)
        vector_exp = vector_group.right_canonical_metric.exp(initial_vec)
        result = self.group.right_canonical_metric.exp(initial_matrix_vec,
                                                       n_steps=25)
        expected = vector_group.matrix_from_vector(vector_exp)
        self.assertAllClose(result, expected)

    def test_basis_belongs(self):
        lie_algebra = self.group.lie_algebra
        result = lie_algebra.belongs(lie_algebra.basis)
        self.assertTrue(gs.all(result))

    def test_basis_has_the_right_dimension(self):
        for n in range(2, 5):
            algebra = SpecialEuclideanMatrixLieAlgebra(n)
            self.assertEqual(int(n * (n + 1) / 2), algebra.dim)

    def test_belongs_lie_algebra(self):
        theta = gs.pi / 3
        vec_1 = gs.array([[0., -theta, 2.], [theta, 0., 3.], [0., 0., 0.]])
        result = self.group.lie_algebra.belongs(vec_1)
        expected = True
        self.assertAllClose(result, expected)

        vec_2 = gs.array([[0., -theta, 2.], [theta, 0., 3.], [0., 0., 1.]])
        result = self.group.lie_algebra.belongs(vec_2)
        expected = False
        self.assertAllClose(result, expected)

        vec = gs.array([vec_1, vec_2])
        expected = gs.array([True, False])
        result = self.group.lie_algebra.belongs(vec)
        self.assertAllClose(result, expected)

    def test_basis_representation_is_correctly_vectorized(self):
        for n in range(2, 5):
            algebra = SpecialEuclideanMatrixLieAlgebra(n)
            shape = gs.shape(algebra.basis_representation(algebra.basis))
            dim = int(n * (n + 1) / 2)
            self.assertAllClose(shape, (dim, dim))

    def test_left_metric_wrong_group(self):
        group = self.group.rotations
        self.assertRaises(
            ValueError,
            lambda: SpecialEuclideanMatrixCannonicalLeftMetric(group))

        group = SpecialEuclidean(3, point_type='vector')
        self.assertRaises(
            ValueError,
            lambda: SpecialEuclideanMatrixCannonicalLeftMetric(group))

    def test_exp_and_belongs(self):
        exp = self.group.left_canonical_metric.exp(self.tangent_vec,
                                                   self.point)
        result = self.group.belongs(exp)
        self.assertTrue(gs.all(result))

        exp = self.group.left_canonical_metric.exp(self.tangent_vec[0],
                                                   self.point[0])
        result = self.group.belongs(exp)
        self.assertTrue(result)

    @geomstats.tests.np_and_tf_only
    def test_log_and_is_tan(self):
        exp = self.group.left_canonical_metric.exp(self.tangent_vec,
                                                   self.point)
        log = self.group.left_canonical_metric.log(exp, self.point)
        result = self.group.is_tangent(log, self.point)
        self.assertTrue(gs.all(result))

        exp = self.group.left_canonical_metric.exp(self.tangent_vec[0],
                                                   self.point[0])
        log = self.group.left_canonical_metric.log(exp, self.point)
        result = self.group.is_tangent(log, self.point)
        self.assertTrue(gs.all(result))

        log = self.group.left_canonical_metric.log(exp, self.point[0])
        result = self.group.is_tangent(log, self.point[0])
        self.assertTrue(result)

    @geomstats.tests.np_and_tf_only
    def test_exp_log(self):
        exp = self.group.left_canonical_metric.exp(self.tangent_vec,
                                                   self.point)
        result = self.group.left_canonical_metric.log(exp, self.point)
        self.assertAllClose(result, self.tangent_vec)

        exp = self.group.left_canonical_metric.exp(self.tangent_vec[0],
                                                   self.point[0])
        result = self.group.left_canonical_metric.log(exp, self.point[0])
        self.assertAllClose(result, self.tangent_vec[0])

    @geomstats.tests.np_and_tf_only
    def test_parallel_transport(self):
        metric = self.group.left_canonical_metric
        tan_a = self.tangent_vec
        tan_b = self.group.to_tangent(
            gs.random.rand(self.n_samples, self.group.n + 1, self.group.n + 1),
            self.point)
        end_point = metric.exp(tan_b, self.point)

        def is_isometry(tan_a, trans_a, basepoint, endpoint):
            is_tangent = self.group.is_tangent(trans_a, endpoint, atol=1e-6)
            is_equinormal = gs.isclose(metric.norm(trans_a, endpoint),
                                       metric.norm(tan_a, basepoint))
            return gs.logical_and(is_tangent, is_equinormal)

        transported = metric.parallel_transport(tan_a, tan_b, self.point)
        result = is_isometry(tan_a, transported, self.point, end_point)
        expected_end_point = metric.exp(tan_b, self.point)
        self.assertTrue(gs.all(result))
        self.assertAllClose(end_point, expected_end_point)

        new_tan_b = metric.log(self.point, end_point)
        result_vec = metric.parallel_transport(transported, new_tan_b,
                                               end_point)
        self.assertAllClose(result_vec, tan_a)

    def test_lie_algebra_basis_belongs(self):
        basis = self.group.lie_algebra.basis
        result = self.group.lie_algebra.belongs(basis)
        self.assertTrue(gs.all(result))

    def test_lie_algebra_projection_and_belongs(self):
        vec = gs.random.rand(self.n_samples, self.group.n + 1,
                             self.group.n + 1)
        tangent_vec = self.group.lie_algebra.projection(vec)
        result = self.group.lie_algebra.belongs(tangent_vec)
        self.assertTrue(gs.all(result))

    def test_basis_representation(self):
        vec = gs.random.rand(self.n_samples, self.group.dim)
        tangent_vec = self.group.lie_algebra.matrix_representation(vec)
        result = self.group.lie_algebra.basis_representation(tangent_vec)
        self.assertAllClose(result, vec)

        result = self.group.lie_algebra.basis_representation(tangent_vec[0])
        self.assertAllClose(result, vec[0])
class TestSpecialEuclidean(geomstats.tests.TestCase):
    def setUp(self):
        self.n = 2
        self.group = SpecialEuclidean(n=self.n)
        self.n_samples = 4

    def test_belongs(self):
        theta = gs.pi / 3
        point_1 = gs.array([[gs.cos(theta), -gs.sin(theta), 2.],
                            [gs.sin(theta), gs.cos(theta), 3.], [0., 0., 1.]])
        result = self.group.belongs(point_1)
        expected = True
        self.assertAllClose(result, expected)

        point_2 = gs.array([[gs.cos(theta), -gs.sin(theta), 2.],
                            [gs.sin(theta), gs.cos(theta), 3.], [0., 0., 0.]])
        result = self.group.belongs(point_2)
        expected = False
        self.assertAllClose(result, expected)

        point = gs.array([point_1, point_2])
        expected = gs.array([True, False])
        result = self.group.belongs(point)
        self.assertAllClose(result, expected)

    def test_random_uniform_and_belongs(self):
        point = self.group.random_uniform()
        result = self.group.belongs(point)
        expected = True
        self.assertAllClose(result, expected)

        point = self.group.random_uniform(self.n_samples)
        result = self.group.belongs(point)
        expected = gs.array([True] * self.n_samples)
        self.assertAllClose(result, expected)

    def test_identity(self):
        result = self.group.identity
        expected = gs.eye(self.n + 1)
        self.assertAllClose(result, expected)

    def test_is_in_lie_algebra(self):
        theta = gs.pi / 3
        vec_1 = gs.array([[0., -theta, 2.], [theta, 0., 3.], [0., 0., 0.]])
        result = self.group.is_tangent(vec_1)
        expected = True
        self.assertAllClose(result, expected)

        vec_2 = gs.array([[0., -theta, 2.], [theta, 0., 3.], [0., 0., 1.]])
        result = self.group.is_tangent(vec_2)
        expected = False
        self.assertAllClose(result, expected)

        vec = gs.array([vec_1, vec_2])
        expected = gs.array([True, False])
        result = self.group.is_tangent(vec)
        self.assertAllClose(result, expected)

    def test_to_tangent_vec_vectorization(self):
        n = self.group.n
        tangent_vecs = gs.arange(self.n_samples * (n + 1)**2)
        tangent_vecs = gs.cast(tangent_vecs, gs.float32)
        tangent_vecs = gs.reshape(tangent_vecs,
                                  (self.n_samples, ) + (n + 1, ) * 2)
        point = self.group.random_uniform(self.n_samples)
        tangent_vecs = self.group.compose(point, tangent_vecs)
        regularized = self.group.to_tangent(tangent_vecs, point)
        result = self.group.compose(
            self.group.transpose(point), regularized) + \
            self.group.compose(self.group.transpose(regularized), point)
        result = result[:, :n, :n]
        expected = gs.zeros_like(result)
        self.assertAllClose(result, expected)

    def test_compose_and_inverse_matrix_form(self):
        point = self.group.random_uniform()
        inv_point = self.group.inverse(point)
        result = self.group.compose(point, inv_point)
        expected = self.group.identity
        self.assertAllClose(result, expected)

        if not geomstats.tests.tf_backend():
            result = self.group.compose(inv_point, point)
            expected = self.group.identity
            self.assertAllClose(result, expected)

    def test_compose_vectorization(self):
        n_samples = self.n_samples
        n_points_a = self.group.random_uniform(n_samples=n_samples)
        n_points_b = self.group.random_uniform(n_samples=n_samples)
        one_point = self.group.random_uniform(n_samples=1)

        result = self.group.compose(one_point, n_points_a)
        self.assertAllClose(gs.shape(result),
                            (n_samples, ) + (self.group.n + 1, ) * 2)

        result = self.group.compose(n_points_a, one_point)

        if not geomstats.tests.tf_backend():
            self.assertAllClose(gs.shape(result),
                                (n_samples, ) + (self.group.n + 1, ) * 2)

            result = self.group.compose(n_points_a, n_points_b)
            self.assertAllClose(gs.shape(result),
                                (n_samples, ) + (self.group.n + 1, ) * 2)

    def test_inverse_vectorization(self):
        n_samples = self.n_samples
        points = self.group.random_uniform(n_samples=n_samples)
        result = self.group.inverse(points)
        self.assertAllClose(gs.shape(result),
                            (n_samples, ) + (self.group.n + 1, ) * 2)

    def test_compose_matrix_form(self):
        point = self.group.random_uniform()
        result = self.group.compose(point, self.group.identity)
        expected = point
        self.assertAllClose(result, expected)

        if not geomstats.tests.tf_backend():
            # Composition by identity, on the left
            # Expect the original transformation
            result = self.group.compose(self.group.identity, point)
            expected = point
            self.assertAllClose(result, expected)

            # Composition of translations (no rotational part)
            # Expect the sum of the translations
            point_a = gs.array([[1., 0., 1.], [0., 1., 1.5], [0., 0., 1.]])
            point_b = gs.array([[1., 0., 2.], [0., 1., 2.5], [0., 0., 1.]])

            result = self.group.compose(point_a, point_b)
            last_line_0 = gs.array_from_sparse([(0, 2), (1, 2)], [1., 1.],
                                               (3, 3))
            expected = point_a + point_b * last_line_0
            self.assertAllClose(result, expected)
Beispiel #7
0
class TestExponentialBarycenter(geomstats.tests.TestCase):
    def setUp(self):
        self.se_mat = SpecialEuclidean(n=3, default_point_type='matrix')
        self.so_vec = SpecialOrthogonal(n=3, default_point_type='vector')
        self.so = SpecialOrthogonal(n=3, default_point_type='matrix')
        self.n_samples = 3

    @geomstats.tests.np_only
    def test_estimate_and_belongs_se(self):
        point = self.se_mat.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.se_mat)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.se_mat.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

    def test_estimate_one_sample_se(self):
        point = self.se_mat.random_uniform(1)
        estimator = ExponentialBarycenter(self.se_mat)
        estimator.fit(point)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(1)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_and_reach_max_iter_se(self):
        point = self.se_mat.random_uniform(1)
        estimator = ExponentialBarycenter(self.se_mat, max_iter=2)
        points = gs.array([point, point])
        estimator.fit(points)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(1)
        estimator = ExponentialBarycenter(self.so_vec, max_iter=2)
        points = gs.array([point, point])
        estimator.fit(points)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_and_belongs_so(self):
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_one_sample_so(self):
        point = self.so.random_uniform(1)
        estimator = ExponentialBarycenter(self.so)
        estimator.fit(point)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(1)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point)
        result = estimator.estimate_
        expected = point
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_and_reach_max_iter_so(self):
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so, max_iter=2)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec, max_iter=2)
        estimator.fit(point)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_coincides_with_frechet_so(self):
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so, max_iter=32, epsilon=1e-12)
        estimator.fit(point)
        result = estimator.estimate_
        print(self.so.default_point_type)
        so_vector = SpecialOrthogonal(3, default_point_type='vector')
        frechet_estimator = FrechetMean(so_vector.bi_invariant_metric,
                                        max_iter=32,
                                        epsilon=1e-10,
                                        point_type='vector')
        vector_point = so_vector.rotation_vector_from_matrix(point)
        frechet_estimator.fit(vector_point)
        mean = frechet_estimator.estimate_
        expected = so_vector.matrix_from_rotation_vector(mean)
        result = estimator.estimate_
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_estimate_weights(self):
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so, verbose=True)
        weights = gs.arange(self.n_samples)
        estimator.fit(point, weights=weights)
        barexp = estimator.estimate_
        result = self.so.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point, weights=weights)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

    def test_linear_mean(self):
        euclidean = Euclidean(3)
        point = euclidean.random_uniform(self.n_samples)

        estimator = ExponentialBarycenter(euclidean)

        estimator.fit(point)
        result = estimator.estimate_

        expected = gs.mean(point, axis=0)

        self.assertAllClose(result, expected)