Adding interface to the SCIP solver
This commit is contained in:
parent
fdb518b76a
commit
ccf7c9c95c
|
@ -99,12 +99,16 @@ def initialize(filename, operating_system='linux', arch='64'):
|
|||
pulp_cbc_path = config.get("locations", "PulpCbcPath")
|
||||
except configparser.Error:
|
||||
pulp_cbc_path = 'cbc'
|
||||
try:
|
||||
scip_path = config.get("locations", "ScipPath")
|
||||
except configparser.Error:
|
||||
scip_path = 'scip'
|
||||
for i,path in enumerate(coinMP_path):
|
||||
if not os.path.dirname(path):
|
||||
#if no pathname is supplied assume the file is in the same directory
|
||||
coinMP_path[i] = os.path.join(os.path.dirname(config_filename),path)
|
||||
return cplex_dll_path, ilm_cplex_license, ilm_cplex_license_signature,\
|
||||
coinMP_path, gurobi_path, cbc_path, glpk_path, pulp_cbc_path
|
||||
coinMP_path, gurobi_path, cbc_path, glpk_path, pulp_cbc_path, scip_path
|
||||
|
||||
#pick up the correct config file depending on operating system
|
||||
PULPCFGFILE = "pulp.cfg"
|
||||
|
@ -134,8 +138,8 @@ else: #run as a script
|
|||
DIRNAME = os.path.dirname(fname)
|
||||
config_filename = os.path.join(DIRNAME,
|
||||
PULPCFGFILE)
|
||||
cplex_dll_path, ilm_cplex_license, ilm_cplex_license_signature, \
|
||||
coinMP_path, gurobi_path, cbc_path, glpk_path, pulp_cbc_path = \
|
||||
cplex_dll_path, ilm_cplex_license, ilm_cplex_license_signature, coinMP_path,\
|
||||
gurobi_path, cbc_path, glpk_path, pulp_cbc_path, scip_path = \
|
||||
initialize(config_filename, operating_system, arch)
|
||||
|
||||
|
||||
|
@ -429,12 +433,12 @@ GLPK = GLPK_CMD
|
|||
|
||||
class CPLEX_CMD(LpSolver_CMD):
|
||||
"""The CPLEX LP solver"""
|
||||
|
||||
|
||||
def __init__(self, path = None, keepFiles = 0, mip = 1,
|
||||
msg = 0, options = [], timelimit = None):
|
||||
LpSolver_CMD.__init__(self, path, keepFiles, mip, msg, options)
|
||||
self.timelimit = timelimit
|
||||
|
||||
|
||||
def defaultPath(self):
|
||||
return self.executableExtension("cplex")
|
||||
|
||||
|
@ -2524,3 +2528,110 @@ class GurobiFormulation(object):
|
|||
else:
|
||||
raise TypeError("Can only add LpConstraint, LpAffineExpression or True objects")
|
||||
return self
|
||||
|
||||
class SCIP_CMD(LpSolver_CMD):
|
||||
"""The SCIP optimization solver"""
|
||||
|
||||
SCIP_STATUSES = {
|
||||
'unknown': LpStatusUndefined,
|
||||
'user interrupt': LpStatusNotSolved,
|
||||
'node limit reached': LpStatusNotSolved,
|
||||
'total node limit reached': LpStatusNotSolved,
|
||||
'stall node limit reached': LpStatusNotSolved,
|
||||
'time limit reached': LpStatusNotSolved,
|
||||
'memory limit reached': LpStatusNotSolved,
|
||||
'gap limit reached': LpStatusNotSolved,
|
||||
'solution limit reached': LpStatusNotSolved,
|
||||
'solution improvement limit reached': LpStatusNotSolved,
|
||||
'restart limit reached': LpStatusNotSolved,
|
||||
'optimal solution found': LpStatusOptimal,
|
||||
'infeasible': LpStatusInfeasible,
|
||||
'unbounded': LpStatusUnbounded,
|
||||
'infeasible or unbounded': LpStatusNotSolved,
|
||||
}
|
||||
|
||||
def defaultPath(self):
|
||||
return self.executableExtension(scip_path)
|
||||
|
||||
def available(self):
|
||||
"""True if the solver is available"""
|
||||
return self.executable(self.path)
|
||||
|
||||
def actualSolve(self, lp):
|
||||
"""Solve a well formulated lp problem"""
|
||||
if not self.executable(self.path):
|
||||
raise PulpSolverError("PuLP: cannot execute "+self.path)
|
||||
|
||||
# TODO: should we use tempfile instead?
|
||||
if not self.keepFiles:
|
||||
pid = os.getpid()
|
||||
tmpLp = os.path.join(self.tmpDir, "%d-pulp.lp" % pid)
|
||||
tmpSol = os.path.join(self.tmpDir, "%d-pulp.sol" % pid)
|
||||
else:
|
||||
tmpLp = lp.name+"-pulp.lp"
|
||||
tmpSol = lp.name+"-pulp.sol"
|
||||
|
||||
lp.writeLP(tmpLp)
|
||||
proc = [
|
||||
'scip', '-c', 'read %s' % tmpLp, '-c', 'optimize',
|
||||
'-c', 'write solution %s' % tmpSol, '-c', 'quit'
|
||||
]
|
||||
proc.extend(self.options)
|
||||
if not self.msg:
|
||||
proc.append('-q')
|
||||
|
||||
self.solution_time = clock()
|
||||
subprocess.check_call(proc, stdout=sys.stdout, stderr=sys.stderr)
|
||||
self.solution_time += clock()
|
||||
|
||||
if not os.path.exists(tmpSol):
|
||||
raise PulpSolverError("PuLP: Error while executing "+self.path)
|
||||
|
||||
lp.status, values = self.readsol(tmpSol)
|
||||
lp.assignVarsVals(values)
|
||||
if not self.keepFiles:
|
||||
for f in (tmpLp, tmpSol):
|
||||
try:
|
||||
os.remove(f)
|
||||
except:
|
||||
pass
|
||||
|
||||
return lp.status
|
||||
|
||||
def readsol(self,filename):
|
||||
"""Read a SCIP solution file"""
|
||||
with open(filename) as f:
|
||||
# First line must containt 'solution status: <something>'
|
||||
try:
|
||||
line = f.readline()
|
||||
comps = line.split(': ')
|
||||
assert comps[0] == 'solution status'
|
||||
assert len(comps) == 2
|
||||
except:
|
||||
raise
|
||||
raise PulpSolverError("Can't read SCIP solver output: %r" % line)
|
||||
|
||||
status = SCIP_CMD.SCIP_STATUSES.get(comps[1].strip(), LpStatusUndefined)
|
||||
|
||||
# Look for an objective value. If we can't find one, stop.
|
||||
try:
|
||||
line = f.readline()
|
||||
comps = line.split(': ')
|
||||
assert comps[0] == 'objective value'
|
||||
assert len(comps) == 2
|
||||
float(comps[1].strip())
|
||||
except:
|
||||
raise PulpSolverError("Can't read SCIP solver output: %r" % line)
|
||||
|
||||
# Parse the variable values.
|
||||
values = {}
|
||||
for line in f:
|
||||
try:
|
||||
comps = line.split()
|
||||
values[comps[0]] = float(comps[1])
|
||||
except:
|
||||
raise PulpSolverError("Can't read SCIP solver output: %r" % line)
|
||||
|
||||
return status, values
|
||||
|
||||
SCIP = SCIP_CMD
|
||||
|
|
Loading…
Reference in New Issue