Okay, this needs https://github.com/jump-dev/JuMP.jl/pull/2916, which will be in the next JuMP release (but likely not today or in the next few days).
Once it lands, you’ll need to implement the Containers.container
function to let JuMP know how to handle the new type. This can be a but tricky as there are a few different indices
that can be passed. But a good first attempt is:
julia> using JuMP, AxisKeys
julia> function Containers.container(f::Function, indices, ::Type{AxisKeys.KeyedArray})
set = collect(indices)
data = [f(s...) for s in set]
return AxisKeys.KeyedArray(data, set)
end
julia> S = ["A", "B", "C", "D"]
4-element Vector{String}:
"A"
"B"
"C"
"D"
julia> model = Model();
julia> @variable(model, x[S], Bin, container = KeyedArray)
1-dimensional KeyedArray(...) with keys:
↓ 4-element Vector{Tuple{String}}
And data, 4-element Vector{VariableRef}:
("A",) x[A]
("B",) x[B]
("C",) x[C]
("D",) x[D]
Note that the keys are x(("A",))
, but you could fix that in the Containers.container
function.
In general though, this syntax isn’t intended for widespread usage or extension (which is why it had a bug and isn’t well documented.
A much better work-around is to go:
julia> model = Model();
julia> @variable(model, x[1:4], Bin)
4-element Vector{VariableRef}:
x[1]
x[2]
x[3]
x[4]
julia> X = KeyedArray(x, S)
1-dimensional KeyedArray(...) with keys:
↓ 4-element Vector{String}
And data, 4-element Vector{VariableRef}:
("A") x[1]
("B") x[2]
("C") x[3]
("D") x[4]
You should think of the built-in JuMP types as a good starting point. But there’s nothing stopping you from creating your own types outside JuMP without trying to interact with the complicated macro machinery.