Python callback example
这篇文章同样转自Gurobi-support
原文链接:https://www.gurobi.com/documentation/10.0/examples/cb_py.html
这篇文章是一个example,可以参考这篇文章《关于如何调用callback来终止Gurobi运行》获取更多相关信息。
————————————————————————————————
直接上代码!
#!/usr/bin/env python3.7
# Copyright 2022, Gurobi Optimization, LLC
# This example reads a model from a file, sets up a callback that
# monitors optimization progress and implements a custom
# termination strategy, and outputs progress information to the
# screen and to a log file.
#
# The termination strategy implemented in this callback stops the
# optimization of a MIP model once at least one of the following two
# conditions have been satisfied:
# 1) The optimality gap is less than 10%
# 2) At least 10000 nodes have been explored, and an integer feasible
# solution has been found.
# Note that termination is normally handled through Gurobi parameters
# (MIPGap, NodeLimit, etc.). You should only use a callback for
# termination if the available parameters don't capture your desired
# termination criterion.
# 一旦满足以下两个条件之一,此callback中实施的终止策略将停止 MIP 模型的优化:
# 1) 最优性差距小于 10%
# 2) 至少有 10000 个节点进行了探索,并找到了一个整数可行的解决方案。
# 请注意,终止通常通过 Gurobi 参数来处理(MIPGap、NodeLimit 等)。
# 如果可用参数没有捕获您想要的 终止条件,您应该只使用回调来终止。
import sys
import gurobipy as gp
from gurobipy import GRB
# Define my callback function
def mycallback(model, where):
if where == GRB.Callback.POLLING:
# Ignore polling callback
pass
elif where == GRB.Callback.PRESOLVE:
# Presolve callback
cdels = model.cbGet(GRB.Callback.PRE_COLDEL)
rdels = model.cbGet(GRB.Callback.PRE_ROWDEL)
if cdels or rdels:
print('%d columns and %d rows are removed' % (cdels, rdels))
elif where == GRB.Callback.SIMPLEX:
# Simplex callback
itcnt = model.cbGet(GRB.Callback.SPX_ITRCNT)
if itcnt - model._lastiter >= 100:
model._lastiter = itcnt
obj = model.cbGet(GRB.Callback.SPX_OBJVAL)
ispert = model.cbGet(GRB.Callback.SPX_ISPERT)
pinf = model.cbGet(GRB.Callback.SPX_PRIMINF)
dinf = model.cbGet(GRB.Callback.SPX_DUALINF)
if ispert == 0:
ch = ' '
elif ispert == 1:
ch = 'S'
else:
ch = 'P'
print('%d %g%s %g %g' % (int(itcnt), obj, ch, pinf, dinf))
elif where == GRB.Callback.MIP:
# General MIP callback
nodecnt = model.cbGet(GRB.Callback.MIP_NODCNT)
objbst = model.cbGet(GRB.Callback.MIP_OBJBST)
objbnd = model.cbGet(GRB.Callback.MIP_OBJBND)
solcnt = model.cbGet(GRB.Callback.MIP_SOLCNT)
if nodecnt - model._lastnode >= 100:
model._lastnode = nodecnt
actnodes = model.cbGet(GRB.Callback.MIP_NODLFT)
itcnt = model.cbGet(GRB.Callback.MIP_ITRCNT)
cutcnt = model.cbGet(GRB.Callback.MIP_CUTCNT)
print('%d %d %d %g %g %d %d' % (nodecnt, actnodes,
itcnt, objbst, objbnd, solcnt, cutcnt))
# 如果最优性差距小于 10%
if abs(objbst - objbnd) < 0.1 * (1.0 + abs(objbst)):
print('Stop early - 10% gap achieved')
model.terminate()
# 至少有 10000 个节点进行了探索,并找到了一个整数可行的解决方案。
if nodecnt >= 10000 and solcnt:
print('Stop early - 10000 nodes explored')
model.terminate()
elif where == GRB.Callback.MIPSOL:
# MIP solution callback
nodecnt = model.cbGet(GRB.Callback.MIPSOL_NODCNT)
obj = model.cbGet(GRB.Callback.MIPSOL_OBJ)
solcnt = model.cbGet(GRB.Callback.MIPSOL_SOLCNT)
x = model.cbGetSolution(model._vars)
print('**** New solution at node %d, obj %g, sol %d, '
'x[0] = %g ****' % (nodecnt, obj, solcnt, x[0]))
elif where == GRB.Callback.MIPNODE:
# MIP node callback
print('**** New node ****')
if model.cbGet(GRB.Callback.MIPNODE_STATUS) == GRB.OPTIMAL:
x = model.cbGetNodeRel(model._vars)
model.cbSetSolution(model.getVars(), x)
elif where == GRB.Callback.BARRIER:
# Barrier callback
itcnt = model.cbGet(GRB.Callback.BARRIER_ITRCNT)
primobj = model.cbGet(GRB.Callback.BARRIER_PRIMOBJ)
dualobj = model.cbGet(GRB.Callback.BARRIER_DUALOBJ)
priminf = model.cbGet(GRB.Callback.BARRIER_PRIMINF)
dualinf = model.cbGet(GRB.Callback.BARRIER_DUALINF)
cmpl = model.cbGet(GRB.Callback.BARRIER_COMPL)
print('%d %g %g %g %g %g' % (itcnt, primobj, dualobj,
priminf, dualinf, cmpl))
elif where == GRB.Callback.MESSAGE:
# Message callback
msg = model.cbGet(GRB.Callback.MSG_STRING)
model._logfile.write(msg)
if len(sys.argv) < 2:
print('Usage: callback.py filename')
sys.exit(0)
# Turn off display and heuristics
gp.setParam('OutputFlag', 0)
gp.setParam('Heuristics', 0)
# Read model from file
model = gp.read(sys.argv[1])
# Open log file
logfile = open('cb.log', 'w')
# Pass data into my callback function
model._lastiter = -GRB.INFINITY
model._lastnode = -GRB.INFINITY
model._logfile = logfile
model._vars = model.getVars()
# Solve model and capture solution information
model.optimize(mycallback)
print('')
print('Optimization complete')
if model.SolCount == 0:
print('No solution found, optimization status = %d' % model.Status)
else:
print('Solution found, objective = %g' % model.ObjVal)
for v in model.getVars():
if v.X != 0.0:
print('%s %g' % (v.VarName, v.X))
# Close log file
logfile.close()