Skip to content

Commit

Permalink
changes to improve custom Benders' plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen J. Maher committed Feb 4, 2019
1 parent 0582617 commit b992e06
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/pyscipopt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# export user-relevant objects:
from pyscipopt.Multidict import multidict
from pyscipopt.scip import Model
from pyscipopt.scip import Benders
from pyscipopt.scip import Branchrule
from pyscipopt.scip import Conshdlr
from pyscipopt.scip import Eventhdlr
Expand Down
23 changes: 14 additions & 9 deletions src/pyscipopt/benders.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ cdef class Benders:
return {}

def benderspresubsolve(self, solution, enfotype, checkint):
pass
return {}

def benderssolvesubconvex(self, solution, probnumber, onlyconvex):
pass
return {}

def benderssolvesub(self, solution, probnumber):
pass
return {}

def benderspostsolve(self, solution, enfotype, mergecandidates, npriomergecands, checkint, infeasible):
pass
return {}

def bendersfreesub(self, probnumber):
pass
Expand All @@ -46,6 +46,12 @@ cdef class Benders:
print("python error in bendersgetvar: this method needs to be implemented")
return {}

# local helper functions for the interface
cdef Variable getPyVar(SCIP_VAR* var):
cdef SCIP_VARDATA* vardata
vardata = SCIPvarGetData(var)
return <Variable>vardata


cdef SCIP_RETCODE PyBendersCopy (SCIP* scip, SCIP_BENDERS* benders):
return SCIP_OKAY
Expand Down Expand Up @@ -125,7 +131,7 @@ cdef SCIP_RETCODE PyBendersSolvesubconvex (SCIP* scip, SCIP_BENDERS* benders, SC
PyBenders = <Benders>bendersdata
solution = Solution()
solution.sol = sol
result_dict = PyBenders.benderssolvesub(solution, probnumber, onlyconvex)
result_dict = PyBenders.benderssolvesubconvex(solution, probnumber, onlyconvex)
objective[0] = result_dict.get("objective", 1e+20)
result[0] = result_dict.get("result", <SCIP_RESULT>result[0])
return SCIP_OKAY
Expand Down Expand Up @@ -169,12 +175,11 @@ cdef SCIP_RETCODE PyBendersGetvar (SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR*
cdef SCIP_BENDERSDATA* bendersdata
bendersdata = SCIPbendersGetData(benders)
PyBenders = <Benders>bendersdata
variable = Variable()
variable.var = var
result_dict = PyBenders.bendersgetvar(variable, probnumber)
PyVar = getPyVar(var)
result_dict = PyBenders.bendersgetvar(PyVar, probnumber)
mappedvariable = result_dict.get("mappedvar", None)
if mappedvariable is None:
mappedvar[0] = NULL
else:
mappedvar[0] = <SCIP_VAR*>mappedvariable.var
mappedvar[0] = <SCIP_VAR*>(mappedvariable.ptr())
return SCIP_OKAY
10 changes: 9 additions & 1 deletion src/pyscipopt/scip.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,9 @@ cdef extern from "scip/scip.h":
ctypedef struct SCIP_CONSDATA:
pass

ctypedef struct SCIP_VARDATA:
pass

ctypedef struct SCIP_EVENT:
pass

Expand Down Expand Up @@ -618,6 +621,8 @@ cdef extern from "scip/scip.h":
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR* var)
SCIP_Real SCIPvarGetObj(SCIP_VAR* var)
SCIP_Real SCIPvarGetLPSol(SCIP_VAR* var)
void SCIPvarSetData(SCIP_VAR* var, SCIP_VARDATA* vardata)
SCIP_VARDATA* SCIPvarGetData(SCIP_VAR* var)

# LP Methods
SCIP_RETCODE SCIPgetLPColsData(SCIP* scip, SCIP_COL*** cols, int* ncols)
Expand Down Expand Up @@ -976,7 +981,7 @@ cdef extern from "scip/scip.h":
SCIP_RETCODE (*bendersfreesub) (SCIP* scip, SCIP_BENDERS* benders, int probnumber),
SCIP_BENDERSDATA* bendersdata)
SCIP_BENDERS* SCIPfindBenders(SCIP* scip, const char* name)
SCIP_RETCODE SCIPactivateBenders(SCIP* scip, SCIP_BENDERS* benders)
SCIP_RETCODE SCIPactivateBenders(SCIP* scip, SCIP_BENDERS* benders, int nsubproblems)
SCIP_BENDERSDATA* SCIPbendersGetData(SCIP_BENDERS* benders)
SCIP_RETCODE SCIPcreateBendersDefault(SCIP* scip, SCIP** subproblems, int nsubproblems)
int SCIPbendersGetNSubproblems(SCIP_BENDERS* benders);
Expand All @@ -991,6 +996,9 @@ cdef extern from "scip/scip.h":
int SCIPgetNActiveBenders(SCIP* scip)
SCIP_BENDERS** SCIPgetBenders(SCIP* scip)
void SCIPbendersUpdateSubproblemLowerbound(SCIP_BENDERS* benders, int probnumber, SCIP_Real lowerbound)
SCIP_RETCODE SCIPaddBendersSubproblem(SCIP* scip, SCIP_BENDERS* benders, SCIP* subproblem)
SCIP_RETCODE SCIPgetBendersMasterVar(SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR* var, SCIP_VAR** mappedvar)
SCIP_RETCODE SCIPgetBendersSubproblemVar(SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR* var, SCIP_VAR** mappedvar, int probnumber)

SCIP_RETCODE SCIPbranchVar(SCIP* scip,
SCIP_VAR* var,
Expand Down
64 changes: 61 additions & 3 deletions src/pyscipopt/scip.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,9 @@ cdef class Model:
PY_SCIP_CALL(SCIPaddVar(self._scip, scip_var))

pyVar = Variable.create(scip_var)

#setting the variable data
SCIPvarSetData(scip_var, <SCIP_VARDATA*>pyVar)
PY_SCIP_CALL(SCIPreleaseVar(self._scip, &scip_var))
return pyVar

Expand Down Expand Up @@ -1049,8 +1052,8 @@ cdef class Model:
cdef SCIP_Bool tightened
PY_SCIP_CALL(SCIPtightenVarUb(self._scip, var.var, ub, force, &infeasible, &tightened))
return infeasible, tightened


def tightenVarUbGlobal(self, Variable var, ub, force=False):
"""Tighten the global upper bound, if the bound is tighter.
Expand All @@ -1066,7 +1069,7 @@ cdef class Model:
cdef SCIP_Bool tightened
PY_SCIP_CALL(SCIPtightenVarUbGlobal(self._scip, var.var, ub, force, &infeasible, &tightened))
return infeasible, tightened

def tightenVarLbGlobal(self, Variable var, lb, force=False):
"""Tighten the global upper bound, if the bound is tighter.
Expand Down Expand Up @@ -1193,6 +1196,10 @@ cdef class Model:
"""Retrieve number of variables in the problems"""
return SCIPgetNVars(self._scip)

def getNConss(self):
"""Retrieve the number of constraints."""
return SCIPgetNConss(self._scip)

def updateNodeLowerbound(self, Node node, lb):
"""if given value is larger than the node's lower bound (in transformed problem),
sets the node's lower bound to the new value
Expand Down Expand Up @@ -2453,6 +2460,57 @@ cdef class Model:
for d in lowerbounds.keys():
SCIPbendersUpdateSubproblemLowerbound(_benders, d, lowerbounds[d])

def activateBenders(self, str name, int nsubproblems):
"""Activates the Benders' decomposition plugin with the input name
Keyword arguments:
name -- the name of the Benders' decomposition plugin
nsubproblems -- the number of subproblems in the Benders' decomposition
"""
n = str_conversion(name)
cdef SCIP_BENDERS* benders
benders = SCIPfindBenders(self._scip, n)
PY_SCIP_CALL(SCIPactivateBenders(self._scip, benders, nsubproblems))

def addBendersSubproblem(self, str name, subproblem):
"""adds a subproblem to the Benders' decomposition given by the input
name.
Keyword arguments:
name -- the Benders' decomposition that the subproblem is added to
subproblem -- the subproblem to add to the decomposition
"""
cdef SCIP_BENDERS* benders
n = str_conversion(name)
benders = SCIPfindBenders(self._scip, n)
PY_SCIP_CALL(SCIPaddBendersSubproblem(self._scip, benders, (<Model>subproblem)._scip))

def getBendersVar(self, Variable var, Benders benders = None, probnumber = -1):
"""Returns the variable for the subproblem or master problem
depending on the input probnumber
Keyword arguments:
var -- the source variable for which the target variable is requested
benders -- the Benders' decomposition to which the subproblem variables belong to
probnumber -- the problem number for which the target variable belongs, -1 for master problem
"""
cdef SCIP_BENDERS* _benders
cdef SCIP_VAR* _mappedvar

if benders is None:
_benders = SCIPfindBenders(self._scip, "default")
else:
n = str_conversion(benders.name)
_benders = SCIPfindBenders(self._scip, n)

if probnumber == -1:
PY_SCIP_CALL(SCIPgetBendersMasterVar(self._scip, _benders, var.var, &_mappedvar))
else:
PY_SCIP_CALL(SCIPgetBendersSubproblemVar(self._scip, _benders, var.var, &_mappedvar, probnumber))

return Variable.create(_mappedvar)


def includeEventhdlr(self, Eventhdlr eventhdlr, name, desc):
"""Include an event handler.
Expand Down

0 comments on commit b992e06

Please sign in to comment.