Exemple #1
0
    def test_real(self):
        """Test real.
        """
        A = np.ones((2, 2))
        expr = Constant(A) + 1j * Constant(A)
        expr = cvx.real(expr)
        assert expr.is_real()
        assert not expr.is_complex()
        assert not expr.is_imag()
        self.assertItemsAlmostEqual(expr.value, A)

        x = Variable(complex=True)
        expr = cvx.imag(x) + cvx.real(x)
        assert expr.is_real()
    def test_neg_indices(self):
        """Test negative indices.
        """
        c = Constant([[1, 2], [3, 4]])
        exp = c[-1, -1]
        self.assertEquals(exp.value, 4)
        self.assertEquals(exp.size, (1, 1))
        self.assertEquals(exp.curvature, u.Curvature.CONSTANT_KEY)

        c = Constant([1, 2, 3, 4])
        exp = c[1:-1]
        self.assertItemsAlmostEqual(exp.value, [2, 3])
        self.assertEquals(exp.size, (2, 1))
        self.assertEquals(exp.curvature, u.Curvature.CONSTANT_KEY)
Exemple #3
0
def quad_form_canon(expr, args):
    # TODO this doesn't work with parameters!
    scale, M1, M2 = decomp_quad(args[1].value)
    # Special case where P == 0.
    if M1.size == M2.size == 0:
        return Constant(0), []

    if M1.size > 0:
        expr = sum_squares(Constant(M1.T) @ args[0])
    if M2.size > 0:
        scale = -scale
        expr = sum_squares(Constant(M2.T) @ args[0])
    obj, constr = quad_over_lin_canon(expr, expr.args)
    return scale * obj, constr
Exemple #4
0
    def test_add_expression(self):
        # Vectors
        c = Constant([2,2])
        exp = self.x + c
        self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY)
        self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY)
        self.assertEqual(exp.canonical_form[0].size, (2,1))
        self.assertEqual(exp.canonical_form[1], [])
        # self.assertEqual(exp.name(), self.x.name() + " + " + c.name())
        self.assertEqual(exp.size, (2,1))

        z = Variable(2, name='z')
        exp = exp + z + self.x

        with self.assertRaises(Exception) as cm:
            (self.x + self.y)
        self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 1) (3, 1)")

        # Matrices
        exp = self.A + self.B
        self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY)
        self.assertEqual(exp.size, (2,2))

        with self.assertRaises(Exception) as cm:
            (self.A + self.C)
        self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)")

        with self.assertRaises(Exception) as cm:
            AddExpression([self.A, self.C])
        self.assertEqual(str(cm.exception), "Incompatible dimensions (2, 2) (3, 2)")

        # Test that sum is flattened.
        exp = self.x + c + self.x
        self.assertEqual(len(exp.args), 3)
def norm_inf_canon(expr, args):
    x = args[0]
    axis = expr.axis
    shape = expr.shape
    t = Variable(shape)

    if axis is None:  # shape = (1, 1)
        promoted_t = promote(t, x.shape)
    elif axis == 0:  # shape = (1, n)
        promoted_t = Constant(np.ones(
            (x.shape[0], 1))) * reshape(t, (1, x.shape[1]))
    else:  # shape = (m, 1)
        promoted_t = reshape(t, (x.shape[0], 1)) * Constant(
            np.ones((1, x.shape[1])))

    return t, [x <= promoted_t, x + promoted_t >= 0]
Exemple #6
0
    def test_sub_expression(self):
        # Vectors
        c = Constant([2, 2])
        exp = self.x - c
        self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY)
        self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY)
        self.assertEqual(exp.canonical_form[0].size, (2, 1))
        self.assertEqual(exp.canonical_form[1], [])
        # self.assertEqual(exp.name(), self.x.name() + " - " + Constant([2,2]).name())
        self.assertEqual(exp.size, (2, 1))

        z = Variable(2, name='z')
        exp = exp - z - self.x

        with self.assertRaises(Exception) as cm:
            (self.x - self.y)
        self.assertEqual(str(cm.exception),
                         "Incompatible dimensions (2, 1) (3, 1)")

        # Matrices
        exp = self.A - self.B
        self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY)
        self.assertEqual(exp.size, (2, 2))

        with self.assertRaises(Exception) as cm:
            (self.A - self.C)
        self.assertEqual(str(cm.exception),
                         "Incompatible dimensions (2, 2) (3, 2)")
def test_constant_atoms(atom_info, objective_type) -> None:

    atom, size, args, obj_val = atom_info

    for indexer in get_indices(size):
        for solver in SOLVERS_TO_TRY:
            # Atoms with Constant arguments.
            prob_val = obj_val[indexer].value
            const_args = [Constant(arg) for arg in args]
            problem = Problem(objective_type(atom(*const_args)[indexer]))
            run_atom(atom, problem, prob_val, solver)

            # Atoms with Variable arguments.
            variables = []
            constraints = []
            for idx, expr in enumerate(args):
                variables.append(Variable(intf.shape(expr)))
                constraints.append(variables[-1] == expr)
            objective = objective_type(atom(*variables)[indexer])
            new_obj_val = prob_val
            if objective_type == cp.Maximize:
                objective = -objective
                new_obj_val = -new_obj_val
            problem = Problem(objective, constraints)
            run_atom(atom, problem, new_obj_val, solver)

            # Atoms with Parameter arguments.
            parameters = []
            for expr in args:
                parameters.append(Parameter(intf.shape(expr)))
                parameters[-1].value = intf.DEFAULT_INTF.const_to_matrix(expr)
            objective = objective_type(atom(*parameters)[indexer])
            run_atom(atom, Problem(objective), prob_val, solver)
Exemple #8
0
 def test_constant_copy(self):
     """Test the copy function for Constants.
     """
     x = Constant(2)
     y = x.copy()
     self.assertEquals(y.size, (1, 1))
     self.assertEquals(y.value, 2)
Exemple #9
0
 def canonicalize(self):
     """Represent the atom as an affine objective and conic constraints.
     """
     # Constant atoms are treated as a leaf.
     if self.is_constant():
         # Parameterized expressions are evaluated later.
         if self.parameters():
             param = CallbackParam(lambda: self.value, self.shape)
             return param.canonical_form
         # Non-parameterized expressions are evaluated immediately.
         else:
             return Constant(self.value).canonical_form
     else:
         arg_objs = []
         constraints = []
         for arg in self.args:
             obj, constr = arg.canonical_form
             arg_objs.append(obj)
             constraints += constr
         # Special info required by the graph implementation.
         data = self.get_data()
         graph_obj, graph_constr = self.graph_implementation(arg_objs,
                                                             self.shape,
                                                             data)
         return graph_obj, constraints + graph_constr
Exemple #10
0
 def test_constant_copy(self):
     """Test the copy function for Constants.
     """
     x = Constant(2)
     y = x.copy()
     self.assertEqual(y.shape, tuple())
     self.assertEqual(y.value, 2)
Exemple #11
0
    def test_sub_expression(self):
        # Vectors
        c = Constant([2, 2])
        exp = self.x - c
        self.assertEqual(exp.curvature, s.AFFINE)
        self.assertEqual(exp.sign, s.UNKNOWN)
        # self.assertEqual(exp.canonical_form[0].shape, (2, 1))
        # self.assertEqual(exp.canonical_form[1], [])
        # self.assertEqual(exp.name(), self.x.name() + " - " + Constant([2,2]).name())
        self.assertEqual(exp.shape, (2, ))

        z = Variable(2, name='z')
        exp = exp - z - self.x

        # Incompatible dimensions
        with self.assertRaises(ValueError):
            (self.x - self.y)

        # Matrices
        exp = self.A - self.B
        self.assertEqual(exp.curvature, s.AFFINE)
        self.assertEqual(exp.shape, (2, 2))

        # Incompatible dimensions
        with self.assertRaises(ValueError):
            (self.A - self.C)

        # Test repr.
        self.assertEqual(repr(self.x - c), "Expression(AFFINE, UNKNOWN, (2,))")
Exemple #12
0
    def test_div_expression(self):
        # Vectors
        exp = self.x / 2
        self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY)
        self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY)
        self.assertEqual(exp.canonical_form[0].size, (2, 1))
        self.assertEqual(exp.canonical_form[1], [])
        # self.assertEqual(exp.name(), c.name() + " * " + self.x.name())
        self.assertEqual(exp.size, (2, 1))

        with self.assertRaises(Exception) as cm:
            (self.x / [2, 2, 3])
        print cm.exception
        self.assertEqual(str(cm.exception),
                         "Can only divide by a scalar constant.")

        # Constant expressions.
        c = Constant(2)
        exp = c / (3 - 5)
        self.assertEqual(exp.curvature, u.Curvature.CONSTANT_KEY)
        self.assertEqual(exp.size, (1, 1))
        self.assertEqual(exp.sign, u.Sign.NEGATIVE_KEY)

        # Parameters.
        p = Parameter(sign="positive")
        exp = 2 / p
        p.value = 2
        self.assertEquals(exp.value, 1)
Exemple #13
0
def separable_canon(expr, real_args, imag_args, real2imag):
    """Canonicalize linear functions that are seprable
       in real and imaginary parts.
    """
    if all(val is None for val in imag_args):
        outputs = (expr.copy(real_args), None)
    elif all(val is None for val in real_args):
        outputs = (None, expr.copy(imag_args))
    else:  # Mixed real_args and imaginaries.
        for idx, real_val in enumerate(real_args):
            if real_val is None:
                real_args[idx] = Constant(np.zeros(imag_args[idx].shape))
            elif imag_args[idx] is None:
                imag_args[idx] = Constant(np.zeros(real_args[idx].shape))
        outputs = (expr.copy(real_args), expr.copy(imag_args))
    return outputs
Exemple #14
0
def test_atom():
    for atom_list, objective_type in atoms:
        for atom, size, args, obj_val in atom_list:
            for row in range(size[0]):
                for col in range(size[1]):
                    for solver in SOLVERS_TO_TRY:
                        # Atoms with Constant arguments.
                        const_args = [Constant(arg) for arg in args]
                        yield (run_atom, atom,
                               Problem(
                                   objective_type(atom(*const_args)[row,
                                                                    col])),
                               obj_val[row, col].value, solver)
                        # Atoms with Variable arguments.
                        variables = []
                        constraints = []
                        for idx, expr in enumerate(args):
                            variables.append(Variable(*intf.size(expr)))
                            constraints.append(variables[-1] == expr)
                        objective = objective_type(atom(*variables)[row, col])
                        yield (run_atom, atom, Problem(objective, constraints),
                               obj_val[row, col].value, solver)
                        # Atoms with Parameter arguments.
                        parameters = []
                        for expr in args:
                            parameters.append(Parameter(*intf.size(expr)))
                            parameters[
                                -1].value = intf.DEFAULT_INTF.const_to_matrix(
                                    expr)
                        objective = objective_type(atom(*parameters)[row, col])
                        yield (run_atom, atom, Problem(objective),
                               obj_val[row, col].value, solver)
Exemple #15
0
    def test_matmul_expression(self):
        """Test matmul function, corresponding to .__matmul__( operator.
        """
        # Vectors
        c = Constant([[2], [2]])
        exp = c.__matmul__(self.x)
        self.assertEqual(exp.curvature, s.AFFINE)
        self.assertEqual(exp.sign, s.UNKNOWN)
        # self.assertEqual(exp.name(), c.name() + " .__matmul__( " + self.x.name())
        self.assertEqual(exp.shape, (1, ))

        with self.assertRaises(Exception) as cm:
            self.x.__matmul__(2)
        self.assertEqual(str(cm.exception),
                         "Scalar operands are not allowed, use '*' instead")

        # Incompatible dimensions
        with self.assertRaises(ValueError) as cm:
            (self.x.__matmul__(np.array([2, 2, 3])))

        # Incompatible dimensions
        with self.assertRaises(Exception) as cm:
            Constant([[2, 1], [2, 2]]).__matmul__(self.C)

        # Affine times affine is okay
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            q = self.A.__matmul__(self.B)
            self.assertTrue(q.is_quadratic())

        # # Nonaffine times nonconstant raises error
        # with warnings.catch_warnings():
        #     warnings.simplefilter("ignore")
        #     with self.assertRaises(Exception) as cm:
        #         (self.A.__matmul__(self.B).__matmul__(self.A))
        #     self.assertEqual(str(cm.exception), "Cannot multiply UNKNOWN and AFFINE.")

        # Constant expressions
        T = Constant([[1, 2, 3], [3, 5, 5]])
        exp = (T + T).__matmul__(self.B)
        self.assertEqual(exp.curvature, s.AFFINE)
        self.assertEqual(exp.shape, (3, 2))

        # Expression that would break sign multiplication without promotion.
        c = Constant([[2], [2], [-2]])
        exp = [[1], [2]] + c.__matmul__(self.C)
        self.assertEqual(exp.sign, s.UNKNOWN)
Exemple #16
0
    def apply(self, problem):
        if not attributes_present(problem.variables(), CONVEX_ATTRIBUTES):
            return problem, ()

        # For each unique variable, add constraints.
        id2new_var = {}
        id2new_obj = {}
        id2old_var = {}
        constr = []
        for var in problem.variables():
            if var.id not in id2new_var:
                id2old_var[var.id] = var
                new_var = False
                new_attr = var.attributes.copy()
                for key in CONVEX_ATTRIBUTES:
                    if new_attr[key]:
                        new_var = True
                        new_attr[key] = False

                if attributes_present([var], SYMMETRIC_ATTRIBUTES):
                    n = var.shape[0]
                    shape = (n*(n+1)//2, 1)
                    upper_tri = Variable(shape, var_id=var.id, **new_attr)
                    upper_tri.set_variable_of_provenance(var)
                    id2new_var[var.id] = upper_tri
                    fill_coeff = Constant(upper_tri_to_full(n))
                    full_mat = fill_coeff @ upper_tri
                    obj = reshape(full_mat, (n, n))
                elif var.attributes['diag']:
                    diag_var = Variable(var.shape[0], var_id=var.id, **new_attr)
                    diag_var.set_variable_of_provenance(var)
                    id2new_var[var.id] = diag_var
                    obj = diag(diag_var)
                elif new_var:
                    obj = Variable(var.shape, var_id=var.id, **new_attr)
                    obj.set_variable_of_provenance(var)
                    id2new_var[var.id] = obj
                else:
                    obj = var
                    id2new_var[var.id] = obj

                id2new_obj[id(var)] = obj
                if var.is_pos() or var.is_nonneg():
                    constr.append(obj >= 0)
                elif var.is_neg() or var.is_nonpos():
                    constr.append(obj <= 0)
                elif var.is_psd():
                    constr.append(obj >> 0)
                elif var.attributes['NSD']:
                    constr.append(obj << 0)

        # Create new problem.
        obj = problem.objective.tree_copy(id_objects=id2new_obj)
        cons_id_map = {}
        for cons in problem.constraints:
            constr.append(cons.tree_copy(id_objects=id2new_obj))
            cons_id_map[cons.id] = constr[-1].id
        inverse_data = (id2new_var, id2old_var, cons_id_map)
        return cvxtypes.problem()(obj, constr), inverse_data
Exemple #17
0
def max_canon(expr, args):
    x = args[0]
    shape = expr.shape
    axis = expr.axis
    t = Variable(shape)

    if axis is None:  # shape = (1, 1)
        promoted_t = promote(t, x.shape)
    elif axis == 0:  # shape = (1, n)
        promoted_t = Constant(np.ones((x.shape[0], 1))) * reshape(
                                                            t, (1, x.shape[1]))
    else:  # shape = (m, 1)
        promoted_t = reshape(t, (x.shape[0], 1)) * Constant(
                                                      np.ones((1, x.shape[1])))

    constraints = [x <= promoted_t]
    return t, constraints
Exemple #18
0
    def exp_cone(self):
        """Test exponential cone problems.
        """
        for solver in self.solvers:
            # Basic.
            p = Problem(Minimize(self.b), [exp(self.a) <= self.b, self.a >= 1])
            pmod = Problem(Minimize(self.b),
                           [ExpCone(self.a, Constant(1), self.b), self.a >= 1])
            self.assertTrue(ConeMatrixStuffing().accepts(pmod))
            p_new = ConeMatrixStuffing().apply(pmod)
            if not solver.accepts(p_new[0]):
                return
            result = p.solve(solver.name())
            sltn = solver.solve(p_new[0], False, False, {})
            self.assertAlmostEqual(sltn.opt_val, result, places=1)
            inv_sltn = ConeMatrixStuffing().invert(sltn, p_new[1])
            self.assertAlmostEqual(inv_sltn.opt_val, result, places=1)
            for var in pmod.variables():
                self.assertItemsAlmostEqual(inv_sltn.primal_vars[var.id],
                                            var.value,
                                            places=1)

            # More complex.
            # TODO CVXOPT fails here.
            if solver.name() == 'CVXOPT':
                return
            p = Problem(Minimize(self.b), [
                exp(self.a / 2 + self.c) <= self.b + 5, self.a >= 1,
                self.c >= 5
            ])
            pmod = Problem(Minimize(self.b), [
                ExpCone(self.a / 2 + self.c, Constant(1), self.b + 5),
                self.a >= 1, self.c >= 5
            ])
            self.assertTrue(ConeMatrixStuffing().accepts(pmod))
            result = p.solve(solver.name())
            p_new = ConeMatrixStuffing().apply(pmod)
            sltn = solver.solve(p_new[0], False, False, {})
            self.assertAlmostEqual(sltn.opt_val, result, places=0)
            inv_sltn = ConeMatrixStuffing().invert(sltn, p_new[1])
            self.assertAlmostEqual(inv_sltn.opt_val, result, places=0)
            for var in pmod.variables():
                self.assertItemsAlmostEqual(inv_sltn.primal_vars[var.id],
                                            var.value,
                                            places=0)
Exemple #19
0
    def test_mul_expression(self):
        # Vectors
        c = Constant([[2], [2]])
        exp = c * self.x
        self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY)
        self.assertEqual((c[0] * self.x).sign, u.Sign.UNKNOWN_KEY)
        self.assertEqual(exp.canonical_form[0].size, (1, 1))
        self.assertEqual(exp.canonical_form[1], [])
        # self.assertEqual(exp.name(), c.name() + " * " + self.x.name())
        self.assertEqual(exp.size, (1, 1))

        with self.assertRaises(Exception) as cm:
            ([2, 2, 3] * self.x)
        self.assertEqual(str(cm.exception),
                         "Incompatible dimensions (3, 1) (2, 1)")

        # Matrices
        with self.assertRaises(Exception) as cm:
            Constant([[2, 1], [2, 2]]) * self.C
        self.assertEqual(str(cm.exception),
                         "Incompatible dimensions (2, 2) (3, 2)")

        with self.assertRaises(Exception) as cm:
            (self.A * self.B)
        self.assertEqual(str(cm.exception),
                         "Cannot multiply two non-constants.")

        # Constant expressions
        T = Constant([[1, 2, 3], [3, 5, 5]])
        exp = (T + T) * self.B
        self.assertEqual(exp.curvature, u.Curvature.AFFINE_KEY)
        self.assertEqual(exp.size, (3, 2))

        # Expression that would break sign multiplication without promotion.
        c = Constant([[2], [2], [-2]])
        exp = [[1], [2]] + c * self.C
        self.assertEqual(exp.sign, u.Sign.UNKNOWN_KEY)

        # Scalar constants on the right should be moved left.
        expr = self.C * 2
        self.assertEqual(expr.args[0].value, 2)

        # Scalar variables on the left should be moved right.
        expr = self.a * [2, 1]
        self.assertItemsAlmostEqual(expr.args[0].value, [2, 1])
Exemple #20
0
    def test_constants(self):
        c = Constant(2)
        self.assertEqual(c.name(), str(2))

        c = Constant(2)
        self.assertEqual(c.value, 2)
        self.assertEqual(c.size, (1, 1))
        self.assertEqual(c.curvature, u.Curvature.CONSTANT_KEY)
        self.assertEqual(c.sign, u.Sign.POSITIVE_KEY)
        self.assertEqual(Constant(-2).sign, u.Sign.NEGATIVE_KEY)
        self.assertEqual(Constant(0).sign, u.Sign.ZERO_KEY)
        self.assertEqual(c.canonical_form[0].size, (1, 1))
        self.assertEqual(c.canonical_form[1], [])

        coeffs = c.coefficients()
        self.assertEqual(coeffs.keys(), [s.CONSTANT])
        self.assertEqual(coeffs[s.CONSTANT], [2])

        # Test the sign.
        c = Constant([[2], [2]])
        self.assertEqual(c.size, (1, 2))
        self.assertEqual(c._dcp_attr.sign.neg_mat.shape, (1, 2))

        # Test sign of a complex expression.
        c = Constant([1, 2])
        A = Constant([[1, 1], [1, 1]])
        exp = c.T * A * c
        self.assertEqual(exp.sign, u.Sign.POSITIVE_KEY)
        self.assertEqual((c.T * c).sign, u.Sign.POSITIVE_KEY)
        exp = c.T.T
        self.assertEqual(exp._dcp_attr.sign.pos_mat.shape, (2, 1))
        exp = c.T * self.A
        self.assertEqual(exp._dcp_attr.sign.pos_mat.shape, (1, 2))
def lp_6() -> SolverTestHelper:
    """Test LP with no constraints"""
    x = cp.Variable()
    from cvxpy.expressions.constants import Constant
    objective = cp.Maximize(Constant(0.23) * x)
    obj_pair = (objective, np.inf)
    var_pairs = [(x, None)]
    sth = SolverTestHelper(obj_pair, var_pairs, [])
    return sth
def mi_lp_4() -> SolverTestHelper:
    """Test MI without constraints"""
    x = cp.Variable(boolean=True)
    from cvxpy.expressions.constants import Constant
    objective = cp.Maximize(Constant(0.23) * x)
    obj_pair = (objective, 0.23)
    var_pairs = [(x, 1)]
    sth = SolverTestHelper(obj_pair, var_pairs, [])
    return sth
Exemple #23
0
    def setUp(self):
        self.x = Variable(2, name='x')
        self.y = Variable(2, name='y')

        self.A = Variable(3, 2, name='A')
        self.B = Variable(5, 2, name='B')

        self.C = Constant([[1, 2], [1, 2]])
        self.intf = intf.DEFAULT_INTERFACE
def log_canon(expr, args):
    x = args[0]
    shape = expr.shape
    t = Variable(shape)
    ones = Constant(np.ones(shape))
    # TODO(akshayka): ExpCone requires each of its inputs to be a Variable;
    # is this something that we want to change?
    constraints = [ExpCone(t, ones, x)]
    return t, constraints
Exemple #25
0
    def test_vector_lp(self):
        for solver in self.solvers:
            c = Constant(numpy.array([1, 2]))
            p = Problem(Minimize(c.T * self.x), [self.x >= c])
            result = p.solve(solver.name())
            self.assertTrue(ConeMatrixStuffing().accepts(p))
            p_new = ConeMatrixStuffing().apply(p)
            # result_new = p_new[0].solve(solver.name())
            # self.assertAlmostEqual(result, result_new)
            self.assertTrue(solver.accepts(p_new[0]))
            sltn = solver.solve(p_new[0], False, False, {})
            self.assertAlmostEqual(sltn.opt_val, result)
            inv_sltn = ConeMatrixStuffing().invert(sltn, p_new[1])

            p_new1 = ConeMatrixStuffing().apply(p)
            self.assertTrue(solver.accepts(p_new1[0]))
            sltn = solver.solve(p_new1[0], False, False, {})
            self.assertAlmostEqual(sltn.opt_val, result)
            inv_sltn = ConeMatrixStuffing().invert(sltn, p_new1[1])

            self.assertAlmostEqual(inv_sltn.opt_val, result)
            self.assertItemsAlmostEqual(inv_sltn.primal_vars[self.x.id],
                                        self.x.value)

            A = Constant(numpy.array([[3, 5], [1, 2]]).T).value
            Imat = Constant([[1, 0], [0, 1]])
            p = Problem(Minimize(c.T * self.x + self.a), [
                A * self.x >= [-1, 1], 4 * Imat * self.z == self.x,
                self.z >= [2, 2], self.a >= 2
            ])
            self.assertTrue(ConeMatrixStuffing().accepts(p))
            result = p.solve(solver.name())
            p_new = ConeMatrixStuffing().apply(p)
            result_new = p_new[0].solve(solver.name())
            self.assertAlmostEqual(result, result_new)
            self.assertTrue(solver.accepts(p_new[0]))
            sltn = solver.solve(p_new[0], False, False, {})
            self.assertAlmostEqual(sltn.opt_val, result, places=1)
            inv_sltn = ConeMatrixStuffing().invert(sltn, p_new[1])
            self.assertAlmostEqual(inv_sltn.opt_val, result, places=1)
            for var in p.variables():
                self.assertItemsAlmostEqual(inv_sltn.primal_vars[var.id],
                                            var.value,
                                            places=1)
Exemple #26
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 cvxcore 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 += [Constant(arg.value).canonical_form[0]]
            else:
                fake_args += [lu.create_var(arg.shape, idx)]
                var_offsets[idx] = offset
                offset += arg.size
        var_length = offset
        fake_expr, _ = self.graph_implementation(fake_args, self.shape,
                                                 self.get_data())
        param_to_size = {lo.CONSTANT_ID: 1}
        param_to_col = {lo.CONSTANT_ID: 0}
        # Get the matrix representation of the function.
        canon_mat = canonInterface.get_problem_matrix(
            [fake_expr],
            var_length,
            var_offsets,
            param_to_size,
            param_to_col,
            self.size,
        )
        # HACK TODO TODO convert tensors back to vectors.
        # COO = (V[lo.CONSTANT_ID][0], (J[lo.CONSTANT_ID][0], I[lo.CONSTANT_ID][0]))
        shape = (var_length + 1, self.size)
        stacked_grad = canon_mat.reshape(shape).tocsc()[:-1, :]
        # Break up into per argument matrices.
        grad_list = []
        start = 0
        for arg in self.args:
            if arg.is_constant():
                grad_shape = (arg.size, 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
                grad_list += [stacked_grad[start:stop, :]]
                start = stop
        return grad_list
def entr_canon(expr, args):
    x = args[0]
    shape = expr.shape
    t = Variable(shape)
    # -x\log(x) >= t <=> x\exp(t/x) <= 1
    # TODO(akshayka): ExpCone requires each of its inputs to be a Variable;
    # is this something that we want to change?
    ones = Constant(np.ones(shape))
    constraints = [ExpCone(t, x, ones)]
    return t, constraints
Exemple #28
0
def linearize(expr):
    """Returns an affine approximation to the expression computed at the variable/parameter values.

    Gives an elementwise lower (upper) bound for convex (concave)
    expressions that is tight at the current variable/parameter values.
    No guarantees for non-DCP expressions.

    If f and g are convex, the objective f - g can be (heuristically) minimized using
    the implementation below of the convex-concave method:

    .. code :: python

        for iters in range(N):
            Problem(Minimize(f - linearize(g))).solve()

    Returns None if cannot be linearized.

    Args:
        expr: An expression.

    Returns:
        An affine expression or None.
    """
    expr = Constant.cast_to_const(expr)
    if expr.is_affine():
        return expr
    else:
        tangent = expr.value
        if tangent is None:
            raise ValueError(
                "Cannot linearize non-affine expression with missing variable values."
            )
        grad_map = expr.grad
        for var in expr.variables():
            if grad_map[var] is None:
                return None
            elif var.is_matrix():
                flattened = Constant(grad_map[var]).T * vec(var - var.value)
                tangent = tangent + reshape(flattened, expr.shape)
            else:
                tangent = tangent + Constant(
                    grad_map[var]).T * (var - var.value)
        return tangent
Exemple #29
0
def logistic_canon(expr, args):
    x = args[0]
    shape = expr.shape
    # log(1 + exp(x)) <= t <=> exp(-t) + exp(x - t) <= 1
    t0 = Variable(shape)
    t1, constr1 = exp_canon(expr, [-t0])
    t2, constr2 = exp_canon(expr, [x - t0])
    ones = Constant(np.ones(shape))
    constraints = constr1 + constr2 + [t1 + t2 <= ones]
    return t0, constraints
Exemple #30
0
    def test_logical_indices(self):
        """Test indexing with boolean arrays.
        """
        A = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
        C = Constant(A)

        # Boolean array.
        expr = C[A <= 2]
        self.assertEqual(expr.shape, (2, ))
        self.assertEqual(expr.sign, s.NONNEG)
        self.assertItemsAlmostEqual(A[A <= 2], expr.value)

        expr = C[A % 2 == 0]
        self.assertEqual(expr.shape, (6, ))
        self.assertEqual(expr.sign, s.NONNEG)
        self.assertItemsAlmostEqual(A[A % 2 == 0], expr.value)

        # Boolean array for rows, index for columns.
        expr = C[np.array([True, False, True]), 3]
        self.assertEqual(expr.shape, (2, ))
        self.assertEqual(expr.sign, s.NONNEG)
        self.assertItemsAlmostEqual(A[np.array([True, False, True]), 3],
                                    expr.value)

        # Index for row, boolean array for columns.
        expr = C[1, np.array([True, False, False, True])]
        self.assertEqual(expr.shape, (2, ))
        self.assertEqual(expr.sign, s.NONNEG)
        self.assertItemsAlmostEqual(A[1,
                                      np.array([True, False, False, True])],
                                    expr.value)

        # Boolean array for rows, slice for columns.
        expr = C[np.array([True, True, True]), 1:3]
        self.assertEqual(expr.shape, (3, 2))
        self.assertEqual(expr.sign, s.NONNEG)
        self.assertItemsAlmostEqual(A[np.array([True, True, True]), 1:3],
                                    expr.value)

        # Slice for row, boolean array for columns.
        expr = C[1:-1, np.array([True, False, True, True])]
        self.assertEqual(expr.shape, (1, 3))
        self.assertEqual(expr.sign, s.NONNEG)
        self.assertItemsAlmostEqual(
            A[1:-1, np.array([True, False, True, True])], expr.value)

        # Boolean arrays for rows and columns.
        # Not sure what this does.
        expr = C[np.array([True, True, True]),
                 np.array([True, False, True, True])]
        self.assertEqual(expr.shape, (3, ))
        self.assertEqual(expr.sign, s.NONNEG)
        self.assertItemsAlmostEqual(
            A[np.array([True, True, True]),
              np.array([True, False, True, True])], expr.value)