Using GUROBI with python. When solving a MILP, I notice that the incumbent is very early (25sec) at the optimal point but the best bound is so slow to fall (maximization problem) that it takes ages (2000sec+) for reaching the optimal solution. Any suggestions for changing the parameters that could make it happen faster?
3 Answers
You could try changing the parameter mipfocus to 2 or 3 (https://www.gurobi.com/documentation/9.0/refman/mipfocus.html) in order to let Gurobi focus more on improving the bound or proving optimality.
You can also try to set Cuts (https://www.gurobi.com/documentation/9.0/refman/cuts.html) to 2 in order to let Gurobi be more aggressive with the Cuts.
But you need to examine the Log and see if the problem is primarily solved with Cuts or Branching or both.
-
$\begingroup$ Thank you very much. There is a minor improvement only though, I guess the hardness in finding a solution quickly can be attributed to the extensive big-M usage. Do you believe that it could improve if I experiment with changing the M values in order to find the minimum possible ones? $\endgroup$ Jul 8, 2020 at 13:27
-
1$\begingroup$ You should probably try indicator constraints if you're using Gurobi $\endgroup$– GgouvineJul 8, 2020 at 19:37
-
$\begingroup$ Makis, as this does not appear to be an answer, I have converted it to a comment under the top answerer's post to notify them. $\endgroup$– TheSimpliFire ♦Jul 8, 2020 at 19:46
If you have a recent enough version of Gurobi, there is a tuning tool that tries to find better parameter sets than the default settings. For best results, run it for a while (at least overnight) and run it with a few different instances of your problem. Here is some example code you can use to run it.
def tune(model, time_limit=-1, trials_per_setting=3):
"""Tunes a Gurobi model with basic settings. Parameter sets that
Gurobi sees as an improvement are saved to tune0.prm, tune1.prm,
etc. Parameter sets are stored in order of decreasing quality, with
parameter set 0 being the best.
Args:
model: an instance of a Gurobi model
time_limit: total number of seconds to spend tuning. Default of
-1 will choose a time limit automatically.
trials_per_setting: number of trials to use per parameter set to
reduce the effects of randomness. Default is 3.
"""
model.setParam('TuneTimeLimit', time_limit)
model.setParam('TuneTrials', trials_per_setting)
model.update()
model.tune()
for i in range(model.tuneResultCount):
model.getTuneResult(i)
model.write('tune'+str(i)+'.prm')
For more information, see the documentation: https://www.gurobi.com/documentation/9.0/refman/parameter_tuning_tool.html#sec:Tuning
In addition to the above answers:
It depends on what you want from the MIP-run. If you want to your run to find feasible solutions quickly, then keep model.params.MIPFocus=1
; if you are not facing difficulty in finding feasible solutions but want to focus on proving the optimality of these solutions, then keep model.params.MIPFocus=2
; or if you want your run to improve the best-objective bound, then keep model.params.MIPFocus=3
.
I found this thread on Google's Gurobi discussion group useful. The other parameters that affect the performance of a MIP-run are (documentation):
model.params.Method
linkmodel.params.ConcurrentMIP
linkmodel.params.Cuts
model.params.NoRelHeuristic
model.params.Heuristics
linkmodel.params.RINS
model.params.ImproveStartNodes
model.params.ImproveStartTime
You could also run grbtune
tool as suggested above to tune the settings of the above parameters.