Value.(x) with direct mode

I’m trying to reconstruct the optimization problem from the LP file that was generated from some commercial tool that has limited flexibility.
I found a few relevant postings here and learned that I have to use the direct mode.
Here’s the MWE of my case:

using JuMP, Gurobi
m = Model(Gurobi.Optimizer)
@variable(m, -1 <= x[i in 1:2] <= 3)
@objective(m, Min, 3x[1] - 5x[2])

write_to_file(m, "test_direct.lp")

Assuming the LP file was generated from the above code, the below code doesn’t work.

m2 = direct_model(Gurobi.Optimizer())
lp = read_from_file("test_direct.lp")
MOI.optimize!(backend(m2), lp);

all_variables(m2)
termination_status(m2)
value.(x_1_)
value.(m2[:x_1_])

Here’s the error message:

Gurobi Optimizer version 11.0.0 build v11.0.0rc2 (mac64[arm] - Darwin 23.2.0 23C71)

CPU model: Apple M2 Pro
Thread count: 12 physical cores, 12 logical processors, using up to 12 threads

Optimize a model with 0 rows, 2 columns and 0 nonzeros
Model fingerprint: 0x3093ddcd
Coefficient statistics:
  Matrix range     [0e+00, 0e+00]
  Objective range  [3e+00, 5e+00]
  Bounds range     [1e+00, 3e+00]
  RHS range        [0e+00, 0e+00]
Presolve removed 0 rows and 2 columns
Presolve time: 0.00s
Presolve: All rows and columns removed
Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0   -1.8000000e+01   0.000000e+00   0.000000e+00      0s

Solved in 0 iterations and 0.00 seconds (0.00 work units)
Optimal objective -1.800000000e+01

User-callback calls 23, time in user-callback 0.00 sec

2-element Vector{VariableRef}:
 x_1_
 x_2_

OPTIMAL::TerminationStatusCode = 1

ERROR: UndefVarError: `x_1_` not defined
Stacktrace:
 [1] top-level scope
   @ ~/Dropbox/Julia/JuMP-lp_file/ex_writeLPfile.jl:14

ERROR: KeyError: key :x_1_ not found
Stacktrace:
 [1] getindex(m::Model, name::Symbol)
   @ JuMP ~/.julia/packages/JuMP/R53zo/src/JuMP.jl:918
 [2] top-level scope
   @ ~/Dropbox/Julia/JuMP-lp_file/ex_writeLPfile.jl:15

Can anyone let me know if there is a way to use value.(x) in this circumstances?

You’re close, but x_1_ isn’t defined. You need to use variable_by_name.

julia> using JuMP, Gurobi

julia> model = Model(Gurobi.Optimizer)
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: EMPTY_OPTIMIZER
Solver name: Gurobi

julia> @variable(model, -1 <= x[1:2] <= 3)
2-element Vector{VariableRef}:
 x[1]
 x[2]

julia> @objective(model, Min, 3x[1] - 5x[2])
3 x[1] - 5 x[2]

julia> write_to_file(model, "test_direct.lp")

Here’s the recommended option:

julia> lp = read_from_file("test_direct.lp")
A JuMP Model
Minimization problem with:
Variables: 2
Objective function type: AffExpr
`VariableRef`-in-`MathOptInterface.Interval{Float64}`: 2 constraints
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.

julia> set_optimizer(lp, Gurobi.Optimizer)

julia> optimize!(lp)
Gurobi Optimizer version 10.0.0 build v10.0.0rc2 (mac64[x86])

CPU model: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Optimize a model with 0 rows, 2 columns and 0 nonzeros
Model fingerprint: 0x3093ddcd
Coefficient statistics:
  Matrix range     [0e+00, 0e+00]
  Objective range  [3e+00, 5e+00]
  Bounds range     [1e+00, 3e+00]
  RHS range        [0e+00, 0e+00]
Presolve removed 0 rows and 2 columns
Presolve time: 0.00s
Presolve: All rows and columns removed
Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0   -1.8000000e+01   0.000000e+00   0.000000e+00      0s

Solved in 0 iterations and 0.00 seconds (0.00 work units)
Optimal objective -1.800000000e+01

User-callback calls 23, time in user-callback 0.00 sec

julia> x_lp = [variable_by_name(lp, "x_$(i)_") for i in 1:2]
2-element Vector{VariableRef}:
 x_1_
 x_2_

julia> all_variables(lp)  # alternative
2-element Vector{VariableRef}:
 x_1_
 x_2_

julia> value.(x_lp)
2-element Vector{Float64}:
 -1.0
  3.0

But if you really want a model in direct-mode, you can do:

julia> lp = read_from_file("test_direct.lp")
A JuMP Model
Minimization problem with:
Variables: 2
Objective function type: AffExpr
`VariableRef`-in-`MathOptInterface.Interval{Float64}`: 2 constraints
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.

julia> direct = direct_model(Gurobi.Optimizer())
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: DIRECT
Solver name: Gurobi

julia> MOI.copy_to(direct, backend(lp))
MathOptInterface.Utilities.IndexMap with 4 entries:
  MOI.VariableIndex(1)                        => MOI.VariableIndex(1)
  MOI.VariableIndex(2)                        => MOI.VariableIndex(2)
  ConstraintIndex{VariableIndex, Interval{Fl… => ConstraintIndex{VariableIndex, Interval{Float64}}(2)
  ConstraintIndex{VariableIndex, Interval{Fl… => ConstraintIndex{VariableIndex, Interval{Float64}}(1)

julia> optimize!(direct)
Gurobi Optimizer version 10.0.0 build v10.0.0rc2 (mac64[x86])

CPU model: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Optimize a model with 0 rows, 2 columns and 0 nonzeros
Model fingerprint: 0x3093ddcd
Coefficient statistics:
  Matrix range     [0e+00, 0e+00]
  Objective range  [3e+00, 5e+00]
  Bounds range     [1e+00, 3e+00]
  RHS range        [0e+00, 0e+00]
Presolve removed 0 rows and 2 columns
Presolve time: 0.00s
Presolve: All rows and columns removed
Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0   -1.8000000e+01   0.000000e+00   0.000000e+00      0s

Solved in 0 iterations and 0.00 seconds (0.00 work units)
Optimal objective -1.800000000e+01

User-callback calls 23, time in user-callback 0.00 sec

julia> x_direct = [variable_by_name(direct, "x_$(i)_") for i in 1:2]
2-element Vector{VariableRef}:
 x_1_
 x_2_

julia> all_variables(direct)  # alternative
2-element Vector{VariableRef}:
 x_1_
 x_2_

julia> value.(x_direct)
2-element Vector{Float64}:
 -1.0
  3.0
1 Like

@odow Thank you so much! :slight_smile:
It’s great to know that I don’t even have to use the direct mode.

1 Like