Julia JuMP - 如何将变量与 CartesianIndex 一起使用?
Julia JuMP - how to use variable with CartesianIndex?
为了减小我的变量的大小,我想用 CartesianIndex 定义一个 JuMP 模型。
我尝试了以下代码,但在使用变量时处理 CartesianIndex 时总是遇到问题:
using JuMP, Cbc, IterTools
Random.seed!(3)
N = 10
cost = rand(1:4, N, N)
# reducing size using an index
idx = findall(cost .< 2)
# size reduce from 100 to 22 variables
model = Model(with_optimizer(Cbc.Optimizer));
@variable(model, x[idx], Bin);
# constraint to have only sum(x) = 1 over each row
for i in 1:N
# creating a second CartesianIndex to select row i, then intersect with the 22 indices of x
cart_idx = CartesianIndex.(collect(product(i,1:N)))
cart_idx = intersect(cart_idx, idx)
@constraint(model, sum(x[cart_idx]) == 1)
# ERROR: KeyError: key CartesianIndex{2}[CartesianIndex(1, 5), CartesianIndex(1, 6)] not found
end
循环中最后一行代码抛出错误:
ERROR: KeyError: key CartesianIndex{2}[CartesianIndex(1, 5),
CartesianIndex(1, 6)] not found
是否可以将 CartesianIndex 与 JuMP 变量一起使用,以及如何解决上述问题?
我找到了一个解决方法,尽管我不确定这是最好的编写方法。
我没有使用带有 CartesianIndex 的变量,而是使用一维索引来引用 CartesianIndex 的元素。请参阅下面 x 的定义。
using JuMP, Cbc, IterTools
Random.seed!(3)
N = 10
cost = rand(1:4, N, N)
# reducing size using an index
idx = findall(cost .< 2)
# size reduce from 100 to 22 variables
K = length(idx)
model = Model(with_optimizer(Cbc.Optimizer));
@variable(model, x[1:K], Bin);
# constraint to have only sum(x) = 1 over each row and each column
for i in 1:N
cart_idx = CartesianIndex.(collect(product(i,1:N)))
cart_idx = intersect(cart_idx, idx)
positions = findall([idx[i] in cart_idx for i in 1:K])
@constraint(model, sum(x[positions]) == 1)
end
如果您尝试使用 CartesianIndices 构造 DenseAxisArray,下一版本的 JuMP 将抛出错误。它们并非用于该目的。
您应该使用替代方法:
选项 1
using JuMP, IterTools
Random.seed!(3)
N = 10
cost = rand(1:4, N, N)
model = Model()
@variable(model, x[i=1:N, j=1:N; cost[i, j] < 2], Bin)
@constraint(
model,
[ii=1:N],
sum(x[i, j] for (i, j) in eachindex(x) if ii == i) == 1,
)
选项 2
using JuMP, IterTools
Random.seed!(3)
N = 10
cost = rand(1:4, N, N)
S = [(i, j) for i in 1:N, j in 1:N if cost[i, j] < 2]
model = Model()
@variable(model, x[S], Bin)
@constraint(model, [ii=1:N], sum(x[i, j] for (i, j) in S if ii == i) == 1)
之前post:
我认为 JuMP 中存在一些与笛卡尔索引相关的错误:
julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.
julia> S = CartesianIndex.([2, 4])
2-element Vector{CartesianIndex{1}}:
CartesianIndex(2,)
CartesianIndex(4,)
julia> @variable(model, x[S])
1-dimensional DenseAxisArray{VariableRef,1,...} with index sets:
Dimension 1, CartesianIndex{1}[CartesianIndex(2,), CartesianIndex(4,)]
And data, a 2-element Vector{VariableRef}:
x[CartesianIndex(2,)]
x[CartesianIndex(4,)]
julia> x[CartesianIndex(2,)]
x[CartesianIndex(4,)]
julia> x[CartesianIndex(1,)]
x[CartesianIndex(2,)]
julia> x[CartesianIndex(4,)]
ERROR: BoundsError: attempt to access 2-element Vector{VariableRef} at index [4]
Stacktrace:
[1] getindex
@ ./array.jl:801 [inlined]
[2] getindex
@ ./multidimensional.jl:637 [inlined]
[3] getindex(A::JuMP.Containers.DenseAxisArray{VariableRef, 1, Tuple{Vector{CartesianIndex{1}}}, Tuple{JuMP.Containers._AxisLookup{Dict{CartesianIndex{1}, Int64}}}}, idx::CartesianIndex{1})
@ JuMP.Containers ~/.julia/packages/JuMP/2IF9U/src/Containers/DenseAxisArray.jl:323
[4] top-level scope
@ REPL[42]:1
似乎如果我们有笛卡尔索引作为键,我们应该通过键查找它们,而不是通过典型的笛卡尔索引。
编辑:我打开了一个问题 https://github.com/jump-dev/JuMP.jl/issues/2825
为了减小我的变量的大小,我想用 CartesianIndex 定义一个 JuMP 模型。
我尝试了以下代码,但在使用变量时处理 CartesianIndex 时总是遇到问题:
using JuMP, Cbc, IterTools
Random.seed!(3)
N = 10
cost = rand(1:4, N, N)
# reducing size using an index
idx = findall(cost .< 2)
# size reduce from 100 to 22 variables
model = Model(with_optimizer(Cbc.Optimizer));
@variable(model, x[idx], Bin);
# constraint to have only sum(x) = 1 over each row
for i in 1:N
# creating a second CartesianIndex to select row i, then intersect with the 22 indices of x
cart_idx = CartesianIndex.(collect(product(i,1:N)))
cart_idx = intersect(cart_idx, idx)
@constraint(model, sum(x[cart_idx]) == 1)
# ERROR: KeyError: key CartesianIndex{2}[CartesianIndex(1, 5), CartesianIndex(1, 6)] not found
end
循环中最后一行代码抛出错误:
ERROR: KeyError: key CartesianIndex{2}[CartesianIndex(1, 5), CartesianIndex(1, 6)] not found
是否可以将 CartesianIndex 与 JuMP 变量一起使用,以及如何解决上述问题?
我找到了一个解决方法,尽管我不确定这是最好的编写方法。 我没有使用带有 CartesianIndex 的变量,而是使用一维索引来引用 CartesianIndex 的元素。请参阅下面 x 的定义。
using JuMP, Cbc, IterTools
Random.seed!(3)
N = 10
cost = rand(1:4, N, N)
# reducing size using an index
idx = findall(cost .< 2)
# size reduce from 100 to 22 variables
K = length(idx)
model = Model(with_optimizer(Cbc.Optimizer));
@variable(model, x[1:K], Bin);
# constraint to have only sum(x) = 1 over each row and each column
for i in 1:N
cart_idx = CartesianIndex.(collect(product(i,1:N)))
cart_idx = intersect(cart_idx, idx)
positions = findall([idx[i] in cart_idx for i in 1:K])
@constraint(model, sum(x[positions]) == 1)
end
如果您尝试使用 CartesianIndices 构造 DenseAxisArray,下一版本的 JuMP 将抛出错误。它们并非用于该目的。
您应该使用替代方法:
选项 1
using JuMP, IterTools
Random.seed!(3)
N = 10
cost = rand(1:4, N, N)
model = Model()
@variable(model, x[i=1:N, j=1:N; cost[i, j] < 2], Bin)
@constraint(
model,
[ii=1:N],
sum(x[i, j] for (i, j) in eachindex(x) if ii == i) == 1,
)
选项 2
using JuMP, IterTools
Random.seed!(3)
N = 10
cost = rand(1:4, N, N)
S = [(i, j) for i in 1:N, j in 1:N if cost[i, j] < 2]
model = Model()
@variable(model, x[S], Bin)
@constraint(model, [ii=1:N], sum(x[i, j] for (i, j) in S if ii == i) == 1)
之前post:
我认为 JuMP 中存在一些与笛卡尔索引相关的错误:
julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.
julia> S = CartesianIndex.([2, 4])
2-element Vector{CartesianIndex{1}}:
CartesianIndex(2,)
CartesianIndex(4,)
julia> @variable(model, x[S])
1-dimensional DenseAxisArray{VariableRef,1,...} with index sets:
Dimension 1, CartesianIndex{1}[CartesianIndex(2,), CartesianIndex(4,)]
And data, a 2-element Vector{VariableRef}:
x[CartesianIndex(2,)]
x[CartesianIndex(4,)]
julia> x[CartesianIndex(2,)]
x[CartesianIndex(4,)]
julia> x[CartesianIndex(1,)]
x[CartesianIndex(2,)]
julia> x[CartesianIndex(4,)]
ERROR: BoundsError: attempt to access 2-element Vector{VariableRef} at index [4]
Stacktrace:
[1] getindex
@ ./array.jl:801 [inlined]
[2] getindex
@ ./multidimensional.jl:637 [inlined]
[3] getindex(A::JuMP.Containers.DenseAxisArray{VariableRef, 1, Tuple{Vector{CartesianIndex{1}}}, Tuple{JuMP.Containers._AxisLookup{Dict{CartesianIndex{1}, Int64}}}}, idx::CartesianIndex{1})
@ JuMP.Containers ~/.julia/packages/JuMP/2IF9U/src/Containers/DenseAxisArray.jl:323
[4] top-level scope
@ REPL[42]:1
似乎如果我们有笛卡尔索引作为键,我们应该通过键查找它们,而不是通过典型的笛卡尔索引。
编辑:我打开了一个问题 https://github.com/jump-dev/JuMP.jl/issues/2825