Question about eachindex behavior in DenseAxisArray in JuMP

This is more of a question of whether this is expected behavior or a corner case that should not work correctly anyway.

When we run this code the access of indices through the use of eachindex in dense axis array is not working as I would expect.

using JuMP
m = Model()
aux = [[1,2,3,4],[2,3],[]]
@variable(m, sparse_var[i = 1:3, j in aux[i]])
@variable(m, dense_var[i = 1:3, j in [1, 2, 4]])
eachindex(sparse_var)
eachindex(dense_var)

(1, 4) in eachindex(sparse_var) # true and I expected it to be true
(1, 4) in eachindex(dense_var) # false but I expected it to be true

# some debug on why it does not work as I was expecting
dense_var[1, 4] == dense_var[CartesianIndex(1, 3)]

I don’t know if eachindex makes any claims about the eltype of the iterator that it returns.

In this case, sparse_var returns the keys of the underlying dictionary:

julia> eachindex(sparse_var)
KeySet for a OrderedCollections.OrderedDict{Tuple{Int64, Int64}, VariableRef} with 6 entries. Keys:
  (1, 1)
  (1, 2)
  (1, 3)
  (1, 4)
  (2, 2)
  (2, 3)

whereas dense_var returns the Cartesian indices

julia> eachindex(dense_var)
CartesianIndices((3, 3))

So (1, 4) in eachindex(dense_var) is false, because they are different types.

One re-occuring problem is that we’ve tried to make it so that sparse_var and dense_var behave similarly. But there are actually many cases where there are subtle differences. Trying to write code that works for both DenseAxisArray and SparseAxisArray is difficult. We probably should have defaulted sparse_var to return a Dict. That’s what it is under the hood…

1 Like