예제 #1
0
    def parallel_transport(self, tangent_vec_a, tangent_vec_b, base_point):
        r"""Parallel transport of a tangent vector.

        Closed-form solution for the parallel transport of a tangent vector a
        along the geodesic defined by exp_(base_point)(tangent_vec_b).
        Denoting `tangent_vec_a` by `S`, `base_point` by `A`, let
        `B = Exp_A(tangent_vec_b)` and :math: `E = (BA^{- 1})^({ 1 / 2})`.
        Then the
        parallel transport to `B`is:

        ..math::
                        S' = ESE^T

        Parameters
        ----------
        tangent_vec_a : array-like, shape=[..., dim + 1]
            Tangent vector at base point to be transported.
        tangent_vec_b : array-like, shape=[..., dim + 1]
            Tangent vector at base point, initial speed of the geodesic along
            which the parallel transport is computed.
        base_point : array-like, shape=[..., dim + 1]
            Point on the manifold of SPD matrices.

        Returns
        -------
        transported_tangent_vec: array-like, shape=[..., dim + 1]
            Transported tangent vector at exp_(base_point)(tangent_vec_b).
        """
        end_point = self.exp(tangent_vec_b, base_point)
        inverse_base_point = GeneralLinear.inverse(base_point)
        congruence_mat = GeneralLinear.mul(end_point, inverse_base_point)
        congruence_mat = gs.linalg.sqrtm(congruence_mat)
        return GeneralLinear.congruent(tangent_vec_a, congruence_mat)
예제 #2
0
    def log(self, point, base_point):
        r"""Compute the Riemannian logarithm of point w.r.t. base_point.

        Given :math:`P, P'` in Gr(n, k) the logarithm from :math:`P`
        to :math:`P` is given by the infinitesimal rotation [Batzies2015]_:

        .. math::

            \omega = \frac 1 2 \log \big((2 P' - 1)(2 P - 1)\big)

        Parameters
        ----------
        point : array-like, shape=[n_samples, n, n]
            Point in the Grassmannian.
        base_point : array-like, shape=[n_samples, n, n]
            Point in the Grassmannian.

        Returns
        -------
        tangent_vec : array-like, shape=[n_samples, n, n]
            Tangent vector at `base_point`.

        References
        ----------
        .. [Batzies2015] Batzies, Hüper, Machado, Leite.
            "Geometric Mean and Geodesic Regression on Grassmannians"
            Linear Algebra and its Applications, 466, 83-101, 2015.
        """
        GLn = GeneralLinear(self.n)
        id_n = GLn.identity()
        sym2 = 2 * point - id_n
        sym1 = 2 * base_point - id_n
        rot = GLn.mul(sym2, sym1)
        return GLn.log(rot) / 2
예제 #3
0
 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 transp(self, base_point, end_point, tangent):
        """

        transports a tangent vector at a base_point
        to the tangent space at end_point.
        """

        if self.exact_transport:
            # https://github.com/geomstats/geomstats/blob/master/geomstats/geometry/spd_matrices.py#L613
            inverse_base_point = GeneralLinear.inverse(base_point)
            congruence_mat = GeneralLinear.mul(end_point, inverse_base_point)
            congruence_mat = gs.linalg.sqrtm(congruence_mat.cpu()).to(tangent)
            return GeneralLinear.congruent(tangent, congruence_mat)

        # https://github.com/NicolasBoumal/manopt/blob/master/manopt/manifolds/symfixedrank/sympositivedefinitefactory.m#L181
        return tangent
예제 #5
0
    def log(self, point, base_point):
        r"""Compute the Riemannian logarithm of point w.r.t. base_point.

        Given :math:`P, P'` in Gr(n, k) the logarithm from :math:`P`
        to :math:`P` is induced by the infinitesimal rotation [Batzies2015]_:

        .. math::

            Y = \frac 1 2 \log \big((2 P' - 1)(2 P - 1)\big)

        The tangent vector :math:`X` at :math:`P`
        is then recovered by :math:`X = [Y, P]`.

        Parameters
        ----------
        point : array-like, shape=[..., n, n]
            Point.
        base_point : array-like, shape=[..., n, n]
            Base point.

        Returns
        -------
        tangent_vec : array-like, shape=[..., n, n]
            Riemannian logarithm, a tangent vector at `base_point`.

        References
        ----------
        .. [Batzies2015] Batzies, Hüper, Machado, Leite.
            "Geometric Mean and Geodesic Regression on Grassmannians"
            Linear Algebra and its Applications, 466, 83-101, 2015.
        """
        GLn = GeneralLinear(self.n)
        id_n = GLn.identity
        id_n, point, base_point = gs.convert_to_wider_dtype(
            [id_n, point, base_point])
        sym2 = 2 * point - id_n
        sym1 = 2 * base_point - id_n
        rot = GLn.mul(sym2, sym1)
        return Matrices.bracket(GLn.log(rot) / 2, base_point)
예제 #6
0
 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)
예제 #7
0
 def tangent_submersion(tangent_vec, base_point):
     product = GeneralLinear.mul(base_point,
                                 GeneralLinear.transpose(tangent_vec))
     return 2 * GeneralLinear.to_symmetric(product)
예제 #8
0
 def submersion(point):
     return GeneralLinear.mul(point, GeneralLinear.transpose(point))