I'm using the Python Interface of SCIP (PySCIPOpt) to write a custom branching rule. As far as I understood from reading the documentation, a good way to do this is making use of the methods self.model.createChild
and self.model.addConsNode
. So I came up with the following test code to try to implement a random branching rule on my own:
class RandomBranching(Branchrule):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.count = 0
def branchexeclp(self, allowaddcons):
self.count += 1
variables = [v for v in self.model.getVars() if (v.vtype() == "BINARY" or v.vtype() == "INTEGER")]
random.shuffle(variables)
for v in variables:
value = self.model.getSolVal(None, v)
if value - math.floor(value) >= 10 ** -6:
child_1 = self.model.createChild(1, 1)
self.model.addConsNode(child_1, v <= math.floor(value))
child_2 = self.model.createChild(1, 1)
self.model.addConsNode(child_2, v >= math.floor(value) + 1)
return {"result": SCIP_RESULT.BRANCHED}
return {"result": SCIP_RESULT.DIDNOTRUN}
This code raises an exception, because addConsNode expects an object of type "Constraint" while I seem to be passing an "ExprCons". After trying my best to dig through the source code, I do not manage to understand the difference between the two and unfortunately have no clue how to correctly initialize an object of type "Constraint".
Note: My code from above is quite similar to the Code used in the PySCIPOpt github to test the Branchingrules (in PySCIPOpt/tests/test_branch_probing_lp.py).
The PySCIPOpt-Interface was lacking the functionality I was searching for. This lead to a pull-request, see here. The pr will extend the functionality and allow to use ExprCons for addConsNode
, which is needed to branch this way.