def simulate_chain(in_prob):
        # Get a ParamConeProg object
        reductions = [Dcp2Cone(), CvxAttr2Constr(), ConeMatrixStuffing()]
        chain = Chain(None, reductions)
        cone_prog, inv_prob2cone = chain.apply(in_prob)

        # Dualize the problem, reconstruct a high-level cvxpy problem for the dual.
        # Solve the problem, invert the dualize reduction.
        solver = ConicSolver()
        cone_prog = solver.format_constraints(cone_prog,
                                              exp_cone_order=[0, 1, 2])
        data, inv_data = a2d.Dualize.apply(cone_prog)
        A, b, c, K_dir = data[s.A], data[s.B], data[s.C], data['K_dir']
        y = cp.Variable(shape=(A.shape[1], ))
        constraints = [A @ y == b]
        i = K_dir[a2d.FREE]
        dual_prims = {a2d.FREE: y[:i], a2d.SOC: []}
        if K_dir[a2d.NONNEG]:
            dim = K_dir[a2d.NONNEG]
            dual_prims[a2d.NONNEG] = y[i:i + dim]
            constraints.append(y[i:i + dim] >= 0)
            i += dim
        for dim in K_dir[a2d.SOC]:
            dual_prims[a2d.SOC].append(y[i:i + dim])
            constraints.append(SOC(y[i], y[i + 1:i + dim]))
            i += dim
        if K_dir[a2d.DUAL_EXP]:
            dual_prims[a2d.DUAL_EXP] = y[i:]
            y_de = cp.reshape(y[i:], ((y.size - i) // 3, 3),
                              order='C')  # fill rows first
            constraints.append(
                ExpCone(-y_de[:, 1], -y_de[:, 0],
                        np.exp(1) * y_de[:, 2]))
        objective = cp.Maximize(c @ y)
        dual_prob = cp.Problem(objective, constraints)
        dual_prob.solve(solver='SCS', eps=1e-8)
        dual_prims[a2d.FREE] = dual_prims[a2d.FREE].value
        if K_dir[a2d.NONNEG]:
            dual_prims[a2d.NONNEG] = dual_prims[a2d.NONNEG].value
        dual_prims[a2d.SOC] = [expr.value for expr in dual_prims[a2d.SOC]]
        if K_dir[a2d.DUAL_EXP]:
            dual_prims[a2d.DUAL_EXP] = dual_prims[a2d.DUAL_EXP].value
        dual_duals = {s.EQ_DUAL: constraints[0].dual_value}
        dual_sol = cp.Solution(dual_prob.status, dual_prob.value, dual_prims,
                               dual_duals, dict())
        cone_sol = a2d.Dualize.invert(dual_sol, inv_data)

        # Pass the solution back up the solving chain.
        in_prob_sol = chain.invert(cone_sol, inv_prob2cone)
        in_prob.unpack(in_prob_sol)
Esempio n. 2
0
    def simulate_chain(in_prob, affine, **solve_kwargs):
        # get a ParamConeProg object
        reductions = [Dcp2Cone(), CvxAttr2Constr(), ConeMatrixStuffing()]
        chain = Chain(None, reductions)
        cone_prog, inv_prob2cone = chain.apply(in_prob)

        # apply the Slacks reduction, reconstruct a high-level problem,
        # solve the problem, invert the reduction.
        cone_prog = ConicSolver().format_constraints(cone_prog,
                                                     exp_cone_order=[0, 1, 2])
        data, inv_data = a2d.Slacks.apply(cone_prog, affine)
        G, h, f, K_dir, K_aff = data[s.A], data[s.B], data[
            s.C], data['K_dir'], data['K_aff']
        G = sp.sparse.csc_matrix(G)
        y = cp.Variable(shape=(G.shape[1], ))
        objective = cp.Minimize(f @ y)
        aff_con = TestSlacks.set_affine_constraints(G, h, y, K_aff)
        dir_con = TestSlacks.set_direct_constraints(y, K_dir)
        int_con = TestSlacks.set_integer_constraints(y, data)
        constraints = aff_con + dir_con + int_con
        slack_prob = cp.Problem(objective, constraints)
        slack_prob.solve(**solve_kwargs)
        slack_prims = {
            a2d.FREE: y[:cone_prog.x.size].value
        }  # nothing else need be populated.
        slack_sol = cp.Solution(slack_prob.status, slack_prob.value,
                                slack_prims, None, dict())
        cone_sol = a2d.Slacks.invert(slack_sol, inv_data)

        # pass solution up the solving chain
        in_prob_sol = chain.invert(cone_sol, inv_prob2cone)
        in_prob.unpack(in_prob_sol)
Esempio n. 3
0
    def apply(self, problem):
        """Returns a new problem and data for inverting the new solution.

        Returns
        -------
        tuple
            (dict of arguments needed for the solver, inverse data)
        """
        data = {}
        inv_data = {self.VAR_ID: problem.variables()[0].id}
        data[s.C], data[s.OFFSET] = ConicSolver.get_coeff_offset(
            problem.objective.args[0])
        data[s.C] = data[s.C].ravel()
        inv_data[s.OFFSET] = data[s.OFFSET][0]

        constr_map = group_constraints(problem.constraints)
        data[ConicSolver.DIMS] = ConeDims(constr_map)

        inv_data[self.EQ_CONSTR] = constr_map[Zero]
        data[s.A], data[s.B] = self.group_coeff_offset(
            problem, constr_map[Zero], ECOS.EXP_CONE_ORDER)

        # Order and group nonlinear constraints.
        neq_constr = constr_map[NonPos] + constr_map[SOC] + constr_map[PSD]
        inv_data[self.NEQ_CONSTR] = neq_constr
        data[s.G], data[s.H] = self.group_coeff_offset(
            problem, neq_constr, ECOS.EXP_CONE_ORDER)

        return data, inv_data
Esempio n. 4
0
    def apply(self, problem):
        """
        Construct QP problem data stored in a dictionary.
        The QP has the following form

            minimize      1/2 x' P x + q' x
            subject to    A x =  b
                          F x <= g

        """
        inverse_data = InverseData(problem)

        obj = problem.objective
        # quadratic part of objective is x.T * P * x but solvers expect
        # 0.5*x.T * P * x.
        P = 2 * obj.expr.args[0].args[1].value
        q = obj.expr.args[1].args[0].value.flatten()

        # Get number of variables
        n = problem.size_metrics.num_scalar_variables

        # TODO(akshayka): This dependence on ConicSolver is hacky; something
        # should change here.
        eq_cons = [c for c in problem.constraints if type(c) == Zero]
        if eq_cons:
            eq_coeffs = list(
                zip(*[
                    ConicSolver.get_coeff_offset(con.expr) for con in eq_cons
                ]))
            A = sp.vstack(eq_coeffs[0])
            b = -np.concatenate(eq_coeffs[1])
        else:
            A, b = sp.csr_matrix((0, n)), -np.array([])

        ineq_cons = [c for c in problem.constraints if type(c) == NonPos]
        if ineq_cons:
            ineq_coeffs = list(
                zip(*[
                    ConicSolver.get_coeff_offset(con.expr) for con in ineq_cons
                ]))
            F = sp.vstack(ineq_coeffs[0])
            g = -np.concatenate(ineq_coeffs[1])
        else:
            F, g = sp.csr_matrix((0, n)), -np.array([])

        # Create dictionary with problem data
        variables = problem.variables()[0]
        data = {}
        data[s.P] = sp.csc_matrix(P)
        data[s.Q] = q
        data[s.A] = sp.csc_matrix(A)
        data[s.B] = b
        data[s.F] = sp.csc_matrix(F)
        data[s.G] = g
        data[s.BOOL_IDX] = [t[0] for t in variables.boolean_idx]
        data[s.INT_IDX] = [t[0] for t in variables.integer_idx]
        data['n_var'] = n
        data['n_eq'] = A.shape[0]
        data['n_ineq'] = F.shape[0]

        inverse_data.sorted_constraints = eq_cons + ineq_cons

        # Add information about integer variables
        inverse_data.is_mip = \
            len(data[s.BOOL_IDX]) > 0 or len(data[s.INT_IDX]) > 0

        return data, inverse_data