def test_socp(self): """Test SOCP problems. """ for solver in self.solvers: # Basic. p = Problem(Minimize(self.b), [pnorm(self.x, p=2) <= self.b]) pmod = Problem(Minimize(self.b), [SOC(self.b, self.x)]) self.assertTrue(ConeMatrixStuffing().accepts(pmod)) p_new = ConeMatrixStuffing().apply(pmod) if not solver.accepts(p_new[0]): return result = p.solve(solver.name()) sltn = solve_wrapper(solver, p_new[0]) self.assertAlmostEqual(sltn.opt_val, result) inv_sltn = ConeMatrixStuffing().invert(sltn, p_new[1]) self.assertAlmostEqual(inv_sltn.opt_val, result) for var in p.variables(): self.assertItemsAlmostEqual(inv_sltn.primal_vars[var.id], var.value) # More complex. p = Problem(Minimize(self.b), [pnorm(self.x/2 + self.y[:2], p=2) <= self.b+5, self.x >= 1, self.y == 5]) pmod = Problem(Minimize(self.b), [SOC(self.b+5, self.x/2 + self.y[:2]), self.x >= 1, self.y == 5]) self.assertTrue(ConeMatrixStuffing().accepts(pmod)) result = p.solve(solver.name()) p_new = ConeMatrixStuffing().apply(pmod) sltn = solve_wrapper(solver, p_new[0]) self.assertAlmostEqual(sltn.opt_val, result, places=2) inv_sltn = ConeMatrixStuffing().invert(sltn, p_new[1]) self.assertAlmostEqual(inv_sltn.opt_val, result, places=2) for var in p.variables(): self.assertItemsAlmostEqual(inv_sltn.primal_vars[var.id], var.value, places=2)
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) """ # TODO use log for n != 2. v = lu.create_var((1, 1)) x = arg_objs[0] y = arg_objs[1] two = lu.create_const(2, (1, 1)) # SOC(x + y, [y - x, 2*v]) constraints = [ SOC(lu.sum_expr([x, y]), [lu.sub_expr(y, x), lu.mul_expr(two, v, (1, 1))]) ] # 0 <= x, 0 <= y constraints += [lu.create_geq(x), lu.create_geq(y)] return (v, constraints)
def soc_canon(expr, real_args, imag_args, real2imag): # Imaginary. if real_args[1] is None: output = [SOC(real_args[0], imag_args[1], axis=expr.axis, constr_id=real2imag[expr.id])] elif imag_args[1] is None: # Real output = [SOC(real_args[0], real_args[1], axis=expr.axis, constr_id=expr.id)] else: # Complex. orig_shape = real_args[1].shape real = real_args[1].flatten() imag = imag_args[1].flatten() flat_X = Variable(real.shape) inner_SOC = SOC(flat_X, vstack([real, imag]), axis=0) real_X = reshape(flat_X, orig_shape) outer_SOC = SOC(real_args[0], real_X, axis=expr.axis, constr_id=expr.id) output = [inner_SOC, outer_SOC] return output, None
def apply(self, problem): inverse_data = InverseData(problem) # Form the constraints extractor = CoeffExtractor(inverse_data) params_to_objective, flattened_variable = self.stuffed_objective( problem, extractor) # Lower equality and inequality to Zero and NonNeg. cons = [] for con in problem.constraints: if isinstance(con, Equality): con = lower_equality(con) elif isinstance(con, Inequality): con = lower_ineq_to_nonneg(con) elif isinstance(con, NonPos): con = nonpos2nonneg(con) elif isinstance(con, SOC) and con.axis == 1: con = SOC(con.args[0], con.args[1].T, axis=0, constr_id=con.constr_id) elif isinstance(con, PowCone3D) and con.args[0].ndim > 1: x, y, z = con.args alpha = con.alpha con = PowCone3D(x.flatten(), y.flatten(), z.flatten(), alpha.flatten(), constr_id=con.constr_id) elif isinstance(con, ExpCone) and con.args[0].ndim > 1: x, y, z = con.args con = ExpCone(x.flatten(), y.flatten(), z.flatten(), constr_id=con.constr_id) cons.append(con) # Reorder constraints to Zero, NonNeg, SOC, PSD, EXP, PowCone3D constr_map = group_constraints(cons) ordered_cons = constr_map[Zero] + constr_map[NonNeg] + \ constr_map[SOC] + constr_map[PSD] + constr_map[ExpCone] + constr_map[PowCone3D] inverse_data.cons_id_map = {con.id: con.id for con in ordered_cons} inverse_data.constraints = ordered_cons # Batch expressions together, then split apart. expr_list = [arg for c in ordered_cons for arg in c.args] params_to_problem_data = extractor.affine(expr_list) inverse_data.minimize = type(problem.objective) == Minimize new_prob = ParamConeProg(params_to_objective, flattened_variable, params_to_problem_data, problem.variables(), inverse_data.var_offsets, ordered_cons, problem.parameters(), inverse_data.param_id_map) return new_prob, inverse_data
def apply(self, problem): inverse_data = InverseData(problem) # Form the constraints extractor = CoeffExtractor(inverse_data) new_obj, new_var, r = self.stuffed_objective(problem, extractor) inverse_data.r = r # Lower equality and inequality to Zero and NonPos. cons = [] for con in problem.constraints: if isinstance(con, Equality): con = lower_equality(con) elif isinstance(con, Inequality): con = lower_inequality(con) elif isinstance(con, SOC) and con.axis == 1: con = SOC(con.args[0], con.args[1].T, axis=0, constr_id=con.constr_id) cons.append(con) # Batch expressions together, then split apart. expr_list = [arg for con in cons for arg in con.args] Afull, bfull = extractor.affine(expr_list) new_cons = [] offset = 0 for con in cons: arg_list = [] for arg in con.args: A = Afull[offset:offset + arg.size, :] b = bfull[offset:offset + arg.size] arg_list.append(reshape(A * new_var + b, arg.shape)) offset += arg.size new_cons.append(con.copy(arg_list)) inverse_data.cons_id_map[con.id] = new_cons[-1].id # Map of old constraint id to new constraint id. inverse_data.minimize = type(problem.objective) == Minimize new_prob = problems.problem.Problem(Minimize(new_obj), new_cons) return new_prob, inverse_data
def apply(self, problem): """Returns a stuffed problem. The returned problem is a minimization problem in which every constraint in the problem has affine arguments that are expressed in the form A @ x + b. Parameters ---------- problem: The problem to stuff; the arguments of every constraint must be affine constraints: A list of constraints, whose arguments are affine Returns ------- Problem The stuffed problem InverseData Data for solution retrieval """ inverse_data = InverseData(problem) # Form the constraints extractor = CoeffExtractor(inverse_data) new_obj, new_var, r = self.stuffed_objective(problem, extractor) inverse_data.r = r # Lower equality and inequality to Zero and NonPos. cons = [] for con in problem.constraints: if isinstance(con, Equality): con = lower_equality(con) elif isinstance(con, Inequality): con = lower_inequality(con) elif isinstance(con, SOC) and con.axis == 1: con = SOC(con.args[0], con.args[1].T, axis=0, constr_id=con.constr_id) cons.append(con) # Batch expressions together, then split apart. expr_list = [arg for c in cons for arg in c.args] Afull, bfull = extractor.affine(expr_list) if 0 not in Afull.shape and 0 not in bfull.shape: Afull = cvxtypes.constant()(Afull) bfull = cvxtypes.constant()(bfull) new_cons = [] offset = 0 for con in cons: arg_list = [] for arg in con.args: A = Afull[offset:offset+arg.size, :] b = bfull[offset:offset+arg.size] arg_list.append(reshape(A*new_var + b, arg.shape)) offset += arg.size new_cons.append(con.copy(arg_list)) # Map old constraint id to new constraint id. inverse_data.cons_id_map[con.id] = new_cons[-1].id inverse_data.minimize = type(problem.objective) == Minimize new_prob = problems.problem.Problem(Minimize(new_obj), new_cons) return new_prob, inverse_data