Example #1
0
def lambda_max_canon(expr, args):
    A = args[0]
    n = A.shape[0]
    t = Variable()
    prom_t = promote(t, (n, ))
    # Constrain I*t - A to be PSD; note that this expression must be symmetric.
    tmp_expr = diag_vec(prom_t) - A
    constr = [tmp_expr == tmp_expr.T, PSD(tmp_expr)]
    return t, constr
Example #2
0
def lambda_max_canon(expr, args):
    A = args[0]
    n = A.shape[0]
    t = Variable()
    prom_t = promote(t, (n, ))
    # Constrain I*t - A to be PSD; note that this expression must be symmetric.
    tmp_expr = diag_vec(prom_t) - A
    constr = [PSD(tmp_expr)]
    if not A.is_symmetric():
        ut = upper_tri(A)
        lt = upper_tri(A.T)
        constr.append(ut == lt)
    return t, constr
Example #3
0
def log_det_canon(expr, args):
    """Reduces the atom to an affine expression and list of constraints.

    Creates the equivalent problem::

       maximize    sum(log(D[i, i]))
       subject to: D diagonal
                   diag(D) = diag(Z)
                   Z is upper triangular.
                   [D Z; Z.T A] is positive semidefinite

    The problem computes the LDL factorization:

    .. math::

       A = (Z^TD^{-1})D(D^{-1}Z)

    This follows from the inequality:

    .. math::

       \\det(A) >= \\det(D) + \\det([D, Z; Z^T, A])/\\det(D)
               >= \\det(D)

    because (Z^TD^{-1})D(D^{-1}Z) is a feasible D, Z that achieves
    det(A) = det(D) and the objective maximizes det(D).

    Parameters
    ----------
    expr : log_det
    args : list
        The arguments for the expression

    Returns
    -------
    tuple
        (Variable for objective, list of constraints)
    """
    A = args[0]  # n by n matrix.
    n, _ = A.shape
    z = Variable(shape=(n * (n + 1) // 2, ))
    Z = vec_to_upper_tri(z, strict=False)
    d = diag_mat(Z)  # a vector
    D = diag_vec(d)  # a matrix
    X = bmat([[D, Z], [Z.T, A]])
    constraints = [PSD(X)]
    log_expr = log(d)
    obj, constr = log_canon(log_expr, log_expr.args)
    constraints += constr
    return sum(obj), constraints
def log_det_canon(expr, args):
    """Reduces the atom to an affine expression and list of constraints.

    Creates the equivalent problem::

       maximize    sum(log(D[i, i]))
       subject to: D diagonal
                   diag(D) = diag(Z)
                   Z is upper triangular.
                   [D Z; Z.T A] is positive semidefinite

    The problem computes the LDL factorization:

    .. math::

       A = (Z^TD^{-1})D(D^{-1}Z)

    This follows from the inequality:

    .. math::

       \\det(A) >= \\det(D) + \\det([D, Z; Z^T, A])/\\det(D)
               >= \\det(D)

    because (Z^TD^{-1})D(D^{-1}Z) is a feasible D, Z that achieves
    det(A) = det(D) and the objective maximizes det(D).

    Parameters
    ----------
    expr : log_det
    args : list
        The arguments for the expression

    Returns
    -------
    tuple
        (Variable for objective, list of constraints)
    """
    A = args[0]  # n by n matrix.
    n, _ = A.shape
    # Require that X and A are PSD.
    X = Variable((2 * n, 2 * n), PSD=True)
    constraints = [PSD(A)]

    # Fix Z as upper triangular
    # TODO represent Z as upper tri vector.
    Z = Variable((n, n))
    Z_lower_tri = upper_tri(transpose(Z))
    constraints.append(Z_lower_tri == 0)

    # Fix diag(D) = diag(Z): D[i, i] = Z[i, i]
    D = Variable(n)
    constraints.append(D == diag_mat(Z))
    # Fix X using the fact that A must be affine by the DCP rules.
    # X[0:n, 0:n] == D
    constraints.append(X[0:n, 0:n] == diag_vec(D))
    # X[0:n, n:2*n] == Z,
    constraints.append(X[0:n, n:2 * n] == Z)
    # X[n:2*n, n:2*n] == A
    constraints.append(X[n:2 * n, n:2 * n] == A)
    # Add the objective sum(log(D[i, i])
    log_expr = log(D)
    obj, constr = log_canon(log_expr, log_expr.args)
    constraints += constr
    return sum(obj), constraints