def test_log_after_exp_with_angles_close_to_pi( self, metric, tangent_vec, base_point ): """ Test that the Riemannian left exponential and the Riemannian left logarithm are inverse. Expect their composition to give the identity function. """ group = SpecialEuclidean(3, "vector") result = metric.log(metric.exp(tangent_vec, base_point), base_point) expected = group.regularize_tangent_vec( tangent_vec=tangent_vec, base_point=base_point, metric=metric ) inv_expected = gs.concatenate([-expected[:3], expected[3:6]]) norm = gs.linalg.norm(expected) atol = ATOL if norm != 0: atol = ATOL * norm self.assertTrue( gs.allclose(result, expected, atol=atol) or gs.allclose(result, inv_expected, atol=atol) )
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
def test_custom_gradient_squared_dist(self): def squared_dist_grad_a(point_a, point_b, metric): return -2 * metric.log(point_b, point_a) def squared_dist_grad_b(point_a, point_b, metric): return -2 * metric.log(point_a, point_b) @gs.autodiff.custom_gradient(squared_dist_grad_a, squared_dist_grad_b) def squared_dist(point_a, point_b, metric): dist = metric.squared_dist(point_a, point_b) return dist space = SpecialEuclidean(n=2) const_metric = space.left_canonical_metric const_point_b = space.random_point() def func(x): return squared_dist(x, const_point_b, metric=const_metric) arg_point_a = space.random_point() expected_value = func(arg_point_a) expected_grad = -2 * const_metric.log(const_point_b, arg_point_a) result_value, result_grad = gs.autodiff.value_and_grad(func)(arg_point_a) self.assertAllClose(result_value, expected_value) self.assertAllClose(result_grad, expected_grad)
def test_load_poses(self): """Test that the poses belong to SE(3).""" se3 = SpecialEuclidean(n=3, point_type="vector") data, _ = data_utils.load_poses(only_rotations=False) result = se3.belongs(data) self.assertTrue(gs.all(result))
def setUp(self): self.n = 2 self.group = SpecialEuclidean(n=self.n) self.n_samples = 4 self.point = self.group.random_point(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_right_exp_coincides(self, n, initial_vec): group = SpecialEuclidean(n=n) vector_group = SpecialEuclidean(n=n, point_type="vector") initial_matrix_vec = group.lie_algebra.matrix_representation(initial_vec) vector_exp = vector_group.right_canonical_metric.exp(initial_vec) result = group.right_canonical_metric.exp(initial_matrix_vec, n_steps=25) expected = vector_group.matrix_from_vector(vector_exp) self.assertAllClose(result, expected, atol=1e-6)
def test_right_exp_coincides(self): vector_group = SpecialEuclidean(n=2, point_type="vector") theta = gs.pi / 2 initial_vec = gs.array([theta, 1.0, 1.0]) 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, atol=1e-6)
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()
def setup_method(self): gs.random.seed(12) self.n = 2 self.group = SpecialEuclidean(n=self.n) self.n_samples = 3 self.point = self.group.random_point(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_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 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()
def setup_method(self): gs.random.seed(1234) self.n_samples = 20 # Set up for hypersphere self.dim_sphere = 4 self.shape_sphere = (self.dim_sphere + 1, ) self.sphere = Hypersphere(dim=self.dim_sphere) X = gs.random.rand(self.n_samples) self.X_sphere = X - gs.mean(X) self.intercept_sphere_true = self.sphere.random_point() self.coef_sphere_true = self.sphere.projection( gs.random.rand(self.dim_sphere + 1)) self.y_sphere = self.sphere.metric.exp( self.X_sphere[:, None] * self.coef_sphere_true, base_point=self.intercept_sphere_true, ) self.param_sphere_true = gs.vstack( [self.intercept_sphere_true, self.coef_sphere_true]) self.param_sphere_guess = gs.vstack([ self.y_sphere[0], self.sphere.to_tangent(gs.random.normal(size=self.shape_sphere), self.y_sphere[0]), ]) # Set up for special euclidean self.se2 = SpecialEuclidean(n=2) self.metric_se2 = self.se2.left_canonical_metric self.metric_se2.default_point_type = "matrix" self.shape_se2 = (3, 3) X = gs.random.rand(self.n_samples) self.X_se2 = X - gs.mean(X) self.intercept_se2_true = self.se2.random_point() self.coef_se2_true = self.se2.to_tangent( 5.0 * gs.random.rand(*self.shape_se2), self.intercept_se2_true) self.y_se2 = self.metric_se2.exp( self.X_se2[:, None, None] * self.coef_se2_true[None], self.intercept_se2_true, ) self.param_se2_true = gs.vstack([ gs.flatten(self.intercept_se2_true), gs.flatten(self.coef_se2_true), ]) self.param_se2_guess = gs.vstack([ gs.flatten(self.y_se2[0]), gs.flatten( self.se2.to_tangent(gs.random.normal(size=self.shape_se2), self.y_se2[0])), ])
def left_metric_wrong_group_test_data(self): smoke_data = [ dict(group=SpecialEuclidean(2), expected=does_not_raise()), dict(group=SpecialEuclidean(3), expected=does_not_raise()), dict( group=SpecialEuclidean(2, point_type="vector"), expected=pytest.raises(ValueError), ), dict(group=SpecialOrthogonal(3), expected=pytest.raises(ValueError)), ] return self.generate_tests(smoke_data)
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)
def orthonormal_basis_se3_test_data(self): smoke_data = [ dict(group=SpecialEuclidean(3), metric_mat_at_identity=None), dict( group=SpecialEuclidean(3), metric_mat_at_identity=from_vector_to_diagonal_matrix( gs.cast(gs.arange(1, SpecialEuclidean(3).dim + 1), gs.float32)), ), ] return self.generate_tests(smoke_data)
def test_value_and_grad_dist(self): space = SpecialEuclidean(3) metric = space.metric point = space.random_point() id = space.identity result_loss, result_grad = gs.autodiff.value_and_grad( lambda v: metric.squared_dist(v, id) )(point) expected_loss = metric.squared_dist(point, id) expected_grad = -2 * metric.log(id, point) self.assertAllClose(result_loss, expected_loss) self.assertAllClose(result_grad, expected_grad)
def test_exp_after_log(self, metric, point, base_point): """ Test that the Riemannian right exponential and the Riemannian right logarithm are inverse. Expect their composition to give the identity function. """ group = SpecialEuclidean(3, "vector") result = metric.exp(metric.log(point, base_point), base_point) expected = group.regularize(point) expected = gs.cast(expected, gs.float64) norm = gs.linalg.norm(expected) atol = ATOL if norm != 0: atol = ATOL * norm self.assertAllClose(result, expected, atol=atol)
def test_exp_after_log_right_with_angles_close_to_pi( self, metric, point, base_point): group = SpecialEuclidean(3, "vector") result = metric.exp(metric.log(point, base_point), base_point) expected = group.regularize(point) inv_expected = gs.concatenate([-expected[:3], expected[3:6]]) norm = gs.linalg.norm(expected) atol = ATOL if norm != 0: atol = ATOL * norm self.assertTrue( gs.allclose(result, expected, atol=atol) or gs.allclose(result, inv_expected, atol=atol))
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) self.M32 = Matrices(m=3, n=2) self.S32 = PreShapeSpace(k_landmarks=3, m_ambient=2) self.KS = visualization.KendallSphere() self.M33 = Matrices(m=3, n=3) self.S33 = PreShapeSpace(k_landmarks=3, m_ambient=3) self.KD = visualization.KendallDisk() plt.figure()
def test_left_metric_wrong_group(self): group = self.group.rotations with pytest.raises(ValueError): SpecialEuclideanMatrixCannonicalLeftMetric(group) group = SpecialEuclidean(3, point_type="vector") with pytest.raises(ValueError): SpecialEuclideanMatrixCannonicalLeftMetric(group)
def inner_product_matrix_and_its_inverse_test_data(self): group = SpecialEuclidean(n=3, point_type="vector") smoke_data = [ dict(group=group, metric_mat_at_identity=None, left_or_right="left") ] return self.generate_tests(smoke_data)
def test_log_after_exp(self, metric, tangent_vec, base_point): """ Test that the Riemannian left exponential and the Riemannian left logarithm are inverse. Expect their composition to give the identity function. """ group = SpecialEuclidean(3, "vector") result = metric.log(metric.exp(tangent_vec, base_point), base_point) expected = group.regularize_tangent_vec( tangent_vec=tangent_vec, base_point=base_point, metric=metric ) norm = gs.linalg.norm(expected) atol = ATOL if norm != 0: atol = ATOL * norm self.assertAllClose(result, expected, atol=atol)
def setUp(self): warnings.simplefilter('ignore', category=ImportWarning) gs.random.seed(1234) n = 3 group = SpecialEuclidean(n=n) # Diagonal left and right invariant metrics diag_mat_at_identity = gs.eye(group.dimension) left_diag_metric = InvariantMetric( group=group, inner_product_mat_at_identity=diag_mat_at_identity, left_or_right='left') right_diag_metric = InvariantMetric( group=group, inner_product_mat_at_identity=diag_mat_at_identity, left_or_right='right') # General left and right invariant metrics # TODO(nina): Replace the matrix below by a general SPD matrix. sym_mat_at_identity = gs.eye(group.dimension) left_metric = InvariantMetric( group=group, inner_product_mat_at_identity=sym_mat_at_identity, left_or_right='left') right_metric = InvariantMetric( group=group, inner_product_mat_at_identity=sym_mat_at_identity, left_or_right='right') metrics = { 'left_diag': left_diag_metric, 'right_diag_metric': right_diag_metric, 'left': left_metric, 'right': right_metric } # General case for the point point_1 = gs.array([[-0.2, 0.9, 0.5, 5., 5., 5.]]) point_2 = gs.array([[0., 2., -0.1, 30., 400., 2.]]) # Edge case for the point, angle < epsilon, point_small = gs.array([[-1e-7, 0., -7 * 1e-8, 6., 5., 9.]]) self.group = group self.metrics = metrics self.left_diag_metric = left_diag_metric self.right_diag_metric = right_diag_metric self.left_metric = left_metric self.right_metric = right_metric self.point_1 = point_1 self.point_2 = point_2 self.point_small = point_small
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')
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 inner_product_mat_at_identity_shape_test_data(self): group = SpecialEuclidean(n=3, point_type="vector") sym_mat_at_identity = gs.eye(group.dim) smoke_data = [ dict( group=group, metric_mat_at_identity=sym_mat_at_identity, left_or_right="left", ) ] return self.generate_tests(smoke_data)
def test_custom_gradient_in_action(self): space = SpecialEuclidean(n=2) const_metric = space.left_canonical_metric const_point_b = space.random_point() def func(x): return const_metric.squared_dist(x, const_point_b) arg_point_a = space.random_point() func_with_grad = gs.autodiff.value_and_grad(func) result_value, result_grad = func_with_grad(arg_point_a) expected_value = const_metric.squared_dist(arg_point_a, const_point_b) expected_grad = -2 * const_metric.log(const_point_b, arg_point_a) self.assertAllClose(result_value, expected_value) self.assertAllClose(result_grad, expected_grad) loss, grad = func_with_grad(const_point_b) self.assertAllClose(loss, 0.0) self.assertAllClose(grad, gs.zeros_like(grad))
def inverse_shape_test_data(self): n_list = random.sample(range(2, 50), 10) n_samples = 10 random_data = [ dict( n=n, points=SpecialEuclidean(n).random_point(n_samples), expected=(n_samples, n + 1, n + 1), ) for n in n_list ] return self.generate_tests([], random_data)
def exp_after_log_right_with_angles_close_to_pi_test_data(self): smoke_data = [] for metric in list( self.metrics.values()) + [SpecialEuclidean(3, "vector")]: for base_point in self.elements.values(): for element_type in self.angles_close_to_pi: point = self.elements[element_type] smoke_data.append( dict( metric=metric, point=point, base_point=base_point, )) return self.generate_tests(smoke_data)
def setUp(self): warnings.simplefilter("ignore", category=ImportWarning) gs.random.seed(1234) group = SpecialEuclidean(n=2, point_type="vector") point_1 = gs.array([0.1, 0.2, 0.3]) point_2 = gs.array([0.5, 5.0, 60.0]) translation_large = gs.array([0.0, 5.0, 6.0]) translation_small = gs.array([0.0, 0.6, 0.7]) elements_all = { "translation_large": translation_large, "translation_small": translation_small, "point_1": point_1, "point_2": point_2, } elements = elements_all if geomstats.tests.tf_backend(): # Tf is extremely slow elements = {"point_1": point_1, "point_2": point_2} elements_matrices_all = { key: group.matrix_from_vector(elements_all[key]) for key in elements_all } elements_matrices = elements_matrices_all self.group = group self.elements_all = elements_all self.elements = elements self.elements_matrices_all = elements_matrices_all self.elements_matrices = elements_matrices self.n_samples = 4