Exemple #1
0
    def _prepare_data_and_inv_data(self, problem):
        data = {}
        inv_data = {self.VAR_ID: problem.x.id}

        # Format constraints
        #
        # SCS requires constraints to be specified in the following order:
        # 1. zero cone
        # 2. non-negative orthant
        # 3. soc
        # 4. psd
        # 5. exponential
        constr_map = group_constraints(problem.constraints)
        data[ConicSolver.DIMS] = ConeDims(constr_map)
        inv_data[ConicSolver.DIMS] = data[ConicSolver.DIMS]
        zero_constr = constr_map[Zero]
        neq_constr = (constr_map[NonPos] + constr_map[SOC]
                      + constr_map[PSD] + constr_map[ExpCone])
        inv_data[SCS.EQ_CONSTR] = zero_constr
        inv_data[SCS.NEQ_CONSTR] = neq_constr

        if not problem.formatted:
            problem = self.format_constraints(problem, self.EXP_CONE_ORDER)
        data[s.PARAM_PROB] = problem
        return problem, data, inv_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 __init__(self, c, x, A,
                 variables,
                 var_id_to_col,
                 constraints,
                 parameters,
                 param_id_to_col,
                 formatted: bool = False) -> None:
        # The problem data tensors; c is for the constraint, and A for
        # the problem data matrix
        self.c = c
        self.A = A

        # The variable
        self.x = x
        self.reduced_A = None
        self.problem_data_tensor = None
        self._A_mapping_nonzero = None

        self.constraints = constraints
        self.constr_size = sum([c.size for c in constraints])
        self.constr_map = group_constraints(constraints)
        self.cone_dims = ConeDims(self.constr_map)
        self.parameters = parameters
        self.param_id_to_col = param_id_to_col
        self.id_to_param = {p.id: p for p in self.parameters}
        self.param_id_to_size = {p.id: p.size for p in self.parameters}
        self.total_param_size = sum([p.size for p in self.parameters])

        # TODO technically part of inverse data.
        self.variables = variables
        self.var_id_to_col = var_id_to_col
        self.id_to_var = {v.id: v for v in self.variables}

        # whether this param cone prog has been formatted for a solver
        self.formatted = formatted
Exemple #4
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.x.id}

        constr_map = group_constraints(problem.constraints)
        data[ConicSolver.DIMS] = ConeDims(constr_map)
        inv_data[ConicSolver.DIMS] = data[ConicSolver.DIMS]
        len_eq = sum([c.size for c in constr_map[Zero]])
        inv_data[self.EQ_CONSTR] = constr_map[Zero]
        neq_constr = constr_map[NonPos] + constr_map[SOC] + constr_map[PSD]
        inv_data[self.NEQ_CONSTR] = neq_constr

        if not problem.formatted:
            problem = self.format_constraints(problem, ECOS.EXP_CONE_ORDER)
        data[s.PARAM_PROB] = problem

        c, d, A, b = problem.apply_parameters()
        data[s.C] = c
        inv_data[s.OFFSET] = d
        data[s.A] = -A[:len_eq]
        if data[s.A].shape[0] == 0:
            data[s.A] = None
        data[s.B] = b[:len_eq].flatten()
        if data[s.B].shape[0] == 0:
            data[s.B] = None
        data[s.G] = -A[len_eq:]
        data[s.H] = b[len_eq:].flatten()
        return data, inv_data
    def _prepare_data_and_inv_data(self, problem):
        data = {}
        inv_data = {self.VAR_ID: problem.x.id}

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

        # Add information about integer variables
        inv_data[QpSolver.IS_MIP] = problem.is_mixed_integer()

        data[s.PARAM_PROB] = problem
        return problem, data, inv_data
    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 __init__(self,
                 c,
                 x,
                 A,
                 variables,
                 var_id_to_col,
                 constraints,
                 parameters,
                 param_id_to_col,
                 formatted=False):
        # The problem data tensors; c is for the constraint, and A for
        # the problem data matrix
        self.c = c
        self.A = A

        # The variable
        self.x = x

        # Form a reduced representation of A, for faster application of
        # parameters.
        if np.prod(A.shape) != 0:
            reduced_A, indices, indptr, shape = (
                canonInterface.reduce_problem_data_tensor(A, self.x.size))
            self.reduced_A = reduced_A
            self.problem_data_index = (indices, indptr, shape)
        else:
            self.reduced_A = A
            self.problem_data_index = None

        self._A_mapping_nonzero = None

        self.constraints = constraints
        self.constr_size = sum([c.size for c in constraints])
        self.constr_map = group_constraints(constraints)
        self.cone_dims = ConeDims(self.constr_map)
        self.parameters = parameters
        self.param_id_to_col = param_id_to_col
        self.id_to_param = {p.id: p for p in self.parameters}
        self.param_id_to_size = {p.id: p.size for p in self.parameters}
        self.total_param_size = sum([p.size for p in self.parameters])

        # TODO technically part of inverse data.
        self.variables = variables
        self.var_id_to_col = var_id_to_col
        self.id_to_var = {v.id: v for v in self.variables}

        # whether this param cone prog has been formatted for a solver
        self.formatted = formatted
Exemple #8
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.x.id}

        # Format constraints
        #
        # ECOS requires constraints to be specified in the following order:
        # 1. zero cone
        # 2. non-negative orthant
        # 3. soc
        # 4. exponential
        constr_map = group_constraints(problem.constraints)
        data[ConicSolver.DIMS] = ConeDims(constr_map)
        inv_data[ConicSolver.DIMS] = data[ConicSolver.DIMS]
        len_eq = sum([c.size for c in constr_map[Zero]])
        inv_data[self.EQ_CONSTR] = constr_map[Zero]
        neq_constr = constr_map[NonPos] + constr_map[SOC] + constr_map[ExpCone]
        inv_data[self.NEQ_CONSTR] = neq_constr

        if not problem.formatted:
            problem = self.format_constraints(problem, self.EXP_CONE_ORDER)
        data[s.PARAM_PROB] = problem

        c, d, A, b = problem.apply_parameters()
        data[s.C] = c
        inv_data[s.OFFSET] = d
        data[s.A] = -A[:len_eq]
        if data[s.A].shape[0] == 0:
            data[s.A] = None
        data[s.B] = b[:len_eq].flatten()
        if data[s.B].shape[0] == 0:
            data[s.B] = None
        data[s.G] = -A[len_eq:]
        if 0 in data[s.G].shape:
            data[s.G] = None
        data[s.H] = b[len_eq:].flatten()
        if 0 in data[s.H].shape:
            data[s.H] = None
        return data, inv_data
Exemple #9
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.x.id}

        # Format constraints
        #
        # SCS requires constraints to be specified in the following order:
        # 1. zero cone
        # 2. non-negative orthant
        # 3. soc
        # 4. psd
        # 5. exponential
        constr_map = group_constraints(problem.constraints)
        data[ConicSolver.DIMS] = ConeDims(constr_map)
        inv_data[ConicSolver.DIMS] = data[ConicSolver.DIMS]
        zero_constr = constr_map[Zero]
        neq_constr = (constr_map[NonPos] + constr_map[SOC] + constr_map[PSD] +
                      constr_map[ExpCone])
        inv_data[SCS.EQ_CONSTR] = zero_constr
        inv_data[SCS.NEQ_CONSTR] = neq_constr

        if not problem.formatted:
            problem = self.format_constraints(problem, self.EXP_CONE_ORDER)
        data[s.PARAM_PROB] = problem

        # Apply parameter values.
        # Obtain A, b such that Ax + s = b, s \in cones.
        #
        # Note that scs mandates that the cones MUST be ordered with
        # zero cones first, then non-nonnegative orthant, then SOC,
        # then PSD, then exponential.
        c, d, A, b = problem.apply_parameters()
        data[s.C] = c
        inv_data[s.OFFSET] = d
        data[s.A] = -A
        data[s.B] = b
        return data, inv_data
Exemple #10
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.x.id}

        constr_map = group_constraints(problem.constraints)
        data[ConicSolver.DIMS] = ConeDims(constr_map)
        inv_data[ConicSolver.DIMS] = data[ConicSolver.DIMS]
        len_eq = sum([c.size for c in constr_map[Zero]])
        inv_data[self.EQ_CONSTR] = constr_map[Zero]
        neq_constr = constr_map[NonPos] + constr_map[SOC] + constr_map[PSD]
        inv_data[self.NEQ_CONSTR] = neq_constr

        if not problem.formatted:
            problem = self.format_constraints(problem, ECOS.EXP_CONE_ORDER)
        data[s.PARAM_PROB] = problem

        c, d, A, b = problem.apply_parameters()
        data[s.C] = c
        inv_data[s.OFFSET] = d
        data[s.A] = -A[:len_eq]
        if data[s.A].shape[0] == 0:
            data[s.A] = None
        data[s.B] = b[:len_eq].flatten()
        if data[s.B].shape[0] == 0:
            data[s.B] = None
        if len_eq > A.shape[1]:
            # Then the given optimization problem has no conic constraints.
            # This is certainly a degenerate case, but we'll handle it downstream.
            data[s.G] = sp.csc_matrix((1, A.shape[1]))
            data[s.H] = np.array([0])
        else:
            data[s.G] = -A[len_eq:]
            data[s.H] = b[len_eq:].flatten()
        return data, inv_data
Exemple #11
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 = dict()
        var = problem.x
        inv_data = {
            self.VAR_ID: var.id,
            'suc_slacks': [],
            'y_slacks': [],
            'snx_slacks': [],
            'psd_dims': []
        }

        # Get integrality constraint information
        data[s.BOOL_IDX] = [int(t[0]) for t in var.boolean_idx]
        data[s.INT_IDX] = [int(t[0]) for t in var.integer_idx]
        inv_data['integer_variables'] = len(data[s.BOOL_IDX]) + len(
            data[s.INT_IDX]) > 0

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

        if not problem.formatted:
            problem = self.format_constraints(problem, MOSEK.EXP_CONE_ORDER)
        data[s.PARAM_PROB] = problem

        inv_data['constraints'] = problem.constraints

        # A is ordered as [Zero, NonPos, SOC, PSD, EXP]
        c, d, A, b = problem.apply_parameters()
        A = -A
        data[s.C] = c.ravel()
        inv_data['n0'] = len(data[s.C])
        data[s.OBJ_OFFSET] = float(d)
        inv_data[s.OBJ_OFFSET] = float(d)

        Gs = []
        hs = []
        # Linear inequalities
        num_linear_equalities = len(constr_map[Zero])
        num_linear_inequalities = len(constr_map[NonPos])
        leq_dim = data[s.DIMS][s.LEQ_DIM]
        eq_dim = data[s.DIMS][s.EQ_DIM]
        if num_linear_inequalities > 0:
            # G, h : G * z <= h
            offset = num_linear_equalities
            for c in problem.constraints[offset:offset +
                                         num_linear_inequalities]:
                assert (isinstance(c, NonPos))
                inv_data['suc_slacks'].append((c.id, c.size))
            row_offset = eq_dim
            Gs.append(A[row_offset:row_offset + leq_dim])
            hs.append(b[row_offset:row_offset + leq_dim])

        # Linear equations
        if num_linear_equalities > 0:
            for c in problem.constraints[:num_linear_equalities]:
                assert (isinstance(c, Zero))
                inv_data['y_slacks'].append((c.id, c.size))
            Gs.append(A[:eq_dim])
            hs.append(b[:eq_dim])

        # Second order cone
        num_soc = len(constr_map[SOC])
        soc_dim = sum(data[s.DIMS][s.SOC_DIM])
        if num_soc > 0:
            offset = num_linear_inequalities + num_linear_equalities
            for c in problem.constraints[offset:offset + num_soc]:
                assert (isinstance(c, SOC))
                inv_data['snx_slacks'].append((c.id, c.size))
            row_offset = leq_dim + eq_dim
            Gs.append(A[row_offset:row_offset + soc_dim])
            hs.append(b[row_offset:row_offset + soc_dim])

        # Exponential cone
        num_exp = len(constr_map[ExpCone])
        if num_exp > 0:
            # G * z <=_{EXP} h.
            for c in problem.constraints[-num_exp:]:
                assert (isinstance(c, ExpCone))
                inv_data['snx_slacks'].append((c.id, c.num_cones()))
            Gs.append(A[-num_exp:])
            hs.append(b[-num_exp:])

        # PSD constraints
        num_psd = len(constr_map[PSD])
        psd_dim = sum([dim**2 for dim in data[s.DIMS][s.PSD_DIM]])
        if num_psd > 0:
            offset = num_linear_inequalities + num_linear_equalities + num_soc
            for c in problem.constraints[offset:offset + num_psd]:
                assert (isinstance(c, PSD))
                inv_data['psd_dims'].append((c.id, c.expr.shape[0]))
            row_offset = leq_dim + eq_dim + soc_dim
            Gs.append(A[row_offset:row_offset + psd_dim])
            hs.append(b[row_offset:row_offset + psd_dim])

        if Gs:
            data[s.G] = sp.sparse.vstack(tuple(Gs))
        else:
            data[s.G] = sp.sparse.csc_matrix((0, 0))
        if hs:
            data[s.H] = np.hstack(tuple(hs))
        else:
            data[s.H] = np.array([])
        inv_data['is_LP'] = (len(constr_map[PSD]) + len(constr_map[ExpCone]) +
                             len(constr_map[SOC])) == 0

        return data, inv_data
Exemple #12
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 = dict()
        inv_data = dict()
        inv_data[self.VAR_ID] = problem.x.id
        constr_map = group_constraints(problem.constraints)
        data[s.DIMS] = ConeDims(constr_map)
        if not problem.formatted:
            problem = self.format_constraints(problem, exp_cone_order=None)
        c, d, A, b = problem.apply_parameters()
        A = -A
        data[s.C] = c.ravel()
        data[s.OBJ_OFFSET] = float(d)
        inv_data[s.OBJ_OFFSET] = float(d)
        inv_data['lin_dim'] = []
        inv_data['soc_dim'] = []
        Gs = list()
        hs = list()
        # Linear inequalities
        num_linear_eq = len(constr_map[Zero])
        num_linear_leq = len(constr_map[NonPos])
        leq_dim = data[s.DIMS][s.LEQ_DIM]
        eq_dim = data[s.DIMS][s.EQ_DIM]
        if num_linear_leq > 0:
            offset = num_linear_eq
            for con in problem.constraints[offset:offset + num_linear_leq]:
                inv_data['lin_dim'].append((con.id, con.size))
            row_offset = eq_dim
            Gs.append(A[row_offset:row_offset + leq_dim])
            hs.append(b[row_offset:row_offset + leq_dim])
        # Linear equations
        if num_linear_eq > 0:
            for con in problem.constraints[:num_linear_eq]:
                inv_data['lin_dim'].append((con.id, con.size))
            Gs.append(A[:eq_dim])
            hs.append(b[:eq_dim])

        # Second order cones
        num_soc = len(constr_map[SOC])
        soc_dim = sum(data[s.DIMS][s.SOC_DIM])
        if num_soc > 0:
            offset = num_linear_eq + num_linear_leq
            for con in problem.constraints[offset:offset + num_soc]:
                inv_data['soc_dim'].append((con.id, con.size))
            row_offset = leq_dim + eq_dim
            Gs.append(A[row_offset:row_offset + soc_dim])
            hs.append(b[row_offset:row_offset + soc_dim])
        data['nvar'] = len(c) + sum(data[s.DIMS][s.SOC_DIM])
        inv_data['nr'] = len(c)
        if Gs:
            data[s.G] = sp.sparse.vstack(tuple(Gs))
        else:
            data[s.G] = sp.sparse.csc_matrix((0, 0))
        if hs:
            data[s.H] = np.hstack(tuple(hs))
        else:
            data[s.H] = np.array([])
        return (data, inv_data)