Callback Setsolution from a MIP solution node
AnsweredI am solving a two stage stochastic program (in the extensive or the "deterministic" form) with integer variables in both the stages. I observe that Gurobi's heuristics find good firststage solutions fast, but the second stage solutions are suboptimal.
But given the firststage solution, it is easy to solve a secondstage problem. So, I would like to do the following:
Whenever gurobi finds a feasible solution, (GRB.Callback.MIPSOL), I would like to retrieve the firststage solutions (by using Model.cbGetSolution), and solve the 100 much smaller secondstage MIPs, and feed the solution of the second stage to gurobi (using Model.cbSetSolution and cbUseSolution). I believe this could considerably improve the objective value of the current solution.
My problem is that Model.cbGetSolution is allowed only if where==GRB.Callback.MIPSOL while Model.cbSetSolution is allowed only if where == GRB.Callback.MIPNODE.
Is there a workaround for this problem? I am using the Python API.

I am facing the same issue.
Is there any solution for that?
1 
Hello, I am facing the same question, the only thing I could find cb.GetNodeRel() can be used to retrieve the variables of the relaxation but I am unsure if it actually works for you, would be helpful if someone could share how can this be solved
0 
In the next major or minor Gurobi release, you will be able to set solutions from the \( \texttt{MIPSOL} \) callback. In the meantime, a workaround is to store the solution, then pass it to Gurobi in the next \( \texttt{MIPNODE} \) callback.
1 
How can you have two callbacks in one function? to my understanding once you set the first \( \texttt{if} \) block, that's the only one it gets to run:
def mycallback(model, where):
if where == GRB.Callback.MIPSOL:
v = model.cbGetSolution(model._vars)
vs = model._vars
vi = v/(v+3)
elif where == GRB.Callback.MIPNODE:
model.cbLazy(lhs,sense,rhs)
model.cbSetSolution(vs,vi)
model.optimize(mycallback)0 
Your callback can definitely handle multiple `where` values with if statements.
0 
You can generate and store the solution when \( \texttt{mycallback} \) is called with \( \texttt{where=MIPSOL} \), then set the solution the next time \( \texttt{mycallback} \) is called with \( \texttt{where=MIPNODE} \). So the solution is generated and set in two different calls to \( \texttt{mycallback} \). E.g.:
def mycallback(model, where):
if where == GRB.Callback.MIPSOL:
vals = model.cbGetSolution(model._vars)
model._vals = [v / (v + 3) for v in vals]
elif where == GRB.Callback.MIPNODE and model._vals is not None:
model.cbSetSolution(model._vars, model._vals)
model._vals = None
model._vars = model.getVars()
model._vals = None
model.optimize(mycallback)1 
Thanks a lot! I am trying to implement this in the model I am working on, when I tried to use \( \texttt{where=MIPNODE} \) nothing seemed to happen, then I checked for the condition to see if it's being read, if the statement is true then the block inside that \(\texttt{elif}\) will be executed
print(str(where==GRB.Callback.MIPNODE))
However, the result I get back is
False
So,
model.cbSetSolution(vars, solution)
won't get executed, my question is, what could make the \(\texttt{GRB.Callback.MIPNODE}\) false?
0 
Note that \( \texttt{where} \) is equal to \( \texttt{GRB.Callback.MIPSOL} \) when the solution is set, then \( \texttt{mycallback} \) will be called later (separately) with a \( \texttt{where} \) value of \( \texttt{GRB.Callback.MIPNODE} \). \( \texttt{where==GRB.Callback.MIPNODE} \) is \( \texttt{false} \) whenever \( \texttt{mycallback} \) is called with a non\( \texttt{MIPNODE} \) value of \( \texttt{where} \) (see the Callback Codes section of the documentation).
Is \( \texttt{mycallback} \) never called with \( \texttt{where==GRB.Callback.MIPNODE} \)? It would be helpful to see the log output from Gurobi and your code for a minimal working callback function.
0 
Hello,
Thanks, I could see what I was doing wrong. Now my code enters \( \texttt{where=MIPNODE} \) and I can make use of \(\texttt{cb.SetSolution}\). However, I also want to use \(\texttt{Model.UseSolution()}\), and when printing to check what value I am about to pass I get 1e+100. What does this value mean and what kind of heuristic does gurobi implement at this point?
0 
The return value of Model.cbUseSolution() is \( \texttt{GRB.INFINITY} \) (1e+100) if Gurobi isn't able to compute an improved solution using the variable values specified in Model.cbSetSolution(). Are you sure your solution is feasible and better than the current incumbent objective value?
Gurobi solves an optimization problem to try to "fill in" any missing variable values. The solution you give to Gurobi generally comes from your own heuristic algorithm.
0 
Hi Everyone,
Gurobi 9.5 was recently released. Included in this release is the ability to set a new solution from the MIP and the MIPSOL callbacks. Therefore, there is no need to store a solution internally and wait for the next MIPNODE callback anymore.
Unfortunately, this new feature is missing in the Gurobi 9.5 documentation. It will be added in the next technical release.
We hope this new feature works well for you. Please let us know if you find any issues using this.
Best regards,
Maliheh
0
Please sign in to leave a comment.
Comments
11 comments