Ticket #8672: trac_8672.patch

File trac_8672.patch, 5.1 KB (added by ncohen, 11 years ago)
  • sage/numerical/mip.pyx

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1270990481 -7200
    # Node ID b4042e25848bfebec4ed31bf0e6539b285214ad9
    # Parent  fa242fc58d6b5bf6f6313b2a38de330276088748
    trac 8672 : SCIP support
    
    diff -r fa242fc58d6b -r b4042e25848b sage/numerical/mip.pyx
    a b  
    8181
    8282        try:
    8383            if self._default_solver == None:
     84                from zibopt import scip
     85                self._default_solver = "SCIP"
     86        except ImportError:
     87            pass
     88
     89        try:
     90            if self._default_solver == None:
    8491                from sage.numerical.mip_glpk import solve_glpk
    8592                self._default_solver = "GLPK"
    8693        except ImportError:
    8794            pass
    8895
    89 
    9096        # List of all the MIPVariables linked to this instance of
    9197        # MixedIntegerLinearProgram
    9298        self._mipvariables = []
     
    928934
    929935          - CPLEX (``solver="CPLEX"``). See the
    930936            `CPLEX <http://www.ilog.com/products/cplex/>`_ web site.
    931             An interface to CPLEX is not yet implemented.
     937
     938          - SCIP (``solver="SCIP"``). See the
     939            `SCIP <http://scip.zib.de/>`_ web site.
    932940
    933941          ``solver`` should then be equal to one of ``"GLPK"``, ``"Coin"``,
    934           ``"CPLEX"``, or ``None``. If ``solver=None`` (default), the default
    935           solver is used (COIN if available, GLPK otherwise).
     942          ``"CPLEX"``, ``"SCIP"`` or ``None``. If ``solver=None`` (default),
     943          the default solver is used (COIN if available, GLPK otherwise).
    936944
    937945        - ``log`` -- This boolean variable indicates whether progress should
    938946          be printed during the computations.
     
    10001008        if solver == None:
    10011009            raise ValueError("There does not seem to be any (Mixed) Integer Linear Program solver installed. Please visit http://www.sagemath.org/doc/constructions/linear_programming.html to learn more about the solvers available.")
    10021010
    1003 
    10041011        try:
    10051012            if solver == "Coin":
    10061013                from sage.numerical.mip_coin import solve_coin as solve
     
    10081015                from sage.numerical.mip_glpk import solve_glpk as solve
    10091016            elif solver == "CPLEX":
    10101017                from sage.numerical.mip_cplex import solve_cplex as solve
     1018            elif solver == "SCIP":
     1019                from sage.numerical.mip_scip import solve_scip as solve
    10111020            else:
    1012                 NotImplementedError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX' or None (in which case the default one is used).")
     1021                NotImplementedError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'SCIP', or None (in which case the default one is used).")
    10131022
    10141023        except ImportError:
    10151024            raise NotImplementedError("The required solver is not installed and cannot be used to solve this (Mixed) Integer Linear Program. To install it, follow the instructions given at http://www.sagemath.org/doc/constructions/linear_programming.html")
  • new file sage/numerical/mip_scip.py

    diff -r fa242fc58d6b -r b4042e25848b sage/numerical/mip_scip.py
    - +  
     1def solve_scip(self,log=0,objective_only=False):
     2    BINARY = 1
     3    REAL = -1
     4    INTEGER = 0
     5
     6    from zibopt import scip
     7    solver = scip.solver(quiet = True if log==0 else False)
     8
     9    # Building the variables
     10    # concatenates the information from Type / Min bound / Max bound
     11    var_data = zip(self._variables_type, self._variables_bounds_min, self._variables_bounds_max)
     12
     13    mk_type = lambda type : scip.INTEGER if type == INTEGER else (scip.CONTINUOUS if type == REAL else scip.BINARY)
     14
     15    def mk_dict((type, min, max)):
     16        d = {}
     17        if min is not None:
     18            d['lower'] = min
     19        if max is not None:
     20            d['upper'] = max
     21
     22        d['vartype'] = mk_type(type)
     23        return d
     24       
     25    scip_variables = map(lambda x : solver.variable(**mk_dict(x)),var_data)
     26
     27    for linear_function, min, max in self.constraints():
     28        f = linear_function.f.copy()
     29        constant = f.pop(-1)
     30
     31        scip_function = sum(map(lambda (id, coeff) : coeff * scip_variables[id], f.items()))
     32        scip_function += constant
     33
     34        if min == max:
     35            solver += scip_function == min
     36        else:
     37            if min is not None:
     38                solver += scip_function >= min
     39            else:
     40                solver += scip_function <= max
     41
     42   
     43    objective = sum(map(lambda (id, coeff) : scip_variables[id] * coeff, zip(self._objective_i, self._objective_values)))
     44
     45    if self._maximization:
     46        if self._objective_i:
     47            sol = solver.maximize(objective = objective)
     48        else:
     49            sol = solver.maximize()
     50    else:
     51        if self._objective_i:
     52            sol = solver.minimize(objective = objective)
     53        else:
     54            sol = solver.minimize()
     55
     56    for var, id in self._variables.iteritems():
     57        self._values[var] = sol[scip_variables[id]]
     58
     59    return sol.objective