# Can you define a JuMP variable using the keys of an existing DenseAxisArray?

**URL:** <https://discourse.julialang.org/t/can-you-define-a-jump-variable-using-the-keys-of-an-existing-denseaxisarray/76443>\
**Category:** Optimization (Mathematical)\
**Tags:** jump\
**Created:** [February 14, 2022, 4:22pm UTC](https://discourse.julialang.org/t/can-you-define-a-jump-variable-using-the-keys-of-an-existing-denseaxisarray/76443 "2022-02-14T16:22:12Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![MartinBonde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martinbonde/32/33200_2.png) [@MartinBonde](https://discourse.julialang.org/u/MartinBonde)\
**Post date:** [February 14, 2022, 4:22pm UTC](https://discourse.julialang.org/t/can-you-define-a-jump-variable-using-the-keys-of-an-existing-denseaxisarray/76443/1 "2022-02-14T16:22:12Z")

</div>

Say I have a variable defined over two axes:

```julia
@variable(m, x[1:3,[:a, :b]])

2-dimensional DenseAxisArray{VariableRef,2,...} with index sets:
    Dimension 1, Base.OneTo(3)
    Dimension 2, [:a, :b]
And data, a 3×2 Matrix{VariableRef}:
 x[1,a] x[1,b]
 x[2,a] x[2,b]
 x[3,a] x[3,b]

```

Is there a way to dynamically define a second variable using the keys of the first?  
For example, one might expect `@variable(m, y[axes(x)...])` to work, but this unfortunately results in an error: “cannot use splatting operator `...` in the definition of an index set.”

Using keys(x) as the index of y results in a variable that cannot be indexed in the same way as x. E.g. y[1,:a] will not work:

```julia
@variable(m, y[keys(x)])

1-dimensional DenseAxisArray{VariableRef,1,...} with index sets:
    Dimension 1, JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}[JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((1, :a)), JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((2, :a)), JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((3, :a)), JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((1, :b)), JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((2, :b)), JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((3, :b))]
And data, a 6-element Vector{VariableRef}:
 y[JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((1, :a))]
 y[JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((2, :a))]
 y[JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((3, :a))]
 y[JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((1, :b))]
 y[JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((2, :b))]
 y[JuMP.Containers.DenseAxisArrayKey{Tuple{Int64, Symbol}}((3, :b))]

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 14, 2022, 6:47pm UTC](https://discourse.julialang.org/t/can-you-define-a-jump-variable-using-the-keys-of-an-existing-denseaxisarray/76443/2 "2022-02-14T18:47:34Z")

</div>

Hmm. You can’t do it via the macros because they use the syntax as typed, not the value of the variable in `axes(x)`. What’s the use-case for this?

It’s not pretty, but:

```nohighlight
julia> m = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.

julia> @variable(m, x[1:3, [:a, :b]])
2-dimensional DenseAxisArray{VariableRef,2,...} with index sets:
    Dimension 1, Base.OneTo(3)
    Dimension 2, [:a, :b]
And data, a 3×2 Matrix{VariableRef}:
 x[1,a] x[1,b]
 x[2,a] x[2,b]
 x[3,a] x[3,b]

julia> N = length.(axes(x))
(3, 2)

julia> Y = reshape([VariableRef(m) for _ in 1:prod(N)], N)
3×2 Matrix{VariableRef}:
 _[7] _[10]
 _[8] _[11]
 _[9] _[12]

julia> y = Containers.DenseAxisArray(Y, axes(x)...)
2-dimensional DenseAxisArray{VariableRef,2,...} with index sets:
    Dimension 1, Base.OneTo(3)
    Dimension 2, [:a, :b]
And data, a 3×2 Matrix{VariableRef}:
 _[7] _[10]
 _[8] _[11]
 _[9] _[12]

```

---

<div class="post-metadata">

**Author:** ![MartinBonde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martinbonde/32/33200_2.png) [@MartinBonde](https://discourse.julialang.org/u/MartinBonde)\
**Post date:** [February 14, 2022, 7:08pm UTC](https://discourse.julialang.org/t/can-you-define-a-jump-variable-using-the-keys-of-an-existing-denseaxisarray/76443/3 "2022-02-14T19:08:59Z")

</div>

Thanks for the example! I might be able to put something together using snippets from there.

I wanted to generate a residual variable for each of my non-linear equations, so that the equations can effectively be turned off by unfixing the residual. I have a mostly working macro written similarly to the existing JuMP macros, but I find it quite difficult to debug some of the macro hygiene edge cases and am trying to refactor as a macro that simply calls a function.

BUT, a much simpler use case is actually right there in the manual:

```julia
julia> N = 10
10

julia> S = [(1, 1, 1), (N, N, N)]
2-element Vector{Tuple{Int64, Int64, Int64}}:
 (1, 1, 1)
 (10, 10, 10)

julia> @time @variable(model, x1[i=1:N, j=1:N, k=1:N; (i, j, k) in S])
  0.203861 seconds (392.22 k allocations: 23.977 MiB, 99.10% compilation time)
JuMP.Containers.SparseAxisArray{VariableRef, 3, Tuple{Int64, Int64, Int64}} with 2 entries:
  [1, 1, 1] = x1[1,1,1]
  [10, 10, 10] = x1[10,10,10]

julia> @time @variable(model, x2[S])
  0.045407 seconds (65.24 k allocations: 3.771 MiB, 99.15% compilation time)
1-dimensional DenseAxisArray{VariableRef,1,...} with index sets:
    Dimension 1, [(1, 1, 1), (10, 10, 10)]
And data, a 2-element Vector{VariableRef}:
 x2[(1, 1, 1)]
 x2[(10, 10, 10)]

```

Note that the second example while more performant results in a different notation.  
E.g. x2 cannot be accessed as `x2[1, 1, 1]`.
