def psd_coeff_offset(problem, c): """ Returns an array "G" and vector "h" such that the given constraint is equivalent to "G * z <=_{PSD} h". :param problem: the cvxpy Problem in which "c" arises. :param c: a cvxpy Constraint defining a linear matrix inequality "B + sum_j A[j] * z[j] >=_{PSD} 0". :return: (G, h) such that "c" holds at "z" iff "G * z <=_{PSD} b" (where the PSD cone is reshaped into a subset of R^N with N = dim ** 2). Note: It is desirable to change this mosek interface so that PSD constraints are represented by a vector in R^N with N = (dim * (dim + 1) / 2). This is possible because arguments to a linear matrix inequality are necessarily symmetric. For now we use N = dim ** 2, because it simplifies implementation and only makes a modest difference in the size of the problem seen by mosek. """ extractor = CoeffExtractor(InverseData(problem)) A_vec, b_vec = extractor.affine(c.expr) G = -A_vec h = b_vec dim = c.expr.shape[0] return G, h, dim
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 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) # Reorder constraints to Zero, NonPos, SOC, PSD, EXP. constr_map = group_constraints(cons) ordered_cons = constr_map[Zero] + constr_map[NonPos] + \ constr_map[SOC] + constr_map[PSD] + constr_map[ExpCone] 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): """See docstring for MatrixStuffing.apply""" inverse_data = InverseData(problem) # Form the constraints extractor = CoeffExtractor(inverse_data) params_to_P, params_to_q, flattened_variable = self.stuffed_objective( problem, extractor) # 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_ineq_to_nonpos(con) cons.append(con) # Reorder constraints to Zero, NonPos. constr_map = group_constraints(cons) ordered_cons = constr_map[Zero] + constr_map[NonPos] 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_Ab = extractor.affine(expr_list) inverse_data.minimize = type(problem.objective) == Minimize new_prob = ParamQuadProg(params_to_P, params_to_q, flattened_variable, params_to_Ab, problem.variables(), inverse_data.var_offsets, ordered_cons, problem.parameters(), inverse_data.param_id_map) 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