Access variables in vector using Symbols

I have a model with variables defined as a is below, I need to be able to access the models variables in a model agnostic way. For this I use Symbols as model[:b] will get me b for any model which has a variable b.

How can I do this when the variables are defined as a vector

model = Model()
@variable(model, 0 ≤  a[1:3] ≤ 1)
@variable(model, 0 ≤  b ≤ 1)
model[:b]
sa = Symbol(a[1])
sb = Symbol(b)
model[sb] # works
model[sa]
ERROR: KeyError: key Symbol("a[1]") not found

A example of why I use symbols, maybe there’s a better way

models = [copy(model) for _ in 1:4]
[MOI.set(models[ii], MOI.Name(), "Model : $ii") for ii in 1:4]
[m[:b] for m in models] # Works
[m[sa] for m in models] # ERROR: KeyError: key Symbol("a[1]") not found

While quite ugly, this does work. It could be made tidier by a PR to JuMP.getindex, would this be wanted in JuMP?

function get_var(m::JuMP.AbstractModel, name::Symbol)
    try
        return JuMP.getindex(m,name)
    catch
        var_name=Symbol(match(r"^\w+", String(name)).match)
        var = JuMP.getindex(m,var_name)
        var_num=parse(Int,(match(r"\d+", String(name)).match))
        return var[var_num]
    end
end

You need model[:a][1]. model[:a] fetches the vector of variables.

See also variable_by_name: Variables · JuMP

3 Likes

I appreciate this, and it is what I am doing here

But given that the symbol has the vector index information I think it would be beneficial if you could access variables in a vector the same way as you can an individual variable.

While the method I wrote works, to use the m[sa] syntax it would require the same function signature as JuMP.getindex causing an infinite loop.

Would you consider a PR which allowed JuMP.getindex to work with m[sa]?

Did you see variable_by_name?

We wont be adding a method for the Symbol lookup. I think you might want the String one instead.

I did, but I was hoping for a method using the concise and consistent []. Although it isn’t a big deal, I can just make a new dispatch for function String(v::VariableRef)

variable_by_name(model,String(Symbol(model[:a][5])))

Thank you.

The syntax model[key] is a short-cut for object_dictionary(model)[key], which has a very particular meaning. In particular, it’s not a mechanism for looking up particular variables and constraints, but also containers of variables and constraints.

We also have to think about more general uses of JuMP. For example if someone did @variable(model, x[[:a, :b]]), then they might also expect model[Symbol("x[:a]")] to work, but that gets tricky to implement.

Thank you for your answer and explaining why this wouldn’t be practical to implement. I’ve adopted the variable_by_name methodology.

2 Likes