Example #1
0
    def log(self, point, base_point):
        """Compute Riemannian logarithm of a point wrt a base point.

        If point_type = 'poincare' then base_point belongs
        to the Poincare ball and point is a vector in the Euclidean
        space of the same dimension as the ball.

        Parameters
        ----------
        point : array-like, shape=[..., dim]
            Point in hyperbolic space.
        base_point : array-like, shape=[..., dim]
            Point in hyperbolic space.

        Returns
        -------
        log : array-like, shape=[..., dim]
            Tangent vector at the base point equal to the Riemannian logarithm
            of point at the base point.
        """
        add_base_point = self.mobius_add(-base_point, point)
        norm_add =\
            gs.expand_dims(gs.linalg.norm(
                           add_base_point, axis=-1), axis=-1)

        norm_base_point =\
            gs.expand_dims(gs.linalg.norm(
                           base_point, axis=-1), axis=-1)

        log = (1 - norm_base_point**2) * gs.arctanh(norm_add)

        mask_0 = gs.isclose(gs.squeeze(norm_add, axis=-1), 0.)
        mask_non0 = ~mask_0
        add_base_point = gs.assignment(
            add_base_point,
            gs.zeros_like(add_base_point[mask_0]),
            mask_0)
        add_base_point = gs.assignment(
            add_base_point,
            add_base_point[mask_non0] / norm_add[mask_non0],
            mask_non0)

        log = gs.einsum(
            '...i,...j->...j', log, add_base_point)
        return log
Example #2
0
    def log(self, point, base_point):
        """Compute Riemannian logarithm of a point wrt a base point.

        If point_type = 'poincare' then base_point belongs
        to the Poincare ball and point is a vector in the Euclidean
        space of the same dimension as the ball.

        Parameters
        ----------
        point : array-like, shape=[n_samples, dim]
            Point in hyperbolic space.
        base_point : array-like, shape=[n_samples, dim]
            Point in hyperbolic space.

        Returns
        -------
        log : array-like, shape=[n_samples, dim]
            Tangent vector at the base point equal to the Riemannian logarithm
            of point at the base point.
        """
        base_point = gs.to_ndarray(base_point, to_ndim=2)
        point = gs.to_ndarray(point, to_ndim=2)

        add_base_point = self.mobius_add(-base_point, point)
        norm_add =\
            gs.expand_dims(gs.linalg.norm(
                           add_base_point, axis=-1), axis=-1)

        norm_base_point =\
            gs.expand_dims(gs.linalg.norm(
                           base_point, axis=-1), axis=-1)

        log = (1 - norm_base_point**2) * gs.arctanh(norm_add)
        log = gs.einsum('...i,...j->...j', log, (add_base_point / norm_add))

        mask_0 = gs.isclose(gs.squeeze(norm_add, axis=-1), 0.)
        if gs.any(mask_0):
            log[mask_0] = 0

        return log
Example #3
0
}
sinch_close_0 = {
    "function": lambda x: gs.sinh(x) / x,
    "coefficients": SINHC_TAYLOR_COEFFS,
}
cosh_close_0 = {"function": gs.cosh, "coefficients": COSH_TAYLOR_COEFFS}
inv_sinch_close_0 = {
    "function": lambda x: x / gs.sinh(x),
    "coefficients": INV_SINHC_TAYLOR_COEFFS,
}
inv_tanh_close_0 = {
    "function": lambda x: x / gs.tanh(x),
    "coefficients": INV_TANH_TAYLOR_COEFFS,
}
arctanh_card_close_0 = {
    "function": lambda x: gs.arctanh(x) / x,
    "coefficients": ARCTANH_CARD_TAYLOR_COEFFS,
}


def from_vector_to_diagonal_matrix(vector, num_diag=0):
    """Create diagonal matrices from rows of a matrix.

    Parameters
    ----------
    vector : array-like, shape=[m, n]
    num_diag : int
        number of diagonal in result matrix. If 0, the result matrix is a
        diagonal matrix; if positive, the result matrix has an upper-right
        non-zero diagonal; if negative, the result matrix has a lower-left
        non-zero diagonal.
Example #4
0
}
sinch_close_0 = {
    'function': lambda x: gs.sinh(x) / x,
    'coefficients': SINHC_TAYLOR_COEFFS
}
cosh_close_0 = {'function': gs.cosh, 'coefficients': COSH_TAYLOR_COEFFS}
inv_sinch_close_0 = {
    'function': lambda x: x / gs.sinh(x),
    'coefficients': INV_SINHC_TAYLOR_COEFFS
}
inv_tanh_close_0 = {
    'function': lambda x: x / gs.tanh(x),
    'coefficients': INV_TANH_TAYLOR_COEFFS
}
arctanh_card_close_0 = {
    'function': lambda x: gs.arctanh(x) / x,
    'coefficients': ARCTANH_CARD_TAYLOR_COEFFS
}


def from_vector_to_diagonal_matrix(vector):
    """Create diagonal matrices from rows of a matrix.

    Parameters
    ----------
    vector : array-like, shape=[m, n]

    Returns
    -------
    diagonals : array-like, shape=[m, n, n]
        3-dimensional array where the `i`-th n-by-n array `diagonals[i, :, :]`
Example #5
0
    def log(self, point, base_point):
        """Compute Riemannian logarithm of a point wrt a base point.

        If point_type = 'poincare' then base_point belongs
        to the Poincare ball and point is a vector in the Euclidean
        space of the same dimension as the ball.

        Parameters
        ----------
        point : array-like, shape=[n_samples, dimension + 1]
            Point in hyperbolic space.
        base_point : array-like, shape=[n_samples, dimension + 1]
            Point in hyperbolic space.

        Returns
        -------
        log : array-like, shape=[n_samples, dimension + 1]
            Tangent vector at the base point equal to the Riemannian logarithm
            of point at the base point.
        """
        if self.point_type == 'extrinsic':
            point = gs.to_ndarray(point, to_ndim=2)
            base_point = gs.to_ndarray(base_point, to_ndim=2)

            angle = self.dist(base_point, point) / self.scale
            angle = gs.to_ndarray(angle, to_ndim=1)
            angle = gs.to_ndarray(angle, to_ndim=2)

            mask_0 = gs.isclose(angle, 0.)
            mask_else = ~mask_0

            mask_0_float = gs.cast(mask_0, gs.float32)
            mask_else_float = gs.cast(mask_else, gs.float32)

            coef_1 = gs.zeros_like(angle)
            coef_2 = gs.zeros_like(angle)

            coef_1 += mask_0_float * (1. + INV_SINH_TAYLOR_COEFFS[1] * angle**2
                                      + INV_SINH_TAYLOR_COEFFS[3] * angle**4 +
                                      INV_SINH_TAYLOR_COEFFS[5] * angle**6 +
                                      INV_SINH_TAYLOR_COEFFS[7] * angle**8)
            coef_2 += mask_0_float * (1. + INV_TANH_TAYLOR_COEFFS[1] * angle**2
                                      + INV_TANH_TAYLOR_COEFFS[3] * angle**4 +
                                      INV_TANH_TAYLOR_COEFFS[5] * angle**6 +
                                      INV_TANH_TAYLOR_COEFFS[7] * angle**8)

            # This avoids dividing by 0.
            angle += mask_0_float * 1.

            coef_1 += mask_else_float * (angle / gs.sinh(angle))
            coef_2 += mask_else_float * (angle / gs.tanh(angle))

            log = (gs.einsum('ni,nj->nj', coef_1, point) -
                   gs.einsum('ni,nj->nj', coef_2, base_point))
            return log

        elif self.point_type == 'ball':

            add_base_point = self.mobius_add(-base_point, point)

            norm_add = gs.to_ndarray(gs.linalg.norm(add_base_point, axis=-1),
                                     2, -1)
            norm_add = gs.repeat(norm_add, base_point.shape[-1], -1)
            norm_base_point = gs.to_ndarray(
                gs.linalg.norm(base_point, axis=-1), 2, -1)
            norm_base_point = gs.repeat(norm_base_point, base_point.shape[-1],
                                        -1)

            log = (1 - norm_base_point**2) * gs.arctanh(norm_add)\
                * (add_base_point / norm_add)

            mask_0 = gs.all(gs.isclose(norm_add, 0.))
            log[mask_0] = 0

            return log
        else:
            raise NotImplementedError(
                'log is only implemented for ball and extrinsic')