Tobias Triesch
Tobias Triesch

Reputation: 162

Pyomo and Gurobi: Does Pyomo support solver callbacks to Gurobi?

I have started using Pyomo for modelling of MILPs and need to add problem specific cutting planes at certain MILP-feasible solutions. I know that it is possible to do that via callbacks in Gurobi's own gurobipy API. However, since I am using Pyomo atm I would like to stick to it if possible. I have seen that there exist persistent/direct solver IO options, however, I could not figure out how to make use of those options for my purposes.

Any help is appreciated.

Upvotes: 1

Views: 1612

Answers (1)

ruaridhw
ruaridhw

Reputation: 2345

Callbacks and lazy constraints are currently supported by Pyomo for the Gurobi Persistent solver interface. Here is a small example from the documentation of that interface:

from gurobipy import GRB
import pyomo.environ as pe
from pyomo.core.expr.taylor_series import taylor_series_expansion

m = pe.ConcreteModel()
m.x = pe.Var(bounds = (0, 4))
m.y = pe.Var(within = pe.Integers, bounds = (0, None))
m.obj = pe.Objective(expr = 2 * m.x + m.y)
m.cons = pe.ConstraintList()  # for the cutting planes


def _add_cut(xval):
    # a function to generate the cut
    m.x.value = xval
    return m.cons.add(m.y >= taylor_series_expansion((m.x - 2) ** 2))


_add_cut(0)  # start with 2 cuts at the bounds of x
_add_cut(4)  # this is an arbitrary choice

opt = pe.SolverFactory('gurobi_persistent')
opt.set_instance(m)
opt.set_gurobi_param('PreCrush', 1)
opt.set_gurobi_param('LazyConstraints', 1)


def my_callback(cb_m, cb_opt, cb_where):
    if cb_where == GRB.Callback.MIPSOL:
        cb_opt.cbGetSolution(vars = [m.x, m.y])
        if m.y.value < (m.x.value - 2) ** 2 - 1e-6:
            print('adding cut')
            cb_opt.cbLazy(_add_cut(m.x.value))


opt.set_callback(my_callback)
opt.solve()
assert abs(m.x.value - 1) <= 1e-6
assert abs(m.y.value - 1) <= 1e-6
Changed value of parameter PreCrush to 1
   Prev: 0  Min: 0  Max: 1  Default: 0
Changed value of parameter LazyConstraints to 1
   Prev: 0  Min: 0  Max: 1  Default: 0
adding cut
adding cut
adding cut
adding cut
adding cut
adding cut
adding cut
adding cut

For further details on the methods available within this Pyomo callback interface, see the GurobiPersistent class.

Upvotes: 1

Related Questions