Reuse a previously optimized model for warm start
AnsweredHi, I'm trying to reuse a previously optimized model as a warm start for the next run. But I'm not sure if I'm doing this correctly. The issue I'm having now is after solving the model, if I directly do "model.optimize()" again, I can see the solving time is significantly shorter. But if I do any slight modification to the model, the solve time is worse.
For example,
# Construct the model
model.update()
model.optimize() # First run
# Modification
for var in model.getVars():
var.Start = var.X
model.update()
model.optimize() # Second run
In this case, the second run is taking longer time than the first run even I'm giving the optimal values to the variables. And technically, I'm not modifying anything in the model, only setting the initial values. But if I remove the modification part, the second run is taking less time, which I assume it is using the previous result. So I'm not sure if this is the correct way to do warm start, or is there anything else I need to set? Thank you.
-
Hi Ruixuan,
Any changes to the model, including setting the
Start
attributes on the variables, reset the solve process. The Gurobi Optimizer uses the previous solution solely as the start solution. For example, consider the following script that solves the example model "glass4.mps":model.read("glass4.mps") model.optimize() # Set the variable Start attributes for var in model.getVars(): var.Start = var.X model.optimize()
When you run the script, you will see the following messages in the log:
Loaded user MIP start with objective 1.20001e+09 MIP start from previous solve did not produce a new incumbent solution
The first message indicates that the Gurobi Optimizer uses the provided start solution. The second message shows that while the optimizer attempted to use the solution from the first call to the
model.optimize()
method, it did not result in a better incumbent than the one already found.It is important to note that the Gurobi Optimizer still needs to prove whether the provided start solution is optimal. Any changes to the model reset the solve process, and the optimizer cannot assume that the provided solution is optimal without further exploration.
Providing a start solution can generally speed up the Gurobi Optimizer, making the second call to the
optimize()
method faster than the first. However, this improvement is not guaranteed.Best regards,
Maliheh
0 -
Thank you so much for the prompt reply.
Can I interpret it as the bottleneck in this particular problem is proving the solution is optimal rather than finding the solution?
Cuz in my case, the solve time is actually quite short (~0.1s), and the solver does not seem taking too much effort in exploring for the solution. The log is attached below.
Gurobi Optimizer version 11.0.3 build v11.0.3rc0 (linux64 - "Ubuntu 20.04.6 LTS")
CPU model: AMD Ryzen 7 3700X 8-Core Processor, instruction set [SSE2|AVX|AVX2]
Thread count: 8 physical cores, 16 logical processors, using up to 16 threads
Optimize a model with 12876 rows, 14822 columns and 60386 nonzeros
Model fingerprint: 0xd12750f4
Model has 3748 quadratic constraints
Model has 664 general constraints
Variable types: 14822 continuous, 0 integer (0 binary)
Coefficient statistics:
Matrix range [1e-03, 1e+00]
QMatrix range [1e+00, 1e+00]
Objective range [1e-06, 1e+00]
Bounds range [1e+03, 1e+03]
RHS range [1e-20, 3e-02]
Loaded user MIP start with objective 0.00306216
MIP start from previous solve did not produce a new incumbent solution
Presolve removed 11547 rows and 12839 columns
Presolve time: 0.07s
Presolved: 1329 rows, 1983 columns, 10069 nonzeros
Presolved model has 1156 SOS constraint(s)
Variable types: 1983 continuous, 0 integer (0 binary)
Root relaxation: cutoff, 406 iterations, 0.02 seconds (0.02 work units)
Nodes | Current Node | Objective Bounds | Work
Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time
0 0 cutoff 0 0.00306 0.00306 0.00% - 0s
Explored 1 nodes (406 simplex iterations) in 0.10 seconds (0.09 work units)
Thread count was 16 (of 16 available processors)
Solution count 1: 0.00306216
Optimal solution found (tolerance 1.00e-04)
Best objective 3.062162877459e-03, best bound 3.062162877459e-03, gap 0.0000%0 -
Can I interpret it as the bottleneck in this particular problem is proving the solution is optimal rather than finding the solution?
This depends on the model and the quality of the start solution. If the provided start solution is optimal, the bottleneck lies in improving the best bound, as is the case in your example. However, if the start solution is merely a feasible but non-optimal solution, the Gurobi Optimizer will need to improve both the incumbent and the best bound.
Maliheh
0 -
Thanks! This makes sense now.
And one more question. If a few more new variables and constraints are added to the model for the second run, will the solver use the previous result to warm start by default? Or should I explicitly set var.Start = var.X, for those variables included in the first run?
0 -
Or should I explicitly set var.Start = var.X, for those variables included in the first run?
As long as you do not call the reset() method on the model object, the solver will utilize the previously computed solution and there is no need to set the Start attributes.
Maliheh
0 -
If I copy the model by model.copy, will the copied model utilize the previously computed solution?
0 -
If I copy the model by model.copy, will the copied model utilize the previously computed solution?
No, you would need to set the Start attributes on the variables of the copied model in this case.
0
Please sign in to leave a comment.
Comments
7 comments