示例#1
0
    def _add_constraints(self, constraints, sloppy=False):
        super(Model, self)._add_constraints(constraints, sloppy=sloppy)
        for constraint in constraints:
            constraint._problem = None  # This needs to be done in order to not trigger constraint._get_expression()
            glp_add_rows(self.problem, 1)
            index = glp_get_num_rows(self.problem)
            glp_set_row_name(self.problem, index,
                             str(constraint.name).encode())
            num_cols = glp_get_num_cols(self.problem)
            index_array = ffi.new("int[{}]".format(num_cols +
                                                   1))  #intArray(num_cols + 1)
            value_array = ffi.new(
                "double[{}]".format(num_cols + 1))  #doubleArray(num_cols + 1)
            num_vars = 0  # constraint.variables is too expensive for large problems

            offset, coef_dict, _ = parse_optimization_expression(constraint,
                                                                 linear=True)

            num_vars = len(coef_dict)
            for i, (var, coef) in enumerate(coef_dict.items()):
                index_array[i + 1] = var._index
                value_array[i + 1] = float(coef)

            glp_set_mat_row(self.problem, index, num_vars, index_array,
                            value_array)
            constraint._problem = self
            self._glpk_set_row_bounds(constraint)
示例#2
0
 def __init__(self,
              presolve="auto",
              verbosity=0,
              timeout=None,
              *args,
              **kwargs):
     super(Configuration, self).__init__(*args, **kwargs)
     self._smcp = ffi.new("glp_smcp *")
     self._iocp = ffi.new("glp_iocp *")
     glp_init_smcp(self._smcp)
     glp_init_iocp(self._iocp)
     self._max_time = min(self._smcp.tm_lim, self._iocp.tm_lim)
     self.presolve = presolve
     self.verbosity = verbosity
     self.timeout = timeout
示例#3
0
 def get_linear_coefficients(self, variables):
     if self.problem is not None:
         num_cols = glp_get_num_cols(self.problem.problem)
         ia = ffi.new("int[{}]".format(num_cols + 1))
         da = ffi.new("double[{}]".format(num_cols + 1))
         nnz = glp_get_mat_row(self.problem.problem, self._index, ia, da)
         coefs = dict.fromkeys(variables, 0.0)
         coefs.update({
             self.problem._variables[ia[i + 1] - 1]: da[i + 1]
             for i in range(nnz)
             if self.problem._variables[ia[i + 1] - 1] in variables
         })
         return coefs
     else:
         raise Exception(
             "Can't get coefficients from solver if constraint is not in a model"
         )
示例#4
0
 def _get_expression(self):
     if self.problem is not None:
         col_num = glp_get_num_cols(self.problem.problem)
         ia = ffi.new("int[{}]".format(col_num +
                                       1))  # intArray(col_num + 1)
         da = ffi.new("double[{}]".format(col_num +
                                          1))  # doubleArray(col_num + 1)
         nnz = glp_get_mat_row(self.problem.problem, self._index, ia, da)
         constraint_variables = [
             self.problem._variables[glp_get_col_name(
                 self.problem.problem, ia[i])] for i in range(1, nnz + 1)
         ]
         expression = symbolics.add([
             symbolics.mul(
                 (symbolics.Real(da[i]), constraint_variables[i - 1]))
             for i in range(1, nnz + 1)
         ])
         self._expression = expression
     return self._expression
示例#5
0
 def _remove_constraints(self, constraints):
     if len(constraints) > 0:
         constraint_indices = [
             constraint._index for constraint in constraints
         ]
         super(Model, self)._remove_constraints(constraints)
         num = ffi.new("int[{}]".format(len(constraints) +
                                        1))  #intArray(len(constraints) + 1)
         for i, constraint_index in enumerate(constraint_indices):
             num[i + 1] = constraint_index
         glp_del_rows(self.problem, len(constraints), num)
示例#6
0
    def set_linear_coefficients(self, coefficients):
        if self.problem is not None:
            problem = self.problem.problem

            num_cols = glp_get_num_cols(problem)

            ia = ffi.new("int[{}]".format(col_num + 1))
            va = ffi.new("double[{}]".format(col_num + 1))

            num_rows = glp_get_mat_row(self.problem.problem, self._index, ia,
                                       va)
            variables_and_coefficients = {
                var.name: coeff
                for var, coeff in six.iteritems(coefficients)
            }

            final_variables_and_coefficients = {
                glp_get_col_name(problem, ia[i]): va[i]
                for i in range(1, num_rows + 1)
            }
            final_variables_and_coefficients.update(variables_and_coefficients)

            ia = ffi.new("int[{}]".format(col_num + 1))
            va = ffi.new("double[{}]".format(col_num + 1))

            for i, (name, coeff) in enumerate(
                    six.iteritems(final_variables_and_coefficients)):
                ia[i + 1] = self.problem._variables[name]._index
                va[i + 1] = float(coeff)

            glp_set_mat_row(problem, self._index,
                            len(final_variables_and_coefficients), ia, va)
        else:
            raise Exception(
                "Can't change coefficients if constraint is not associated with a model."
            )
示例#7
0
    def _remove_variables(self, variables):
        if len(variables) > 0:
            if len(variables) > 350:
                delete_indices = [
                    variable._index - 1 for variable in variables
                ]
                keep_indices = [
                    i for i in range(0, len(self._variables))
                    if i not in delete_indices
                ]
                self._variables = self._variables.fromkeys(keep_indices)
            else:
                for variable in variables:
                    del self._variables[variable.name]

            num = ffi.new("int[{}]".format(len(variables) +
                                           1))  #intArray(len(variables) + 1)
            for i, variable in enumerate(variables):
                num[i + 1] = variable._index
            glp_del_cols(self.problem, len(variables), num)

            for variable in variables:
                del self._variables_to_constraints_mapping[variable.name]
                variable.problem = None
示例#8
0
    def __init__(self, problem=None, *args, **kwargs):

        super(Model, self).__init__(*args, **kwargs)

        self.configuration = Configuration()

        if problem is None:
            self.problem = glp_create_prob()
            glp_create_index(self.problem)
            if self.name is not None:
                glp_set_prob_name(self.problem, str(self.name).encode())

        else:
            try:
                self.problem = problem
                glp_create_index(self.problem)
            except TypeError:
                raise TypeError("Provided problem is not a valid GLPK model.")
            row_num = glp_get_num_rows(self.problem)
            col_num = glp_get_num_cols(self.problem)
            for i in range(1, col_num + 1):
                var = Variable(glp_get_col_name(self.problem, i),
                               lb=glp_get_col_lb(self.problem, i),
                               ub=glp_get_col_ub(self.problem, i),
                               problem=self,
                               type=_GLPK_VTYPE_TO_VTYPE[glp_get_col_kind(
                                   self.problem, i)])
                # This avoids adding the variable to the glpk problem
                super(Model, self)._add_variables([var])
            variables = self.variables

            for j in range(1, row_num + 1):
                ia = ffi.new("int[{}]".format(col_num + 1))
                da = ffi.new("double[{}]".format(col_num + 1))
                nnz = glp_get_mat_row(self.problem, j, ia, da)
                constraint_variables = [
                    variables[ia[i] - 1] for i in range(1, nnz + 1)
                ]

                # Since constraint expressions are lazily retrieved from the solver they don't have to be built here
                # lhs = _unevaluated_Add(*[da[i] * constraint_variables[i - 1]
                #                         for i in range(1, nnz + 1)])
                lhs = 0

                glpk_row_type = glp_get_row_type(self.problem, j)
                if glpk_row_type == GLP_FX:
                    row_lb = glp_get_row_lb(self.problem, j)
                    row_ub = row_lb
                elif glpk_row_type == GLP_LO:
                    row_lb = glp_get_row_lb(self.problem, j)
                    row_ub = None
                elif glpk_row_type == GLP_UP:
                    row_lb = None
                    row_ub = glp_get_row_ub(self.problem, j)
                elif glpk_row_type == GLP_DB:
                    row_lb = glp_get_row_lb(self.problem, j)
                    row_ub = glp_get_row_ub(self.problem, j)
                elif glpk_row_type == GLP_FR:
                    row_lb = None
                    row_ub = None
                else:
                    raise Exception(
                        "Currently, optlang does not support glpk row type %s"
                        % str(glpk_row_type))
                    log.exception()
                if isinstance(lhs, int):
                    lhs = symbolics.Integer(lhs)
                elif isinstance(lhs, float):
                    lhs = symbolics.Real(lhs)
                constraint_id = glp_get_row_name(self.problem, j)
                for variable in constraint_variables:
                    try:
                        self._variables_to_constraints_mapping[
                            variable.name].add(constraint_id)
                    except KeyError:
                        self._variables_to_constraints_mapping[
                            variable.name] = set([constraint_id])

                super(Model, self)._add_constraints([
                    Constraint(lhs,
                               lb=row_lb,
                               ub=row_ub,
                               name=constraint_id,
                               problem=self,
                               sloppy=True)
                ],
                                                    sloppy=True)

            term_generator = ((glp_get_obj_coef(self.problem,
                                                index), variables[index - 1])
                              for index in range(1,
                                                 glp_get_num_cols(problem) +
                                                 1))
            self._objective = Objective(symbolics.add([
                symbolics.mul((symbolics.Real(term[0]), term[1]))
                for term in term_generator if term[0] != 0.
            ]),
                                        problem=self,
                                        direction={
                                            GLP_MIN: 'min',
                                            GLP_MAX: 'max'
                                        }[glp_get_obj_dir(self.problem)])
        glp_scale_prob(self.problem, GLP_SF_AUTO)