Hello, in a JuMP model I need to fix some variables, and these variables to fix are defined in a dictionary.
This works:
using JuMP, Ipopt
fvars = Dict{String,Float64}("c" => 5)
m = Model(Ipopt.Optimizer)
# [...]
@variable(m, c)
for (k,v) in fvars
fix(eval(Symbol(k)), v; force = true)
end
# [...]
However if I wrap the model in a module I got an UndefVarError:
module Foo
using JuMP, Ipopt
function foo()
fvars = Dict{String,Float64}("c" => 5)
m = Model(Ipopt.Optimizer)
# [...]
@variable(m, c)
for (k,v) in fvars
fix(eval(Symbol(k)), v; force = true)
end
# [...]
end
end
ERROR: UndefVarError: cnot defined inMain.Foo``
I guess the “eval” somehow happens too early, is there any workaround ?
First. Never use eval. It is always the wrong thing to do.
Either use variable_by_name, or, if the variable is registered, convert the string to a symbol and do model[Symbol(k)]:
using JuMP, Ipopt
function foo()
fvars = Dict{String,Float64}("c" => 5)
m = Model(Ipopt.Optimizer)
@variable(m, c)
for (k, v) in fvars
# Option 1
x = variable_by_name(m, k)
fix(x, v; force = true)
# Option 2
x = m[Symbol(k)]
fix(x, v; force = true)
end
end
More generally, consider using some sort of data structure that you control:
using JuMP, Ipopt
function foo()
fvars = Dict{String,Float64}("c" => 5)
my_variables = Dict{String,VariableRef}()
m = Model(Ipopt.Optimizer)
my_variables["c"] = @variable(m, c)
for (k, v) in fvars
fix(my_variables[k], v; force = true)
end
end