Skip to content

Commit

Permalink
Merge pull request scipopt#262 from SCIP-Interfaces/sm/benderscut-plu…
Browse files Browse the repository at this point in the history
…gins

Adds the class for Benders' decomposition cutting methods
  • Loading branch information
mattmilten authored Mar 15, 2019
2 parents 608ae97 + 78cf6e2 commit f1fdc1f
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/pyscipopt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pyscipopt.Multidict import multidict
from pyscipopt.scip import Model
from pyscipopt.scip import Benders
from pyscipopt.scip import Benderscut
from pyscipopt.scip import Branchrule
from pyscipopt.scip import Conshdlr
from pyscipopt.scip import Eventhdlr
Expand Down
75 changes: 75 additions & 0 deletions src/pyscipopt/benderscut.pxi
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
cdef class Benderscut:
cdef public Model model
cdef public Benders benders
cdef public str name

def benderscutfree(self):
pass

def benderscutinit(self):
pass

def benderscutexit(self):
pass

def benderscutinitsol(self):
pass

def benderscutexitsol(self):
pass

def benderscutexec(self, solution, probnumber, enfotype):
print("python error in benderscutexec: this method needs to be implemented")
return {}

cdef SCIP_RETCODE PyBenderscutCopy (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut):
return SCIP_OKAY

cdef SCIP_RETCODE PyBenderscutFree (SCIP* scip, SCIP_BENDERSCUT* benderscut):
cdef SCIP_BENDERSCUTDATA* benderscutdata
benderscutdata = SCIPbenderscutGetData(benderscut)
PyBenderscut = <Benderscut>benderscutdata
PyBenderscut.benderscutfree()
Py_DECREF(PyBenderscut)
return SCIP_OKAY

cdef SCIP_RETCODE PyBenderscutInit (SCIP* scip, SCIP_BENDERSCUT* benderscut):
cdef SCIP_BENDERSCUTDATA* benderscutdata
benderscutdata = SCIPbenderscutGetData(benderscut)
PyBenderscut = <Benderscut>benderscutdata
PyBenderscut.benderscutinit()
return SCIP_OKAY

cdef SCIP_RETCODE PyBenderscutExit (SCIP* scip, SCIP_BENDERSCUT* benderscut):
cdef SCIP_BENDERSCUTDATA* benderscutdata
benderscutdata = SCIPbenderscutGetData(benderscut)
PyBenderscut = <Benderscut>benderscutdata
PyBenderscut.benderscutexit()
return SCIP_OKAY

cdef SCIP_RETCODE PyBenderscutInitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut):
cdef SCIP_BENDERSCUTDATA* benderscutdata
benderscutdata = SCIPbenderscutGetData(benderscut)
PyBenderscut = <Benderscut>benderscutdata
PyBenderscut.benderscutinitsol()
return SCIP_OKAY

cdef SCIP_RETCODE PyBenderscutExitsol (SCIP* scip, SCIP_BENDERSCUT* benderscut):
cdef SCIP_BENDERSCUTDATA* benderscutdata
benderscutdata = SCIPbenderscutGetData(benderscut)
PyBenderscut = <Benderscut>benderscutdata
PyBenderscut.benderscutexitsol()
return SCIP_OKAY

cdef SCIP_RETCODE PyBenderscutExec (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut, SCIP_SOL* sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT* result):
cdef SCIP_BENDERSCUTDATA* benderscutdata
benderscutdata = SCIPbenderscutGetData(benderscut)
PyBenderscut = <Benderscut>benderscutdata
if sol == NULL:
solution = None
else:
solution = Solution.create(sol)
enfotype = type
result_dict = PyBenderscut.benderscutexec(solution, probnumber, enfotype)
result[0] = result_dict.get("result", <SCIP_RESULT>result[0])
return SCIP_OKAY
26 changes: 26 additions & 0 deletions src/pyscipopt/scip.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,12 @@ cdef extern from "scip/scip.h":
ctypedef struct SCIP_BENDERSDATA:
pass

ctypedef struct SCIP_BENDERSCUT:
pass

ctypedef struct SCIP_BENDERSCUTDATA:
pass

ctypedef struct SCIP_QUADVAREVENTDATA:
pass

Expand Down Expand Up @@ -1047,6 +1053,26 @@ cdef extern from "scip/scip.h":
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)

# Benders' decomposition cuts plugin
SCIP_RETCODE SCIPincludeBenderscut(SCIP* scip,
SCIP_BENDERS* benders,
const char* name,
const char* desc,
int priority,
SCIP_Bool islpcut,
SCIP_RETCODE (*benderscutcopy) (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut),
SCIP_RETCODE (*benderscutfree) (SCIP* scip, SCIP_BENDERSCUT* benderscut),
SCIP_RETCODE (*benderscutinit) (SCIP* scip, SCIP_BENDERSCUT* benderscut),
SCIP_RETCODE (*benderscutexit) (SCIP* scip, SCIP_BENDERSCUT* benderscut),
SCIP_RETCODE (*benderscutinitsol) (SCIP* scip, SCIP_BENDERSCUT* benderscut),
SCIP_RETCODE (*benderscutexitsol) (SCIP* scip, SCIP_BENDERSCUT* benderscut),
SCIP_RETCODE (*benderscutexec) (SCIP* scip, SCIP_BENDERS* benders, SCIP_BENDERSCUT* benderscut, SCIP_SOL* sol, int probnumber, SCIP_BENDERSENFOTYPE type, SCIP_RESULT* result),
SCIP_BENDERSCUTDATA* benderscutdata)
SCIP_BENDERSCUT* SCIPfindBenderscut(SCIP_BENDERS* benders, const char* name)
SCIP_BENDERSCUTDATA* SCIPbenderscutGetData(SCIP_BENDERSCUT* benderscut)
SCIP_RETCODE SCIPstoreBendersCut(SCIP* scip, SCIP_BENDERS* benders, SCIP_VAR** vars, SCIP_Real* vals, SCIP_Real lhs, SCIP_Real rhs, int nvars)
SCIP_RETCODE SCIPapplyBendersStoredCuts(SCIP* scip, SCIP_BENDERS* benders)

SCIP_RETCODE SCIPbranchVar(SCIP* scip,
SCIP_VAR* var,
SCIP_NODE** downchild,
Expand Down
32 changes: 32 additions & 0 deletions src/pyscipopt/scip.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ from libc.stdio cimport fdopen
include "expr.pxi"
include "lp.pxi"
include "benders.pxi"
include "benderscut.pxi"
include "branchrule.pxi"
include "conshdlr.pxi"
include "event.pxi"
Expand Down Expand Up @@ -2885,6 +2886,37 @@ cdef class Model:
benders.model = <Model>weakref.proxy(self)
benders.name = name
Py_INCREF(benders)

def includeBenderscut(self, Benders benders, Benderscut benderscut, name, desc, priority=1, islpcut=True):
""" Include a Benders' decomposition cutting method
Keyword arguments:
benders -- the Benders' decomposition that this cutting method is attached to
benderscut --- the Benders' decomposition cutting method
name -- the name
desc -- the description
priority -- priority of the Benders' decomposition
islpcut -- is this cutting method suitable for generating cuts for convex relaxations?
"""
cdef SCIP_BENDERS* _benders

bendersname = str_conversion(benders.name)
_benders = SCIPfindBenders(self._scip, bendersname)

n = str_conversion(name)
d = str_conversion(desc)
PY_SCIP_CALL(SCIPincludeBenderscut(self._scip, _benders, n, d, priority, islpcut,
PyBenderscutCopy, PyBenderscutFree, PyBenderscutInit, PyBenderscutExit,
PyBenderscutInitsol, PyBenderscutExitsol, PyBenderscutExec,
<SCIP_BENDERSCUTDATA*>benderscut))

cdef SCIP_BENDERSCUT* scip_benderscut
scip_benderscut = SCIPfindBenderscut(_benders, n)
benderscut.model = <Model>weakref.proxy(self)
benderscut.benders = <Benders>weakref.proxy(benders)
benderscut.name = name
# TODO: It might be necessary in increment the reference to benders i.e Py_INCREF(benders)
Py_INCREF(benderscut)


def getLPBranchCands(self):
Expand Down

0 comments on commit f1fdc1f

Please sign in to comment.