def setup_method(self): gs.random.seed(0) n = 3 self.bundle = BuresWassersteinBundle(n) self.base = self.bundle.base self.base_metric = SPDMetricBuresWasserstein(n) self.quotient_metric = QuotientMetric(self.bundle)
def setUp(self): gs.random.seed(0) n = 3 self.base = SPDMatrices(n) self.base_metric = SPDMetricBuresWasserstein(n) self.group = SpecialOrthogonal(n) self.bundle = FiberBundle(GeneralLinear(n), base=self.base, group=self.group) self.quotient_metric = QuotientMetric(self.bundle, ambient_metric=MatricesMetric( n, n)) def submersion(point): return GeneralLinear.mul(point, GeneralLinear.transpose(point)) def tangent_submersion(tangent_vec, base_point): product = GeneralLinear.mul(base_point, GeneralLinear.transpose(tangent_vec)) return 2 * GeneralLinear.to_symmetric(product) def horizontal_lift(tangent_vec, point, base_point=None): if base_point is None: base_point = submersion(point) sylvester = gs.linalg.solve_sylvester(base_point, base_point, tangent_vec) return GeneralLinear.mul(sylvester, point) self.bundle.submersion = submersion self.bundle.tangent_submersion = tangent_submersion self.bundle.horizontal_lift = horizontal_lift self.bundle.lift = gs.linalg.cholesky
class TestQuotientMetric(geomstats.tests.TestCase): def setup_method(self): gs.random.seed(0) n = 3 self.bundle = BuresWassersteinBundle(n) self.base = self.bundle.base self.base_metric = SPDMetricBuresWasserstein(n) self.quotient_metric = QuotientMetric(self.bundle) def test_belongs(self): point = self.base.random_point() result = self.bundle.belongs(point) self.assertTrue(result) def test_riemannian_submersion(self): mat = self.bundle.random_point() point = self.bundle.riemannian_submersion(mat) result = self.bundle.belongs(point) self.assertTrue(result) def test_lift_and_riemannian_submersion(self): point = self.base.random_point() mat = self.bundle.lift(point) result = self.bundle.riemannian_submersion(mat) self.assertAllClose(result, point) def test_tangent_riemannian_submersion(self): mat = self.bundle.random_point() point = self.bundle.riemannian_submersion(mat) vec = self.bundle.random_point() tangent_vec = self.bundle.tangent_riemannian_submersion(vec, point) result = self.base.is_tangent(tangent_vec, point) self.assertTrue(result) def test_horizontal_projection(self): mat = self.bundle.random_point() vec = self.bundle.random_point() horizontal_vec = self.bundle.horizontal_projection(vec, mat) product = Matrices.mul(horizontal_vec, GeneralLinear.inverse(mat)) is_horizontal = Matrices.is_symmetric(product) self.assertTrue(is_horizontal) def test_vertical_projection(self): mat = self.bundle.random_point() vec = self.bundle.random_point() vertical_vec = self.bundle.vertical_projection(vec, mat) result = self.bundle.tangent_riemannian_submersion(vertical_vec, mat) expected = gs.zeros_like(result) self.assertAllClose(result, expected, atol=1e-5) def test_horizontal_lift_and_tangent_riemannian_submersion(self): mat = self.bundle.random_point() tangent_vec = Matrices.to_symmetric(self.bundle.random_point()) horizontal = self.bundle.horizontal_lift(tangent_vec, fiber_point=mat) result = self.bundle.tangent_riemannian_submersion(horizontal, mat) self.assertAllClose(result, tangent_vec) def test_is_horizontal(self): mat = self.bundle.random_point() tangent_vec = Matrices.to_symmetric(self.bundle.random_point()) horizontal = self.bundle.horizontal_lift(tangent_vec, fiber_point=mat) result = self.bundle.is_horizontal(horizontal, mat) self.assertTrue(result) def test_is_vertical(self): mat = self.bundle.random_point() tangent_vec = self.bundle.random_point() vertical = self.bundle.vertical_projection(tangent_vec, mat) result = self.bundle.is_vertical(vertical, mat) self.assertTrue(result) @geomstats.tests.autograd_tf_and_torch_only def test_align(self): point = self.bundle.random_point(2) aligned = self.bundle.align(point[0], point[1], tol=1e-10) result = self.bundle.is_horizontal(point[1] - aligned, point[1], atol=1e-4) self.assertTrue(result) def test_inner_product(self): mat = self.bundle.random_point() point = self.bundle.riemannian_submersion(mat) tangent_vecs = Matrices.to_symmetric(self.bundle.random_point(2)) / 10 result = self.quotient_metric.inner_product(tangent_vecs[0], tangent_vecs[1], fiber_point=mat) expected = self.base_metric.inner_product(tangent_vecs[0], tangent_vecs[1], point) self.assertAllClose(result, expected) def test_exp(self): mat = self.bundle.random_point() point = self.bundle.riemannian_submersion(mat) tangent_vec = Matrices.to_symmetric(self.bundle.random_point()) / 5 result = self.quotient_metric.exp(tangent_vec, point) expected = self.base_metric.exp(tangent_vec, point) self.assertAllClose(result, expected) @geomstats.tests.autograd_tf_and_torch_only def test_log(self): mats = self.bundle.random_point(2) points = self.bundle.riemannian_submersion(mats) result = self.quotient_metric.log(points[1], points[0]) expected = self.base_metric.log(points[1], points[0]) self.assertAllClose(result, expected, atol=3e-4) @geomstats.tests.autograd_tf_and_torch_only def test_squared_dist(self): mats = self.bundle.random_point(2) points = self.bundle.riemannian_submersion(mats) result = self.quotient_metric.squared_dist(points[1], points[0], tol=1e-10) expected = self.base_metric.squared_dist(points[1], points[0]) self.assertAllClose(result, expected) def test_integrability_tensor(self): mat = self.bundle.random_point() point = self.bundle.riemannian_submersion(mat) tangent_vec = Matrices.to_symmetric(self.bundle.random_point()) / 5 with pytest.raises(NotImplementedError): self.bundle.integrability_tensor(tangent_vec, tangent_vec, point)
class TestQuotientMetric(geomstats.tests.TestCase): def setUp(self): gs.random.seed(0) n = 3 self.base = SPDMatrices(n) self.base_metric = SPDMetricBuresWasserstein(n) self.group = SpecialOrthogonal(n) self.bundle = FiberBundle(GeneralLinear(n), base=self.base, group=self.group) self.quotient_metric = QuotientMetric(self.bundle, ambient_metric=MatricesMetric( n, n)) def submersion(point): return GeneralLinear.mul(point, GeneralLinear.transpose(point)) def tangent_submersion(tangent_vec, base_point): product = GeneralLinear.mul(base_point, GeneralLinear.transpose(tangent_vec)) return 2 * GeneralLinear.to_symmetric(product) def horizontal_lift(tangent_vec, point, base_point=None): if base_point is None: base_point = submersion(point) sylvester = gs.linalg.solve_sylvester(base_point, base_point, tangent_vec) return GeneralLinear.mul(sylvester, point) self.bundle.submersion = submersion self.bundle.tangent_submersion = tangent_submersion self.bundle.horizontal_lift = horizontal_lift self.bundle.lift = gs.linalg.cholesky def test_belongs(self): point = self.base.random_uniform() result = self.bundle.belongs(point) self.assertTrue(result) def test_submersion(self): mat = self.bundle.total_space.random_uniform() point = self.bundle.submersion(mat) result = self.bundle.belongs(point) self.assertTrue(result) def test_lift_and_submersion(self): point = self.base.random_uniform() mat = self.bundle.lift(point) result = self.bundle.submersion(mat) self.assertAllClose(result, point) def test_tangent_submersion(self): mat = self.bundle.total_space.random_uniform() point = self.bundle.submersion(mat) vec = self.bundle.total_space.random_uniform() tangent_vec = self.bundle.tangent_submersion(vec, point) result = self.base.is_tangent(tangent_vec, point) self.assertTrue(result) def test_horizontal_projection(self): mat = self.bundle.total_space.random_uniform() vec = self.bundle.total_space.random_uniform() horizontal_vec = self.bundle.horizontal_projection(vec, mat) product = GeneralLinear.mul(horizontal_vec, GeneralLinear.inverse(mat)) is_horizontal = GeneralLinear.is_symmetric(product) self.assertTrue(is_horizontal) def test_vertical_projection(self): mat = self.bundle.total_space.random_uniform() vec = self.bundle.total_space.random_uniform() vertical_vec = self.bundle.vertical_projection(vec, mat) result = self.bundle.tangent_submersion(vertical_vec, mat) expected = gs.zeros_like(result) self.assertAllClose(result, expected, atol=1e-5) def test_horizontal_lift_and_tangent_submersion(self): mat = self.bundle.total_space.random_uniform() tangent_vec = GeneralLinear.to_symmetric( self.bundle.total_space.random_uniform()) horizontal = self.bundle.horizontal_lift(tangent_vec, mat) result = self.bundle.tangent_submersion(horizontal, mat) self.assertAllClose(result, tangent_vec) def test_is_horizontal(self): mat = self.bundle.total_space.random_uniform() tangent_vec = GeneralLinear.to_symmetric( self.bundle.total_space.random_uniform()) horizontal = self.bundle.horizontal_lift(tangent_vec, mat) result = self.bundle.is_horizontal(horizontal, mat) self.assertTrue(result) def test_is_vertical(self): mat = self.bundle.total_space.random_uniform() tangent_vec = self.bundle.total_space.random_uniform() vertical = self.bundle.vertical_projection(tangent_vec, mat) result = self.bundle.is_vertical(vertical, mat) self.assertTrue(result) def test_align(self): point = self.bundle.total_space.random_uniform(2) aligned = self.bundle.align(point[0], point[1], tol=1e-10) result = self.bundle.is_horizontal(point[1] - aligned, point[1], atol=1e-5) self.assertTrue(result) def test_inner_product(self): mat = self.bundle.total_space.random_uniform() point = self.bundle.submersion(mat) tangent_vecs = GeneralLinear.to_symmetric( self.bundle.total_space.random_uniform(2)) / 10 result = self.quotient_metric.inner_product(tangent_vecs[0], tangent_vecs[1], point=mat) expected = self.base_metric.inner_product(tangent_vecs[0], tangent_vecs[1], point) self.assertAllClose(result, expected) def test_exp(self): mat = self.bundle.total_space.random_uniform() point = self.bundle.submersion(mat) tangent_vec = GeneralLinear.to_symmetric( self.bundle.total_space.random_uniform()) / 5 result = self.quotient_metric.exp(tangent_vec, point) expected = self.base_metric.exp(tangent_vec, point) self.assertAllClose(result, expected) def test_log(self): mats = self.bundle.total_space.random_uniform(2) points = self.bundle.submersion(mats) result = self.quotient_metric.log(points[1], points[0], tol=1e-10) expected = self.base_metric.log(points[1], points[0]) self.assertAllClose(result, expected, atol=3e-4) def test_squared_dist(self): mats = self.bundle.total_space.random_uniform(2) points = self.bundle.submersion(mats) result = self.quotient_metric.squared_dist(points[1], points[0], tol=1e-10) expected = self.base_metric.squared_dist(points[1], points[0]) self.assertAllClose(result, expected, atol=1e-5)