Closed odow closed 4 months ago
This is actually pretty nasty.
We fallback to AbstractVector
methods:
julia> using JuMP
julia> A = [[1, 2, 10], [2, 3, 30]]
2-element Vector{Vector{Int64}}:
[1, 2, 10]
[2, 3, 30]
julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.
julia> @variable(model, x[i in 1:2, j in A[i]])
JuMP.Containers.SparseAxisArray{VariableRef, 2, Tuple{Int64, Int64}} with 6 entries:
[1, 1 ] = x[1,1]
[1, 10] = x[1,10]
[1, 2 ] = x[1,2]
[2, 2 ] = x[2,2]
[2, 3 ] = x[2,3]
[2, 30] = x[2,30]
julia> @constraint(model, x[1, :] in SecondOrderCone())
[x[1,2], x[1,10], x[1,1]] ∈ MathOptInterface.SecondOrderCone(3)
julia> x[1, :] isa AbstractVector{<:AbstractJuMPScalar}
true
entry point is:
which calls:
And eachindex
isn't ordered:
julia> y = x[1, :]
JuMP.Containers.SparseAxisArray{VariableRef, 1, Tuple{Int64}} with 3 entries:
[1 ] = x[1,1]
[10] = x[1,10]
[2 ] = x[1,2]
julia> [y[k] for k in eachindex(y)]
3-element Vector{VariableRef}:
x[1,2]
x[1,10]
x[1,1]
I don't know what a good answer is.
We can't throw an error because that will break existing code like this:
julia> @constraint(model, x[1, :] >= 0)
[x[1,2], x[1,10], x[1,1]] ∈ MathOptInterface.Nonnegatives(3)
The issue is that some vector sets are ordered, and some are not. Here's another set that is problematic:
julia> @constraint(model, x[1, :] in SecondOrderCone())
[x[1,2], x[1,10], x[1,1]] ∈ MathOptInterface.SecondOrderCone(3)
The user could still do dot(a, x[1, :])
where a is some vector of constant so I don't think this is about vector constraints. Maybe we could use an OrderedDict
Hmm:
julia> using JuMP
julia> A = [[1, 2, 10], [2, 3, 30]]
2-element Vector{Vector{Int64}}:
[1, 2, 10]
[2, 3, 30]
julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.
julia> @variable(model, x[i in 1:2, j in A[i]])
JuMP.Containers.SparseAxisArray{VariableRef, 2, Tuple{Int64, Int64}} with 6 entries:
[1, 1 ] = x[1,1]
[1, 10] = x[1,10]
[1, 2 ] = x[1,2]
[2, 2 ] = x[2,2]
[2, 3 ] = x[2,3]
[2, 30] = x[2,30]
julia> y = x[1, :]
JuMP.Containers.SparseAxisArray{VariableRef, 1, Tuple{Int64}} with 3 entries:
[1 ] = x[1,1]
[10] = x[1,10]
[2 ] = x[1,2]
julia> z = rand(3)
3-element Vector{Float64}:
0.508529766285344
0.32511007041899975
0.6771958164053773
julia> using LinearAlgebra
julia> dot(z, y)
0.508529766285344 x[1,2] + 0.32511007041899975 x[1,10] + 0.6771958164053773 x[1,1]
This is more than just a slicing issue:
julia> model = Model();
julia> @variable(model, x[i in 1:2], container = SparseAxisArray)
JuMP.Containers.SparseAxisArray{VariableRef, 1, Tuple{Int64}} with 2 entries:
[1] = x[1]
[2] = x[2]
julia> dot(1:2, x)
x[2] + 2 x[1]
So perhaps we do need an OrderedDict
x-ref https://discourse.julialang.org/t/unexpected-jump-variable-order-when-indexed-by-tuple/110262
User could reasonably expect constraint function to be
[foo[1,1.0], foo[1,11.0], foo[1,100.0]]
.This is because we store the data in a
Dict
.We could swap to an
OrderedDict
, or throw an error or a warning when we convert aSparseAxisArray
to a vector.