Ejemplo n.º 1
0
 def constr_func(aff_obj):
     # Combine the constraints from both sides and add an equality constraint.
     lh_obj, lh_constr = lh_set.canonical_form
     rh_obj, rh_constr = rh_set.canonical_form
     constraints = [lu.create_eq(aff_obj, lh_obj),
                    lu.create_eq(aff_obj, rh_obj),
     ]
     return constraints + lh_constr + rh_constr
Ejemplo n.º 2
0
 def constraints(self):
     obj, constraints = super(BoolVar, self).canonicalize()
     one = lu.create_const(1, (1, 1))
     constraints += [lu.create_geq(obj),
                     lu.create_leq(obj, one)]
     for i in range(self.size[0]):
         row_sum = lu.sum_expr([self[i, j] for j in range(self.size[0])])
         col_sum = lu.sum_expr([self[j, i] for j in range(self.size[0])])
         constraints += [lu.create_eq(row_sum, one),
                         lu.create_eq(col_sum, one)]
     return constraints
Ejemplo n.º 3
0
    def _grad(self, values):
        """Gives the (sub/super)gradient of the atom w.r.t. each argument.

        Matrix expressions are vectorized, so the gradient is a matrix.

        Args:
            values: A list of numeric values for the arguments.

        Returns:
            A list of SciPy CSC sparse matrices or None.
        """
        # TODO should be a simple function in CVXcanon for this.
        # Make a fake lin op tree for the function.
        fake_args = []
        var_offsets = {}
        offset = 0
        for idx, arg in enumerate(self.args):
            fake_args += [lu.create_var(arg.size, idx)]
            var_offsets[idx] = offset
            offset += arg.size[0] * arg.size[1]
        fake_expr, _ = self.graph_implementation(fake_args, self.size,
                                                 self.get_data())
        # Get the matrix representation of the function.
        V, I, J, _ = canonInterface.get_problem_matrix(
            [lu.create_eq(fake_expr)], var_offsets, None)
        shape = (offset, self.size[0] * self.size[1])
        stacked_grad = sp.coo_matrix((V, (J, I)), shape=shape).tocsc()
        # Break up into per argument matrices.
        grad_list = []
        start = 0
        for idx, arg in enumerate(self.args):
            stop = start + arg.size[0] * arg.size[1]
            grad_list += [stacked_grad[start:stop, :]]
            start = stop
        return grad_list
Ejemplo n.º 4
0
 def _get_obj(self, objective, var_offsets, x_length,
              matrix_intf, vec_intf):
     """Wraps _constr_matrix so it can be called for the objective.
     """
     dummy_constr = lu.create_eq(objective)
     return self._constr_matrix([dummy_constr], var_offsets, x_length,
                                matrix_intf, vec_intf)
Ejemplo n.º 5
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]
        n, _ = A.size
        # Requires that A is symmetric.
        # A == A.T
        obj, constraints = transpose.graph_implementation([A], (n, n))
        constraints.append(lu.create_eq(A, obj))
        # SDP constraint.
        t = lu.create_var((1, 1))
        prom_t = lu.promote(t, (n, 1))
        # I*t - A
        expr = lu.sub_expr(lu.diag_vec(prom_t), A)
        return (t, [SDP(expr)] + constraints)
Ejemplo n.º 6
0
    def graph_implementation(self,
                             arg_objs,
                             shape: Tuple[int, ...],
                             data=None) -> Tuple[lo.LinOp, List[Constraint]]:
        """Cumulative sum via difference matrix.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        shape : tuple
            The shape of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # Implicit O(n) definition:
        # X = Y[1:,:] - Y[:-1, :]
        Y = lu.create_var(shape)
        axis = data[0]
        dim = shape[axis]
        diff_mat = get_diff_mat(dim, axis)
        diff_mat = lu.create_const(diff_mat, (dim, dim), sparse=True)
        if axis == 0:
            diff = lu.mul_expr(diff_mat, Y)
        else:
            diff = lu.rmul_expr(Y, diff_mat)
        return (Y, [lu.create_eq(arg_objs[0], diff)])
Ejemplo n.º 7
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]
        n, _ = A.size
        # Requires that A is symmetric.
        obj, constraints = transpose.graph_implementation([A], (n, n))
        # A == A.T
        constraints.append(lu.create_eq(A, obj))
        # SDP constraint.
        t = lu.create_var((1, 1))
        prom_t = lu.promote(t, (n, 1))
        # I*t - A
        expr = lu.sub_expr(A, lu.diag_vec(prom_t))
        return (t, [SDP(expr)] + constraints)
Ejemplo n.º 8
0
    def block_eq(matrix, block, constraints,
                 row_start, row_end, col_start, col_end):
        """Adds an equality setting a section of the matrix equal to block.

        Assumes block does not need to be promoted.

        Parameters
        ----------
        matrix : LinOp
            The matrix in the block equality.
        block : LinOp
            The block in the block equality.
        constraints : list
            A list of constraints to append to.
        row_start : int
            The first row of the matrix section.
        row_end : int
            The last row + 1 of the matrix section.
        col_start : int
            The first column of the matrix section.
        col_end : int
            The last column + 1 of the matrix section.
        """
        key = (slice(row_start, row_end, None),
               slice(col_start, col_end, None))
        rows = row_end - row_start
        cols = col_end - col_start
        assert block.size == (rows, cols)
        slc, idx_constr = index.graph_implementation([matrix],
                                                     (rows, cols),
                                                     [key])
        constraints += [lu.create_eq(slc, block)] + idx_constr
Ejemplo n.º 9
0
    def format(self, eq_constr, leq_constr, dims, solver):
        """Formats EXP constraints for the solver.

        Parameters
        ----------
        eq_constr : list
            A list of the equality constraints in the canonical problem.
        leq_constr : list
            A list of the inequality constraints in the canonical problem.
        dims : dict
            A dict with the dimensions of the conic constraints.
        solver : str
            The solver being called.
        """
        # Need x, y, z to be lone Variables.
        if solver == s.CVXOPT:
            constraints = []
            for i, var in enumerate(self.vars_):
                if not var.type is VARIABLE:
                    lone_var = lu.create_var(var.size)
                    constraints.append(lu.create_eq(lone_var, var))
                    self.vars_[i] = lone_var
            eq_constr += constraints
        # Converts to an inequality constraint.
        elif solver == s.SCS:
            leq_constr += format_elemwise([self.x, self.y, self.z])
        else:
            raise ValueError("Solver does not support exponential cone.")
        # Update dims.
        dims[s.EXP_DIM] += self.size[0]*self.size[1]
Ejemplo n.º 10
0
 def constr_func(aff_obj):
     theta = [lu.create_var((1, 1)) for i in range(len(values))]
     convex_objs = []
     for val, theta_var in zip(values, theta):
         val_aff = val.canonical_form[0]
         convex_objs.append(
             lu.mul_expr(val_aff, theta_var, val_aff.size))
     convex_combo = lu.sum_expr(convex_objs)
     one = lu.create_const(1, (1, 1))
     constraints = [
         lu.create_eq(aff_obj, convex_combo),
         lu.create_eq(lu.sum_expr(theta), one)
     ]
     for theta_var in theta:
         constraints.append(lu.create_geq(theta_var))
     return constraints
Ejemplo n.º 11
0
    def format(self, eq_constr, leq_constr, dims, solver):
        """Formats EXP constraints for the solver.

        Parameters
        ----------
        eq_constr : list
            A list of the equality constraints in the canonical problem.
        leq_constr : list
            A list of the inequality constraints in the canonical problem.
        dims : dict
            A dict with the dimensions of the conic constraints.
        solver : str
            The solver being called.
        """
        # Need x, y, z to be lone Variables.
        if solver == s.CVXOPT:
            constraints = []
            for i, var in enumerate(self.vars_):
                if not var.type is VARIABLE:
                    lone_var = lu.create_var(var.size)
                    constraints.append(lu.create_eq(lone_var, var))
                    self.vars_[i] = lone_var
            eq_constr += constraints
        # Converts to an inequality constraint.
        elif solver == s.SCS:
            leq_constr += format_elemwise([self.x, self.y, self.z])
        else:
            raise ValueError("Solver does not support exponential cone.")
        # Update dims.
        dims[s.EXP_DIM] += self.size[0] * self.size[1]
Ejemplo n.º 12
0
    def __format(self, solver):
        """Internal version of format with cached results.

        Returns
        -------
        tuple
            (equality constraints, inequality constraints)
        """
        eq_constr = []
        leq_constr = []
        # Need x, y, z to be lone Variables.
        if solver == s.CVXOPT:
            constraints = []
            for i, var in enumerate(self.vars_):
                if not var.type is VARIABLE:
                    lone_var = lu.create_var(var.size)
                    constraints.append(lu.create_eq(lone_var, var))
                    self.vars_[i] = lone_var
            eq_constr += constraints
        # Converts to an inequality constraint.
        elif solver == s.SCS:
            leq_constr += format_elemwise([self.x, self.y, self.z])
        else:
            raise SolverError("Solver does not support exponential cone.")
        return (eq_constr, leq_constr)
Ejemplo n.º 13
0
    def block_eq(matrix, block, constraints,
                 row_start, row_end, col_start, col_end):
        """Adds an equality setting a section of the matrix equal to block.

        Assumes block does not need to be promoted.

        Parameters
        ----------
        matrix : LinOp
            The matrix in the block equality.
        block : LinOp
            The block in the block equality.
        constraints : list
            A list of constraints to append to.
        row_start : int
            The first row of the matrix section.
        row_end : int
            The last row + 1 of the matrix section.
        col_start : int
            The first column of the matrix section.
        col_end : int
            The last column + 1 of the matrix section.
        """
        key = (slice(row_start, row_end, None),
               slice(col_start, col_end, None))
        rows = row_end - row_start
        cols = col_end - col_start
        assert block.size == (rows, cols)
        slc, idx_constr = index.graph_implementation([matrix],
                                                     (rows, cols),
                                                     [key])
        constraints += [lu.create_eq(slc, block)] + idx_constr
Ejemplo n.º 14
0
    def graph_implementation(arg_objs, size, data=None):
        """Cumulative sum via difference matrix.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        # Implicit O(n) definition:
        # X = Y[:1,:] - Y[1:,:]
        Y = lu.create_var(size)
        axis = data[0]
        dim = size[axis]
        diff_mat = get_diff_mat(dim, axis)
        diff_mat = lu.create_const(diff_mat, (dim, dim), sparse=True)
        if axis == 0:
            diff = lu.mul_expr(diff_mat, Y, size)
        else:
            diff = lu.rmul_expr(Y, diff_mat, size)
        return (Y, [lu.create_eq(arg_objs[0], diff)])
Ejemplo n.º 15
0
 def _coeffs_affine(self, expr):
     sz = expr.size[0]*expr.size[1]
     s, _ = expr.canonical_form
     V, I, J, R = canonInterface.get_problem_matrix([lu.create_eq(s)], self.id_map)
     Q = sp.csr_matrix((V, (I, J)), shape=(sz, self.N))
     Ps = [sp.csr_matrix((self.N, self.N)) for i in range(sz)]
     return (Ps, Q, R.flatten())
Ejemplo n.º 16
0
 def _get_obj(self, objective, var_offsets, x_length, matrix_intf,
              vec_intf):
     """Wraps _constr_matrix so it can be called for the objective.
     """
     dummy_constr = lu.create_eq(objective)
     return self._constr_matrix([dummy_constr], var_offsets, x_length,
                                matrix_intf, vec_intf)
Ejemplo n.º 17
0
 def __CVXOPT_format(self):
     constraints = []
     for i, var in enumerate(self.vars_):
         if not var.type is VARIABLE:
             lone_var = lu.create_var(var.size)
             constraints.append(lu.create_eq(lone_var, var))
             self.vars_[i] = lone_var
     return (constraints, [])
Ejemplo n.º 18
0
 def _coeffs_affine(self, expr):
     sz = expr.size[0] * expr.size[1]
     s, _ = expr.canonical_form
     V, I, J, R = canonInterface.get_problem_matrix([lu.create_eq(s)],
                                                    self.id_map)
     Q = sp.csr_matrix((V, (I, J)), shape=(sz, self.N))
     Ps = [sp.csr_matrix((self.N, self.N)) for i in range(sz)]
     return (Ps, Q, R.flatten())
Ejemplo n.º 19
0
 def constr_func(aff_obj):
     theta = [lu.create_var((1, 1)) for i in xrange(len(values))]
     convex_objs = []
     for val, theta_var in zip(values, theta):
         val_aff = val.canonical_form[0]
         convex_objs.append(
             lu.mul_expr(val_aff, 
                         theta_var, 
                         val_aff.size)
         )
     convex_combo = lu.sum_expr(convex_objs)
     one = lu.create_const(1, (1, 1))
     constraints = [lu.create_eq(aff_obj, convex_combo),
                    lu.create_eq(lu.sum_expr(theta), one)]
     for theta_var in theta:
         constraints.append(lu.create_geq(theta_var))
     return constraints
Ejemplo n.º 20
0
 def __CVXOPT_format(self):
     constraints = []
     for i, var in enumerate(self.vars_):
         if var.type is not VARIABLE:
             lone_var = lu.create_var(var.size)
             constraints.append(lu.create_eq(lone_var, var))
             self.vars_[i] = lone_var
     return (constraints, [])
Ejemplo n.º 21
0
    def __format(self):
        """Internal version of format with cached results.

        Returns
        -------
        tuple
            (equality constraints, inequality constraints)
        """
        eq_constr = lu.create_eq(self.A, lu.transpose(self.A))
        leq_constr = lu.create_geq(self.A)
        return ([eq_constr], [leq_constr])
Ejemplo n.º 22
0
    def __format(self):
        """Internal version of format with cached results.

        Returns
        -------
        tuple
            (equality constraints, inequality constraints)
        """
        eq_constr = lu.create_eq(self.A, lu.transpose(self.A))
        leq_constr = lu.create_geq(self.A)
        return ([eq_constr], [leq_constr])
Ejemplo n.º 23
0
    def canonicalize(self):
        """Returns the graph implementation of the object.

        Marks the top level constraint as the dual_holder,
        so the dual value will be saved to the EqConstraint.

        Returns:
            A tuple of (affine expression, [constraints]).
        """
        obj, constraints = self._expr.canonical_form
        dual_holder = lu.create_eq(obj, constr_id=self.id)
        return (None, constraints + [dual_holder])
Ejemplo n.º 24
0
 def constr_func(aff_obj):
     G_aff = G.canonical_form[0]
     h_aff = h.canonical_form[0]
     Gx = lu.mul_expr(G_aff, aff_obj, h_aff.size)
     constraints = [lu.create_leq(Gx, h_aff)]
     if A is not None:
         A_const, b_const = map(self.cast_to_const, [A, b])
         A_aff = A_const.canonical_form[0]
         b_aff = b_const.canonical_form[0]
         Ax = lu.mul_expr(A_aff, aff_obj, b_aff.size)
         constraints += [lu.create_eq(Ax, b_aff)]
     return constraints
Ejemplo n.º 25
0
 def constr_func(aff_obj):
     G_aff = G.canonical_form[0]
     h_aff = h.canonical_form[0]
     Gx = lu.mul_expr(G_aff, aff_obj, h_aff.size)
     constraints = [lu.create_leq(Gx, h_aff)]
     if A is not None:
         A_const, b_const = map(self.cast_to_const, [A, b])
         A_aff = A_const.canonical_form[0]
         b_aff = b_const.canonical_form[0]
         Ax = lu.mul_expr(A_aff, aff_obj, b_aff.size)
         constraints += [lu.create_eq(Ax, b_aff)]
     return constraints
Ejemplo n.º 26
0
    def canonicalize(self):
        """Returns the graph implementation of the object.

        Marks the top level constraint as the dual_holder,
        so the dual value will be saved to the EqConstraint.

        Returns:
            A tuple of (affine expression, [constraints]).
        """
        obj, constraints = self._expr.canonical_form
        dual_holder = lu.create_eq(obj, constr_id=self.id)
        return (None, constraints + [dual_holder])
Ejemplo n.º 27
0
    def __format(self):
        """Internal version of format with cached results.

        Returns
        -------
        tuple
            (equality constraints, inequality constraints)
        """
        eq_constr = []
        # If a bool var was created, add an equality constraint.
        if self.noncvx_var != self.lin_op:
            eq_constr += lu.create_eq(self.lin_op, noncvx_var)
        return (eq_constr, [])
Ejemplo n.º 28
0
 def canonicalize(self):
     obj, constraints = super(Assign, self).canonicalize()
     shape = (self.size[1], 1)
     one_row_vec = lu.create_const(np.ones(shape), shape)
     shape = (1, self.size[0])
     one_col_vec = lu.create_const(np.ones(shape), shape)
     # Row sum <= 1
     row_sum = lu.rmul_expr(obj, one_row_vec, (self.size[0], 1))
     constraints += [lu.create_leq(row_sum, lu.transpose(one_col_vec))]
     # Col sum == 1.
     col_sum = lu.mul_expr(one_col_vec, obj, (1, self.size[1]))
     constraints += [lu.create_eq(col_sum, lu.transpose(one_row_vec))]
     return (obj, constraints)
Ejemplo n.º 29
0
    def __format(self):
        """Internal version of format with cached results.

        Returns
        -------
        tuple
            (equality constraints, inequality constraints)
        """
        eq_constr = []
        # If a noncvx var was created, add an equality constraint.
        if self.noncvx_var != self.lin_op:
            eq_constr += lu.create_eq(self.lin_op, self.noncvx_var)
        return (eq_constr, [])
Ejemplo n.º 30
0
 def canonicalize(self):
     obj, constraints = super(Assign, self).canonicalize()
     shape = (self.size[1], 1)
     one_row_vec = lu.create_const(np.ones(shape), shape)
     shape = (1, self.size[0])
     one_col_vec = lu.create_const(np.ones(shape), shape)
     # Row sum <= 1
     row_sum = lu.rmul_expr(obj, one_row_vec, (self.size[0], 1))
     constraints += [lu.create_leq(row_sum, lu.transpose(one_col_vec))]
     # Col sum == 1.
     col_sum = lu.mul_expr(one_col_vec, obj, (1, self.size[1]))
     constraints += [lu.create_eq(col_sum, lu.transpose(one_row_vec))]
     return (obj, constraints)
Ejemplo n.º 31
0
 def test_eq_constr(self):
     """Test creating an equality constraint.
     """
     shape = (5, 5)
     x = create_var(shape)
     y = create_var(shape)
     lh_expr = sum_expr([x, y])
     value = np.ones(shape)
     rh_expr = create_const(value, shape)
     constr = create_eq(lh_expr, rh_expr)
     self.assertEqual(constr.shape, shape)
     vars_ = get_expr_vars(constr.expr)
     ref = [(x.data, shape), (y.data, shape)]
     self.assertCountEqual(vars_, ref)
Ejemplo n.º 32
0
Archivo: cir.py Proyecto: giserh/cvxpy
 def graph_implementation(arg_objs, size, data=None):
     # min 1-sqrt(2z-z^2)
     # s.t. x>=0, z<=1, z = x+s, s<=0
     x = arg_objs[0]
     z = lu.create_var(size)
     s = lu.create_var(size)
     zeros = lu.create_const(np.mat(np.zeros(size)),size)
     ones = lu.create_const(np.mat(np.ones(size)),size)
     z2, constr_square = power.graph_implementation([z],size, (2, (Fraction(1,2), Fraction(1,2))))
     two_z = lu.sum_expr([z,z])
     sub = lu.sub_expr(two_z, z2)
     sq, constr_sqrt = power.graph_implementation([sub],size, (Fraction(1,2), (Fraction(1,2), Fraction(1,2))))
     obj = lu.sub_expr(ones, sq)
     constr = [lu.create_eq(z, lu.sum_expr([x,s]))]+[lu.create_leq(zeros,x)]+[lu.create_leq(z, ones)]+[lu.create_leq(s,zeros)]+constr_square+constr_sqrt
     return (obj, constr)
Ejemplo n.º 33
0
    def _grad(self, values):
        """Gives the (sub/super)gradient of the atom w.r.t. each argument.

        Matrix expressions are vectorized, so the gradient is a matrix.

        Args:
            values: A list of numeric values for the arguments.

        Returns:
            A list of SciPy CSC sparse matrices or None.
        """
        # TODO should be a simple function in CVXcanon for this.
        # Make a fake lin op tree for the function.
        fake_args = []
        var_offsets = {}
        offset = 0
        for idx, arg in enumerate(self.args):
            if arg.is_constant():
                fake_args += [lu.create_const(arg.value, arg.size)]
            else:
                fake_args += [lu.create_var(arg.size, idx)]
                var_offsets[idx] = offset
                offset += arg.size[0]*arg.size[1]
        fake_expr, _ = self.graph_implementation(fake_args, self.size,
                                                 self.get_data())
        # Get the matrix representation of the function.
        V, I, J, _ = canonInterface.get_problem_matrix(
            [lu.create_eq(fake_expr)],
            var_offsets,
            None
        )
        shape = (offset, self.size[0]*self.size[1])
        stacked_grad = sp.coo_matrix((V, (J, I)), shape=shape).tocsc()
        # Break up into per argument matrices.
        grad_list = []
        start = 0
        for arg in self.args:
            if arg.is_constant():
                grad_shape = (arg.size[0]*arg.size[1], shape[1])
                if grad_shape == (1, 1):
                    grad_list += [0]
                else:
                    grad_list += [sp.coo_matrix(grad_shape, dtype='float64')]
            else:
                stop = start + arg.size[0]*arg.size[1]
                grad_list += [stacked_grad[start:stop, :]]
                start = stop
        return grad_list
Ejemplo n.º 34
0
    def graph_implementation(arg_objs, shape, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        minimize n^2 + 2M|s|
        subject to s + n = x

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        shape : tuple
            The shape of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        M = data[0]
        x = arg_objs[0]
        n = lu.create_var(shape)
        s = lu.create_var(shape)
        two = lu.create_const(2, (1, 1))
        if isinstance(M, Parameter):
            M = lu.create_param(M, (1, 1))
        else:  # M is constant.
            M = lu.create_const(M.value, (1, 1))

        # n**2 + 2*M*|s|
        n2, constr_sq = power.graph_implementation(
            [n],
            shape, (2, (Fraction(1, 2), Fraction(1, 2)))
        )
        abs_s, constr_abs = abs.graph_implementation([s], shape)
        M_abs_s = lu.mul_expr(M, abs_s)
        obj = lu.sum_expr([n2, lu.mul_expr(two, M_abs_s)])
        # x == s + n
        constraints = constr_sq + constr_abs
        constraints.append(lu.create_eq(x, lu.sum_expr([n, s])))
        return (obj, constraints)
Ejemplo n.º 35
0
 def graph_implementation(arg_objs, size, data=None):
     # min 1-sqrt(2z-z^2)
     # s.t. x>=0, z<=1, z = x+s, s<=0
     x = arg_objs[0]
     z = lu.create_var(size)
     s = lu.create_var(size)
     zeros = lu.create_const(np.mat(np.zeros(size)), size)
     ones = lu.create_const(np.mat(np.ones(size)), size)
     z2, constr_square = power.graph_implementation(
         [z], size, (2, (Fraction(1, 2), Fraction(1, 2))))
     two_z = lu.sum_expr([z, z])
     sub = lu.sub_expr(two_z, z2)
     sq, constr_sqrt = power.graph_implementation(
         [sub], size, (Fraction(1, 2), (Fraction(1, 2), Fraction(1, 2))))
     obj = lu.sub_expr(ones, sq)
     constr = [lu.create_eq(z, lu.sum_expr([x, s]))] + [
         lu.create_leq(zeros, x)
     ] + [lu.create_leq(z, ones)] + [lu.create_leq(s, zeros)
                                     ] + constr_square + constr_sqrt
     return (obj, constr)
Ejemplo n.º 36
0
    def graph_implementation(arg_objs,size,data=None):
        x = arg_objs[0]
        beta,x0 = data[0],data[1]
        beta_val,x0_val = beta.value,x0.value

        if isinstance(beta,Parameter):
            beta = lu.create_param(beta,(1,1))
        else:
            beta = lu.create_const(beta.value,(1,1))
        if isinstance(x0,Parameter):
            x0 = lu.create_param(x0,(1,1))
        else:
            x0 = lu.create_const(x0.value,(1,1))

        xi,psi = lu.create_var(size),lu.create_var(size)
        one = lu.create_const(1,(1,1))
        one_over_beta = lu.create_const(1/beta_val,(1,1))
        k = np.exp(-beta_val*x0_val)
        k = lu.create_const(k,(1,1))

        # 1/beta * (1 - exp(-beta*(xi+x0)))
        xi_plus_x0 = lu.sum_expr([xi,x0])
        minus_beta_times_xi_plus_x0  = lu.neg_expr(lu.mul_expr(beta,xi_plus_x0,size))
        exp_xi,constr_exp = exp.graph_implementation([minus_beta_times_xi_plus_x0],size)
        minus_exp_minus_etc = lu.neg_expr(exp_xi)
        left_branch = lu.mul_expr(one_over_beta, lu.sum_expr([one,minus_exp_minus_etc]),size)

        # psi*exp(-beta*r0)
        right_branch = lu.mul_expr(k,psi,size)

        obj = lu.sum_expr([left_branch,right_branch])

        #x-x0 == xi + psi, xi >= 0, psi <= 0
        zero = lu.create_const(0,size)
        constraints = constr_exp
        prom_x0 = lu.promote(x0, size)
        constraints.append(lu.create_eq(x,lu.sum_expr([prom_x0,xi,psi])))
        constraints.append(lu.create_geq(xi,zero))
        constraints.append(lu.create_leq(psi,zero))

        return (obj, constraints)
Ejemplo n.º 37
0
    def format(self, eq_constr, leq_constr, dims, solver):
        """Formats SDP constraints as inequalities for the solver.

        Parameters
        ----------
        eq_constr : list
            A list of the equality constraints in the canonical problem.
        leq_constr : list
            A list of the inequality constraints in the canonical problem.
        dims : dict
            A dict with the dimensions of the conic constraints.
        solver : str
            The solver being called.
        """
        # A == A.T
        eq_constr.append(lu.create_eq(self.A, lu.transpose(self.A)))
        # 0 <= A
        leq_constr.append(lu.create_geq(self.A))
        # Update dims.
        dims[s.EQ_DIM] += self.size[0]*self.size[1]
        dims[s.SDP_DIM].append(self.size[0])
Ejemplo n.º 38
0
    def format(self, solver):
        """Formats EXP constraints for the solver.

        Parameters
        ----------
            solver : str
                The solver targetted.
        """
        # Need x, y, z to be lone Variables.
        if solver == s.CVXOPT:
            constraints = []
            for i, var in enumerate(self.vars_):
                if not var.type is VARIABLE:
                    lone_var = lu.create_var(var.size)
                    constraints.append(lu.create_eq(lone_var, var))
                    self.vars_[i] = lone_var
            return constraints
        # Converts to an inequality constraint.
        elif solver == s.SCS:
            return format_elemwise([self.x, self.y, self.z])
        else:
            raise TypeError("Solver does not support exponential cone.")
Ejemplo n.º 39
0
    def affine(self, expr):
        """Extract A, b from an expression that is reducable to A*x + b.

        Parameters
        ----------
        expr : Expression
            The expression to process.

        Returns
        -------
        SciPy CSR matrix
            The coefficient matrix A of shape (np.prod(expr.shape), self.N).
        NumPy.ndarray
            The offset vector b of shape (np.prod(expr.shape,)).
        """
        if not expr.is_affine():
            raise ValueError("Expression is not affine")
        s, _ = expr.canonical_form
        V, I, J, b = canonInterface.get_problem_matrix([lu.create_eq(s)],
                                                       self.id_map)
        A = sp.csr_matrix((V, (I, J)), shape=(expr.size, self.N))
        return A, b.flatten()
Ejemplo n.º 40
0
    def _coeffs_affine_atom(self, expr):
        sz = expr.size[0] * expr.size[1]
        Ps = [sp.lil_matrix((self.N, self.N)) for i in range(sz)]
        Q = sp.lil_matrix((sz, self.N))
        Parg = None
        Qarg = None
        Rarg = None

        fake_args = []
        offsets = {}
        offset = 0
        for idx, arg in enumerate(expr.args):
            if arg.is_constant():
                fake_args += [lu.create_const(arg.value, arg.size)]
            else:
                if Parg is None:
                    (Parg, Qarg, Rarg) = self.get_coeffs(arg)
                else:
                    (p, q, r) = self.get_coeffs(arg)
                    Parg += p
                    Qarg = sp.vstack([Qarg, q])
                    Rarg = np.concatenate([Rarg, r])
                fake_args += [lu.create_var(arg.size, idx)]
                offsets[idx] = offset
                offset += arg.size[0] * arg.size[1]
        fake_expr, _ = expr.graph_implementation(fake_args, expr.size,
                                                 expr.get_data())
        # Get the matrix representation of the function.
        V, I, J, R = canonInterface.get_problem_matrix(
            [lu.create_eq(fake_expr)], offsets)
        R = R.flatten()
        # return "AX+b"
        for (v, i, j) in zip(V, I.astype(int), J.astype(int)):
            Ps[i] += v * Parg[j]
            Q[i, :] += v * Qarg[j, :]
            R[i] += v * Rarg[j]

        Ps = [P.tocsr() for P in Ps]
        return (Ps, Q.tocsr(), R)
Ejemplo n.º 41
0
    def graph_implementation(arg_objs, size, data=None):
        """Reduces the atom to an affine expression and list of constraints.

        minimize n^2 + 2M|s|
        subject to s + n = x

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        M = data
        x = arg_objs[0]
        n = lu.create_var(size)
        s = lu.create_var(size)
        two = lu.create_const(2, (1, 1))
        if isinstance(M, Parameter):
            M = lu.create_param(M, (1, 1))
        else: # M is constant.
            M = lu.create_const(M.value, (1, 1))

        # n**2 + 2*M*|s|
        n2, constr_sq = square.graph_implementation([n], size)
        abs_s, constr_abs = abs.graph_implementation([s], size)
        M_abs_s = lu.mul_expr(M, abs_s, size)
        obj = lu.sum_expr([n2, lu.mul_expr(two, M_abs_s, size)])
        # x == s + n
        constraints = constr_sq + constr_abs
        constraints.append(lu.create_eq(x, lu.sum_expr([n, s])))
        return (obj, constraints)
Ejemplo n.º 42
0
    def _coeffs_affine_atom(self, expr):
        sz = expr.size[0]*expr.size[1]
        Ps = [sp.lil_matrix((self.N, self.N)) for i in range(sz)]
        Q = sp.lil_matrix((sz, self.N))
        Parg = None
        Qarg = None
        Rarg = None

        fake_args = []
        offsets = {}
        offset = 0
        for idx, arg in enumerate(expr.args):
            if arg.is_constant():
                fake_args += [lu.create_const(arg.value, arg.size)]
            else:
                if Parg is None:
                    (Parg, Qarg, Rarg) = self.get_coeffs(arg)
                else:
                    (p, q, r) = self.get_coeffs(arg)
                    Parg += p
                    Qarg = sp.vstack([Qarg, q])
                    Rarg = np.vstack([Rarg, r])
                fake_args += [lu.create_var(arg.size, idx)]
                offsets[idx] = offset
                offset += arg.size[0]*arg.size[1]
        fake_expr, _ = expr.graph_implementation(fake_args, expr.size, expr.get_data())
        # Get the matrix representation of the function.
        V, I, J, R = canonInterface.get_problem_matrix([lu.create_eq(fake_expr)], offsets)
        R = R.flatten()
        # return "AX+b"
        for (v, i, j) in zip(V, I.astype(int), J.astype(int)):
            Ps[i] += v*Parg[j]
            Q[i, :] += v*Qarg[j, :]
            R[i] += v*Rarg[j]

        Ps = [P.tocsr() for P in Ps]        
        return (Ps, Q.tocsr(), R)
Ejemplo n.º 43
0
    def graph_implementation(arg_objs, size, data=None):
        """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
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]  # n by n matrix.
        n, _ = A.size
        X = lu.create_var((2 * n, 2 * n))
        Z = lu.create_var((n, n))
        D = lu.create_var((n, n))
        # Require that X is symmetric (which implies
        # A is symmetric).
        # X == X.T
        obj, constraints = transpose.graph_implementation([X], (n, n))
        constraints.append(lu.create_eq(X, obj))
        # Require that X and A are PSD.
        constraints += [SDP(X), SDP(A)]
        # Fix Z as upper triangular, D as diagonal,
        # and diag(D) as diag(Z).
        for i in xrange(n):
            for j in xrange(n):
                if i == j:
                    # D[i, j] == Z[i, j]
                    Dij = index.get_index(D, constraints, i, j)
                    Zij = index.get_index(Z, constraints, i, j)
                    constraints.append(lu.create_eq(Dij, Zij))
                if i != j:
                    # D[i, j] == 0
                    Dij = index.get_index(D, constraints, i, j)
                    constraints.append(lu.create_eq(Dij))
                if i > j:
                    # Z[i, j] == 0
                    Zij = index.get_index(Z, constraints, i, j)
                    constraints.append(lu.create_eq(Zij))
        # Fix X using the fact that A must be affine by the DCP rules.
        # X[0:n, 0:n] == D
        index.block_eq(X, D, constraints, 0, n, 0, n)
        # X[0:n, n:2*n] == Z,
        index.block_eq(X, Z, constraints, 0, n, n, 2 * n)
        # X[n:2*n, n:2*n] == A
        index.block_eq(X, A, constraints, n, 2 * n, n, 2 * n)
        # Add the objective sum(log(D[i, i])
        log_diag = []
        for i in xrange(n):
            Dii = index.get_index(D, constraints, i, i)
            obj, constr = log.graph_implementation([Dii], (1, 1))
            constraints += constr
            log_diag.append(obj)
        obj = lu.sum_expr(log_diag)
        return (obj, constraints)
Ejemplo n.º 44
0
 def _dummy_constr(self):
     """Returns a dummy constraint for the objective.
     """
     return [lu.create_eq(self.sym_data.objective)]
Ejemplo n.º 45
0
    def graph_implementation(arg_objs, size, data=None):
        """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
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]  # n by n matrix.
        n, _ = A.size
        X = lu.create_var((2 * n, 2 * n))
        Z = lu.create_var((n, n))
        D = lu.create_var((n, n))
        # Require that X is symmetric (which implies
        # A is symmetric).
        # X == X.T
        obj, constraints = transpose.graph_implementation([X], (n, n))
        constraints.append(lu.create_eq(X, obj))
        # Require that X and A are PSD.
        constraints += [SDP(X), SDP(A)]
        # Fix Z as upper triangular, D as diagonal,
        # and diag(D) as diag(Z).
        for i in xrange(n):
            for j in xrange(n):
                if i == j:
                    # D[i, j] == Z[i, j]
                    Dij = index.get_index(D, constraints, i, j)
                    Zij = index.get_index(Z, constraints, i, j)
                    constraints.append(lu.create_eq(Dij, Zij))
                if i != j:
                    # D[i, j] == 0
                    Dij = index.get_index(D, constraints, i, j)
                    constraints.append(lu.create_eq(Dij))
                if i > j:
                    # Z[i, j] == 0
                    Zij = index.get_index(Z, constraints, i, j)
                    constraints.append(lu.create_eq(Zij))
        # Fix X using the fact that A must be affine by the DCP rules.
        # X[0:n, 0:n] == D
        index.block_eq(X, D, constraints, 0, n, 0, n)
        # X[0:n, n:2*n] == Z,
        index.block_eq(X, Z, constraints, 0, n, n, 2 * n)
        # X[n:2*n, n:2*n] == A
        index.block_eq(X, A, constraints, n, 2 * n, n, 2 * n)
        # Add the objective sum(log(D[i, i])
        log_diag = []
        for i in xrange(n):
            Dii = index.get_index(D, constraints, i, i)
            obj, constr = log.graph_implementation([Dii], (1, 1))
            constraints += constr
            log_diag.append(obj)
        obj = lu.sum_expr(log_diag)
        return (obj, constraints)
Ejemplo n.º 46
0
 def _get_eq_constr(self):
     """Returns the equality constraints for the SDP constraint.
     """
     upper_tri = lu.upper_tri(self.A)
     lower_tri = lu.upper_tri(lu.transpose(self.A))
     return lu.create_eq(upper_tri, lower_tri)
Ejemplo n.º 47
0
    def graph_implementation(arg_objs, size, data=None):
        """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
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0]  # n by n matrix.
        n, _ = A.size
        X = lu.create_var((2 * n, 2 * n))
        X, constraints = Semidef(2 * n).canonical_form
        Z = lu.create_var((n, n))
        D = lu.create_var((n, 1))
        # Require that X and A are PSD.
        constraints += [SDP(A)]
        # Fix Z as upper triangular, D as diagonal,
        # and diag(D) as diag(Z).
        Z_lower_tri = lu.upper_tri(lu.transpose(Z))
        constraints.append(lu.create_eq(Z_lower_tri))
        # D[i, i] = Z[i, i]
        constraints.append(lu.create_eq(D, lu.diag_mat(Z)))
        # Fix X using the fact that A must be affine by the DCP rules.
        # X[0:n, 0:n] == D
        index.block_eq(X, lu.diag_vec(D), constraints, 0, n, 0, n)
        # X[0:n, n:2*n] == Z,
        index.block_eq(X, Z, constraints, 0, n, n, 2 * n)
        # X[n:2*n, n:2*n] == A
        index.block_eq(X, A, constraints, n, 2 * n, n, 2 * n)
        # Add the objective sum(log(D[i, i])
        obj, constr = log.graph_implementation([D], (n, 1))
        return (lu.sum_entries(obj), constraints + constr)
Ejemplo n.º 48
0
    def graph_implementation(arg_objs, size, data=None):
        r"""Reduces the atom to an affine expression and list of constraints.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)

        Notes
        -----

        Implementation notes.

        - For general :math:`p \geq 1`, the inequality :math:`\|x\|_p \leq t`
          is equivalent to the following convex inequalities:

          .. math::

              |x_i| &\leq r_i^{1/p} t^{1 - 1/p}\\
              \sum_i r_i &= t.

          These inequalities happen to also be correct for :math:`p = +\infty`,
          if we interpret :math:`1/\infty` as :math:`0`.

        - For general :math:`0 < p < 1`, the inequality :math:`\|x\|_p \geq t`
          is equivalent to the following convex inequalities:

          .. math::

              r_i &\leq x_i^{p} t^{1 - p}\\
              \sum_i r_i &= t.

        - For general :math:`p < 0`, the inequality :math:`\|x\|_p \geq t`
          is equivalent to the following convex inequalities:

          .. math::

              t &\leq x_i^{-p/(1-p)} r_i^{1/(1 - p)}\\
              \sum_i r_i &= t.




        Although the inequalities above are correct, for a few special cases, we can represent the p-norm
        more efficiently and with fewer variables and inequalities.

        - For :math:`p = 1`, we use the representation

            .. math::

                x_i &\leq r_i\\
                -x_i &\leq r_i\\
                \sum_i r_i &= t

        - For :math:`p = \infty`, we use the representation

            .. math::

                x_i &\leq t\\
                -x_i &\leq t

          Note that we don't need the :math:`r` variable or the sum inequality.

        - For :math:`p = 2`, we use the natural second-order cone representation

            .. math::

                \|x\|_2 \leq t

          Note that we could have used the set of inequalities given above if we wanted an alternate decomposition
          of a large second-order cone into into several smaller inequalities.

        """
        p = data[0]
        x = arg_objs[0]
        t = lu.create_var((1, 1))
        constraints = []

        # first, take care of the special cases of p = 2, inf, and 1
        if p == 2:
            return t, [SOC(t, [x])]

        if p == np.inf:
            t_ = lu.promote(t, x.size)
            return t, [lu.create_leq(x, t_), lu.create_geq(lu.sum_expr([x, t_]))]

        # we need an absolute value constraint for the symmetric convex branches (p >= 1)
        # we alias |x| as x from this point forward to make the code pretty :)
        if p >= 1:
            absx = lu.create_var(x.size)
            constraints += [lu.create_leq(x, absx), lu.create_geq(lu.sum_expr([x, absx]))]
            x = absx

        if p == 1:
            return lu.sum_entries(x), constraints

        # now, we take care of the remaining convex and concave branches
        # to create the rational powers, we need a new variable, r, and
        # the constraint sum(r) == t
        r = lu.create_var(x.size)
        t_ = lu.promote(t, x.size)
        constraints += [lu.create_eq(lu.sum_entries(r), t)]

        # make p a fraction so that the input weight to gm_constrs
        # is a nice tuple of fractions.
        p = Fraction(p)
        if p < 0:
            constraints += gm_constrs(t_, [x, r], (-p / (1 - p), 1 / (1 - p)))
        if 0 < p < 1:
            constraints += gm_constrs(r, [x, t_], (p, 1 - p))
        if p > 1:
            constraints += gm_constrs(x, [r, t_], (1 / p, 1 - 1 / p))

        return t, constraints
Ejemplo n.º 49
0
    def graph_implementation(arg_objs, size, data=None):
        """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
        ----------
        arg_objs : list
            LinExpr for each argument.
        size : tuple
            The size of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        """
        A = arg_objs[0] # n by n matrix.
        n, _ = A.size
        X = lu.create_var((2*n, 2*n))
        Z = lu.create_var((n, n))
        D = lu.create_var((n, 1))
        # Require that X and A are PSD.
        constraints = [SDP(X), SDP(A)]
        # Fix Z as upper triangular, D as diagonal,
        # and diag(D) as diag(Z).
        Z_lower_tri = lu.upper_tri(lu.transpose(Z))
        constraints.append(lu.create_eq(Z_lower_tri))
        # D[i, i] = Z[i, i]
        constraints.append(lu.create_eq(D, lu.diag_mat(Z)))
        # Fix X using the fact that A must be affine by the DCP rules.
        # X[0:n, 0:n] == D
        index.block_eq(X, lu.diag_vec(D), constraints, 0, n, 0, n)
        # X[0:n, n:2*n] == Z,
        index.block_eq(X, Z, constraints, 0, n, n, 2*n)
        # X[n:2*n, n:2*n] == A
        index.block_eq(X, A, constraints, n, 2*n, n, 2*n)
        # Add the objective sum(log(D[i, i])
        obj, constr = log.graph_implementation([D], (n, 1))
        return (lu.sum_entries(obj), constraints + constr)
Ejemplo n.º 50
0
 def _dummy_constr(self):
     """Returns a dummy constraint for the objective.
     """
     return [lu.create_eq(self.sym_data.objective)]