Beispiel #1
0
    def normalization_factor(self, variances):
        """Return normalization factor.

        Parameters
        ----------
        variances : array-like, shape=[n,]
            Array of equally distant values of the
            variance precision time.

        Returns
        -------
        norm_func : array-like, shape=[n,]
            Normalisation factor for all given variances.
        """
        binomial_coefficient = None
        n_samples = variances.shape[0]

        expand_variances = gs.expand_dims(variances, axis=0)
        expand_variances = gs.repeat(expand_variances, self.dim, axis=0)

        if binomial_coefficient is None:

            dim_range = gs.arange(self.dim)
            dim_range[0] = 1
            n_fact = dim_range.prod()

            k_fact = gs.concatenate([
                gs.expand_dims(dim_range[:i].prod(), 0)
                for i in range(1, dim_range.shape[0] + 1)
            ], 0)

            nmk_fact = gs.flip(k_fact, 0)

            binomial_coefficient = n_fact / (k_fact * nmk_fact)

        binomial_coefficient = gs.expand_dims(binomial_coefficient, -1)
        binomial_coefficient = gs.repeat(binomial_coefficient,
                                         n_samples,
                                         axis=1)

        range_ = gs.expand_dims(gs.arange(self.dim), -1)
        range_ = gs.repeat(range_, n_samples, axis=1)

        ones_ = gs.expand_dims(gs.ones(self.dim), -1)
        ones_ = gs.repeat(ones_, n_samples, axis=1)

        alternate_neg = (-ones_)**(range_)

        erf_arg = ((
            (self.dim - 1) - 2 * range_) * expand_variances) / gs.sqrt(2)
        exp_arg = ((((self.dim - 1) - 2 * range_) * expand_variances) /
                   gs.sqrt(2))**2
        norm_func_1 = (1 + gs.erf(erf_arg)) * gs.exp(exp_arg)
        norm_func_2 = binomial_coefficient * norm_func_1
        norm_func_3 = alternate_neg * norm_func_2

        norm_func = NORMALIZATION_FACTOR_CST * variances * \
            norm_func_3.sum(0) * (1 / (2 ** (self.dim - 1)))

        return norm_func
Beispiel #2
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)
Beispiel #3
0
    def test_cumsum(self):
        result = gs.cumsum(gs.arange(10))
        expected = gs.array(([0, 1, 3, 6, 10, 15, 21, 28, 36, 45]))
        self.assertAllClose(result, expected)

        result = gs.cumsum(gs.arange(10).reshape(2, 5), axis=1)
        expected = gs.array(([[0, 1, 3, 6, 10], [5, 11, 18, 26, 35]]))
        self.assertAllClose(result, expected)
Beispiel #4
0
    def test_cumprod(self):
        result = gs.cumprod(gs.arange(1, 10))
        expected = gs.array(([1, 2, 6, 24, 120, 720, 5040, 40320, 362880]))
        self.assertAllClose(result, expected)

        result = gs.reshape(gs.arange(1, 11), (2, 5))
        result = gs.cumprod(result, axis=1)
        expected = gs.array(([[1, 2, 6, 24, 120], [6, 42, 336, 3024, 30240]]))
        self.assertAllClose(result, expected)
 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
    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)
Beispiel #7
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
Beispiel #8
0
    def test_normalization_factor(self):
        """Test for Gaussian distribution normalization factor."""
        gmm = RiemannianEM(self.metric)
        variances_range, normalization_factor_var, phi_inv_var = \
            gmm.normalization_factor_init(
                gs.arange(ZETA_LOWER_BOUND, ZETA_UPPER_BOUND, ZETA_STEP))
        self.assertAllClose(normalization_factor_var[4], 0.00291884, TOLERANCE)
        self.assertAllClose(phi_inv_var[3], 0.00562326, TOLERANCE)

        variances_test = gs.array([0.8, 1.2])
        norm_factor_test = find_normalization_factor(variances_test,
                                                     variances_range,
                                                     normalization_factor_var)
        norm_factor_verdict = gs.array([0.79577319, 2.3791778])
        self.assertAllClose(norm_factor_test, norm_factor_verdict, TOLERANCE)

        norm_factor_test2 = self.metric.normalization_factor(variances_test)
        self.assertAllClose(norm_factor_test2, norm_factor_verdict, TOLERANCE)

        norm_factor_test3, norm_factor_gradient_test = \
            self.metric.norm_factor_gradient(variances_test)
        norm_factor_gradient_verdict = gs.array([3.0553115709, 2.53770926])
        self.assertAllClose(norm_factor_test3, norm_factor_verdict, TOLERANCE)
        self.assertAllClose(norm_factor_gradient_test,
                            norm_factor_gradient_verdict, TOLERANCE)

        find_var_test = find_variance_from_index(
            gs.array([0.5, 0.4, 0.3, 0.2]), variances_range, phi_inv_var)
        find_var_verdict = gs.array([0.481, 0.434, 0.378, 0.311])
        self.assertAllClose(find_var_test, find_var_verdict, TOLERANCE)
    def square_root_velocity(self, curve):
        """Compute the square root velocity representation of a curve.

        The velocity is computed using the log map. In the case of several
        curves, an index selection procedure allows to get rid of the log
        between the end point of curve[k, :, :] and the starting point of
        curve[k + 1, :, :].

        Parameters
        ----------
        curve : array-like, shape=[..., n_sampling_points, ambient_dim]
            Discrete curve.

        Returns
        -------
        srv : array-like, shape=[..., n_sampling_points - 1, ambient_dim]
            Square-root velocity representation of a discrete curve.
        """
        curve = gs.to_ndarray(curve, to_ndim=3)
        n_curves, n_sampling_points, n_coords = curve.shape
        srv_shape = (n_curves, n_sampling_points - 1, n_coords)

        curve = gs.reshape(curve, (n_curves * n_sampling_points, n_coords))
        coef = gs.cast(gs.array(n_sampling_points - 1), gs.float32)
        velocity = coef * self.ambient_metric.log(point=curve[1:, :],
                                                  base_point=curve[:-1, :])
        velocity_norm = self.ambient_metric.norm(velocity, curve[:-1, :])
        srv = gs.einsum(
            '...i,...->...i', velocity, 1. / gs.sqrt(velocity_norm))

        index = gs.arange(n_curves * n_sampling_points - 1)
        mask = ~((index + 1) % n_sampling_points == 0)
        srv = gs.reshape(srv[mask], srv_shape)

        return srv
Beispiel #10
0
    def test_svd(self):
        gs_point = gs.reshape(gs.arange(12), (4, 3))
        gs_point = gs.cast(gs_point, gs.float64)
        np_point = _np.arange(12).reshape(4, 3)
        reconstruction = gs.array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.],
                                   [0., 0., 0.]])
        u, s, v = _np.linalg.svd(np_point)
        u_r, s_r, v_r = gs.linalg.svd(gs_point)
        s_r_reconstructed = gs.einsum('kl,l->kl', reconstruction, s_r)
        gs_a_approx = gs.matmul(gs.matmul(u_r, s_r_reconstructed), v_r)
        s_reconstructed = _np.einsum('kl,l->kl', reconstruction, s)
        np_a_approx = _np.dot(u, _np.dot(s_reconstructed, v))
        self.assertAllClose(gs_a_approx, np_a_approx)

        full_matrices = False
        u, s, v = _np.linalg.svd(np_point, full_matrices=full_matrices)
        u_r, s_r, v_r = gs.linalg.svd(gs_point, full_matrices)
        reconstruction = gs.eye(3)
        s_r_reconstructed = gs.einsum('kl,l->kl', reconstruction, s_r)
        gs_a_approx = gs.matmul(gs.matmul(u_r, s_r_reconstructed), v_r)
        s_reconstructed = _np.einsum('kl,l->kl', reconstruction, s)
        np_a_approx = _np.dot(u, _np.dot(s_reconstructed, v))
        self.assertAllClose(gs_a_approx, np_a_approx)

        compute_uv = False
        s = _np.linalg.svd(np_point, compute_uv=compute_uv)
        s_r = gs.linalg.svd(gs_point, compute_uv=compute_uv)
        self.assertAllClose(s, s_r)
Beispiel #11
0
    def test_is_diagonal(self):
        base_point = gs.array([
            [1., 2., 3.],
            [0., 0., 0.],
            [3., 1., 1.]])
        result = self.space.is_diagonal(base_point)
        expected = False
        self.assertAllClose(result, expected)

        diagonal = gs.eye(3)
        result = self.space.is_diagonal(diagonal)
        self.assertTrue(result)

        base_point = gs.stack([base_point, diagonal])
        result = self.space.is_diagonal(base_point)
        expected = gs.array([False, True])
        self.assertAllClose(result, expected)

        base_point = gs.stack([diagonal] * 2)
        result = self.space.is_diagonal(base_point)
        self.assertTrue(gs.all(result))

        base_point = gs.reshape(gs.arange(6), (2, 3))
        result = self.space.is_diagonal(base_point)
        self.assertTrue(~result)
Beispiel #12
0
    def square_root_velocity(self, curve):
        """Compute the square root velocity representation of a curve.

        The velocity is computed using the log map. The case of several curves
        is handled through vectorization. In that case, an index selection
        procedure allows to get rid of the log between the end point of
        curve[k, :, :] and the starting point of curve[k + 1, :, :].

        Parameters
        ----------
        curve :

        Returns
        -------
        srv :
        """
        curve = gs.to_ndarray(curve, to_ndim=3)
        n_curves, n_sampling_points, n_coords = curve.shape
        srv_shape = (n_curves, n_sampling_points - 1, n_coords)

        curve = gs.reshape(curve, (n_curves * n_sampling_points, n_coords))
        coef = gs.cast(gs.array(n_sampling_points - 1), gs.float32)
        velocity = coef * self.ambient_metric.log(point=curve[1:, :],
                                                  base_point=curve[:-1, :])
        velocity_norm = self.ambient_metric.norm(velocity, curve[:-1, :])
        srv = velocity / gs.sqrt(velocity_norm)

        index = gs.arange(n_curves * n_sampling_points - 1)
        mask = ~gs.equal((index + 1) % n_sampling_points, 0)
        index_select = gs.gather(index, gs.squeeze(gs.where(mask)))
        srv = gs.reshape(gs.gather(srv, index_select), srv_shape)

        return srv
Beispiel #13
0
    def __init__(self, n_meridians=40, n_circles_latitude=None, points=None):
        if n_circles_latitude is None:
            n_circles_latitude = max(n_meridians / 2, 4)

        u, v = gs.meshgrid(gs.arange(0, 2 * gs.pi, 2 * gs.pi / n_meridians),
                           gs.arange(0, gs.pi, gs.pi / n_circles_latitude))

        self.center = gs.zeros(3)
        self.radius = 1
        self.sphere_x = self.center[0] + self.radius * gs.cos(u) * gs.sin(v)
        self.sphere_y = self.center[1] + self.radius * gs.sin(u) * gs.sin(v)
        self.sphere_z = self.center[2] + self.radius * gs.cos(v)

        self.points = []
        if points is not None:
            self.add_points(points)
Beispiel #14
0
    def _initialize_medoids(self, distances):
        """Select initial medoids when beginning clustering."""
        if self.init == "random":
            medoids = gs.random.choice(gs.arange(len(distances)), self.n_clusters)
        else:
            logging.error("Unknown initialization method.")

        return medoids
Beispiel #15
0
    def norm_factor_gradient(self, variances):
        """Compute normalization factor and its gradient.

        Compute normalization factor given current variance
        and dimensionality.

        Parameters
        ----------
        variances : array-like, shape=[n]
            Value of variance.

        Returns
        -------
        norm_factor : array-like, shape=[n]
            Normalisation factor.
        norm_factor_gradient : array-like, shape=[n]
            Gradient of the normalization factor.
        """
        variances = gs.transpose(gs.to_ndarray(variances, to_ndim=2))
        dim_range = gs.arange(0, self.dim, 1.0)
        alpha = self._compute_alpha(dim_range)

        binomial_coefficient = gs.ones(self.dim)
        binomial_coefficient[1:] = (self.dim - 1 + 1 - dim_range[1:]) / dim_range[1:]
        binomial_coefficient = gs.cumprod(binomial_coefficient)

        beta = ((-gs.ones(self.dim)) ** dim_range) * binomial_coefficient

        sigma_repeated = gs.repeat(variances, self.dim, -1)
        prod_alpha_sigma = gs.einsum("ij,j->ij", sigma_repeated, alpha)
        term_2 = gs.exp((prod_alpha_sigma) ** 2) * (1 + gs.erf(prod_alpha_sigma))
        term_1 = gs.sqrt(gs.pi / 2.0) * (1.0 / (2 ** (self.dim - 1)))
        term_2 = gs.einsum("ij,j->ij", term_2, beta)
        norm_factor = term_1 * variances * gs.sum(term_2, axis=-1, keepdims=True)
        grad_term_1 = 1 / variances

        grad_term_21 = 1 / gs.sum(term_2, axis=-1, keepdims=True)

        grad_term_211 = (
            gs.exp((prod_alpha_sigma) ** 2)
            * (1 + gs.erf(prod_alpha_sigma))
            * gs.einsum("ij,j->ij", sigma_repeated, alpha**2)
            * 2
        )

        grad_term_212 = gs.repeat(
            gs.expand_dims((2 / gs.sqrt(gs.pi)) * alpha, axis=0),
            variances.shape[0],
            axis=0,
        )

        grad_term_22 = grad_term_211 + grad_term_212
        grad_term_22 = gs.einsum("ij, j->ij", grad_term_22, beta)
        grad_term_22 = gs.sum(grad_term_22, axis=-1, keepdims=True)

        norm_factor_gradient = grad_term_1 + (grad_term_21 * grad_term_22)

        return gs.squeeze(norm_factor), gs.squeeze(norm_factor_gradient)
Beispiel #16
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)
Beispiel #17
0
def main():
    norm_rv_1 = gs.normal(size=DIM)
    tan_rv_1 = ALGEBRA.matrix_representation(
        norm_rv_1 / gs.norm(norm_rv_1, axis=0) / 2
    )
    exp_1 = gs.linalg.expm(tan_rv_1)

    norm_rv_2 = gs.normal(size=DIM)
    tan_rv_2 = ALGEBRA.matrix_representation(
        norm_rv_2 / gs.norm(norm_rv_2, axis=0) / 2
    )
    exp_2 = gs.linalg.expm(tan_rv_2)

    composition = GROUP.compose(exp_1, exp_2)

    orders = gs.arange(1, MAX_ORDER + 1)
    bch_approximations = gs.array(
        [
            ALGEBRA.baker_campbell_hausdorff(tan_rv_1, tan_rv_2, order=n)
            for n in orders
        ]
    )
    bch_approximations = ALGEBRA.basis_representation(bch_approximations)
    correct = ALGEBRA.basis_representation(gs.linalg.logm(composition))
    t_numpy = timeit.timeit(
        lambda: gs.linalg.logm(
            gs.matmul(gs.linalg.expm(tan_rv_1), gs.linalg.expm(tan_rv_2))
        ),
        number=100,
    )
    t_bch = [
        timeit.timeit(
            lambda: ALGEBRA.baker_campbell_hausdorff(
                tan_rv_1, tan_rv_2, order=n
            ),
            number=100,
        )
        for n in orders
    ]
    frobenius_error = gs.linalg.norm(bch_approximations - correct, axis=1)

    plt.subplot(2, 1, 1)
    plt.scatter(orders, frobenius_error)
    plt.xlabel('Order of approximation')
    plt.ylabel('Error in Frob. norm')
    plt.grid()

    plt.subplot(2, 1, 2)
    plt.scatter(orders, t_bch)
    plt.hlines(y=t_numpy, xmin=1, xmax=MAX_ORDER)
    plt.xlabel('Order of approximation')
    plt.ylabel('Execution time[s] for 100 replications vs. numpy')
    plt.grid()

    plt.show()
    plt.close()
Beispiel #18
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)
    def __init__(self, n):
        """Instantiate the class.

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

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

        for row in gs.arange(n - 1):
            for col in gs.arange(row + 1, n):
                self.basis[loop_index, row, col] = 1
                self.basis[loop_index, col, row] = -1
                loop_index += 1
Beispiel #20
0
def sample_from(points, n_samples=1):
    """
    Sample from the empirical distribution associated to points.
    """
    n_points = points.shape[0]
    dimension = points.shape[-1]

    index = gs.random.randint(low=0, high=n_points, size=(n_samples, ))
    sample = points[gs.ix_(index, gs.arange(dimension))]

    return sample
Beispiel #21
0
 def orthonormal_basis_se3_test_data(self):
     smoke_data = [
         dict(group=SpecialEuclidean(3), metric_mat_at_identity=None),
         dict(
             group=SpecialEuclidean(3),
             metric_mat_at_identity=from_vector_to_diagonal_matrix(
                 gs.cast(gs.arange(1,
                                   SpecialEuclidean(3).dim + 1),
                         gs.float32)),
         ),
     ]
     return self.generate_tests(smoke_data)
Beispiel #22
0
 def test_to_tangent_vec_vectorization(self):
     n = self.group.n
     tangent_vecs = gs.arange(self.n_samples * (n + 1) ** 2)
     tangent_vecs = gs.cast(tangent_vecs, gs.float32)
     tangent_vecs = gs.reshape(tangent_vecs, (self.n_samples,) + (n + 1,) * 2)
     point = self.group.random_point(self.n_samples)
     tangent_vecs = Matrices.mul(point, tangent_vecs)
     regularized = self.group.to_tangent(tangent_vecs, point)
     result = Matrices.mul(Matrices.transpose(point), regularized) + Matrices.mul(
         Matrices.transpose(regularized), point
     )
     result = result[:, :n, :n]
     expected = gs.zeros_like(result)
     self.assertAllClose(result, expected)
Beispiel #23
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)
Beispiel #24
0
def load_optical_nerves():
    """Load data from data/optical_nerves/optical_nerves.txt.

    Load the dataset of sets of 5 landmarks, labelled S, T, I, N, V, in 3D
    on monkeys' optical nerve heads:

    - 1st landmark (S): superior aspect of the retina,
    - 2nd landmark (T): side of the retina closest to the temporal
      bone of the skull,
    - 3rd landmark (N): nose side of the retina,
    - 4th landmark (I): inferior point,
    - 5th landmarks (V): optical nerve head deepest point.

    For each monkey, an experimental glaucoma was introduced in one eye,
    while the second eye was kept as control. This dataset can be used to
    investigate a significant difference between the glaucoma and the
    control eyes.

    Label 0 refers to a normal eye, and Label 1 to an eye with glaucoma.

    References
    ----------
    .. [PE2015] V. Patrangenaru and L. Ellingson. Nonparametric Statistics
        on Manifolds and Their Applications to Object Data, 2015.
        https://doi.org/10.1201/b18969


    Returns
    -------
    data : array-like, shape=[22, 5, 3]
        Data representing the 5 landmarks, in 3D, for 11 different monkeys.
    labels : array-like, shape=[22,]
        Labels in {0, 1} classifying the corresponding optical nerve as
        normal (label = 0) or glaucoma (label = 1).
    monkeys : array-like, shape=[22,]
        Indices in 0...10 referencing the index of the monkey to which a given
        optical nerve belongs.
    """
    nerves = pd.read_csv(OPTICAL_NERVES_PATH, sep="\t")
    nerves = nerves.set_index("Filename")
    nerves = nerves.drop(index=["laljn103.12b", "lalj0103.12b"])
    nerves = nerves.reset_index(drop=True)
    nerves_gs = gs.array(nerves.values)

    data = gs.reshape(nerves_gs, (nerves_gs.shape[0], -1, 3))
    labels = gs.tile([0, 1], [nerves_gs.shape[0] // 2])
    monkeys = gs.repeat(gs.arange(11), 2)

    return data, labels, monkeys
Beispiel #25
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)
Beispiel #26
0
    def baker_campbell_hausdorff(self, matrix_a, matrix_b, order=2):
        """Calculate the Baker-Campbell-Hausdorff approximation of given order.

        The implementation is based on [CM2009a]_ with the pre-computed
        constants taken from [CM2009b]_. Our coefficients are truncated to
        enable us to calculate BCH up to order 15.

        This represents Z = log(exp(X)exp(Y)) as an infinite linear combination
        of the form Z = sum z_i e_i where z_i are rational numbers and e_i are
        iterated Lie brackets starting with e_1 = X, e_2 = Y, each e_i is given
        by some i',i'': e_i = [e_i', e_i''].

        Parameters
        ----------
        matrix_a, matrix_b : array-like, shape=[..., n, n]
            Matrices.
        order : int
            The order to which the approximation is calculated. Note that this
            is NOT the same as using only e_i with i < order.
            Optional, default 2.

        References
        ----------
        .. [CM2009a] F. Casas and A. Murua. An efficient algorithm for
            computing the Baker–Campbell–Hausdorff series and some of its
            applications. Journal of Mathematical Physics 50, 2009
        .. [CM2009b] http://www.ehu.eus/ccwmuura/research/bchHall20.dat
        """
        if order > 15:
            raise NotImplementedError("BCH is not implemented for order > 15.")

        number_of_hom_degree = gs.array(
            [2, 1, 2, 3, 6, 9, 18, 30, 56, 99, 186, 335, 630, 1161, 2182]
        )
        n_terms = gs.sum(number_of_hom_degree[:order])

        el = [matrix_a, matrix_b]
        result = matrix_a + matrix_b

        for i in gs.arange(2, n_terms):
            i_p = BCH_COEFFICIENTS[i, 1] - 1
            i_pp = BCH_COEFFICIENTS[i, 2] - 1

            el.append(self.bracket(el[i_p], el[i_pp]))
            result += (
                float(BCH_COEFFICIENTS[i, 3]) / float(BCH_COEFFICIENTS[i, 4]) * el[i]
            )
        return result
Beispiel #27
0
    def test_estimate_weights(self):
        point = self.so.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so, verbose=True)
        weights = gs.arange(self.n_samples)
        estimator.fit(point, weights=weights)
        barexp = estimator.estimate_
        result = self.so.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)

        point = self.so_vec.random_uniform(self.n_samples)
        estimator = ExponentialBarycenter(self.so_vec)
        estimator.fit(point, weights=weights)
        barexp = estimator.estimate_
        result = self.so_vec.belongs(barexp)
        expected = True
        self.assertAllClose(result, expected)
    def basis_representation(self, matrix_representation):
        """Calculate the coefficients of given matrix in the basis.

        Parameters
        ----------
        matrix_representation: array-like, shape=[n_sample, n, n]

        Returns
        ------
        basis_representation: array-like, shape=[n_sample, dimension]
        """
        old_shape = gs.shape(matrix_representation)
        as_vector = gs.reshape(matrix_representation, (old_shape[0], -1))
        upper_tri_indices = gs.reshape(gs.arange(
            0, self.n**2), (self.n, self.n))[gs.triu_indices(self.n, k=1)]

        return as_vector[:, upper_tri_indices]
Beispiel #29
0
    def baker_campbell_hausdorff(self, matrix_a, matrix_b, order=2):
        """Calculate the Baker Campbell Hausdorff approximation of given order.

        We use the algorithm published by Casas / Murua in their paper
        "An efficient algorithm for computing the Baker–Campbell–Hausdorff
        series and some of its applications" in J.o.Math.Physics 50 (2009) as
        well as their computed constants from
        http://www.ehu.eus/ccwmuura/research/bchHall20.dat.
        Our file is truncated to enable us to calculate BCH up to order 15

        This represents Z =log(exp(X)exp(Y)) as an infinite linear combination
        of the form
        Z = sum z_i e_i
        where z_i are rational numbers and e_i are iterated Lie brackets
        starting with e_1 = X, e_2 = Y, each e_i is given by some i',i'':
        e_i = [e_i', e_i''].

        Parameters
        ----------
        matrix_a: array-like, shape=[n_sample, n, n]
        matrix_b: array-like, shape=[n_sample, n, n]
        order: int
            the order to which the approximation is calculated. Note that this
            is NOT the same as using only e_i with i < order
        """
        if order > 15:
            raise NotImplementedError("BCH is not implemented for order > 15.")

        number_of_hom_degree = gs.array(
            [2, 1, 2, 3, 6, 9, 18, 30, 56, 99, 186, 335, 630, 1161, 2182])
        n_terms = gs.sum(number_of_hom_degree[:order])

        ei = gs.zeros((n_terms, self.n, self.n))
        ei[0] = matrix_a
        ei[1] = matrix_b
        result = matrix_a + matrix_b

        for i in gs.arange(2, n_terms):
            i_p = BCH_INFO[i, 1] - 1
            i_pp = BCH_INFO[i, 2] - 1

            ei[i] = self.lie_bracket(ei[i_p], ei[i_pp])
            result = result + BCH_INFO[i, 3] / float(BCH_INFO[i, 4]) * ei[i]

        return result
Beispiel #30
0
def _circle_variances(mean, var, n_samples, points):
    """Compute the minimizer of the variance functional.

    Parameters
    ----------
    mean : float
        Mean angle.
    var : float
        Variance of the angles.
    n_samples : int
        Number of samples.
    points : array-like, shape=[n,]
        Data set of ordered angles.

    References
    ---------
    ..[HH15]     Hotz, T. and S. F. Huckemann (2015), "Intrinsic means on the circle:
                 Uniqueness, locus and asymptotics", Annals of the Institute of
                 Statistical Mathematics 67 (1), 177–193.
                 https://arxiv.org/abs/1108.2141
    """
    means = (mean + gs.linspace(0.0, 2 * gs.pi, n_samples + 1)[:-1]) % (2 * gs.pi)
    means = gs.where(means >= gs.pi, means - 2 * gs.pi, means)
    parts = gs.array([sum(points) / n_samples if means[0] < 0 else 0])
    m_plus = means >= 0
    left_sums = gs.cumsum(points)
    right_sums = left_sums[-1] - left_sums
    i = gs.arange(n_samples, dtype=right_sums.dtype)
    j = i[1:]
    parts2 = right_sums[:-1] / (n_samples - j)
    first_term = parts2[:1]
    parts2 = gs.where(m_plus[1:], left_sums[:-1] / j, parts2)
    parts = gs.concatenate([parts, first_term, parts2[1:]])

    # Formula (6) from [HH15]_
    plus_vec = (4 * gs.pi * i / n_samples) * (gs.pi + parts - mean) - (
        2 * gs.pi * i / n_samples
    ) ** 2
    minus_vec = (4 * gs.pi * (n_samples - i) / n_samples) * (gs.pi - parts + mean) - (
        2 * gs.pi * (n_samples - i) / n_samples
    ) ** 2
    minus_vec = gs.where(m_plus, plus_vec, minus_vec)
    means = gs.transpose(gs.vstack([means, var + minus_vec]))
    return means