Issue providing start/hint values to variables with Gurobi

Hello to everyone!
I am trying to provide initial guess values or hint values to some variables of an optimization problem, which is intended to be solved using Gurobi. I have read this previous topic for the assignment of inital guesses/hints, and I am using the same command, which is actually accepted during the definition of the optimization model.
Below is reported a minimum example:

using Gurobi
using JuMP

model = Model(Gurobi.Optimizer)

@variable(model, 0.0 <= x1 <= 60.0)
@variable(model, 0.0 <= x2 <= 30.0)
@variable(model, y, Bin)

MOI.set.(model, Gurobi.VariableAttribute("VarHintVal"), x1, 5.0)

@objective(model, Min, 5*x1 - 3*x2)
@constraint(model, 2*x1 + x2 <= 20)
@constraint(model, 10*y <= x2)

JuMP.optimize!(model)

However, when I try to execute the optimization Julia returns this error:

ERROR: ArgumentError: Attribute VarHintVal is Real but Nothing provided.
Stacktrace:
 [1] set(::Gurobi.Optimizer, ::Gurobi.VariableAttribute, ::MathOptInterface.VariableIndex, ::Nothing) at C:\Users\umbe\.julia\packages\Gurobi\7YNJV\src\MOI_wrapper.jl:2928
 [2] _broadcast_getindex_evalf at .\broadcast.jl:631 [inlined]
 [3] _broadcast_getindex at .\broadcast.jl:604 [inlined]
 [4] getindex at .\broadcast.jl:564 [inlined]
 [5] macro expansion at .\broadcast.jl:910 [inlined]
 [6] macro expansion at .\simdloop.jl:77 [inlined]
 [7] copyto! at .\broadcast.jl:909 [inlined]
 [8] copyto! at .\broadcast.jl:864 [inlined]
 [9] copy at .\broadcast.jl:840 [inlined]
 [10] materialize at .\broadcast.jl:820 [inlined]
 [11] set(::Gurobi.Optimizer, ::Gurobi.VariableAttribute, ::Array{MathOptInterface.VariableIndex,1}, ::Array{Union{Nothing, Float64},1}) at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\attributes.jl:369
 [12] set(::MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, ::Gurobi.VariableAttribute, ::Array{MathOptInterface.VariableIndex,1}, ::Array{Union{Nothing, Float64},1}) at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Bridges\bridge_optimizer.jl:842
 [13] _pass_attributes(::MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, ::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}, ::MathOptInterface.Utilities.IndexMap, ::Array{MathOptInterface.AbstractVariableAttribute,1}, ::Tuple{DataType}, ::Tuple{Array{MathOptInterface.VariableIndex,1}}, ::Tuple{Array{MathOptInterface.VariableIndex,1}}, ::Function) at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Utilities\copy.jl:193
 [14] pass_attributes at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Utilities\copy.jl:160 [inlined]
 [15] pass_attributes at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Utilities\copy.jl:154 [inlined]
 [16] default_copy_to(::MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, ::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}, ::Bool, ::Nothing) at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Utilities\copy.jl:468
 [17] #automatic_copy_to#137 at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Utilities\copy.jl:21 [inlined]
 [18] #copy_to#3 at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Bridges\bridge_optimizer.jl:293 [inlined]
 [19] attach_optimizer(::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}) at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Utilities\cachingoptimizer.jl:150
 [20] optimize!(::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}) at C:\Users\umbe\.julia\packages\MathOptInterface\ZJFKw\src\Utilities\cachingoptimizer.jl:211
 [21] optimize!(::Model, ::Nothing; bridge_constraints::Bool, ignore_optimize_hook::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at C:\Users\umbe\.julia\packages\JuMP\e0Uc2\src\optimizer_interface.jl:130
 [22] optimize! at C:\Users\umber\.julia\packages\JuMP\e0Uc2\src\optimizer_interface.jl:106 [inlined] (repeats 2 times)
 [23] top-level scope at none:0

Does anyone have any idea of how can I solve this issue?

Use the start keyword:

@variable(model, 0.0 <= x1 <= 60.0, start = 5.0)

or set_start_value(x1, 5.0).

Docs: Variables · JuMP

Thank you for the answer, I’ll use one of these commands then.
But please, forgive me for insisting, do you think that exists another turnaround to provide the value of the VarHintVal parameter?
Because, according to the Gurobi documentation, this parameter does not imposes an initial guess value, but it guides the optimization process such that the hint values are considered as suggestions to evaluate more carefully with respect to other values.

Hints will affect the heuristics that Gurobi uses to find feasible solutions, and the branching decisions that Gurobi makes to explore the MIP search tree.

And this is something that could be very useful to my case.

Yes, both things are distinct, I think using start will end up in this line so it sets the “Start” parameter, not “VarHintVal”. For solver specific variable attributes your probably will need to unwrap your variables to get the solver-specific reference (I know you need to start usingJuMP.index for this but I do not remember the whole shebang) and then call the low-level functions of Gurobi.jl over them.

1 Like

Two options:

  1. Use model = direct_model(Gurobi.Optimizer()). This gets you closer to the Gurobi model without some of the overhead of JuMP.
  2. Your example exposed a bug in Gurobi.jl To work-around it, set VarHintVal for every variable (not just x1). I’ll open an issue in Gurobi.jl to see if we can fix this.
1 Like