JuMP non-rectangular variable container: more efficient representation?

Let’s consider a minimal case. I have three kinds of variables: x of length 50, y of length 80, z of length 100. The length actually represents the number of time steps. I know that after time 50, x is always zero, and y becomes zero after time 80. I want to collect them into an array-like container to facilitate subsequent operations, e.g., sum along dim 1. In reality, there are many more than three variables. Essentially, the container should be non-rectangular.

Currently I do it like this:

using JuMP
model = JuMP.Model()
@variable(model, v[1:3, 1:100])
fix.(v[1, 51:100], 0)
fix.(v[1, 81:100], 0)

However,

  • More variables are created than necessary, though the extra variables are fixed to zero. Will these fixed variables still be treated as variables or replaced by 0 in JuMP?
  • Is it appropriate to use SparseAxisArray? Can we apply common array operations like sum to it?
  • Is there any suggestion to improve efficiency by reducing the number of unnecessary variables?
  1. IIRC fix will not replace variables with constant because converting it to a constant is an irreversible operation, you cannot set its upper bound or lower bound afterwards.
  2. SparseAxisArray behaves like a SparseArray. It is also an AbstractArray so sum should work as usual, but common index operation of dense array cannot be used (like v[1, :]). You can access all indices via eachindex(v). It is closer to a Dict{Index, Value} where index is a N dimensional tuple.
    Containers · JuMP gives a clear comparison.
  3. Use SparseAxisArray if your variables are really sparse, otherwise using DenseAxisArray then fixing variables is more convenient.
    If creating variables is not your bottleneck, do not worry about it before profiling. Most solvers will eliminate fixed variables at the presolve step so it will impact the solution time significantly.
2 Likes