Esempio n. 1
0
    def projection(self, mat):
        """
        Project a matrix on SO(n), using the Frobenius norm.
        """
        # TODO(nina): projection when the point_type is not 'matrix'?
        mat = gs.to_ndarray(mat, to_ndim=3)

        n_mats, mat_dim_1, mat_dim_2 = mat.shape
        assert mat_dim_1 == mat_dim_2 == self.n

        if self.n == 3:
            mat_unitary_u, diag_s, mat_unitary_v = gs.linalg.svd(mat)
            rot_mat = gs.matmul(mat_unitary_u, mat_unitary_v)
            mask = gs.nonzero(gs.linalg.det(rot_mat) < 0)
            diag = gs.array([1, 1, -1])
            new_mat_diag_s = gs.tile(gs.diag(diag), len(mask))

            rot_mat[mask] = gs.matmul(
                gs.matmul(mat_unitary_u[mask], new_mat_diag_s),
                mat_unitary_v[mask])
        else:
            aux_mat = gs.matmul(gs.transpose(mat, axes=(0, 2, 1)), mat)

            inv_sqrt_mat = gs.zeros_like(mat)
            for i in range(n_mats):
                sym_mat = aux_mat[i]

                assert spd_matrices_space.is_symmetric(sym_mat)
                inv_sqrt_mat[i] = gs.linalg.inv(
                    spd_matrices_space.sqrtm(sym_mat))
            rot_mat = gs.matmul(mat, inv_sqrt_mat)

        assert gs.ndim(rot_mat) == 3
        return rot_mat
def closest_rotation_matrix(mat):
    """
    Compute the closest rotation matrix of a given matrix mat,
    in terms of the Frobenius norm.
    """
    mat = gs.to_ndarray(mat, to_ndim=3)

    n_mats, mat_dim_1, mat_dim_2 = mat.shape
    assert mat_dim_1 == mat_dim_2

    if mat_dim_1 == 3:
        mat_unitary_u, diag_s, mat_unitary_v = gs.linalg.svd(mat)
        rot_mat = gs.matmul(mat_unitary_u, mat_unitary_v)

        mask = gs.where(gs.linalg.det(rot_mat) < 0)
        new_mat_diag_s = gs.tile(gs.diag([1, 1, -1]), len(mask))

        rot_mat[mask] = gs.matmul(
            gs.matmul(mat_unitary_u[mask], new_mat_diag_s),
            mat_unitary_v[mask])
    else:
        aux_mat = gs.matmul(gs.transpose(mat, axes=(0, 2, 1)), mat)

        inv_sqrt_mat = gs.zeros_like(mat)
        for i in range(n_mats):
            sym_mat = aux_mat[i]

            assert spd_matrices_space.is_symmetric(sym_mat)
            inv_sqrt_mat[i] = gs.linalg.inv(spd_matrices_space.sqrtm(sym_mat))
        rot_mat = gs.matmul(mat, inv_sqrt_mat)

    assert rot_mat.ndim == 3
    return rot_mat
Esempio n. 3
0
    def left_exp_from_identity(self, tangent_vec):
        """
        Compute the *left* Riemannian exponential from the identity of the
        Lie group of tangent vector tangent_vec.

        The left Riemannian exponential has a special role since the
        left Riemannian exponential of the canonical metric parameterizes
        the points.

        Note: In the case where the method is called by a right-invariant
        metric, it used the left-invariant metric associated to the same
        inner-product at the identity.
        """
        import geomstats.spd_matrices_space as spd_matrices_space
        tangent_vec = gs.to_ndarray(tangent_vec, to_ndim=2)

        tangent_vec = self.group.regularize_tangent_vec_at_identity(
            tangent_vec=tangent_vec, metric=self)
        sqrt_inner_product_mat = spd_matrices_space.sqrtm(
            self.inner_product_mat_at_identity)
        mat = gs.transpose(sqrt_inner_product_mat, axes=(0, 2, 1))
        exp = gs.matmul(tangent_vec, mat)
        exp = gs.squeeze(exp, axis=0)

        exp = self.group.regularize(exp)
        return exp
Esempio n. 4
0
    def test_sqrtm(self):
        n_samples = self.n_samples
        points = self.space.random_uniform(n_samples=n_samples)

        result = spd_matrices_space.sqrtm(points)
        expected = gs.zeros((n_samples, self.n, self.n))
        for i in range(n_samples):
            expected[i] = scipy.linalg.sqrtm(points[i])

        self.assertTrue(gs.allclose(result, expected))
Esempio n. 5
0
    def left_exp_from_identity(self, tangent_vec):
        """
        Riemannian exponential of a tangent vector wrt the identity associated
        to the left-invariant metric.

        If the method is called by a right-invariant metric, it uses the
        left-invariant metric associated to the same inner-product matrix
        at the identity.
        """
        import geomstats.spd_matrices_space as spd_matrices_space
        tangent_vec = gs.to_ndarray(tangent_vec, to_ndim=2)

        tangent_vec = self.group.regularize_tangent_vec_at_identity(
            tangent_vec=tangent_vec, metric=self)
        sqrt_inner_product_mat = spd_matrices_space.sqrtm(
            self.inner_product_mat_at_identity)
        mat = gs.transpose(sqrt_inner_product_mat, axes=(0, 2, 1))
        exp = gs.einsum('ni,nij->nj', tangent_vec, mat)

        exp = self.group.regularize(exp)
        return exp
Esempio n. 6
0
    def left_log_from_identity(self, point):
        """
        Riemannian logarithm of a point wrt the identity associated
        to the left-invariant metric.

        If the method is called by a right-invariant metric, it uses the
        left-invariant metric associated to the same inner-product matrix
        at the identity.
        """
        import geomstats.spd_matrices_space as spd_matrices_space

        point = self.group.regularize(point)
        inner_prod_mat = self.inner_product_mat_at_identity
        inv_inner_prod_mat = gs.linalg.inv(inner_prod_mat)
        sqrt_inv_inner_prod_mat = spd_matrices_space.sqrtm(inv_inner_prod_mat)
        assert sqrt_inv_inner_prod_mat.shape == ((1, ) +
                                                 (self.group.dimension, ) * 2)
        aux = gs.squeeze(sqrt_inv_inner_prod_mat, axis=0)
        log = gs.matmul(point, aux)
        log = self.group.regularize_tangent_vec_at_identity(tangent_vec=log,
                                                            metric=self)
        assert log.ndim == 2
        return log
Esempio n. 7
0
    def left_log_from_identity(self, point):
        """
        Compute the *left* Riemannian logarithm from the identity of the
        Lie group of tangent vector tangent_vec.

        The left Riemannian logarithm has a special role since the
        left Riemannian logarithm of the canonical metric parameterizes
        the points.
        """
        import geomstats.spd_matrices_space as spd_matrices_space

        point = self.group.regularize(point)
        inner_prod_mat = self.inner_product_mat_at_identity
        inv_inner_prod_mat = gs.linalg.inv(inner_prod_mat)
        sqrt_inv_inner_prod_mat = spd_matrices_space.sqrtm(inv_inner_prod_mat)
        assert sqrt_inv_inner_prod_mat.shape == ((1, ) +
                                                 (self.group.dimension, ) * 2)
        aux = gs.squeeze(sqrt_inv_inner_prod_mat, axis=0)
        log = gs.matmul(point, aux)
        log = self.group.regularize_tangent_vec_at_identity(tangent_vec=log,
                                                            metric=self)
        assert log.ndim == 2
        return log