Пример #1
0
    def __init__(self, problem=None, *args, **kwargs):

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

        if problem is None:
            self.problem = gurobipy.Model()
            self.problem.params.OutputFlag = 0
            if self.name is not None:
                self.problem.setAttr('ModelName', self.name)
                self.problem.update()

        elif isinstance(problem, gurobipy.Model):
            self.problem = problem
            variables = []
            for gurobi_variable in self.problem.getVars():
                variables.append(Variable(
                    gurobi_variable.getAttr("VarName"),
                    lb=gurobi_variable.getAttr("lb"),
                    ub=gurobi_variable.getAttr("ub"),
                    problem=self,
                    type=_GUROBI_VTYPE_TO_VTYPE[gurobi_variable.getAttr("vType")]
                ))
            super(Model, self)._add_variables(variables)
            constraints = []
            for gurobi_constraint in self.problem.getConstrs():
                sense = gurobi_constraint.Sense
                name = gurobi_constraint.getAttr("ConstrName")
                rhs = gurobi_constraint.RHS
                row = self.problem.getRow(gurobi_constraint)
                lhs = _unevaluated_Add(
                    *[sympy.RealNumber(row.getCoeff(i)) * self.variables[row.getVar(i).VarName] for i in
                      range(row.size())])

                if sense == '=':
                    constraint = Constraint(lhs, name=name, lb=rhs, ub=rhs, problem=self)
                elif sense == '>':
                    constraint = Constraint(lhs, name=name, lb=rhs, ub=None, problem=self)
                elif sense == '<':
                    constraint = Constraint(lhs, name=name, lb=None, ub=rhs, problem=self)
                else:
                    raise ValueError('{} is not a valid sense'.format(sense))
                constraints.append(constraint)
            super(Model, self)._add_constraints(constraints, sloppy=True)

            gurobi_objective = self.problem.getObjective()
            linear_expression = _unevaluated_Add(
                *[sympy.RealNumber(gurobi_objective.getCoeff(i)) * self.variables[gurobi_objective.getVar(i).VarName]
                  for i in range(gurobi_objective.size())])

            self._objective = Objective(
                linear_expression,
                problem=self,
                direction={1: 'min', -1: 'max'}[self.problem.getAttr('ModelSense')]
            )
        else:
            raise TypeError("Provided problem is not a valid Gurobi model.")

        self.configuration = Configuration(problem=self, verbosity=0)
Пример #2
0
    def __init__(self, problem=None, *args, **kwargs):

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

        if problem is None:
            self.problem = gurobipy.Model()
            self.problem.params.OutputFlag = 0
            if self.name is not None:
                self.problem.setAttr('ModelName', self.name)
                self.problem.update()

        elif isinstance(problem, gurobipy.Model):
            self.problem = problem
            variables = []
            for gurobi_variable in self.problem.getVars():
                variables.append(Variable(
                    gurobi_variable.getAttr("VarName"),
                    lb=gurobi_variable.getAttr("lb"),
                    ub=gurobi_variable.getAttr("ub"),
                    problem=self,
                    type=_GUROBI_VTYPE_TO_VTYPE[gurobi_variable.getAttr("vType")]
                ))
            super(Model, self)._add_variables(variables)
            constraints = []
            for gurobi_constraint in self.problem.getConstrs():
                sense = gurobi_constraint.Sense
                name = gurobi_constraint.getAttr("ConstrName")
                rhs = gurobi_constraint.RHS
                row = self.problem.getRow(gurobi_constraint)
                lhs = _unevaluated_Add(
                    *[sympy.RealNumber(row.getCoeff(i)) * self.variables[row.getVar(i).VarName] for i in
                      range(row.size())])

                if sense == '=':
                    constraint = Constraint(lhs, name=name, lb=rhs, ub=rhs, problem=self)
                elif sense == '>':
                    constraint = Constraint(lhs, name=name, lb=rhs, ub=None, problem=self)
                elif sense == '<':
                    constraint = Constraint(lhs, name=name, lb=None, ub=rhs, problem=self)
                else:
                    raise ValueError('{} is not a valid sense'.format(sense))
                constraints.append(constraint)
            super(Model, self)._add_constraints(constraints, sloppy=True)

            gurobi_objective = self.problem.getObjective()
            linear_expression = _unevaluated_Add(
                *[sympy.RealNumber(gurobi_objective.getCoeff(i)) * self.variables[gurobi_objective.getVar(i).VarName]
                  for i in range(gurobi_objective.size())])

            self._objective = Objective(
                linear_expression,
                problem=self,
                direction={1: 'min', -1: 'max'}[self.problem.getAttr('ModelSense')]
            )
        else:
            raise TypeError("Provided problem is not a valid Gurobi model.")

        self.configuration = Configuration(problem=self, verbosity=0)
Пример #3
0
 def _eval_rewrite_as_Add(self, *args, **kwargs):
     """return Equation(L, R) as L - R. To control the evaluation of
     the result set pass `evaluate=True` to give L - R;
     if `evaluate=None` then terms in L and R will not cancel
     but they will be listed in canonical order; otherwise
     non-canonical args will be returned.
     Examples
     ========
     >>> from sympy import Eq, Add
     >>> from sympy.abc import b, x
     >>> eq = Eq(x + b, x - b)
     >>> eq.rewrite(Add)
     2*b
     >>> eq.rewrite(Add, evaluate=None).args
     (b, b, x, -x)
     >>> eq.rewrite(Add, evaluate=False).args
     (b, x, b, -x)
     """
     L, R = args
     evaluate = kwargs.get('evaluate', True)
     if evaluate:
         # allow cancellation of args
         return L - R
     args = Add.make_args(L) + Add.make_args(-R)
     if evaluate is None:
         # no cancellation, but canonical
         return _unevaluated_Add(*args)
     # no cancellation, not canonical
     return Add._from_args(args)
Пример #4
0
def _convert_to_Add(eq, evaluate=True):
    # Mimic Equality._eval_rewrite_as_Add.
    args = eq.lhs, eq.rhs
    L, R = args
    if evaluate:
        # allow cancellation of args
        return L - R
    args = Add.make_args(L) + Add.make_args(-R)
    if evaluate is None:
        # no cancellation, but canonical
        return _unevaluated_Add(*args)
    # no cancellation, not canonical
    return Add._from_args(args)
 def quad_expression_getter(self, quadratic=None):
     if quadratic is None:
         try:
             quadratic = self.LP_Problem.Objective_Obj.get_quadratic()
         except IndexError:
             return Zero
     express_terms = []
     for i, SparsePair_maker in enumerate(quadratic):
         for j, val in zip(SparsePair_maker.ind, SparsePair_maker.val):
             if i < j:
                 express_terms.append(val*self.LP_Vars[i]*self.LP_Vars[j])
             elif i == j:
                 express_terms.append(0.5*val*self.LP_Vars[i]**2)
             else:
                 pass  # Only look at upper triangle for solving
     return _unevaluated_Add(*express_terms)
Пример #6
0
 def _get_quadratic_expression(self, quadratic=None):
     if quadratic is None:
         try:
             quadratic = self.problem.objective.get_quadratic()
         except IndexError:
             return Zero
     terms = []
     for i, sparse_pair in enumerate(quadratic):
         for j, val in zip(sparse_pair.ind, sparse_pair.val):
             if i < j:
                 terms.append(val * self._variables[i] * self._variables[j])
             elif i == j:
                 terms.append(0.5 * val * self._variables[i] ** 2)
             else:
                 pass  # Only look at upper triangle
     return _unevaluated_Add(*terms)
Пример #7
0
 def _get_quadratic_expression(self, quadratic=None):
     if quadratic is None:
         try:
             quadratic = self.problem.objective.get_quadratic()
         except IndexError:
             return Zero
     terms = []
     for i, sparse_pair in enumerate(quadratic):
         for j, val in zip(sparse_pair.ind, sparse_pair.val):
             i_name, j_name = self.problem.variables.get_names([i, j])
             if i < j:
                 terms.append(val * self._variables[i_name] * self._variables[j_name])
             elif i == j:
                 terms.append(0.5 * val * self._variables[i_name] ** 2)
             else:
                 pass  # Only look at upper triangle
     return _unevaluated_Add(*terms)
Пример #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))

        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 = intArray(col_num + 1)
                da = doubleArray(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 = sympy.Integer(lhs)
                elif isinstance(lhs, float):
                    lhs = sympy.RealNumber(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(_unevaluated_Add(*[
                _unevaluated_Mul(sympy.RealNumber(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)
Пример #9
0
    def __init__(self, problem=None, *args, **kwargs):

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

        if problem is None:
            self.problem = cplex.Cplex()

        elif isinstance(problem, cplex.Cplex):
            self.problem = problem
            zipped_var_args = zip(
                self.problem.variables.get_names(),
                self.problem.variables.get_lower_bounds(),
                self.problem.variables.get_upper_bounds(),
                # self.problem.variables.get_types(), # TODO uncomment when cplex is fixed
            )
            for name, lb, ub in zipped_var_args:
                var = Variable(name, lb=lb, ub=ub,
                               problem=self)  # Type should also be in there
                super(Model, self)._add_variables([
                    var
                ])  # This avoids adding the variable to the glpk problem
            zipped_constr_args = zip(
                self.problem.linear_constraints.get_names(),
                self.problem.linear_constraints.get_rows(),
                self.problem.linear_constraints.get_senses(),
                self.problem.linear_constraints.get_rhs())
            variables = self._variables
            for name, row, sense, rhs in zipped_constr_args:
                constraint_variables = [variables[i - 1] for i in row.ind]

                # Since constraint expressions are lazily retrieved from the solver they don't have to be built here
                # lhs = _unevaluated_Add(*[val * variables[i - 1] for i, val in zip(row.ind, row.val)])
                lhs = 0
                if isinstance(lhs, int):
                    lhs = sympy.Integer(lhs)
                elif isinstance(lhs, float):
                    lhs = sympy.RealNumber(lhs)
                if sense == 'E':
                    constr = Constraint(lhs,
                                        lb=rhs,
                                        ub=rhs,
                                        name=name,
                                        problem=self)
                elif sense == 'G':
                    constr = Constraint(lhs, lb=rhs, name=name, problem=self)
                elif sense == 'L':
                    constr = Constraint(lhs, ub=rhs, name=name, problem=self)
                elif sense == 'R':
                    range_val = self.problem.linear_constraints.get_rhs(name)
                    if range_val > 0:
                        constr = Constraint(lhs,
                                            lb=rhs,
                                            ub=rhs + range_val,
                                            name=name,
                                            problem=self)
                    else:
                        constr = Constraint(lhs,
                                            lb=rhs + range_val,
                                            ub=rhs,
                                            name=name,
                                            problem=self)
                else:
                    raise Exception(
                        '%s is not a recognized constraint sense.' % sense)

                for variable in constraint_variables:
                    try:
                        self._variables_to_constraints_mapping[
                            variable.name].add(name)
                    except KeyError:
                        self._variables_to_constraints_mapping[
                            variable.name] = set([name])

                super(Model, self)._add_constraints([constr], sloppy=True)
            try:
                objective_name = self.problem.objective.get_name()
            except cplex.exceptions.CplexSolverError as e:
                if 'CPLEX Error  1219:' not in str(e):
                    raise e
            else:
                linear_expression = _unevaluated_Add(*[
                    _unevaluated_Mul(sympy.RealNumber(coeff), variables[index])
                    for index, coeff in enumerate(
                        self.problem.objective.get_linear()) if coeff != 0.
                ])

                try:
                    quadratic = self.problem.objective.get_quadratic()
                except IndexError:
                    quadratic_expression = Zero
                else:
                    quadratic_expression = self._get_quadratic_expression(
                        quadratic)

                self._objective = Objective(
                    linear_expression + quadratic_expression,
                    problem=self,
                    direction={
                        self.problem.objective.sense.minimize: 'min',
                        self.problem.objective.sense.maximize: 'max'
                    }[self.problem.objective.get_sense()],
                    name=objective_name)
        else:
            raise TypeError("Provided problem is not a valid CPLEX model.")
        self.configuration = Configuration(problem=self, verbosity=0)
Пример #10
0
def collect_const(expr, *vars, Numbers=True):
    """A non-greedy collection of terms with similar number coefficients in
    an Add expr. If ``vars`` is given then only those constants will be
    targeted. Although any Number can also be targeted, if this is not
    desired set ``Numbers=False`` and no Float or Rational will be collected.

    Parameters
    ==========

    expr : sympy expression
        This parameter defines the expression the expression from which
        terms with similar coefficients are to be collected. A non-Add
        expression is returned as it is.

    vars : variable length collection of Numbers, optional
        Specifies the constants to target for collection. Can be multiple in
        number.

    Numbers : bool
        Specifies to target all instance of
        :class:`sympy.core.numbers.Number` class. If ``Numbers=False``, then
        no Float or Rational will be collected.

    Returns
    =======

    expr : Expr
        Returns an expression with similar coefficient terms collected.

    Examples
    ========

    >>> from sympy import sqrt
    >>> from sympy.abc import s, x, y, z
    >>> from sympy.simplify.radsimp import collect_const
    >>> collect_const(sqrt(3) + sqrt(3)*(1 + sqrt(2)))
    sqrt(3)*(sqrt(2) + 2)
    >>> collect_const(sqrt(3)*s + sqrt(7)*s + sqrt(3) + sqrt(7))
    (sqrt(3) + sqrt(7))*(s + 1)
    >>> s = sqrt(2) + 2
    >>> collect_const(sqrt(3)*s + sqrt(3) + sqrt(7)*s + sqrt(7))
    (sqrt(2) + 3)*(sqrt(3) + sqrt(7))
    >>> collect_const(sqrt(3)*s + sqrt(3) + sqrt(7)*s + sqrt(7), sqrt(3))
    sqrt(7) + sqrt(3)*(sqrt(2) + 3) + sqrt(7)*(sqrt(2) + 2)

    The collection is sign-sensitive, giving higher precedence to the
    unsigned values:

    >>> collect_const(x - y - z)
    x - (y + z)
    >>> collect_const(-y - z)
    -(y + z)
    >>> collect_const(2*x - 2*y - 2*z, 2)
    2*(x - y - z)
    >>> collect_const(2*x - 2*y - 2*z, -2)
    2*x - 2*(y + z)

    See Also
    ========

    collect, collect_sqrt, rcollect
    """
    if not expr.is_Add:
        return expr

    recurse = False

    if not vars:
        recurse = True
        vars = set()
        for a in expr.args:
            for m in Mul.make_args(a):
                if m.is_number:
                    vars.add(m)
    else:
        vars = sympify(vars)
    if not Numbers:
        vars = [v for v in vars if not v.is_Number]

    vars = list(ordered(vars))
    for v in vars:
        terms = defaultdict(list)
        Fv = Factors(v)
        for m in Add.make_args(expr):
            f = Factors(m)
            q, r = f.div(Fv)
            if r.is_one:
                # only accept this as a true factor if
                # it didn't change an exponent from an Integer
                # to a non-Integer, e.g. 2/sqrt(2) -> sqrt(2)
                # -- we aren't looking for this sort of change
                fwas = f.factors.copy()
                fnow = q.factors
                if not any(k in fwas and fwas[k].is_Integer and not
                        fnow[k].is_Integer for k in fnow):
                    terms[v].append(q.as_expr())
                    continue
            terms[S.One].append(m)

        args = []
        hit = False
        uneval = False
        for k in ordered(terms):
            v = terms[k]
            if k is S.One:
                args.extend(v)
                continue

            if len(v) > 1:
                v = Add(*v)
                hit = True
                if recurse and v != expr:
                    vars.append(v)
            else:
                v = v[0]

            # be careful not to let uneval become True unless
            # it must be because it's going to be more expensive
            # to rebuild the expression as an unevaluated one
            if Numbers and k.is_Number and v.is_Add:
                args.append(_keep_coeff(k, v, sign=True))
                uneval = True
            else:
                args.append(k*v)

        if hit:
            if uneval:
                expr = _unevaluated_Add(*args)
            else:
                expr = Add(*args)
            if not expr.is_Add:
                break

    return expr
Пример #11
0
    def __init__(self, problem=None, *args, **kwargs):

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

        if problem is None:
            self.problem = cplex.Cplex()

        elif isinstance(problem, cplex.Cplex):
            self.problem = problem
            zipped_var_args = zip(self.problem.variables.get_names(),
                                  self.problem.variables.get_lower_bounds(),
                                  self.problem.variables.get_upper_bounds(),
                                  # self.problem.variables.get_types(), # TODO uncomment when cplex is fixed
                                  )
            for name, lb, ub in zipped_var_args:
                var = Variable(name, lb=lb, ub=ub, problem=self)  # Type should also be in there
                super(Model, self)._add_variables([var])  # This avoids adding the variable to the glpk problem
            zipped_constr_args = zip(self.problem.linear_constraints.get_names(),
                                     self.problem.linear_constraints.get_rows(),
                                     self.problem.linear_constraints.get_senses(),
                                     self.problem.linear_constraints.get_rhs()

                                     )
            variables = self._variables
            for name, row, sense, rhs in zipped_constr_args:
                constraint_variables = [variables[i - 1] for i in row.ind]

                # Since constraint expressions are lazily retrieved from the solver they don't have to be built here
                # lhs = _unevaluated_Add(*[val * variables[i - 1] for i, val in zip(row.ind, row.val)])
                lhs = 0
                if isinstance(lhs, int):
                    lhs = sympy.Integer(lhs)
                elif isinstance(lhs, float):
                    lhs = sympy.RealNumber(lhs)
                if sense == 'E':
                    constr = Constraint(lhs, lb=rhs, ub=rhs, name=name, problem=self)
                elif sense == 'G':
                    constr = Constraint(lhs, lb=rhs, name=name, problem=self)
                elif sense == 'L':
                    constr = Constraint(lhs, ub=rhs, name=name, problem=self)
                elif sense == 'R':
                    range_val = self.problem.linear_constraints.get_rhs(name)
                    if range_val > 0:
                        constr = Constraint(lhs, lb=rhs, ub=rhs + range_val, name=name, problem=self)
                    else:
                        constr = Constraint(lhs, lb=rhs + range_val, ub=rhs, name=name, problem=self)
                else:
                    raise Exception('%s is not a recognized constraint sense.' % sense)

                for variable in constraint_variables:
                    try:
                        self._variables_to_constraints_mapping[variable.name].add(name)
                    except KeyError:
                        self._variables_to_constraints_mapping[variable.name] = set([name])

                super(Model, self)._add_constraints(
                    [constr],
                    sloppy=True
                )
            try:
                objective_name = self.problem.objective.get_name()
            except cplex.exceptions.CplexSolverError as e:
                if 'CPLEX Error  1219:' not in str(e):
                    raise e
            else:
                linear_expression = _unevaluated_Add(
                    *[_unevaluated_Mul(sympy.RealNumber(coeff), variables[index]) for index, coeff in
                      enumerate(self.problem.objective.get_linear()) if coeff != 0.])

                try:
                    quadratic = self.problem.objective.get_quadratic()
                except IndexError:
                    quadratic_expression = Zero
                else:
                    quadratic_expression = self._get_quadratic_expression(quadratic)

                self._objective = Objective(
                    linear_expression + quadratic_expression,
                    problem=self,
                    direction=
                    {self.problem.objective.sense.minimize: 'min', self.problem.objective.sense.maximize: 'max'}[
                        self.problem.objective.get_sense()],
                    name=objective_name
                )
        else:
            raise TypeError("Provided problem is not a valid CPLEX model.")
        self.configuration = Configuration(problem=self, verbosity=0)
Пример #12
0
def collect_const(expr, *vars, **kwargs):
    """A non-greedy collection of terms with similar number coefficients in
    an Add expr. If ``vars`` is given then only those constants will be
    targeted. Although any Number can also be targeted, if this is not
    desired set ``Numbers=False`` and no Float or Rational will be collected.

    Examples
    ========

    >>> from sympy import sqrt
    >>> from sympy.abc import a, s, x, y, z
    >>> from sympy.simplify.radsimp import collect_const
    >>> collect_const(sqrt(3) + sqrt(3)*(1 + sqrt(2)))
    sqrt(3)*(sqrt(2) + 2)
    >>> collect_const(sqrt(3)*s + sqrt(7)*s + sqrt(3) + sqrt(7))
    (sqrt(3) + sqrt(7))*(s + 1)
    >>> s = sqrt(2) + 2
    >>> collect_const(sqrt(3)*s + sqrt(3) + sqrt(7)*s + sqrt(7))
    (sqrt(2) + 3)*(sqrt(3) + sqrt(7))
    >>> collect_const(sqrt(3)*s + sqrt(3) + sqrt(7)*s + sqrt(7), sqrt(3))
    sqrt(7) + sqrt(3)*(sqrt(2) + 3) + sqrt(7)*(sqrt(2) + 2)

    The collection is sign-sensitive, giving higher precedence to the
    unsigned values:

    >>> collect_const(x - y - z)
    x - (y + z)
    >>> collect_const(-y - z)
    -(y + z)
    >>> collect_const(2*x - 2*y - 2*z, 2)
    2*(x - y - z)
    >>> collect_const(2*x - 2*y - 2*z, -2)
    2*x - 2*(y + z)

    See Also
    ========
    collect, collect_sqrt, rcollect
    """
    if not expr.is_Add:
        return expr

    recurse = False
    Numbers = kwargs.get('Numbers', True)

    if not vars:
        recurse = True
        vars = set()
        for a in expr.args:
            for m in Mul.make_args(a):
                if m.is_number:
                    vars.add(m)
    else:
        vars = sympify(vars)
    if not Numbers:
        vars = [v for v in vars if not v.is_Number]

    vars = list(ordered(vars))
    for v in vars:
        terms = defaultdict(list)
        Fv = Factors(v)
        for m in Add.make_args(expr):
            f = Factors(m)
            q, r = f.div(Fv)
            if r.is_one:
                # only accept this as a true factor if
                # it didn't change an exponent from an Integer
                # to a non-Integer, e.g. 2/sqrt(2) -> sqrt(2)
                # -- we aren't looking for this sort of change
                fwas = f.factors.copy()
                fnow = q.factors
                if not any(k in fwas and fwas[k].is_Integer and not
                        fnow[k].is_Integer for k in fnow):
                    terms[v].append(q.as_expr())
                    continue
            terms[S.One].append(m)

        args = []
        hit = False
        uneval = False
        for k in ordered(terms):
            v = terms[k]
            if k is S.One:
                args.extend(v)
                continue

            if len(v) > 1:
                v = Add(*v)
                hit = True
                if recurse and v != expr:
                    vars.append(v)
            else:
                v = v[0]

            # be careful not to let uneval become True unless
            # it must be because it's going to be more expensive
            # to rebuild the expression as an unevaluated one
            if Numbers and k.is_Number and v.is_Add:
                args.append(_keep_coeff(k, v, sign=True))
                uneval = True
            else:
                args.append(k*v)

        if hit:
            if uneval:
                expr = _unevaluated_Add(*args)
            else:
                expr = Add(*args)
            if not expr.is_Add:
                break

    return expr
Пример #13
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))

        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 = intArray(col_num + 1)
                da = doubleArray(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 = sympy.Integer(lhs)
                elif isinstance(lhs, float):
                    lhs = sympy.RealNumber(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(
                _unevaluated_Add(
                    *[_unevaluated_Mul(sympy.RealNumber(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)
    def __init__(self, LP_Problem=None, *args, **kwargs):

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

        if LP_Problem is None:
            self.LP_Problem = cplex.Cplex()

        elif isinstance(LP_Problem, cplex.Cplex):
            self.LP_Problem = LP_Problem
            zipped_var_args = zip(self.LP_Problem.LP_Vars.get_names(),
                                  self.LP_Problem.LP_Vars.get_lower_bounds(),
                                  self.LP_Problem.LP_Vars.get_upper_bounds()
            )
            for name, Lower_Bound, Upper_Bound in zipped_var_args:
                var = Prob_Variable(name, Lower_Bound=Lower_Bound, Upper_Bound=Upper_Bound, LP_Problem=self)
                super(Prob_Model, self).Add_Variable_Prob(var)  # To addtion of the variable to the glpk LP_Problem
            zipped_constr_args = zip(self.LP_Problem.linear_constraints.get_names(),
                                     self.LP_Problem.linear_constraints.get_rows(),
                                     self.LP_Problem.linear_constraints.get_senses(),
                                     self.LP_Problem.linear_constraints.get_rhs()

            )
            LP_Vars = self.LP_Vars
            for name, row, eq_Sense, rhs in zipped_constr_args:
                constraint_variables = [LP_Vars[i - 1] for i in row.ind]
                lhs = _unevaluated_Add(*[val * LP_Vars[i - 1] for i, val in zip(row.ind, row.val)])
                if isinstance(lhs, int):
                    lhs = sympy.Integer(lhs)
                elif isinstance(lhs, float):
                    lhs = sympy.RealNumber(lhs)
                if eq_Sense == 'E':
                    constr = Prob_Constraint(lhs, Lower_Bound=rhs, Upper_Bound=rhs, name=name, LP_Problem=self)
                elif eq_Sense == 'G':
                    constr = Prob_Constraint(lhs, Lower_Bound=rhs, name=name, LP_Problem=self)
                elif eq_Sense == 'L':
                    constr = Prob_Constraint(lhs, Upper_Bound=rhs, name=name, LP_Problem=self)
                elif eq_Sense == 'R':
                    range_val = self.LP_Problem.linear_constraints.get_rhs(name)
                    if range_val > 0:
                        constr = Prob_Constraint(lhs, Lower_Bound=rhs, Upper_Bound=rhs + range_val, name=name, LP_Problem=self)
                    else:
                        constr = Prob_Constraint(lhs, Lower_Bound=rhs + range_val, Upper_Bound=rhs, name=name, LP_Problem=self)
                else:
                    raise Exception('%s is not a known constraint eq_Sense.' % eq_Sense)

                for variable in constraint_variables:
                    try:
                        self.Vars_To_Constr_Map[variable.name].add(name)
                    except KeyError:
                        self.Vars_To_Constr_Map[variable.name] = set([name])

                super(Prob_Model, self).Constraint_Adder(
                    constr,
                    sloppy=True
                )
            try:
                objective_name = self.LP_Problem.Objective_Obj.get_name()
            except cplex.exceptions.CplexSolverError as e:
                if 'CPLEX Error  1219:' not in str(e):
                    raise e
            else:
                linear_expression = _unevaluated_Add(*[_unevaluated_Mul(sympy.RealNumber(coeff), LP_Vars[index]) for index, coeff in
                                       enumerate(self.LP_Problem.Objective_Obj.get_linear()) if coeff != 0.])

                try:
                    quadratic = self.LP_Problem.Objective_Obj.get_quadratic()
                except IndexError:
                    quadratic_expression = Zero
                else:
                    quadratic_expression = self.quad_expression_getter(quadratic)

                self.objective_var = Prob_Objective(
                    linear_expression + quadratic_expression,
                    LP_Problem=self,
                    Max_Or_Min_type={self.LP_Problem.Objective_Obj.eq_Sense.minimize: 'min', self.LP_Problem.Objective_Obj.eq_Sense.maximize: 'max'}[
                        self.LP_Problem.Objective_Obj.get_sense()],
                    name=objective_name
                )
        else:
            raise Exception("the given Problem is not CPLEX model in nature.")
        self.configuration = Prob_Configure(LP_Problem=self, Verbosity_Level=0)