Hello,
I seem to frequently encounter situations where accounting for boundary/initial conditions requires “extending” vectors in a way similar to padding, but where padded values are not necessarily constant and might not even be of the same type as the values stored in the parent vector.
Latest case in point:
(Minimal code to make the example runnable)
struct ExtendedVector{N, T, V}
vec :: V
ext :: NTuple{N, Pair{Int, T}}
end
extend_vector(vec, args...) = ExtendedVector(vec, args)
function Base.getindex(ev::ExtendedVector, i::Int)
for (j, v) in ev.ext
i == j && return v
end
return ev.vec[i]
end
julia> using JuMP
julia> m = Model();
julia> N = 5;
julia> @variable(m, x[1:N]);
julia> # Everything should behave as if
# x̄[0] == 0, and
# x̄[N+1] == 1
x̄ = extend_vector(x, 0=>0, N+1=>1);
julia> # No need for explicit code to take care of boundary conditions
@constraint(m, [i∈1:N],
x̄[i+1] - 2x̄[i] + x̄[i-1] <= 1)
5-element Vector{ConstraintRef{...}}:
-2 x[1] + x[2] ≤ 1
x[1] - 2 x[2] + x[3] ≤ 1
x[2] - 2 x[3] + x[4] ≤ 1
x[3] - 2 x[4] + x[5] ≤ 1
x[4] - 2 x[5] ≤ 0
I’m not sure how to call such an “extended vector”. Does there exist anything like this in the ecosystem? Under what name?
I can use the minimal implementation above in my real use case, but I expect things might get more complicated very quickly if I ever need more features (like a full AbstractVector
-like behavior). And if something more fancy already exists, I might as well use it instead.