Exemple #1
0
class TestLieAlgebraMethods(geomstats.tests.TestCase):
    def setUp(self):
        self.n = 4
        self.dim = int(self.n * (self.n - 1) / 2)
        self.algebra = SkewSymmetricMatrices(n=self.n)

    def test_dimension(self):
        result = self.algebra.dim
        expected = self.dim
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_matrix_representation_and_belongs(self):
        n_samples = 2
        point = gs.random.rand(n_samples * self.dim)
        point = gs.reshape(point, (n_samples, self.dim))
        mat = self.algebra.matrix_representation(point)
        result = self.algebra.belongs(mat).all()
        expected = True
        self.assertAllClose(result, expected)

    @geomstats.tests.np_only
    def test_basis_and_matrix_representation(self):
        n_samples = 2
        expected = gs.random.rand(n_samples * self.dim)
        expected = gs.reshape(expected, (n_samples, self.dim))
        mat = self.algebra.matrix_representation(expected)
        result = self.algebra.basis_representation(mat)
        self.assertAllClose(result, expected)
Exemple #2
0
class TestLieAlgebra(geomstats.tests.TestCase):
    def setUp(self):
        self.n = 4
        self.dim = int(self.n * (self.n - 1) / 2)
        self.algebra = SkewSymmetricMatrices(n=self.n)

    def test_dimension(self):
        result = self.algebra.dim
        expected = self.dim
        self.assertAllClose(result, expected)

    def test_matrix_representation_and_belongs(self):
        n_samples = 2
        point = gs.random.rand(n_samples * self.dim)
        point = gs.reshape(point, (n_samples, self.dim))
        mat = self.algebra.matrix_representation(point)
        result = gs.all(self.algebra.belongs(mat))
        expected = True
        self.assertAllClose(result, expected)

    @geomstats.tests.np_and_pytorch_only
    def test_basis_and_matrix_representation(self):
        n_samples = 2
        expected = gs.random.rand(n_samples * self.dim)
        expected = gs.reshape(expected, (n_samples, self.dim))
        mat = self.algebra.matrix_representation(expected)
        result = self.algebra.basis_representation(mat)
        self.assertAllClose(result, expected)

    def test_orthonormal_basis(self):
        group = SpecialOrthogonal(3)
        lie_algebra = SkewSymmetricMatrices(3)
        metric = InvariantMetric(group=group, algebra=lie_algebra)
        basis = lie_algebra.orthonormal_basis(metric.metric_mat_at_identity)
        result = metric.inner_product_at_identity(basis[0], basis[1])
        self.assertAllClose(result, 0.)

        result = metric.inner_product_at_identity(basis[1], basis[1])
        self.assertAllClose(result, 1.)

        metric_mat = from_vector_to_diagonal_matrix(gs.array([1., 2., 3.]))
        metric = InvariantMetric(group=group,
                                 algebra=lie_algebra,
                                 metric_mat_at_identity=metric_mat)
        basis = lie_algebra.orthonormal_basis(metric.metric_mat_at_identity)
        result = metric.inner_product_at_identity(basis[0], basis[1])
        self.assertAllClose(result, 0.)

        result = metric.inner_product_at_identity(basis[1], basis[1])
        self.assertAllClose(result, 1.)
class SpecialEuclideanMatrixLieAlgebra(MatrixLieAlgebra):
    r"""Lie Algebra of the special Euclidean group.

    This is the tangent space at the identity. It is identified with the
    :math:`n + 1 \times n + 1` block matrices of the form:
    .. math:
                ((A, t), (0, 0))

    where A is an :math:`n \times n` skew-symmetric matrix, :math: `t` is an
    n-dimensional vector.

    Parameters
    ----------
    n : int
        Integer dimension of the underlying Euclidean space. Matrices will
        be of size: (n+1) x (n+1).
    """
    def __init__(self, n):
        dim = int(n * (n + 1) / 2)
        super(SpecialEuclideanMatrixLieAlgebra, self).__init__(dim, n + 1)

        self.skew = SkewSymmetricMatrices(n)
        self.n = n

    def _create_basis(self):
        """Create the canonical basis."""
        n = self.n
        basis = homogeneous_representation(
            self.skew.basis,
            gs.zeros((self.skew.dim, n)),
            (self.skew.dim, n + 1, n + 1),
            0.0,
        )
        basis = list(basis)

        for row in gs.arange(n):
            basis.append(
                gs.array_from_sparse([(row, n)], [1.0], (n + 1, n + 1)))
        return gs.stack(basis)

    def belongs(self, mat, atol=ATOL):
        """Evaluate if the rotation part of mat is a skew-symmetric matrix.

        Parameters
        ----------
        mat : array-like, shape=[..., n + 1, n + 1]
            Square matrix to check.
        atol : float
            Tolerance for the equality evaluation.
            Optional, default: backend atol.

        Returns
        -------
        belongs : array-like, shape=[...,]
            Boolean evaluating if rotation part of matrix is skew symmetric.
        """
        point_dim1, point_dim2 = mat.shape[-2:]
        belongs = point_dim1 == point_dim2 == self.n + 1

        rotation = mat[..., :self.n, :self.n]
        rot_belongs = self.skew.belongs(rotation, atol=atol)

        belongs = gs.logical_and(belongs, rot_belongs)

        last_line = mat[..., -1, :]
        all_zeros = ~gs.any(last_line, axis=-1)

        belongs = gs.logical_and(belongs, all_zeros)
        return belongs

    def random_point(self, n_samples=1, bound=1.0):
        """Sample in the lie algebra with a uniform distribution in a box.

        Parameters
        ----------
        n_samples : int
            Number of samples.
            Optional, default: 1.
        bound : float
            Side of hypercube support of the uniform distribution.
            Optional, default: 1.0

        Returns
        -------
        point : array-like, shape=[..., n + 1, n + 1]
           Sample.
        """
        point = super(SpecialEuclideanMatrixLieAlgebra,
                      self).random_point(n_samples, bound)
        return self.projection(point)

    def projection(self, mat):
        """Project a matrix to the Lie Algebra.

        Compute the skew-symmetric projection of the rotation part of matrix.

        Parameters
        ----------
        mat : array-like, shape=[..., n + 1, n + 1]
            Matrix.

        Returns
        -------
        projected : array-like, shape=[..., n + 1, n + 1]
            Matrix belonging to Lie Algebra.
        """
        rotation = mat[..., :self.n, :self.n]
        skew = SkewSymmetricMatrices.projection(rotation)
        return homogeneous_representation(skew, mat[..., :self.n, self.n],
                                          mat.shape, 0.0)

    def basis_representation(self, matrix_representation):
        """Calculate the coefficients of given matrix in the basis.

        Compute a 1d-array that corresponds to the input matrix in the basis
        representation.

        Parameters
        ----------
        matrix_representation : array-like, shape=[..., n + 1, n + 1]
            Matrix.

        Returns
        -------
        basis_representation : array-like, shape=[..., dim]
            Representation in the basis.
        """
        skew_part = self.skew.basis_representation(
            matrix_representation[..., :self.n, :self.n])
        translation_part = matrix_representation[..., :-1, self.n]
        return gs.concatenate([skew_part, translation_part[..., :]], axis=-1)
class TestLieAlgebra(geomstats.tests.TestCase):
    def setup_method(self):
        self.n = 4
        self.dim = int(self.n * (self.n - 1) / 2)
        self.algebra = SkewSymmetricMatrices(n=self.n)

    def test_dimension(self):
        result = self.algebra.dim
        expected = self.dim
        self.assertAllClose(result, expected)

    def test_matrix_representation_and_belongs(self):
        n_samples = 2
        point = gs.random.rand(n_samples * self.dim)
        point = gs.reshape(point, (n_samples, self.dim))
        mat = self.algebra.matrix_representation(point)
        result = gs.all(self.algebra.belongs(mat))
        self.assertTrue(result)

    def test_basis_and_matrix_representation(self):
        n_samples = 2
        expected = gs.random.rand(n_samples * self.dim)
        expected = gs.reshape(expected, (n_samples, self.dim))
        mat = self.algebra.matrix_representation(expected)
        result = self.algebra.basis_representation(mat)
        self.assertAllClose(result, expected)

    def test_orthonormal_basis(self):
        group = SpecialOrthogonal(3)
        lie_algebra = SkewSymmetricMatrices(3)
        metric = InvariantMetric(group=group)
        basis = metric.normal_basis(lie_algebra.basis)
        result = metric.inner_product_at_identity(basis[0], basis[1])
        self.assertAllClose(result, 0.0)

        result = metric.inner_product_at_identity(basis[1], basis[1])
        self.assertAllClose(result, 1.0)

        metric_mat = from_vector_to_diagonal_matrix(gs.array([1.0, 2.0, 3.0]))
        metric = InvariantMetric(group=group, metric_mat_at_identity=metric_mat)
        basis = metric.normal_basis(lie_algebra.basis)
        result = metric.inner_product_at_identity(basis[0], basis[1])
        self.assertAllClose(result, 0.0)

        result = metric.inner_product_at_identity(basis[1], basis[1])
        self.assertAllClose(result, 1.0)

    def test_orthonormal_basis_se3(self):
        group = SpecialEuclidean(3)
        lie_algebra = group.lie_algebra
        metric = InvariantMetric(group=group)
        basis = metric.normal_basis(lie_algebra.basis)
        for i, x in enumerate(basis):
            for y in basis[i:]:
                result = metric.inner_product_at_identity(x, y)
                expected = 0.0 if gs.any(x != y) else 1.0
                self.assertAllClose(result, expected)

        metric_mat = from_vector_to_diagonal_matrix(
            gs.cast(gs.arange(1, group.dim + 1), gs.float32)
        )
        metric = InvariantMetric(group=group, metric_mat_at_identity=metric_mat)
        basis = metric.normal_basis(lie_algebra.basis)
        for i, x in enumerate(basis):
            for y in basis[i:]:
                result = metric.inner_product_at_identity(x, y)
                expected = 0.0 if gs.any(x != y) else 1.0
                self.assertAllClose(result, expected)