Example #1
0
def diff(x, k=1):
    """ Vector of kth order differences.

    Takes in a vector of length n and returns a vector
    of length n-k of the kth order differences.

    diff(x) returns the vector of differences between
    adjacent elements in the vector, that is

    [x[2] - x[1], x[3] - x[2], ...]

    diff(x, 2) is the second-order differences vector,
    equivalently diff(diff(x))

    diff(x, 0) returns the vector x unchanged
    """
    x = Expression.cast_to_const(x)
    m, n = x.size

    try:
        assert 0 <= k < m
        assert n == 1
    except:
        raise ValueError('Must have k >= 0 and x must be a 1D vector with < k elements')

    d = x
    for i in range(k):
        d = d[1:] - d[:-1]
        
    return d
Example #2
0
def norm(x, p=2):
    """Wrapper on the different norm atoms.

    Parameters
    ----------
    x : Expression or numeric constant
        The value to take the norm of.
    p : int or str, optional
        The type of norm.

    Returns
    -------
    Expression
        An Expression representing the norm.
    """
    x = Expression.cast_to_const(x)
    if p == 1:
        return norm1(x)
    elif p == "inf":
        return normInf(x)
    elif p == "nuc":
        return normNuc(x)
    elif p == "fro":
        return norm2(x)
    elif p == 2:
        if x.is_matrix():
            return sigma_max(x)
        else:
            return norm2(x)
    else:
        raise Exception("Invalid value %s for p." % p)
Example #3
0
def log_normcdf(x):  # noqa: E501
    """Elementwise log of the cumulative distribution function of a standard normal random variable.

    The implementation is a quadratic approximation with modest accuracy over [-4, 4].
    For details on the nature of the approximation, refer to
    `CVXPY GitHub PR #1224 <https://github.com/cvxpy/cvxpy/pull/1224#issue-793221374>`_.

    .. note::

        SciPy's analog of ``log_normcdf`` is called `log_ndtr <https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.log_ndtr.html>`_.
        We opted not to use that name because its meaning would not be obvious to the casual user.
    """
    A = scipy.sparse.diags(
        np.sqrt(
            [
                0.02301291,
                0.08070214,
                0.16411522,
                0.09003495,
                0.08200854,
                0.01371543,
                0.04641081,
            ]
        )
    )
    b = np.array([[3.0, 2.0, 1.0, 0.0, -1.0, -2.5, -3.5]]).reshape(-1, 1)

    x = Expression.cast_to_const(x)
    flat_x = reshape(x, (1, x.size))

    y = A @ (b @ np.ones(flat_x.shape) - np.ones(b.shape) @ flat_x)
    out = -sum_(maximum(y, 0) ** 2, axis=0)

    return reshape(out, x.shape)
Example #4
0
def diff(x, k=1, axis=0):
    """Vector of kth order differences.

    Takes in a vector of length n and returns a vector
    of length n-k of the kth order differences.

    diff(x) returns the vector of differences between
    adjacent elements in the vector, that is

    [x[2] - x[1], x[3] - x[2], ...]

    diff(x, 2) is the second-order differences vector,
    equivalently diff(diff(x))

    diff(x, 0) returns the vector x unchanged
    """
    x = Expression.cast_to_const(x)
    if (axis == 1 and x.ndim < 2) or x.ndim == 0:
        raise ValueError("Invalid axis given input dimensions.")
    elif axis == 0:
        x = x.T

    if k < 0 or k >= x.shape[axis]:
        raise ValueError("Must have k >= 0 and X must have < k elements along "
                         "axis")
    for i in range(k):
        if x.ndim == 2:
            x = x[1:, :] - x[:-1, :]
        else:
            x = x[1:] - x[:-1]
    return x.T if axis == 1 else x
Example #5
0
def vec_to_upper_tri(expr, strict=False):
    expr = Expression.cast_to_const(expr)
    ell = expr.shape[0]
    if strict:
        # n * (n-1)/2 == ell
        n = ((8 * ell + 1)**0.5 + 1) // 2
    else:
        # n * (n+1)/2 == ell
        n = ((8 * ell + 1)**0.5 - 1) // 2
    n = int(n)
    # form a matrix P, of shape (n**2, ell).
    #       the i-th block of n rows of P gives the entries of the i-th row
    #       of the upper-triangular matrix associated with expr.
    # compute expr2 = P @ expr
    # compute expr3 = reshape(expr2, shape=(n, n)).T
    #   expr3 is the matrix formed by reading length-n blocks of expr2,
    #   and letting each block form a row of expr3.
    P_rows = []
    P_row = 0
    for mat_row in range(n):
        entries_in_row = n - mat_row
        if strict:
            entries_in_row -= 1
        P_row += n - entries_in_row  # these are zeros
        P_rows.extend(range(P_row, P_row + entries_in_row))
        P_row += entries_in_row
    P_cols = np.arange(ell)
    P_vals = np.ones(P_cols.size)
    P = csc_matrix((P_vals, (P_rows, P_cols)), shape=(n**2, ell))
    expr2 = P @ expr
    expr3 = reshape(expr2, (n, n)).T
    return expr3
Example #6
0
def norm(x, p=2):
    """Wrapper on the different norm atoms.

    Parameters
    ----------
    x : Expression or numeric constant
        The value to take the norm of.
    p : int or str, optional
        The type of norm.

    Returns
    -------
    Expression
        An Expression representing the norm.
    """
    x = Expression.cast_to_const(x)
    if p == 1:
        return norm1(x)
    elif p == "inf":
        return normInf(x)
    elif p == "nuc":
        return normNuc(x)
    elif p == "fro":
        return norm2(x)
    elif p == 2:
        if x.is_matrix():
            return sigma_max(x)
        else:
            return norm2(x)
    else:
        raise Exception("Invalid value %s for p." % p)
Example #7
0
def norm(x, p=2, axis=None):
    """Wrapper on the different norm atoms.

    Parameters
    ----------
    x : Expression or numeric constant
        The value to take the norm of.
    p : int or str, optional
        The type of norm.

    Returns
    -------
    Expression
        An Expression representing the norm.
    """
    x = Expression.cast_to_const(x)
    # Norms for scalars same as absolute value.
    if p == 1 or x.is_scalar():
        return pnorm(x, 1, axis)
    elif p == "inf":
        return pnorm(x, 'inf', axis)
    elif p == "nuc":
        return normNuc(x)
    elif p == "fro":
        return pnorm(x, 2, axis)
    elif p == 2:
        if axis is None and x.is_matrix():
            return sigma_max(x)
        else:
            return pnorm(x, 2, axis)
    else:
        return pnorm(x, p, axis)
Example #8
0
def diff(x, k=1, axis=0):
    """ Vector of kth order differences.

    Takes in a vector of length n and returns a vector
    of length n-k of the kth order differences.

    diff(x) returns the vector of differences between
    adjacent elements in the vector, that is

    [x[2] - x[1], x[3] - x[2], ...]

    diff(x, 2) is the second-order differences vector,
    equivalently diff(diff(x))

    diff(x, 0) returns the vector x unchanged
    """
    x = Expression.cast_to_const(x)
    if axis == 1:
        x = x.T
    m, n = x.size
    if k < 0 or k >= m:
        raise ValueError(
            'Must have k >= 0 and X must have < k elements along axis')

    d = x
    for i in range(k):
        d = d[1:, :] - d[:-1, :]

    if axis == 1:
        return d.T
    else:
        return d
Example #9
0
def tv(value):
    """Total variation of a vector or matrix.

    Uses L1 norm of discrete gradients for vectors and
    L2 norm of discrete gradients for matrices.

    Parameters
    ----------
    value : Expression or numeric constant
        The value to take the total variation of.

    Returns
    -------
    Expression
        An Expression representing the total variation.
    """
    value = Expression.cast_to_const(value)
    rows, cols = value.size
    if value.is_scalar():
        raise ValueError("tv cannot take a scalar argument.")
    # L1 norm for vectors.
    elif value.is_vector():
        return norm(value[1:] - value[0:max(rows, cols) - 1], 1)
    # L2 norm for matrices.
    else:
        row_diff = value[0:rows - 1, 1:cols] - value[0:rows - 1, 0:cols - 1]
        col_diff = value[1:rows, 0:cols - 1] - value[0:rows - 1, 0:cols - 1]
        return sum_entries(norm2_elemwise(row_diff, col_diff))
Example #10
0
File: norm.py Project: giserh/cvxpy
def norm(x, p=2, axis=None):
    """Wrapper on the different norm atoms.

    Parameters
    ----------
    x : Expression or numeric constant
        The value to take the norm of.
    p : int or str, optional
        The type of norm.

    Returns
    -------
    Expression
        An Expression representing the norm.
    """
    x = Expression.cast_to_const(x)
    if p == 1:
        return pnorm(x, 1, axis)
    elif p == "inf":
        return pnorm(x, 'inf', axis)
    elif p == "nuc":
        return normNuc(x)
    elif p == "fro":
        return pnorm(x, 2, axis)
    elif p == 2:
        if x.is_matrix():
            return sigma_max(x)
        else:
            return pnorm(x, 2, axis)
    else:
        return pnorm(x, p, axis)
Example #11
0
def diff(x, k=1, axis=0):
    """ Vector of kth order differences.

    Takes in a vector of length n and returns a vector
    of length n-k of the kth order differences.

    diff(x) returns the vector of differences between
    adjacent elements in the vector, that is

    [x[2] - x[1], x[3] - x[2], ...]

    diff(x, 2) is the second-order differences vector,
    equivalently diff(diff(x))

    diff(x, 0) returns the vector x unchanged
    """
    x = Expression.cast_to_const(x)
    if axis == 1:
        x = x.T
    m, n = x.size
    if k < 0 or k >= m:
        raise ValueError('Must have k >= 0 and X must have < k elements along axis')

    d = x
    for i in range(k):
        d = d[1:, :] - d[:-1, :]

    if axis == 1:
        return d.T
    else:
        return d
Example #12
0
def l1_aniso_2d(value1, value2):
    """\sum \sqrt{value1^2 + value2^2}
    Parameters
    ----------
    value : Expression or numeric constant
        The value to take the total variation of.
    Returns
    -------
    Expression
        An Expression representing the total variation.
    """
    value1 = Expression.cast_to_const(value1)
    value2 = Expression.cast_to_const(value2)
    len = value1.size[0]

    return sum_entries(cvxnorm(value1 + value2, p='1'))
Example #13
0
def lambda_sum_largest(X, k):
    """Sum of the largest k eigenvalues.
    """
    X = Expression.cast_to_const(X)
    if X.size[0] != X.size[1]:
        raise ValueError("First argument must be a square matrix.")
    elif int(k) != k or k <= 0:
        raise ValueError("Second argument must be a positive integer.")
    """
    S_k(X) denotes lambda_sum_largest(X, k)
    t >= k S_k(X - Z) + trace(Z), Z is PSD
    implies
    t >= ks + trace(Z)
    Z is PSD
    sI >= X - Z (PSD sense)
    which implies
    t >= ks + trace(Z) >= S_k(sI + Z) >= S_k(X)
    We use the fact that
    S_k(X) = sup_{sets of k orthonormal vectors u_i}\sum_{i}u_i^T X u_i
    and if Z >= X in PSD sense then
    \sum_{i}u_i^T Z u_i >= \sum_{i}u_i^T X u_i

    We have equality when s = lambda_k and Z diagonal
    with Z_{ii} = (lambda_i - lambda_k)_+
    """
    Z = Semidef(X.size[0])
    return k*lambda_max(X - Z) + trace(Z)
Example #14
0
def lambda_sum_largest(X, k):
    """Sum of the largest k eigenvalues.
    """
    X = Expression.cast_to_const(X)
    if X.size[0] != X.size[1]:
        raise ValueError("First argument must be a square matrix.")
    elif int(k) != k or k <= 0:
        raise ValueError("Second argument must be a positive integer.")
    """
    S_k(X) denotes lambda_sum_largest(X, k)
    t >= k S_k(X - Z) + trace(Z), Z is PSD
    implies
    t >= ks + trace(Z)
    Z is PSD
    sI >= X - Z (PSD sense)
    which implies
    t >= ks + trace(Z) >= S_k(sI + Z) >= S_k(X)
    We use the fact that
    S_k(X) = sup_{sets of k orthonormal vectors u_i}\sum_{i}u_i^T X u_i
    and if Z >= X in PSD sense then
    \sum_{i}u_i^T Z u_i >= \sum_{i}u_i^T X u_i

    We have equality when s = lambda_k and Z diagonal
    with Z_{ii} = (lambda_i - lambda_k)_+
    """
    Z = Semidef(X.size[0])
    return k*lambda_max(X - Z) + trace(Z)
Example #15
0
def log_normcdf(x):
    """Elementwise log of the cumulative distribution function of a standard normal random variable.

    Implementation is a quadratic approximation with modest accuracy over [-4, 4].
    """
    A = scipy.sparse.diags(
        np.sqrt(
            [
                0.02301291,
                0.08070214,
                0.16411522,
                0.09003495,
                0.08200854,
                0.01371543,
                0.04641081,
            ]
        )
    )
    b = np.array([[3.0, 2.0, 1.0, 0.0, -1.0, -2.5, -3.5]]).reshape(-1, 1)

    x = Expression.cast_to_const(x)
    flat_x = reshape(x, (1, x.size))

    y = A @ (b @ np.ones(flat_x.shape) - np.ones(b.shape) @ flat_x)
    out = -sum_(maximum(y, 0) ** 2, axis=0)

    return reshape(out, x.shape)
Example #16
0
def promote(expr, shape):
    expr = Expression.cast_to_const(expr)
    if expr.shape != shape:
        if not expr.is_scalar():
            raise ValueError('Only scalars may be promoted.')
        return Promote(expr, shape)
    else:
        return expr
Example #17
0
 def __init__(self, expr):
     self.args = [Expression.cast_to_const(expr)]
     # Validate that the objective resolves to a scalar.
     if not self.args[0].is_scalar():
         raise ValueError("The '%s' objective must resolve to a scalar."
                          % self.NAME)
     if not self.args[0].is_real():
         raise ValueError("The '%s' objective must be real valued."
                          % self.NAME)
Example #18
0
def tvnorm_trace_2d(value1, value2, Dx, Dy):
    """Total variation of a vector, matrix, or list of matrices.
    Uses L1 norm of discrete gradients for vectors and
    L2 norm of discrete gradients for matrices.
    Parameters
    ----------
    value : Expression or numeric constant
        The value to take the total variation of.
    Returns
    -------
    Expression
        An Expression representing the total variation.
    """
    value1 = Expression.cast_to_const(value1)
    value2 = Expression.cast_to_const(value2)
    len = value1.size[0]

    diffs = [Dx * (value1 + value2), Dy * (value1 + value2)]

    stack = vstack(*[reshape(diff, 1, len) for diff in diffs])
    return sum_entries(cvxnorm(stack, p='fro', axis=0))
Example #19
0
def promote(expr: Expression, shape: Tuple[int, ...]):
    """ Promote a scalar expression to a vector/matrix.

    Parameters
    ----------
    expr : Expression
        The expression to promote.
    shape : tuple
        The shape to promote to.

    Raises
    ------
    ValueError
        If ``expr`` is not a scalar.
    """

    expr = Expression.cast_to_const(expr)
    if expr.shape != shape:
        if not expr.is_scalar():
            raise ValueError('Only scalars may be promoted.')
        return Promote(expr, shape)
    else:
        return expr
Example #20
0
def vec(X):
    """Flattens the matrix X into a vector in column-major order.

    Parameters
    ----------
    X : Expression or numeric constant
        The matrix to flatten.

    Returns
    -------
    Expression
        An Expression representing the flattened matrix.
    """
    X = Expression.cast_to_const(X)
    return reshape(X, (X.size, ))
Example #21
0
File: vec.py Project: heath9/cvxpy
def vec(X):
    """Flattens the matrix X into a vector in column-major order.

    Parameters
    ----------
    X : Expression or numeric constant
        The matrix to flatten.

    Returns
    -------
    Expression
        An Expression representing the flattened matrix.
    """
    X = Expression.cast_to_const(X)

    return reshape(X, X.size[0]*X.size[1], 1)
Example #22
0
def expr_as_np_array(cvx_expr: Expression) -> np.ndarray:
    """
    Convert cvxpy expression into a numpy array.

    :param cvx_expr: The cvxpy expression to be converted.
    :return: The numpy array of the cvxpy expression.
    """
    if cvx_expr.is_scalar():
        return np.array(cvx_expr)
    if len(cvx_expr.shape) == 1:
        return np.array(list(cvx_expr))
    # Then cvx_expr is a 2-D array.
    rows = []
    for i in range(cvx_expr.shape[0]):
        row = [cvx_expr[i, j] for j in range(cvx_expr.shape[1])]
        rows.append(row)
    arr = np.array(rows)
    return arr
Example #23
0
def norm(x, p=2, axis=None):
    """Wrapper on the different norm atoms.

    Parameters
    ----------
    x : Expression or numeric constant
        The value to take the norm of.  If `x` is 2D and `axis` is None,
        this function constructs a matrix norm.
    p : int or str, optional
        The type of norm. Valid options include any positive integer,
        'fro' (for frobenius), 'nuc' (sum of singular values), np.inf or
        'inf' (infinity norm).
    axis : The axis along which to apply the norm, if any.

    Returns
    -------
    Expression
        An Expression representing the norm.
    """
    x = Expression.cast_to_const(x)
    # matrix norms take precedence
    num_nontrivial_idxs = sum([d > 1 for d in x.shape])
    if axis is None and x.ndim == 2:
        if p == 1:  # matrix 1-norm
            return cvxpy.atoms.max(norm1(x, axis=0))
        # Frobenius norm
        elif p == 'fro' or (p == 2 and num_nontrivial_idxs == 1):
            return pnorm(vec(x), 2)
        elif p == 2:  # matrix 2-norm is largest singular value
            return sigma_max(x)
        elif p == 'nuc':  # the nuclear norm (sum of singular values)
            return normNuc(x)
        elif p in [np.inf, "inf", "Inf"]:  # the matrix infinity-norm
            return cvxpy.atoms.max(norm1(x, axis=1))
        else:
            raise RuntimeError('Unsupported matrix norm.')
    else:
        if p == 1 or x.is_scalar():
            return norm1(x, axis=axis)
        elif p in [np.inf, "inf", "Inf"]:
            return norm_inf(x, axis)
        else:
            return pnorm(x, p, axis)
Example #24
0
def tv(value, *args):
    """Total variation of a vector, matrix, or list of matrices.

    Uses L1 norm of discrete gradients for vectors and
    L2 norm of discrete gradients for matrices.

    Parameters
    ----------
    value : Expression or numeric constant
        The value to take the total variation of.
    args : Matrix constants/expressions
        Additional matrices extending the third dimension of value.

    Returns
    -------
    Expression
        An Expression representing the total variation.
    """
    # Accept single list as argument.
    if isinstance(value, list) and len(args) == 0:
        args = value[1:]
        value = value[0]
    value = Expression.cast_to_const(value)
    rows, cols = value.size
    if value.is_scalar():
        raise ValueError("tv cannot take a scalar argument.")
    # L1 norm for vectors.
    elif value.is_vector():
        return norm(value[1:] - value[0:max(rows, cols)-1], 1)
    # L2 norm for matrices.
    else:
        args = map(Expression.cast_to_const, args)
        values = [value] + list(args)
        diffs = []
        for mat in values:
            diffs += [
                mat[0:rows-1, 1:cols] - mat[0:rows-1, 0:cols-1],
                mat[1:rows, 0:cols-1] - mat[0:rows-1, 0:cols-1],
            ]
        length = diffs[0].size[0]*diffs[1].size[1]
        stacked = vstack(*[reshape(diff, 1, length) for diff in diffs])
        return sum_entries(norm(stacked, p='fro', axis=0))
Example #25
0
def tv(value, *args):
    """Total variation of a vector, matrix, or list of matrices.

    Uses L1 norm of discrete gradients for vectors and
    L2 norm of discrete gradients for matrices.

    Parameters
    ----------
    value : Expression or numeric constant
        The value to take the total variation of.
    args : Matrix constants/expressions
        Additional matrices extending the third dimension of value.

    Returns
    -------
    Expression
        An Expression representing the total variation.
    """
    # Accept single list as argument.
    if isinstance(value, list) and len(args) == 0:
        args = value[1:]
        value = value[0]
    value = Expression.cast_to_const(value)
    rows, cols = value.size
    if value.is_scalar():
        raise ValueError("tv cannot take a scalar argument.")
    # L1 norm for vectors.
    elif value.is_vector():
        return norm(value[1:] - value[0:max(rows, cols)-1], 1)
    # L2 norm for matrices.
    else:
        args = list(map(Expression.cast_to_const, args))
        values = [value] + list(args)
        diffs = []
        for mat in values:
            diffs += [
                mat[0:rows-1, 1:cols] - mat[0:rows-1, 0:cols-1],
                mat[1:rows, 0:cols-1] - mat[0:rows-1, 0:cols-1],
            ]
        length = diffs[0].size[0]*diffs[1].size[1]
        stacked = vstack(*[reshape(diff, 1, length) for diff in diffs])
        return sum_entries(norm(stacked, p='fro', axis=0))
Example #26
0
def sos_to_sdp(syms, poly, z):
    deg = len(z)
    A, b = construct_constraints(syms, poly, z)
    obj = cvx.Minimize(0)
    q = cvx.Variable(deg * deg, 1)
    X = Expression.cast_to_const(q)

    #Find a solution to the equality constraints for setting up the starting strongly feasible point
    constraints = [-A * q == b]
    prob = cvx.Problem(obj, constraints)
    prob.solve()
    Q0 = np.reshape(np.array(q.value), (deg, deg))
    largest_eval = np.max(np.linalg.eigvals(Q0))
    if (largest_eval <= 1e-10):
        return (prob.status, -np.matrix(Q0))
    s0 = largest_eval + 10

    #initialize starting points
    Q = cvx.Variable(deg, deg)
    q = cvx.vec(Q)
    s = cvx.Variable()
    Q.value = Q0
    s.value = s0
    m = b.shape[0]
    eps = 0.0001
    t = 0.1
    mu = 1.5
    iteration = 1
    print("Running barrier method:")
    while (s.value > 0) and (m / t > eps):
        obj = cvx.Minimize(s - (1 / t) * atom.log_det(s * np.eye(deg) - Q))
        constraints = [-A * q == b, Q == Q.T, q == cvx.vec(Q)]
        prob = cvx.Problem(obj, constraints)
        prob.solve()
        #print(Q.value)
        #print(obj.value)
        print("Iteration: {} Value of s: {}".format(iteration, s.value))
        t *= mu
        iteration += 1

    return (prob.status, -np.matrix(Q.value))
Example #27
0
def deep_flatten(x):
    # base cases
    if isinstance(x, Expression):
        if len(x.shape) == 1:
            return x
        else:
            return x.flatten()
    elif isinstance(x, np.ndarray) or isinstance(x, (int, float)):
        x = Expression.cast_to_const(x)
        return x.flatten()
    # recursion
    if isinstance(x, list):
        y = []
        for x0 in x:
            x1 = deep_flatten(x0)
            y.append(x1)
        y = hstack(y)
        return y
    msg = 'The input to deep_flatten must be an Expression, a NumPy array, an int'\
          + ' or float, or a nested list thereof. Received input of type %s' % type(x)
    raise ValueError(msg)
Example #28
0
def harmonic_mean(x):
    """The harmonic mean of ``x``.

    Parameters
    ----------
    x : Expression or numeric
        The expression whose harmonic mean is to be computed. Must have
        positive entries.

    Returns
    -------
    Expression
        .. math::
            \\frac{n}{\\left(\\sum_{i=1}^{n} x_i^{-1} \\right)},

        where :math:`n` is the length of :math:`x`.
    """
    x = Expression.cast_to_const(x)
    # TODO(akshayka): Behavior of the below is incorrect when x has negative
    # entries. Either fail fast or provide a correct expression with
    # unknown curvature.
    return x.size*pnorm(x, -1)
Example #29
0
def tv(value, *args):
    """Total variation of a vector, matrix, or list of matrices.

    Uses L1 norm of discrete gradients for vectors and
    L2 norm of discrete gradients for matrices.

    Parameters
    ----------
    value : Expression or numeric constant
        The value to take the total variation of.
    args : Matrix constants/expressions
        Additional matrices extending the third dimension of value.

    Returns
    -------
    Expression
        An Expression representing the total variation.
    """
    value = Expression.cast_to_const(value)
    if value.ndim == 0:
        raise ValueError("tv cannot take a scalar argument.")
    # L1 norm for vectors.
    elif value.ndim == 1:
        return norm(value[1:] - value[0:value.shape[0]-1], 1)
    # L2 norm for matrices.
    else:
        rows, cols = value.shape
        args = map(Expression.cast_to_const, args)
        values = [value] + list(args)
        diffs = []
        for mat in values:
            diffs += [
                mat[0:rows-1, 1:cols] - mat[0:rows-1, 0:cols-1],
                mat[1:rows, 0:cols-1] - mat[0:rows-1, 0:cols-1],
            ]
        length = diffs[0].shape[0]*diffs[1].shape[1]
        stacked = vstack([reshape(diff, (1, length)) for diff in diffs])
        return sum(norm(stacked, p=2, axis=0))
Example #30
0
def mixed_norm(X, p=2, q=1):
    """Lp,q norm; :math:`(\\sum_k (\\sum_l \\lvert x_{k,l} \\rvert^p)^{q/p})^{1/q}`.

    Parameters
    ----------
    X : Expression or numeric constant
        The matrix to take the l_{p,q} norm of.
    p : int or str, optional
        The type of inner norm.
    q : int or str, optional
        The type of outer norm.

    Returns
    -------
    Expression
        An Expression representing the mixed norm.
    """
    X = Expression.cast_to_const(X)

    # inner norms
    vecnorms = norm(X, p, axis=1)
    # outer norm
    return norm(vecnorms, q)
Example #31
0
def norm(x, p=2, axis=None):
    """Wrapper on the different norm atoms.

    Parameters
    ----------
    x : Expression or numeric constant
        The value to take the norm of.
    p : int or str, optional
        The type of norm.

    Returns
    -------
    Expression
        An Expression representing the norm.
    """
    x = Expression.cast_to_const(x)
    # matrix norms take precedence
    if axis is None and x.ndim == 2:
        if p == 1:  # matrix 1-norm
            return cvxpy.atoms.max(norm1(x, axis=0))
        elif p == 2:  # matrix 2-norm is largest singular value
            return sigma_max(x)
        elif p == 'nuc':  # the nuclear norm (sum of singular values)
            return normNuc(x)
        elif p == 'fro':  # Frobenius norm
            return pnorm(vec(x), 2)
        elif p in [np.inf, "inf", "Inf"]:  # the matrix infinity-norm
            return cvxpy.atoms.max(norm1(x, axis=1))
        else:
            raise RuntimeError('Unsupported matrix norm.')
    else:
        if p == 1 or x.is_scalar():
            return norm1(x, axis=axis)
        elif p in [np.inf, "inf", "Inf"]:
            return norm_inf(x, axis)
        else:
            return pnorm(x, p, axis)
Example #32
0
def tv(value, *args):
    """Total variation of a vector, matrix, or list of matrices.

    Uses L1 norm of discrete gradients for vectors and
    L2 norm of discrete gradients for matrices.

    Parameters
    ----------
    value : Expression or numeric constant
        The value to take the total variation of.
    args : Matrix constants/expressions
        Additional matrices extending the third dimension of value.

    Returns
    -------
    Expression
        An Expression representing the total variation.
    """
    value = Expression.cast_to_const(value)
    rows, cols = value.size
    if value.is_scalar():
        raise ValueError("tv cannot take a scalar argument.")
    # L1 norm for vectors.
    elif value.is_vector():
        return norm(value[1:] - value[0:max(rows, cols)-1], 1)
    # L2 norm for matrices.
    else:
        args = list(map(Expression.cast_to_const, args))
        values = [value] + list(args)
        diffs = []
        for mat in values:
            diffs += [
                mat[0:rows-1, 1:cols] - mat[0:rows-1, 0:cols-1],
                mat[1:rows, 0:cols-1] - mat[0:rows-1, 0:cols-1],
            ]
        return sum_entries(norm2_elemwise(*diffs))
Example #33
0
def mixed_norm(X, p=2, q=1):
    """Lp,q norm; :math:` (\sum_k (\sum_l \lvert x_{k,l} \rvert )^q/p)^{1/q}`.

    Parameters
    ----------
    X : Expression or numeric constant
        The matrix to take the l_{p,q} norm of.
    p : int or str, optional
        The type of inner norm.
    q : int or str, optional
        The type of outer norm.

    Returns
    -------
    Expression
        An Expression representing the mixed norm.
    """
    X = Expression.cast_to_const(X)

    # inner norms
    vecnorms = [norm(X[i, :], p) for i in range(X.size[0])]

    # outer norm
    return norm(hstack(*vecnorms), q)
Example #34
0
def tv(value, *args):
    """Total variation of a vector, matrix, or list of matrices.

    Uses L1 norm of discrete gradients for vectors and
    L2 norm of discrete gradients for matrices.

    Parameters
    ----------
    value : Expression or numeric constant
        The value to take the total variation of.
    args : Matrix constants/expressions
        Additional matrices extending the third dimension of value.

    Returns
    -------
    Expression
        An Expression representing the total variation.
    """
    value = Expression.cast_to_const(value)
    rows, cols = value.size
    if value.is_scalar():
        raise ValueError("tv cannot take a scalar argument.")
    # L1 norm for vectors.
    elif value.is_vector():
        return norm(value[1:] - value[0:max(rows, cols) - 1], 1)
    # L2 norm for matrices.
    else:
        args = map(Expression.cast_to_const, args)
        values = [value] + list(args)
        diffs = []
        for mat in values:
            diffs += [
                mat[0:rows - 1, 1:cols] - mat[0:rows - 1, 0:cols - 1],
                mat[1:rows, 0:cols - 1] - mat[0:rows - 1, 0:cols - 1],
            ]
        return sum_entries(norm2_elemwise(*diffs))
Example #35
0
def mixed_norm(X, p=2, q=1):
    """Lp,q norm; :math:` (\sum_k (\sum_l \lvert x_{k,l} \rvert )^q/p)^{1/q}`.

    Parameters
    ----------
    X : Expression or numeric constant
        The matrix to take the l_{p,q} norm of.
    p : int or str, optional
        The type of inner norm.
    q : int or str, optional
        The type of outer norm.

    Returns
    -------
    Expression
        An Expression representing the mixed norm.
    """
    X = Expression.cast_to_const(X)

    # inner norms
    vecnorms = [norm(X[i, :], p) for i in range(X.size[0])]

    # outer norm
    return norm(hstack(*vecnorms), q)
Example #36
0
def min_entries(x, axis=None):
    """:math:`\min_{i,j}\{X_{i,j}\}`.
    """
    x = Expression.cast_to_const(x)
    return -max_entries(-x, axis=axis)
Example #37
0
 def __init__(self, expr):
     self.args = [Expression.cast_to_const(expr)]
     # Validate that the objective resolves to a scalar.
     if self.args[0].size != (1, 1):
         raise Exception("The '%s' objective must resolve to a scalar."
                         % self.NAME)
Example #38
0
def col_norm(X, p=2):

    X = Expression.cast_to_const(X)
    vecnorms = [ norm(X[:, i], p) for i in range(X.size[1]) ]
    return hstack(*vecnorms)
Example #39
0
def lambda_sum_smallest(X, k):
    """Sum of the largest k eigenvalues.
    """
    X = Expression.cast_to_const(X)
    return -lambda_sum_largest(-X, k)
Example #40
0
def min_entries(x, axis=None):
    """:math:`\min_{i,j}\{X_{i,j}\}`.
    """
    x = Expression.cast_to_const(x)
    return -max_entries(-x, axis=axis)
Example #41
0
def sum_smallest(x, k):
    """Sum of the smallest k values.
    """
    x = Expression.cast_to_const(x)
    return -sum_largest(-x, k)
Example #42
0
def sum_smallest(x, k):
    """Sum of the smallest k values.
    """
    x = Expression.cast_to_const(x)
    return -sum_largest(-x, k)
Example #43
0
def harmonic_mean(x):
    x = Expression.cast_to_const(x)
    return np.prod(x.size)*pnorm(x, -1)
Example #44
0
def row_norm(X, p=2):

    X = Expression.cast_to_const(X)
    vecnorms = [ norm(X[i, :], p) for i in range(X.size[0]) ]
    return hstack(*vecnorms).T