Ejemplo n.º 1
0
    def jacobian_translation(self, point, left_or_right="left"):
        """Compute the Jacobian matrix of left/right translation by a point.

        This calculates the differential of the left translation L_(point)
        evaluated at 'point'. Note that it only depends on the point we are
        left-translating by, not on the point where the differential is evaluated.

        Parameters
        ----------
        point : array-like, shape=[..., 3]
            Point.
        left_or_right : str, {'left', 'right'}
            Indicate whether to calculate the differential of left or right
            translations.
            Optional, default: 'left'.

        Returns
        -------
        _ : array-like, shape=[..., 3, 3]
            Jacobian of the left/right translation by point.
        """
        e31 = gs.array_from_sparse([(2, 0)], [1.0], (3, 3))
        e32 = gs.array_from_sparse([(2, 1)], [1.0], (3, 3))

        if left_or_right == "left":
            return (gs.eye(3) +
                    gs.einsum("..., ij -> ...ij", -point[..., 1] / 2, e31) +
                    gs.einsum("..., ij -> ...ij", point[..., 0] / 2, e32))

        return (gs.eye(3) +
                gs.einsum("..., ij -> ...ij", point[..., 1] / 2, e31) +
                gs.einsum("..., ij -> ...ij", -point[..., 0] / 2, e32))
Ejemplo n.º 2
0
    def from_vector(vec, dtype=gs.float32):
        """Convert a vector into a symmetric matrix.

        Parameters
        ----------
        vec : array-like, shape=[..., n(n+1)/2]
            Vector.

        Returns
        -------
        mat : array-like, shape=[..., n, n]
            Symmetric matrix.
        """
        vec_dim = vec.shape[-1]
        mat_dim = (gs.sqrt(8. * vec_dim + 1) - 1) / 2
        if mat_dim != int(mat_dim):
            raise ValueError('Invalid input dimension, it must be of the form'
                             '(n_samples, n * (n + 1) / 2)')
        mat_dim = int(mat_dim)
        shape = (mat_dim, mat_dim)
        mask = 2 * gs.ones(shape) - gs.eye(mat_dim)
        indices = list(zip(*gs.triu_indices(mat_dim)))
        vec = gs.cast(vec, dtype)
        upper_triangular = gs.stack(
            [gs.array_from_sparse(indices, data, shape) for data in vec])
        mat = Matrices.to_symmetric(upper_triangular) * mask
        return mat
Ejemplo n.º 3
0
    def tait_bryan_angles_quaternion_test_data(self):
        xyz = gs.array([
            [cos_angle_pi_12, 0.0, 0.0, sin_angle_pi_12],
            [cos_angle_pi_12, 0.0, sin_angle_pi_12, 0.0],
            [cos_angle_pi_12, sin_angle_pi_12, 0.0, 0.0],
        ])

        zyx = gs.flip(xyz, axis=0)
        data = {"xyz": xyz, "zyx": zyx}
        smoke_data = []
        e1 = gs.array([1.0, 0.0, 0.0, 0.0])
        for coord, order in itertools.product(["intrinsic", "extrinsic"],
                                              orders):
            for i in range(3):
                vec = gs.squeeze(
                    gs.array_from_sparse([(0, i)], [angle_pi_6], (1, 3)))
                smoke_data += [
                    dict(coord=coord,
                         order=order,
                         vec=vec,
                         quat=data[order][i])
                ]
            smoke_data += [
                dict(coord=coord, order=order, vec=gs.zeros(3), quat=e1)
            ]
        return self.generate_tests(smoke_data)
Ejemplo n.º 4
0
    def tait_bryan_angles_matrix_test_data(self):
        xyz = gs.array([
            [
                [cos_angle_pi_6, -sin_angle_pi_6, 0.0],
                [sin_angle_pi_6, cos_angle_pi_6, 0.0],
                [0.0, 0.0, 1.0],
            ],
            [
                [cos_angle_pi_6, 0.0, sin_angle_pi_6],
                [0.0, 1.0, 0.0],
                [-sin_angle_pi_6, 0.0, cos_angle_pi_6],
            ],
            [
                [1.0, 0.0, 0.0],
                [0.0, cos_angle_pi_6, -sin_angle_pi_6],
                [0.0, sin_angle_pi_6, cos_angle_pi_6],
            ],
        ])
        zyx = gs.flip(xyz, axis=0)
        data = {"xyz": xyz, "zyx": zyx}
        smoke_data = []

        for coord, order in itertools.product(coords, orders):
            for i in range(3):
                vec = gs.squeeze(
                    gs.array_from_sparse([(0, i)], [angle_pi_6], (1, 3)))
                smoke_data += [
                    dict(coord=coord, order=order, vec=vec, mat=data[order][i])
                ]
            smoke_data += [
                dict(coord=coord, order=order, vec=gs.zeros(3), mat=gs.eye(3))
            ]
        return self.generate_tests(smoke_data)
Ejemplo n.º 5
0
    def __init__(self, n):
        dim = int(n * (n - 1) / 2)
        super(SkewSymmetricMatrices, self).__init__(dim, n)

        if n == 2:
            self.basis = gs.array([[[0., -1.], [1., 0.]]])
        elif n == 3:
            self.basis = gs.array([
                [[0., 0., 0.],
                 [0., 0., -1.],
                 [0., 1., 0.]],
                [[0., 0., 1.],
                 [0., 0., 0.],
                 [-1., 0., 0.]],
                [[0., -1., 0.],
                 [1., 0., 0.],
                 [0., 0., 0.]]])
        else:
            self.basis = gs.zeros((dim, n, n))
            basis = []
            for row in gs.arange(n - 1):
                for col in gs.arange(row + 1, n):
                    basis.append(gs.array_from_sparse(
                        [(row, col), (col, row)], [1., -1.], (n, n)))
            self.basis = gs.stack(basis)
Ejemplo n.º 6
0
 def get_basis(self):
     """Compute the basis of the vector space of symmetric matrices."""
     basis = [
         gs.array_from_sparse([(row, col), (col, row)], [1., 1.],
                              (self.n, self.n)) for row in gs.arange(self.n)
         for col in gs.arange(row, self.n)
     ]
     basis = gs.stack(basis) * (gs.ones(
         (self.n, self.n)) - 1. / 2 * gs.eye(self.n))
     return basis
Ejemplo n.º 7
0
 def basis_test_data(self):
     smoke_data = [
         dict(
             n=2,
             m=2,
             expected=gs.array([
                 gs.array_from_sparse([(i, j)], [1], (2, 2))
                 for i in range(2) for j in range(2)
             ]),
         ),
         dict(
             n=2,
             m=3,
             expected=gs.array([
                 gs.array_from_sparse([(i, j)], [1], (2, 3))
                 for i in range(2) for j in range(3)
             ]),
         ),
     ]
     return self.generate_tests(smoke_data)
Ejemplo n.º 8
0
    def __init__(self, n):
        dimension = int(n * (n - 1) / 2)
        super(SkewSymmetricMatrices, self).__init__(dimension, n)

        self.basis = gs.zeros((dimension, n, n))

        basis = []
        for row in gs.arange(n - 1):
            for col in gs.arange(row + 1, n):
                basis.append(gs.array_from_sparse(
                    [(row, col), (col, row)], [1., -1.], (n, n)))
        self.basis = gs.stack(basis)
Ejemplo n.º 9
0
 def _create_basis(self):
     """Compute the basis of the vector space of symmetric matrices."""
     basis = []
     for row in gs.arange(self.n):
         for col in gs.arange(row, self.n):
             if row == col:
                 indices = [(row, row)]
                 values = [1.0]
             else:
                 indices = [(row, col), (col, row)]
                 values = [1.0, 1.0]
             basis.append(gs.array_from_sparse(indices, values, (self.n,) * 2))
     basis = gs.stack(basis)
     return basis
Ejemplo n.º 10
0
    def __init__(self, n):
        dim = int(n * (n + 1) / 2)
        super(SpecialEuclideanMatrixLieAlgebra, self).__init__(dim, n)

        self.skew = SkewSymmetricMatrices(n)
        basis = homogeneous_representation(
            self.skew.basis,
            gs.zeros((self.skew.dim, n)), (self.skew.dim, n + 1, n + 1), 0.)
        basis = list(basis)

        for row in gs.arange(n):
            basis.append(gs.array_from_sparse(
                [(row, n)], [1.], (n + 1, n + 1)))
        self.basis = gs.stack(basis)
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
 def symmetric_matrix_from_vector(vec, dtype=gs.float32):
     """Convert a vector into a symmetric matrix."""
     vec_dim = vec.shape[-1]
     mat_dim = (gs.sqrt(8. * vec_dim + 1) - 1) / 2
     if mat_dim != int(mat_dim):
         raise ValueError('Invalid input dimension, it must be of the form'
                          '(n_samples, n * (n - 1) / 2)')
     mat_dim = int(mat_dim)
     mask = 2 * gs.ones((mat_dim, mat_dim)) - gs.eye(mat_dim)
     indices = list(zip(*gs.triu_indices(3)))
     shape = (mat_dim, mat_dim)
     vec = gs.cast(vec, dtype)
     upper_triangular = gs.stack(
         [gs.array_from_sparse(indices, data, shape) for data in vec])
     mat = Matrices.make_symmetric(upper_triangular) * mask
     return mat
Ejemplo n.º 13
0
 def _create_basis(self):
     """Create the canonical basis."""
     n = self.n
     if n == 2:
         return gs.array([[[0.0, -1.0], [1.0, 0.0]]])
     if n == 3:
         return gs.array([
             [[0.0, 0.0, 0.0], [0.0, 0.0, -1.0], [0.0, 1.0, 0.0]],
             [[0.0, 0.0, 1.0], [0.0, 0.0, 0.0], [-1.0, 0.0, 0.0]],
             [[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
         ])
     basis = []
     for row in gs.arange(n - 1):
         for col in gs.arange(row + 1, n):
             basis.append(
                 gs.array_from_sparse([(row, col), (col, row)], [1.0, -1.0],
                                      (n, n)))
     return gs.stack(basis)
Ejemplo n.º 14
0
    def __init__(self, n):
        """Instantiate the class.

        Parameters
        ----------
        n: int
            The number of rows and columns.
        """
        dimension = int(n * (n - 1) / 2)
        super(SkewSymmetricMatrices, self).__init__(dimension, n)

        self.basis = gs.zeros((dimension, n, n))

        basis = []
        for row in gs.arange(n - 1):
            for col in gs.arange(row + 1, n):
                basis.append(gs.array_from_sparse(
                    [(row, col), (col, row)], [1., -1.], (n, n)))
        self.basis = gs.stack(basis)
Ejemplo n.º 15
0
    def permute(self, graph_to_permute, permutation):
        r"""Permutation action applied to graph observation.

        Parameters
        ----------
        graph_to_permute : array-like, shape=[..., n, n]
            Input graphs to be permuted.
        permutation: array-like, shape=[..., n]
            Node permutations where in position i we have the value j meaning
            the node i should be permuted with node j.

        Returns
        -------
        graphs_permuted : array-like, shape=[..., n, n]
            Graphs permuted.
        """
        nodes = self.nodes
        single_graph = len(graph_to_permute.shape) < 3
        if single_graph:
            graph_to_permute = [graph_to_permute]
            permutation = [permutation]
        result = []
        for i, p in enumerate(permutation):
            if gs.all(gs.array(nodes) == gs.array(p)):
                result.append(graph_to_permute[i])
            else:
                gtype = graph_to_permute[i].dtype
                permutation_matrix = gs.array_from_sparse(
                    data=gs.ones(nodes, dtype=gtype),
                    indices=list(zip(list(range(nodes)), p)),
                    target_shape=(nodes, nodes),
                )
                result.append(
                    self.adjmat.mul(
                        permutation_matrix,
                        graph_to_permute[i],
                        gs.transpose(permutation_matrix),
                    ))
        return result[0] if single_graph else gs.array(result)
Ejemplo n.º 16
0
    def test_compose_matrix_form(self):
        point = self.group.random_point()
        result = self.group.compose(point, self.group.identity)
        expected = point
        self.assertAllClose(result, expected)

        if not geomstats.tests.tf_backend():
            # Composition by identity, on the left
            # Expect the original transformation
            result = self.group.compose(self.group.identity, point)
            expected = point
            self.assertAllClose(result, expected)

            # Composition of translations (no rotational part)
            # Expect the sum of the translations
            point_a = gs.array([[1.0, 0.0, 1.0], [0.0, 1.0, 1.5], [0.0, 0.0, 1.0]])
            point_b = gs.array([[1.0, 0.0, 2.0], [0.0, 1.0, 2.5], [0.0, 0.0, 1.0]])

            result = self.group.compose(point_a, point_b)
            last_line_0 = gs.array_from_sparse([(0, 2), (1, 2)], [1.0, 1.0], (3, 3))
            expected = point_a + point_b * last_line_0
            self.assertAllClose(result, expected)
Ejemplo n.º 17
0
 def test_array_from_sparse(self):
     expected = gs.array([[0, 1, 0], [0, 0, 2]])
     result = gs.array_from_sparse([(0, 1), (1, 2)], [1, 2], (2, 3))
     self.assertAllClose(result, expected)
Ejemplo n.º 18
0
 def _get_permutation_matrix(indices_):
     return gs.array_from_sparse(
         data=gs.ones(self.n_nodes, dtype=gs.int64),
         indices=list(zip(range(self.n_nodes), indices_)),
         target_shape=(self.n_nodes, self.n_nodes),
     )