Callback to print bestbound solution raises errors or does not print
AnsweredI am trying to print the bestbound solution (that is the coordinates of the point at which the bestbound is achieved at termination) together with the optimal solution in a nonconvex MIP maximisation problem once it has reached optimality within 0.01 MIPgap. However either my callback raises an error:
NameError: name 'x' is not defined
or, some other times (I have no idea why at these times the behaviour is different) the callback is ignored completely and nothing is printed. The log reports that there have been 47 callbacks with 0.00 time spent on it. Is there any error in the following code? Without the callback it works just fine, but unfortunately there is no attribute to get the bestbound solution so I read in the documentation, from which my callback is copied, that this is the only way to get it.
import gurobipy as gp
from gurobipy import GRB
def bbsol(model, where):
if where == GRB.Callback.MIPNODE:
status = model.cbGet(GRB.Callback.MIPNODE_STATUS)
if status == GRB.OPTIMAL:
print(model.cbGetNodeRel(x))
model.terminate()
m = gp.Model("bilinear")
#then I go onto defining variables, objective, constraints, none of which involves the letter x
#finally
m.Params.NonConvex = 2
m.Params.MIPGap = 0.01 #I want status=GRB.OPTIMAL at this tolerance to cut times
m.Params.MIPFocus = 3 #focus on improving bestbound, which matters to me the most
m.Params.FeasibilityTol = 1e-4
m.Params.OptimalityTol = 1e-3
m.optimize(callback = bbsol)
m.printAttr('x')
-
Hi Giordano,
The error happens because the function \(\texttt{bbsol}\) does not know what the variable \(\texttt{x}\) is. You need to pass the model variables as data to the callback function. See the callback example implementation for Python and look for the section GRB.Callback.MIPNODE. for the correct implementation of how to use the cbGetNodeRel() method.
Best regards,
Maliheh
0 -
Thank you for your reply, if I understand correctly, since I set two list of variables for the model,
s = [m.addVar(lb = 0.0, ub = 1.0, name = "s" + str(i)) for i in range(n)]
b = [m.addVar(lb = 0.0, ub = 1.0, name = "b" + str(i)) for i in range(n)]I should use
print(model.cbGetNodeRel(s))
print(model.cbGetNodeRel(b))
I tried and it does work now. However, I noticed that evaluating the objective on [s, b] does not return the bestbound on the objective reported at termination, which is 0.9986500364875883 and coincides with the bound I can also check at the MIPNODE by adding print(model.cbGet(GRB.Callback.MIPNODE_OBJBND)) to the callback. Instead evaluating at [s,b] returns somehow a slightly better bound: 0.9747766007192235. In this model n=16 and the function is well-behaved, I do not think this could be due to truncation error, it seems that [s,b] is genuinely not the same solution of the best bound (and it is neither the solution for the optimal objective). I read in a related question it could be due to some additional work made by the optimizer on other Threads than the callback one, yet this persists, with a slightly different value, even after setting
m.Params.Threads = 1
Since the difference between the two values is quite large, is there a way to get a more accurate solution for the best bound? Did I perhaps implement model.cbGetNodeRel wrong again?
0 -
Do you solve the model to optimality? The best bound solution at optimality is equal to the optimal solution. I am not sure why you need to look at the node solution at optimality.
The best bound does not necessarily come from nodes solved to optimality. It might come from partially explored nodes and global improvements that are not tied to any specific node.
Let us assume at a given time, the incumbent is 0.99 and the best bound is 0.97 and there is only one node left to explore. The Gurobi optimizer might not solve the relaxation to optimality as soon as it can prove that its solution cannot be lower than than 0.99. It would then terminate with CUTOFF status. In this example, the best bound solution retrieved via MIPNode will not necessarily have an equal objective value to the model optimal objective value.
Best regards,
Maliheh0
Please sign in to leave a comment.
Comments
3 comments