def test_distance_ball_extrinsic_from_ball(self, dim, x_ball, y_ball): ball_manifold = PoincareBall(dim) space = Hyperboloid(dim) x_extr = ball_manifold.to_coordinates(x_ball, to_coords_type="extrinsic") y_extr = ball_manifold.to_coordinates(y_ball, to_coords_type="extrinsic") dst_ball = ball_manifold.metric.dist(x_ball, y_ball) dst_extr = space.metric.dist(x_extr, y_extr) self.assertAllClose(dst_ball, dst_extr)
class TestPoincareBallMethods(geomstats.tests.TestCase): def setUp(self): self.manifold = PoincareBall(2) self.metric = self.manifold.metric self.hyperboloid_manifold = Hyperboloid(2) self.hyperboloid_metric = self.hyperboloid_manifold.metric def test_squared_dist(self): point_a = gs.array([-0.3, 0.7]) point_b = gs.array([0.2, 0.5]) distance_a_b = self.metric.dist(point_a, point_b) squared_distance = self.metric.squared_dist(point_a, point_b) # TODO(nmiolane): # Remove this line when poincare ball is properly vectorized squared_distance = gs.to_ndarray(squared_distance, to_ndim=2, axis=1) self.assertAllClose(distance_a_b**2, squared_distance, atol=1e-8) @geomstats.tests.np_and_pytorch_only def test_coordinates(self): point_a = gs.array([-0.3, 0.7]) point_b = gs.array([0.2, 0.5]) point_a_h =\ self.manifold.to_coordinates(point_a, 'extrinsic') point_b_h =\ self.manifold.to_coordinates(point_b, 'extrinsic') dist_in_ball =\ self.metric.dist(point_a, point_b) dist_in_hype =\ self.hyperboloid_metric.dist(point_a_h, point_b_h) # TODO(ninamiolane): Remove this to_ndarray when poincare_ball # is properly vectorized dist_in_hype = gs.to_ndarray(dist_in_hype, to_ndim=2, axis=1) self.assertAllClose(dist_in_ball, dist_in_hype, atol=1e-8) def test_dist_poincare(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([0.5, -0.5]) dist_a_b =\ self.manifold.metric.dist(point_a, point_b) result = dist_a_b expected = gs.array([[2.887270927429199]]) self.assertAllClose(result, expected) def test_dist_vectorization(self): point_a = gs.array([0.2, 0.5]) point_b = gs.array([[0.3, -0.5], [0.2, 0.2]]) dist_a_b =\ self.manifold.metric.dist(point_a, point_b) result_vect = dist_a_b result =\ [self.manifold.metric.dist(point_a, point_b[i]) for i in range(len(point_b))] result = gs.concatenate(result, axis=0) self.assertAllClose(result_vect, result) def test_mobius_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.5, -0.3], [0.3, 0.4]]) dist_a_b =\ self.manifold.metric.mobius_add(point_a, point_b) result_vect = dist_a_b result =\ [self.manifold.metric.mobius_add(point_a, point_b[i]) for i in range(len(point_b))] result = gs.concatenate(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b =\ self.manifold.metric.mobius_add(point_b, point_a) result_vect = dist_a_b result =\ [self.manifold.metric.mobius_add(point_b[i], point_a) for i in range(len(point_b))] result = gs.concatenate(result, axis=0) self.assertAllClose(result_vect, result) def test_log_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.5, -0.5], [0.4, 0.4]]) dist_a_b =\ self.manifold.metric.log(point_a, point_b) result_vect = dist_a_b result =\ [self.manifold.metric.log(point_a, point_b[i]) for i in range(len(point_b))] result = gs.concatenate(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b =\ self.manifold.metric.log(point_b, point_a) result_vect = dist_a_b result =\ [self.manifold.metric.log(point_b[i], point_a) for i in range(len(point_b))] result = gs.concatenate(result, axis=0) self.assertAllClose(result_vect, result) def test_exp_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.5, -0.5], [0.4, 0.4]]) dist_a_b =\ self.manifold.metric.exp(point_a, point_b) result_vect = dist_a_b result =\ [self.manifold.metric.exp(point_a, point_b[i]) for i in range(len(point_b))] result = gs.concatenate(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b =\ self.manifold.metric.exp(point_b, point_a) result_vect = dist_a_b result =\ [self.manifold.metric.exp(point_b[i], point_a) for i in range(len(point_b))] result = gs.concatenate(result, axis=0) self.assertAllClose(result_vect, result) def test_log_poincare(self): point = gs.array([[0.3, 0.5]]) base_point = gs.array([[0.3, 0.3]]) result = self.manifold.metric.log(point, base_point) expected = gs.array([[-0.01733576, 0.21958634]]) self.manifold.metric.coords_type = 'extrinsic' self.assertAllClose(result, expected) def test_belong_true_poincare(self): point = gs.array([[0.3, 0.5]]) belong = self.manifold.belongs(point) self.assertTrue(belong) def test_belong_false_poincare(self): point = gs.array([[1.2, 0.5]]) belong = self.manifold.belongs(point) self.assertFalse(belong) def test_exp_poincare(self): point = gs.array([[0.3, 0.5]]) base_point = gs.array([[0.3, 0.3]]) tangent_vec = self.manifold.metric.log(point, base_point) result = self.manifold.metric.exp(tangent_vec, base_point) self.manifold.metric.coords_type = 'extrinsic' self.assertAllClose(result, point) def test_ball_retraction(self): x = gs.array([[0.5, 0.6], [0.2, -0.1], [0.2, -0.4]]) y = gs.array([[0.3, 0.5], [0.3, -0.6], [0.3, -0.3]]) ball_metric = self.manifold.metric tangent_vec = ball_metric.log(y, x) ball_metric.retraction(tangent_vec, x)
class TestPoincareBall(geomstats.tests.TestCase): def setUp(self): self.manifold = PoincareBall(2) self.metric = self.manifold.metric self.hyperboloid_manifold = Hyperboloid(2) self.hyperboloid_metric = self.hyperboloid_manifold.metric def test_squared_dist(self): point_a = gs.array([-0.3, 0.7]) point_b = gs.array([0.2, 0.5]) distance_a_b = self.metric.dist(point_a, point_b) squared_distance = self.metric.squared_dist(point_a, point_b) self.assertAllClose(distance_a_b**2, squared_distance, atol=1e-8) @geomstats.tests.np_and_pytorch_only def test_coordinates(self): point_a = gs.array([-0.3, 0.7]) point_b = gs.array([0.2, 0.5]) point_a_h =\ self.manifold.to_coordinates(point_a, 'extrinsic') point_b_h =\ self.manifold.to_coordinates(point_b, 'extrinsic') dist_in_ball =\ self.metric.dist(point_a, point_b) dist_in_hype =\ self.hyperboloid_metric.dist(point_a_h, point_b_h) self.assertAllClose(dist_in_ball, dist_in_hype, atol=1e-8) def test_dist_poincare(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([0.5, -0.5]) dist_a_b =\ self.manifold.metric.dist(point_a, point_b) result = dist_a_b expected = 2.887270927429199 self.assertAllClose(result, expected) def test_dist_vectorization(self): point_a = gs.array([0.2, 0.5]) point_b = gs.array([[0.3, -0.5], [0.2, 0.2]]) dist_a_b =\ self.manifold.metric.dist(point_a, point_b) result_vect = dist_a_b result =\ [self.manifold.metric.dist(point_a, point_b[i]) for i in range(len(point_b))] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) def test_dist_broadcast(self): point_a = gs.array([[0.2, 0.5], [0.3, 0.1]]) point_b = gs.array([[0.3, -0.5], [0.2, 0.2]]) point_c = gs.array([[0.2, 0.3], [0.5, 0.5], [-0.4, 0.1]]) point_d = gs.array([0.1, 0.2, 0.3]) dist_a_b =\ self.manifold.metric.dist_broadcast(point_a, point_b) dist_b_c = gs.flatten( self.manifold.metric.dist_broadcast(point_b, point_c)) result_vect = gs.concatenate((dist_a_b, dist_b_c), axis=0) result_a_b =\ [self.manifold.metric.dist_broadcast(point_a[i], point_b[i]) for i in range(len(point_b))] result_b_c = \ [self.manifold.metric.dist_broadcast(point_b[i], point_c[j]) for i in range(len(point_b)) for j in range(len(point_c)) ] result = result_a_b + result_b_c result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) with self.assertRaises(ValueError): self.manifold.metric.dist_broadcast(point_a, point_d) @geomstats.tests.np_and_pytorch_only def test_dist_pairwise(self): point = gs.array([[0.1, 0.2], [0.3, 0.4], [0.5, 0.5]]) result = self.manifold.metric.dist_pairwise(point) expected = gs.array([[0., 0.65821943, 1.34682524], [0.65821943, 0., 0.71497076], [1.34682524, 0.71497076, 0.]]) self.assertAllClose(result, expected, rtol=1e-3) def test_mobius_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.5, -0.3], [0.3, 0.4]]) dist_a_b =\ self.manifold.metric.mobius_add(point_a, point_b) result_vect = dist_a_b result =\ [self.manifold.metric.mobius_add(point_a, point_b[i]) for i in range(len(point_b))] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b =\ self.manifold.metric.mobius_add(point_b, point_a) result_vect = dist_a_b result =\ [self.manifold.metric.mobius_add(point_b[i], point_a) for i in range(len(point_b))] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) def test_log_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.5, -0.5], [0.4, 0.4]]) dist_a_b =\ self.manifold.metric.log(point_a, point_b) result_vect = dist_a_b result =\ [self.manifold.metric.log(point_a, point_b[i]) for i in range(len(point_b))] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b =\ self.manifold.metric.log(point_b, point_a) result_vect = dist_a_b result =\ [self.manifold.metric.log(point_b[i], point_a) for i in range(len(point_b))] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) def test_exp_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.0, 0.0], [0.5, -0.5], [0.4, 0.4]]) dist_a_b =\ self.manifold.metric.exp(point_a, point_b) result_vect = dist_a_b result =\ [self.manifold.metric.exp(point_a, point_b[i]) for i in range(len(point_b))] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b =\ self.manifold.metric.exp(point_b, point_a) result_vect = dist_a_b result =\ [self.manifold.metric.exp(point_b[i], point_a) for i in range(len(point_b))] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) def test_log_poincare(self): point = gs.array([0.3, 0.5]) base_point = gs.array([0.3, 0.3]) result = self.manifold.metric.log(point, base_point) expected = gs.array([-0.01733576, 0.21958634]) self.manifold.metric.coords_type = 'extrinsic' self.assertAllClose(result, expected) def test_belong_true_poincare(self): point = gs.array([0.3, 0.5]) belong = self.manifold.belongs(point) self.assertTrue(belong) def test_belong_false_poincare(self): point = gs.array([1.2, 0.5]) belong = self.manifold.belongs(point) self.assertFalse(belong) def test_projection(self): point = gs.array([1.2, 0.5]) projected_point = self.manifold.projection(point) self.assertTrue(gs.sum(projected_point * projected_point) < 1.) def test_exp_poincare(self): point = gs.array([0.3, 0.5]) base_point = gs.array([0.3, 0.3]) tangent_vec = self.manifold.metric.log(point, base_point) result = self.manifold.metric.exp(tangent_vec, base_point) self.manifold.metric.coords_type = 'extrinsic' self.assertAllClose(result, point) def test_ball_retraction(self): x = gs.array([[0.5, 0.6], [0.2, -0.1], [0.2, -0.4]]) y = gs.array([[0.3, 0.5], [0.3, -0.6], [0.3, -0.3]]) ball_metric = self.manifold.metric tangent_vec = ball_metric.log(y, x) ball_metric.retraction(tangent_vec, x)
class TestHyperbolicCoords(geomstats.tests.TestCase): def setUp(self): gs.random.seed(1234) self.dimension = 2 self.extrinsic_manifold = Hyperboloid(dim=self.dimension) self.extrinsic_metric = self.extrinsic_manifold.metric self.ball_manifold = PoincareBall(dim=self.dimension) self.ball_metric = self.ball_manifold.metric self.intrinsic_manifold = Hyperboloid(dim=self.dimension, coords_type="intrinsic") self.intrinsic_metric = self.intrinsic_manifold.metric self.n_samples = 10 def test_extrinsic_ball_extrinsic(self): x_in = gs.array([0.5, 7]) x = self.intrinsic_manifold.to_coordinates(x_in, to_coords_type="extrinsic") x_b = self.extrinsic_manifold.to_coordinates(x, to_coords_type="ball") x2 = self.ball_manifold.to_coordinates(x_b, to_coords_type="extrinsic") self.assertAllClose(x, x2) def test_belongs_intrinsic(self): x_in = gs.array([0.5, 7]) is_in = self.intrinsic_manifold.belongs(x_in) self.assertTrue(is_in) def test_belongs_extrinsic(self): x_true = self.intrinsic_manifold.to_coordinates( gs.array([0.5, 7]), "extrinsic") x_false = gs.array([0.5, 7, 3.0]) is_in = self.extrinsic_manifold.belongs(x_true) self.assertTrue(is_in) is_out = self.extrinsic_manifold.belongs(x_false) self.assertFalse(is_out) def test_belongs_ball(self): x_true = gs.array([0.5, 0.5]) x_false = gs.array([0.8, 0.8]) is_in = self.ball_manifold.belongs(x_true) self.assertTrue(is_in) is_out = self.ball_manifold.belongs(x_false) self.assertFalse(is_out) def test_extrinsic_half_plane_extrinsic(self): x_in = gs.array([0.5, 7], dtype=gs.float64) x = self.intrinsic_manifold.to_coordinates(x_in, to_coords_type="extrinsic") x_up = self.extrinsic_manifold.to_coordinates( x, to_coords_type="half-space") x2 = Hyperbolic.change_coordinates_system(x_up, "half-space", "extrinsic") self.assertAllClose(x, x2) def test_intrinsic_extrinsic_intrinsic(self): x_intr = gs.array([0.5, 7]) x_extr = self.intrinsic_manifold.to_coordinates( x_intr, to_coords_type="extrinsic") x_intr2 = self.extrinsic_manifold.to_coordinates( x_extr, to_coords_type="intrinsic") self.assertAllClose(x_intr, x_intr2) def test_ball_extrinsic_ball(self): x = gs.array([0.5, 0.2]) x_e = self.ball_manifold.to_coordinates(x, to_coords_type="extrinsic") x2 = self.extrinsic_manifold.to_coordinates(x_e, to_coords_type="ball") self.assertAllClose(x, x2) def test_distance_ball_extrinsic_from_ball(self): x_ball = gs.array([0.7, 0.2]) y_ball = gs.array([0.2, 0.2]) x_extr = self.ball_manifold.to_coordinates(x_ball, to_coords_type="extrinsic") y_extr = self.ball_manifold.to_coordinates(y_ball, to_coords_type="extrinsic") dst_ball = self.ball_metric.dist(x_ball, y_ball) dst_extr = self.extrinsic_metric.dist(x_extr, y_extr) self.assertAllClose(dst_ball, dst_extr) def test_distance_ball_extrinsic_from_extr(self): x_int = gs.array([10, 0.2]) y_int = gs.array([1, 6.0]) x_extr = self.intrinsic_manifold.to_coordinates( x_int, to_coords_type="extrinsic") y_extr = self.intrinsic_manifold.to_coordinates( y_int, to_coords_type="extrinsic") x_ball = self.extrinsic_manifold.to_coordinates(x_extr, to_coords_type="ball") y_ball = self.extrinsic_manifold.to_coordinates(y_extr, to_coords_type="ball") dst_ball = self.ball_metric.dist(x_ball, y_ball) dst_extr = self.extrinsic_metric.dist(x_extr, y_extr) self.assertAllClose(dst_ball, dst_extr) def test_distance_ball_extrinsic_from_extr_4_dim(self): x_int = gs.array([10, 0.2, 3, 4]) y_int = gs.array([1, 6, 2.0, 1]) ball_manifold = PoincareBall(4) extrinsic_manifold = Hyperboloid(4) ball_metric = ball_manifold.metric extrinsic_metric = extrinsic_manifold.metric x_extr = extrinsic_manifold.from_coordinates( x_int, from_coords_type="intrinsic") y_extr = extrinsic_manifold.from_coordinates( y_int, from_coords_type="intrinsic") x_ball = extrinsic_manifold.to_coordinates(x_extr, to_coords_type="ball") y_ball = extrinsic_manifold.to_coordinates(y_extr, to_coords_type="ball") dst_ball = ball_metric.dist(x_ball, y_ball) dst_extr = extrinsic_metric.dist(x_extr, y_extr) self.assertAllClose(dst_ball, dst_extr) def test_log_exp_ball_extrinsic_from_extr(self): """Compare log exp in different parameterizations.""" x_int = gs.array([4.0, 0.2]) y_int = gs.array([3.0, 3]) x_extr = self.intrinsic_manifold.to_coordinates( x_int, to_coords_type="extrinsic") y_extr = self.intrinsic_manifold.to_coordinates( y_int, to_coords_type="extrinsic") x_ball = self.extrinsic_manifold.to_coordinates(x_extr, to_coords_type="ball") y_ball = self.extrinsic_manifold.to_coordinates(y_extr, to_coords_type="ball") x_ball_log_exp = self.ball_metric.exp( self.ball_metric.log(y_ball, x_ball), x_ball) x_extr_a = self.extrinsic_metric.exp( self.extrinsic_metric.log(y_extr, x_extr), x_extr) x_extr_b = self.extrinsic_manifold.from_coordinates( x_ball_log_exp, from_coords_type="ball") self.assertAllClose(x_extr_a, x_extr_b, atol=3e-4) def test_log_exp_ball(self): x = gs.array([0.1, 0.2]) y = gs.array([0.2, 0.5]) log = self.ball_metric.log(point=y, base_point=x) exp = self.ball_metric.exp(tangent_vec=log, base_point=x) self.assertAllClose(exp, y) def test_log_exp_ball_vectorization(self): x = gs.array([0.1, 0.2]) y = gs.array([[0.2, 0.5], [0.1, 0.7]]) log = self.ball_metric.log(y, x) exp = self.ball_metric.exp(log, x) self.assertAllClose(exp, y) def test_log_exp_ball_null_tangent(self): x = gs.array([[0.1, 0.2], [0.1, 0.2]]) tangent_vec = gs.array([[0.0, 0.0], [0.0, 0.0]]) exp = self.ball_metric.exp(tangent_vec, x) self.assertAllClose(exp, x)
class TestHyperbolicMethods(geomstats.tests.TestCase): def setUp(self): gs.random.seed(1234) self.dimension = 2 self.extrinsic_manifold = Hyperboloid( dim=self.dimension) self.extrinsic_metric = self.extrinsic_manifold.metric self.ball_manifold = PoincareBall( dim=self.dimension) self.ball_metric = self.ball_manifold.metric self.intrinsic_manifold = Hyperboloid( dim=self.dimension, coords_type='intrinsic') self.intrinsic_metric = self.intrinsic_manifold.metric self.n_samples = 10 @geomstats.tests.np_and_pytorch_only def test_extrinsic_ball_extrinsic(self): x_in = gs.array([[0.5, 7]]) x = self.intrinsic_manifold.to_coordinates( x_in, to_coords_type='extrinsic') x_b = self.extrinsic_manifold.to_coordinates(x, to_coords_type='ball') x2 = self.ball_manifold.to_coordinates(x_b, to_coords_type='extrinsic') self.assertAllClose(x, x2, atol=1e-8) @geomstats.tests.np_and_pytorch_only def test_belongs_intrinsic(self): x_in = gs.array([[0.5, 7]]) is_in = self.intrinsic_manifold.belongs(x_in) self.assertTrue(is_in) @geomstats.tests.np_and_pytorch_only def test_belongs_extrinsic(self): x_true = self.intrinsic_manifold.to_coordinates(gs.array([[0.5, 7]]), 'extrinsic') x_false = gs.array([[0.5, 7, 3.]]) is_in = self.extrinsic_manifold.belongs(x_true) self.assertTrue(is_in) is_out = self.extrinsic_manifold.belongs(x_false) self.assertFalse(is_out) @geomstats.tests.np_and_pytorch_only def test_belongs_ball(self): x_true = gs.array([[0.5, 0.5]]) x_false = gs.array([[0.8, 0.8]]) is_in = self.ball_manifold.belongs(x_true) self.assertTrue(is_in) is_out = self.ball_manifold.belongs(x_false) self.assertFalse(is_out) @geomstats.tests.np_and_pytorch_only def test_extrinsic_half_plane_extrinsic(self): x_in = gs.array([[0.5, 7]]) x = self.intrinsic_manifold.to_coordinates( x_in, to_coords_type='extrinsic') x_up = self.extrinsic_manifold.to_coordinates( x, to_coords_type='half-plane') x2 = Hyperbolic.change_coordinates_system(x_up, "half-plane", "extrinsic") self.assertAllClose(x, x2, atol=1e-8) @geomstats.tests.np_and_pytorch_only def test_intrinsic_extrinsic_intrinsic(self): x_intr = gs.array([[0.5, 7]]) x_extr = self.intrinsic_manifold.to_coordinates( x_intr, to_coords_type='extrinsic') x_intr2 = self.extrinsic_manifold.to_coordinates( x_extr, to_coords_type='intrinsic') self.assertAllClose(x_intr, x_intr2, atol=1e-8) @geomstats.tests.np_and_pytorch_only def test_ball_extrinsic_ball(self): x = gs.array([[0.5, 0.2]]) x_e = self.ball_manifold.to_coordinates(x, to_coords_type='extrinsic') x2 = self.extrinsic_manifold.to_coordinates(x_e, to_coords_type='ball') self.assertAllClose(x, x2, atol=1e-10) @geomstats.tests.np_and_pytorch_only def test_distance_ball_extrinsic_from_ball(self): x_ball = gs.array([[0.7, 0.2]]) y_ball = gs.array([[0.2, 0.2]]) x_extr = self.ball_manifold.to_coordinates( x_ball, to_coords_type='extrinsic') y_extr = self.ball_manifold.to_coordinates( y_ball, to_coords_type='extrinsic') dst_ball = self.ball_metric.dist(x_ball, y_ball) dst_extr = self.extrinsic_metric.dist(x_extr, y_extr) # TODO(nmiolane): Remove this when ball is properly vectorized dst_extr = gs.to_ndarray(dst_extr, to_ndim=2, axis=1) self.assertAllClose(dst_ball, dst_extr) @geomstats.tests.np_and_pytorch_only def test_distance_ball_extrinsic_from_extr(self): x_int = gs.array([[10, 0.2]]) y_int = gs.array([[1, 6.]]) x_extr = self.intrinsic_manifold.to_coordinates( x_int, to_coords_type='extrinsic') y_extr = self.intrinsic_manifold.to_coordinates( y_int, to_coords_type='extrinsic') x_ball = self.extrinsic_manifold.to_coordinates( x_extr, to_coords_type='ball') y_ball = self.extrinsic_manifold.to_coordinates( y_extr, to_coords_type='ball') dst_ball = self.ball_metric.dist(x_ball, y_ball) dst_extr = self.extrinsic_metric.dist(x_extr, y_extr) # TODO(nmiolane): Remove this when ball is properly vectorized dst_extr = gs.to_ndarray(dst_extr, to_ndim=2, axis=1) self.assertAllClose(dst_ball, dst_extr) @geomstats.tests.np_and_pytorch_only def test_distance_ball_extrinsic_from_extr_4_dim(self): x_int = gs.array([[10, 0.2, 3, 4]]) y_int = gs.array([[1, 6, 2., 1]]) ball_manifold = PoincareBall(4) extrinsic_manifold = Hyperboloid(4) ball_metric = ball_manifold.metric extrinsic_metric = extrinsic_manifold.metric x_extr = extrinsic_manifold.from_coordinates( x_int, from_coords_type='intrinsic') y_extr = extrinsic_manifold.from_coordinates( y_int, from_coords_type='intrinsic') x_ball = extrinsic_manifold.to_coordinates( x_extr, to_coords_type='ball') y_ball = extrinsic_manifold.to_coordinates( y_extr, to_coords_type='ball') dst_ball = ball_metric.dist(x_ball, y_ball) dst_extr = extrinsic_metric.dist(x_extr, y_extr) # TODO(nmiolane): Remove this when ball is properly vectorized dst_extr = gs.to_ndarray(dst_extr, to_ndim=2, axis=1) self.assertAllClose(dst_ball, dst_extr) @geomstats.tests.np_and_pytorch_only def test_log_exp_ball_extrinsic_from_extr(self): """Compare log exp in different parameterizations.""" # TODO(Hazaatiti): Fix this test # x_int = gs.array([[4., 0.2]]) # y_int = gs.array([[3., 3]]) # x_extr = self.intrinsic_manifold.to_coordinates( # x_int, to_point_type='extrinsic') # y_extr = self.intrinsic_manifold.to_coordinates( # y_int, to_point_type='extrinsic') # x_ball = self.extrinsic_manifold.to_coordinates( # x_extr, to_point_type='ball') # y_ball = self.extrinsic_manifold.to_coordinates( # y_extr, to_point_type='ball') # x_ball_log_exp = self.ball_metric.exp( # self.ball_metric.log(y_ball, x_ball), x_ball) # x_extr_a = self.extrinsic_metric.exp( # self.extrinsic_metric.log(y_extr, x_extr), x_extr) # x_extr_b = self.extrinsic_manifold.from_coordinates( # x_ball_log_exp, from_point_type='ball') # self.assertAllClose(x_extr_a, x_extr_b, atol=1e-4) @geomstats.tests.np_only def test_log_exp_ball(self): x = gs.array([[0.1, 0.2]]) y = gs.array([[0.2, 0.5]]) log = self.ball_metric.log(point=y, base_point=x) exp = self.ball_metric.exp(tangent_vec=log, base_point=x) self.assertAllClose(exp, y, atol=1e-1) @geomstats.tests.np_only def test_log_exp_ball_vectorization(self): x = gs.array([[0.1, 0.2]]) y = gs.array([[0.2, 0.5], [0.1, 0.7]]) log = self.ball_metric.log(y, x) exp = self.ball_metric.exp(log, x) self.assertAllClose(exp, y, atol=1e-1) @geomstats.tests.np_only def test_log_exp_ball_null_tangent(self): x = gs.array([[0.1, 0.2], [0.1, 0.2]]) tangent_vec = gs.array([[0.0, 0.0], [0.0, 0.0]]) exp = self.ball_metric.exp(tangent_vec, x) self.assertAllClose(exp, x, atol=1e-10)
class TestPoincareBall(geomstats.tests.TestCase): def setUp(self): self.manifold = PoincareBall(2) self.metric = self.manifold.metric self.hyperboloid_manifold = Hyperboloid(2) self.hyperboloid_metric = self.hyperboloid_manifold.metric def test_squared_dist(self): point_a = gs.array([-0.3, 0.7]) point_b = gs.array([0.2, 0.5]) distance_a_b = self.metric.dist(point_a, point_b) squared_distance = self.metric.squared_dist(point_a, point_b) self.assertAllClose(distance_a_b ** 2, squared_distance) def test_coordinates(self): point_a = gs.array([-0.3, 0.7]) point_b = gs.array([0.2, 0.5]) point_a_h = self.manifold.to_coordinates(point_a, "extrinsic") point_b_h = self.manifold.to_coordinates(point_b, "extrinsic") dist_in_ball = self.metric.dist(point_a, point_b) dist_in_hype = self.hyperboloid_metric.dist(point_a_h, point_b_h) self.assertAllClose(dist_in_ball, dist_in_hype) def test_dist_poincare(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([0.5, -0.5]) dist_a_b = self.manifold.metric.dist(point_a, point_b) result = dist_a_b expected = 2.887270927429199 self.assertAllClose(result, expected) def test_dist_vectorization(self): point_a = gs.array([0.2, 0.5]) point_b = gs.array([[0.3, -0.5], [0.2, 0.2]]) dist_a_b = self.manifold.metric.dist(point_a, point_b) result_vect = dist_a_b result = [ self.manifold.metric.dist(point_a, point_b[i]) for i in range(len(point_b)) ] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) def test_dist_broadcast(self): point_a = gs.array([[0.2, 0.5], [0.3, 0.1]]) point_b = gs.array([[0.3, -0.5], [0.2, 0.2]]) point_c = gs.array([[0.2, 0.3], [0.5, 0.5], [-0.4, 0.1]]) point_d = gs.array([0.1, 0.2, 0.3]) dist_a_b = self.manifold.metric.dist_broadcast(point_a, point_b) dist_b_c = gs.flatten(self.manifold.metric.dist_broadcast(point_b, point_c)) result_vect = gs.concatenate((dist_a_b, dist_b_c), axis=0) result_a_b = [ self.manifold.metric.dist_broadcast(point_a[i], point_b[i]) for i in range(len(point_b)) ] result_b_c = [ self.manifold.metric.dist_broadcast(point_b[i], point_c[j]) for i in range(len(point_b)) for j in range(len(point_c)) ] result = result_a_b + result_b_c result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) with self.assertRaises(ValueError): self.manifold.metric.dist_broadcast(point_a, point_d) def test_dist_pairwise(self): point = gs.array([[0.1, 0.2], [0.3, 0.4], [0.5, 0.5]]) result = self.manifold.metric.dist_pairwise(point) expected = gs.array( [ [0.0, 0.65821943, 1.34682524], [0.65821943, 0.0, 0.71497076], [1.34682524, 0.71497076, 0.0], ] ) self.assertAllClose(result, expected, rtol=1e-3) def test_mobius_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.5, -0.3], [0.3, 0.4]]) dist_a_b = self.manifold.metric.mobius_add(point_a, point_b) result_vect = dist_a_b result = [ self.manifold.metric.mobius_add(point_a, point_b[i]) for i in range(len(point_b)) ] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b = self.manifold.metric.mobius_add(point_b, point_a) result_vect = dist_a_b result = [ self.manifold.metric.mobius_add(point_b[i], point_a) for i in range(len(point_b)) ] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) def test_log_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.5, -0.5], [0.4, 0.4]]) dist_a_b = self.manifold.metric.log(point_a, point_b) result_vect = dist_a_b result = [ self.manifold.metric.log(point_a, point_b[i]) for i in range(len(point_b)) ] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b = self.manifold.metric.log(point_b, point_a) result_vect = dist_a_b result = [ self.manifold.metric.log(point_b[i], point_a) for i in range(len(point_b)) ] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) def test_exp_vectorization(self): point_a = gs.array([0.5, 0.5]) point_b = gs.array([[0.0, 0.0], [0.5, -0.5], [0.4, 0.4]]) dist_a_b = self.manifold.metric.exp(point_a, point_b) result_vect = dist_a_b result = [ self.manifold.metric.exp(point_a, point_b[i]) for i in range(len(point_b)) ] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) dist_a_b = self.manifold.metric.exp(point_b, point_a) result_vect = dist_a_b result = [ self.manifold.metric.exp(point_b[i], point_a) for i in range(len(point_b)) ] result = gs.stack(result, axis=0) self.assertAllClose(result_vect, result) def test_log_poincare(self): point = gs.array([0.3, 0.5]) base_point = gs.array([0.3, 0.3]) result = self.manifold.metric.log(point, base_point) expected = gs.array([-0.01733576, 0.21958634]) self.manifold.metric.coords_type = "extrinsic" self.assertAllClose(result, expected) def test_belong_true_poincare(self): point = gs.array([0.3, 0.5]) belong = self.manifold.belongs(point) self.assertTrue(belong) def test_belong_false_poincare(self): point = gs.array([1.2, 0.5]) belong = self.manifold.belongs(point) self.assertFalse(belong) def test_projection(self): point = gs.array([1.2, 0.5]) projected_point = self.manifold.projection(point) self.assertTrue(gs.sum(projected_point * projected_point) < 1.0) def test_exp_poincare(self): point = gs.array([0.3, 0.5]) base_point = gs.array([0.3, 0.3]) tangent_vec = self.manifold.metric.log(point, base_point) result = self.manifold.metric.exp(tangent_vec, base_point) self.manifold.metric.coords_type = "extrinsic" self.assertAllClose(result, point) def test_ball_retraction(self): x = gs.array([[0.5, 0.6], [0.2, -0.1], [0.2, -0.4]]) y = gs.array([[0.3, 0.5], [0.3, -0.6], [0.3, -0.3]]) ball_metric = self.manifold.metric tangent_vec = ball_metric.log(y, x) ball_metric.retraction(tangent_vec, x) def test_ball_geodesic(self): path_function = self.manifold.metric.geodesic( gs.array([0.1, 0.1]), gs.array([0.2, 0.2]) ) steps = gs.array(gs.linspace(-1000.0, 1000.0, 10000)) path_function(steps) def test_mobius_out_of_the_ball(self): x, y = gs.array([0.7, 0.9]), gs.array([0.2, 0.2]) with self.assertRaises(ValueError): self.manifold.metric.mobius_add(x, y, project_first=False)