Solving to optimal within a timelimit, after which terminating at a feasible solution in gurobipy using callbacks
AnsweredHello there,
I was trying to solve an MIP using gurobipy. I would like to make the optimization two steps:
1. For the first 7200 seconds, solve exhaustedly to optimal;
2. If no feasible solution is found in Step 1 after 7200 seconds, continue running, once one feasible solution is found, terminate with the feasible solution.
I was using call back to implement such strategy, like this (self.m is the gp.Model object)
def optimize(self):
self.m.setParam('TimeLimit', 100)
self.m.setParam('MIPGap', 1e5)
self.m.setParam("SolutionLimit", 1e9)
self.m.optimize(callback=stop_at_feasible)
# Check if any feasible solution was found within 7200 seconds
if self.m.SolCount == 0:
# Reset the TimeLimit and SolutionLimit for the second round of optimization
self.m.setParam('TimeLimit', GRB.INFINITY)
self.m.setParam('SolutionLimit', 1)
self.m.optimize()
# record the solution time
self.sol_time = self.m.Runtime
# record the objective value
self.obj = self.m.objVal
# record the solution status
self.sol_status = self.m.status
self.lb = self.m.ObjBound
# record the solution
self.sol = {}
The call back function `stop_at_feasible`:
def stop_at_feasible(model, where):While the process worked as expected, I found a problem that, for large instances where the presolve takes a lot of time (up to 7200 seconds), then after the callback was called and the second step optimization started, the presolve started from beginning again.
if where == GRB.Callback.MIP:
runtime = model.cbGet(GRB.Callback.RUNTIME)
solcount = model.cbGet(GRB.Callback.MIP_SOLCNT)
if runtime >= 7200 and solcount == 0:
model.terminate() # terminate the current optimization process

Hi Runqiu,
As long as you set a time limit that is smaller or equal to 7200 before calling
self.m.optimize(callback=stop_at_feasible)
your callback function is useless. When setting the time limit, the optimization is stopped as soon as the time limit is reached. When terminating during presolve, the progress cannot be saved, and optimization will continue from the beginning when calling optimize again.
The best option is probably to allow presolve to finish. For this purpose, your callback is needed, and you must remove the time limit. You can stop in your callback when runtime exceeds 7200, regardless of whether a solution was found.I hope this helps,
Marika0 
Hello Marika,
Thank you for your response. I am not sure whether I follow your idea here, here is my modification:
 In the noncallback function, set no time limit and call optimize with the callback. After the callback, check whether there is feasible solution found, if not, run optimize with solution limit 1 but still no time limit.
def optimize(self): self.m.setParam('MIPGap', 1e5) self.m.setParam("SolutionLimit", 1e9) self.m.optimize(callback=stop_at_feasible) # Check if any feasible solution was found within 7200 seconds if self.m.SolCount == 0: # Reset the TimeLimit and SolutionLimit for the second round of optimization self.m.setParam('SolutionLimit', 1) self.m.optimize()
 In the callback function, do model.terminate() if runtime exceeds 7200, i.e.,
def stop_at_feasible(model, where):
if where == GRB.Callback.MIP:
runtime = model.cbGet(GRB.Callback.RUNTIME)
solcount = model.cbGet(GRB.Callback.MIP_SOLCNT)
if runtime >= 7200:
model.terminate() # terminate the current optimization processAm I right here? Then why would this prevent the optimization from starting again? I guess the major difference here is using "terminate() to stop after runtime reached in callback" vs "stop by timelimit parameter"?
Hope I got it right. Thank you again.
Regards,
Runqiu0 
Hi Runqiu,
No, the difference is that your callback does not do anything during presolve. Because you have
if where == GRB.Callback.MIP:
Hence, presolve is completed and not interrupted because of a time limit.
The problem is that the "current status" of the model cannot be saved when terminating during presolve. So, the presolve starts again when calling optimize again.Best regards,
Marika0
Please sign in to leave a comment.
Comments
3 comments