Ejemplo n.º 1
0
def setup_RPn_cost(D, return_grad=False):
    """Create the cost functions for pymanopt.

    The cost function is given by
        F(X) = (1/2)*||W * |X^T X| - cos(D))||^2
    Where `W` is the weight matrix accounting for removing the arccos term.
    Currently only returns the cost. For better performance, could add gradient
    as a return value.

    Parameters
    ----------
    D : ndarray (n, n)
        Matrix of target distances.

    Returns
    -------
    cost : function
        Weighted Frobenius norm cost function.
    egrad : function
        Gradient (in Euclidean space) of cost function.

    """

    W = distance_to_weights(D)
    C = np.cos(D)

    def cost(Y):
        """Weighted Frobenius norm cost function."""
        return 0.5 * np.linalg.norm(W * (C - np.abs(Y.T @ Y)))**2

    def egrad(Y):
        """Derivative of the cost function."""
        return 2 * Y @ (W**2 * (np.abs(Y.T @ Y) - C) * np.sign(Y.T @ Y))

    return cost, egrad
Ejemplo n.º 2
0
def setup_CPn_cost(D, n, return_grad=False):
    """Cost using geodesic metric on CPn."""
    W = distance_to_weights(D)
    C = np.cos(D)**2
    i_mtx = np.vstack((np.hstack((np.zeros(
        (n, n)), -np.eye(n))), np.hstack((np.eye(n), np.zeros((n, n))))))

    def cost(Y):
        return 0.5 * np.linalg.norm(W * ((Y.T @ Y)**2 +
                                         (Y.T @ (i_mtx @ Y))**2 - C))**2

    if return_grad:

        def egrad(Y):
            J = np.vstack((np.hstack((np.zeros(
                (n, n)), np.eye(n))), np.zeros((n, 2 * n))))
            R = np.vstack((np.hstack((np.eye(n), np.zeros(
                (n, n)))), np.zeros((n, 2 * n))))
            return (Y @ (2 * (Y.T @ Y)) @ (2 *
                                           (W *
                                            ((Y.T @ Y)**2 +
                                             (Y.T @ (i_mtx @ Y))**2 - C))) +
                    (R @ Y + J @ Y) @ (2 * (Y.T @ J @ Y)) @ (2 * (W * (
                        (Y.T @ Y)**2 + (Y.T @ (i_mtx @ Y))**2 - C))))
    else:
        egrad = None
    return cost, egrad
def setup_CPn_cost(D, n, return_grad=False):
    """Cost using geodesic metric on CPn."""
    W = distance_to_weights(D)
    i_mtx = np.vstack((np.hstack((np.zeros(
        (n, n)), -np.eye(n))), np.hstack((np.eye(n), np.zeros((n, n))))))

    def cost(Y):
        return 0.5 * np.linalg.norm(
            np.sqrt((Y.T @ Y)**2 + (Y.T @ (i_mtx @ Y))**2) - D)**2

    return cost, None