Is there a way to control/prevent how a LP solver may use information from a previous solve to warm start? I know, e.g., for Gurobi there is LPWarmStart, but I struggle to prevent that for example when using HiGHS.
What happens?
See the MWE at the end. I’d like to use some kind of force_fresh_solve parameter, but could not find anything (even though I vaguely remembered to have seen something similar some time ago…).
Background
Maybe also important why I’m stuck at this: I’m repeatedly solving a model while switching around some settings based on an (un)educated guess of what I expect to be working better for the next solve. Unfortunately, the previous solve prevents a presolve, which hurts more than the warm start helps.
Thanks!
Code for MWE
The following constructs a model, solves it, changes the objective, and re-solves. Not having a previous solution - can be tested by not executing “line 42” - requires 241 simplex iterations, compared to 410 when optimize! was called before.
Note: Happens for dual simplex, or other settings that are changed too.
using JuMP
import HiGHS
import Random: seed!
# Random data.
seed!(12345)
N, M = (500, 500)
A = abs.(randn(N, M))
b = randn(N)
c = abs.(randn(M)), abs.(randn(M))
r = randn(M) .* 100
# Model setup.
m = Model(HiGHS.Optimizer)
set_attribute(m, "simplex_strategy", 4)
@variable(m, r[i] <= x[i = 1:M] <= (r .+ 100)[i])
@constraint(m, A * x .>= b)
@objective(m, Min, c[1]' * x)
# Solve 1.
optimize!(m) # := line 42
# Modify.
@objective(m, Min, c[2]' * x)
# Solve 2.
optimize!(m)
As a high level comment, I get the sense that you are trying too hard to tune the solvers. Worrying about whether it takes 241 or 410 simplex iterations can make a difference for HiGHS and your current test set, but you might find that your parameters etc are suboptimal if you update HiGHS, or if you use some new data in a couple of months. In most cases, letting HiGHS decide to warmstart is probably a good thing.
With that said, the MWE was probably chosen too simple (but it was the only one I could quickly draft). One example for a setting that is a “no-brainer” (ok… under specific circumstances), is presolve: off.
It’s really hard convincing HiGHS to turn presolve on again, for example:
solve (ret: infeasible)
presolve: off
resolve => dualray
ensure feasibility
presolve: on
turn on presolve
try resolve.
Having presolve skipped (even though it’s set to on) - based on an infeasible previous run - may (worst case) prevent HiGHS from finding a solution to the now feasible model.
Buuut… yeah, the actual “performance” code makes use of direct_model. I’ll just refactor to using non direct mode for HiGHS for now, and see if that helps. Maybe I don’t need direct mode at all afterwards.