LP Warm Starts - using Gurobi with JuMP

Is there any way to warm start (choose initial vertex for dual simplex algorithm) for a linear program that you’ve created? I have tried using the “PStart” attribute for LPs to no avail, and the “.start” attribute is for MIPs only.

Any help or guidance would be appreciated.

Thanks!

Hi, and welcome!

Long story short: (i) yes there is, but (ii) it depends on the LP solver (and algorithm) you use.
The JuMP function that does so is set_start_value.

I have tried using the “PStart” attribute for LPs to no avail

Can you give more details about what happened there? For instance, did you encounter an error? Did the code run smoothly but the provided warm-start changed nothing?
Providing a minimal working example would help giving specific feedback and identifying the issue: see Please read: make it easier to help you.

There is a lot that may be happening: could be an issue with how you call JuMP, it could be a bug in JuMP itself, it could be that Gurobi silently rejects your warm-start, or that the warm-start you provide is actually detrimental to Gurobi’s performance, etc.
Without a working example one can only speculate which it is.

It is news to me that set_start_value can be used this way, until now I was only able to initialize MIP models with a MIP-start using it, never an LP. Even the documentation pointed in this direction with:

Note: VariablePrimalStarts are sometimes called “MIP-starts” or “warmstarts”.

1 Like

It is news to me that set_start_value can be used this way, until now I was only able to initialize MIP models with a MIP-start using it, never an LP

I wrote so because, in this JuMP tutorial it’s used for a continuous problem (with Ipopt).

Back to Gurobi, the MOI wrapper for VariablePrimalStart falls back to Gurobi’s Start attribute, which is indeed for MIP problems only.

2 Likes

How did you set the attributes?

You probably need to set PStart for every variable and DStart for every constraint.

Hi, thank you very much for your response!

I have been trying to solve an LP with the dual simplex method. I’d like to have a warm start that is not necessarily feasible. I’ll provide a simple code example that shows what I’m trying to do.

import Clp
import Gurobi
import Random
using JuMP
using Gurobi

model = Model(Gurobi.Optimizer)
@variable(model, x[1:2] >= 0)
@objective(model, Max, 2*x[1] + x[2])

@constraint(model, c1, x[1] <= 1)
@constraint(model, c3, x[2] <= 1)
set_optimizer_attribute(model, “Method”, 1) #use dual simplex
set_optimizer_attribute(model, “Presolve”, 0)

set_start_value(x[1], 0.75)
set_start_value(x[2], 0.75)

print(model)
optimize!(model)

The output indicates that the warm start is being ignored. I tried to work around this by adding a superfluous binary variable to the model. This actually worked, and seemed to provide warm starts given that they were feasible. However, when I tried to provide an infeasible initial solution (1.5, 1.5), an error message appears indicating that the warm start is being ignored:

“User MIP start did not produce a new incumbent solution
User MIP start violates constraint R0 by 0.500000000”

Also, regarding PStart - I will try setting the DStart values as well as the previous user suggested. However, it seems like the attribute is unrecognized. When I try “x[1].Start(0.5)” I get the error message “type VariableRef has no field Start”, and a similar message when trying to use PStart.

Thanks again for you help and advice!

The key is in the Gurobi documentation for PStart, DStart, et cetera:

Note that any model modifications which are pending or are made after setting PStart (adding variables or constraints, changing coefficients, etc.) will discard the start. You should only set this attribute after you are done modifying your model.

Check the following minimal working example (note the use of direct_model and the corresponding update). For the primal simplex (Method = 0), it appears sufficient to specify the PStart; conversely, for the dual simplex (Method = 1), it appears sufficient to specify just the DStart). If these values are not specified in the corresponding cases the solver outputs LP warm-start: discard starts.

using JuMP
using Gurobi

model = direct_model(Gurobi.Optimizer())

@variable(model, x[1:2] >= 0)
@objective(model, Max, 2*x[1] + x[2])
@constraint(model, c1, x[1] <= 1)
@constraint(model, c3, x[2] <= 1)
set_optimizer_attribute(model, "Method", 0) # Primal Simplex
set_optimizer_attribute(model, "Presolve", 0)

grb = backend(model)
@show(grb.needs_update) # This yields true
Gurobi.GRBupdatemodel(grb) # Thus, we need to do this

MOI.set(model, Gurobi.VariableAttribute("PStart"), x[1], 0.75)
MOI.set(model, Gurobi.VariableAttribute("PStart"), x[2], 0.75)
#MOI.set(model, Gurobi.ConstraintAttribute("DStart"), c1, 2.0)
#MOI.set(model, Gurobi.ConstraintAttribute("DStart"), c3, 1.0)

optimize!(model)

Output (using Gurobi 9.5):

Optimize a model with 2 rows, 2 columns and 2 nonzeros
Coefficient statistics:
  Matrix range     [1e+00, 1e+00]
  Objective range  [1e+00, 2e+00]
  Bounds range     [0e+00, 0e+00]
  RHS range        [1e+00, 1e+00]
Primal warm-start: 2 superbasic variables.
Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    2.2500000e+00   0.000000e+00   3.000000e+00      0s
       2    3.0000000e+00   0.000000e+00   0.000000e+00      0s

Solved in 2 iterations and 0.00 seconds (0.00 work units)
Optimal objective  3.000000000e+00
1 Like