Passing feasible solutions to GUROBI when solving non-convex models.
AnsweredHi there,
I am solving a non-convex quadratically constrained linear program, where all non-linearity is captured by a set of bilinear constraints (I modeled it like this because I believe it works well with GUROBIS McCormick relaxations). In any case, for large-scale problems, it takes a long time for the solver to find a first feasible solution, which I believe would help in the branching. Also in my case, due to total unimodularity, every relaxation can be used to derive a feasible solution as well.
Is there a way on how I could pass an initial feasible solution to GUROBI, or even better, pass a function that computes a feasible solution at each node in the spatial branch and bound tree that GRB is building?
So far I've only found the option to use setNode to pass a solution to GRB, but then you need to use the MIPSOL callback, which is only possible at integer solutions, so it doesn't really help much. Is there maybe a better way?
-
Hi Tom,
You can set a MIPStart for nonconvex models as described in How do I use MIP starts?
From a callback, you can use cbSetSolution().
So far I've only found the option to use setNode to pass a solution to GRB
Could you point me to the "setNode" function you mean?
Best regards,
Jaromił0 -
Hi Jaromil,
Thanks a lot, you're right, I totally forgot about the .start attribute! And I meant GRBCallback.setSolution(), not setNode, sorry. Both setSolution() and cbSetSolution() say they're only possible to use for the MIP, MIPSOL, and MIPNODE callbacks. MIPSOL being a new incumbent makes sense, but what exactly is the difference between the MIP ("Currently in MIP") and MIPNODE ("Currently exploring a MIP node") callbacks? I'd like to do the callback at every single node basically, not just at integer solutions. Related to this I'm not sure why it's actually called any kind of MIP callback, as I don't have any integer variables in my model, but I assume it's just a naming convention?
Best,
Tom0 -
Hi Tom,
MIPSOL being a new incumbent makes sense, but what exactly is the difference between the MIP ("Currently in MIP") and MIPNODE ("Currently exploring a MIP node") callbacks?
The MIPNODE callback is called at every node while the MIP callback is called less frequently because it is not called at every single node. The main impact of the difference can be seen when using a Compute Server. For a MIPNODE callback, we would have to start a communication for every solved node while for the MIP callback we do it less frequently to not die of communication overhead. It's also the reason why MIPNODE callback is not supported when using a Compute server.
Note that nonconvex models are treated as a MIP, i.e., MIPSOL will also be called at incumbents if your model is purely continuous, because continuous variables participating in nonlinear terms are treated the same way as integer variables (namely they are branched on).
Related to this I'm not sure why it's actually called any kind of MIP callback, as I don't have any integer variables in my model, but I assume it's just a naming convention?
We try to explain this naming convention in the Tech Talk - A practical Tour Through Non-Convex Optimization.
Best regards,
Jaromił0 -
Hi Jaromil,
Thanks a lot for the explanations, they were very helpful. I tried to implement a callback function, however, I run into another issue now, before I'm even able to set the heuristic solution. Basically, I need to know the solution from the relaxation at the current node, which is why I start the callback something like this:
where == GRB.Callback.MIPNODE:
sol = model.cbGetSolution([model._vars[0], model._vars[1]]which gives me the following error:
gurobipy.GurobiError: where != GRB.Callback.MIPSOL
Does it mean that cbGetSolution is only callable when using MIPSOL?
Best,
Tom0 -
Hi Tom,
If you want the node relaxation solution point, then you have to use the cbGetNodeRel method. Note that you have to check the node status as described in the documentation.
The cbGetSolution method is used to get the incumbent values and can be called only from MIPSOL and MULTIOBJ callbacks.
Best regards,
Jaromił0 -
Hi Jaromil,
Fantastic, thanks, that worked. Thanks a lot for all the help.
Best,
Tom0
Please sign in to leave a comment.
Comments
6 comments