You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JuMP中能否用VariableRef作索引?最优路径求解遇索引报错

JuMP中使用变量作为矩阵索引的解决方案

你遇到的这个问题是JuMP(以及几乎所有数学规划求解器)的核心限制——优化变量不能直接作为数组或矩阵的索引。这是因为求解器本质上是处理数值变量(连续或离散),而矩阵的索引是离散的标签(比如1、2、3这类确定的整数),求解器无法理解“用一个待求解的变量去定位矩阵元素”这种操作,所以才会抛出ArgumentError: invalid index: chemins[1,1] of type VariableRef的错误。

针对你的路径优化问题,有两种常用的建模方式可以绕过这个限制,具体如下:

方案1:弧流建模(Arc Flow Formulation)

这是路径规划类问题的标准建模方法,核心是把“选择整条路径”拆解为“选择路径中的每一段弧”,用二进制变量来表示是否使用某条弧。

具体步骤:

  1. 定义弧流变量:创建二进制变量x[i, u, v],表示工厂i是否使用从节点u到节点v的弧。
  2. 添加流量守恒约束:确保每个工厂的路径是连续的——除了起点和终点,流入某个节点的弧数量等于流出的弧数量;起点恰好流出1条弧,终点恰好流入1条弧。
  3. 重构目标函数:直接对所有可能的弧求和,用弧的成本R[u,v]乘以对应的变量x[i,u,v]。

修改后的代码示例:

nb_dem, nb_prod, nb_mag, nb_noeuds, S, Q, R = read_data_24(inputfilepath, inputfilename)
@variable(model, produits[1:nb_mag,1:nb_prod,1:nb_dem] >= 0, Int)
# 新增弧流变量:x[i, u, v] 标记工厂i是否使用弧u->v
@variable(model, x[1:nb_mag, 1:nb_noeuds, 1:nb_noeuds], Bin)
@variable(model, binaires[1:nb_mag,1:nb_dem], Bin)

# 重构目标函数:计算所有选中弧的总成本
@objective(model, Min, sum(R[u, v] * x[i, u, v] for i in 1:nb_mag, u in 1:nb_noeuds, v in 1:nb_noeuds))

# 路径约束(请根据你的实际场景替换起点s和终点t)
# 示例:假设所有工厂的起点都是节点1,终点都是最后一个节点nb_noeuds
s = fill(1, nb_mag)
t = fill(nb_noeuds, nb_mag)

for i in 1:nb_mag
    # 流量守恒:中间节点的流入等于流出
    for u in 1:nb_noeuds
        if u != s[i] && u != t[i]
            @constraint(model, sum(x[i, u, v] for v in 1:nb_noeuds) == sum(x[i, v, u] for v in 1:nb_noeuds))
        end
    end
    # 起点必须流出1条弧
    @constraint(model, sum(x[i, s[i], v] for v in 1:nb_noeuds) == 1)
    # 终点必须流入1条弧
    @constraint(model, sum(x[i, v, t[i]] for v in 1:nb_noeuds) == 1)
end

# 保留你原来的其他约束...

方案2:枚举所有可能路径(适合路径数量较少的场景)

如果你的问题中,每个工厂可能的路径数量有限且可以预先枚举,那么可以直接把路径作为候选选项,用二进制变量选择对应的路径。

具体步骤:

  1. 预先生成所有可能的路径集合paths,每个路径是一个节点序列(比如[u1, u2, ..., u_{nb_noeuds+1}])。
  2. 定义二进制变量y[i, p],表示工厂i是否选择第p条路径。
  3. 添加约束:每个工厂恰好选择一条路径(sum(y[i,p] for p in paths) = 1)。
  4. 目标函数:计算每条路径的总成本,再乘以对应的选择变量求和。

简化示例代码:

# 假设你已经生成了所有可能的路径集合paths,每个元素是节点数组
paths = generate_all_possible_paths(nb_noeuds) # 你需要实现这个生成函数

nb_dem, nb_prod, nb_mag, nb_noeuds, S, Q, R = read_data_24(inputfilepath, inputfilename)
@variable(model, produits[1:nb_mag,1:nb_prod,1:nb_dem] >= 0, Int)
@variable(model, y[1:nb_mag, 1:length(paths)], Bin)
@variable(model, binaires[1:nb_mag,1:nb_dem], Bin)

# 计算每条路径的成本
path_costs = [sum(R[path[k], path[k+1]] for k in 1:nb_noeuds) for path in paths]

# 目标函数
@objective(model, Min, sum(path_costs[p] * y[i, p] for i in 1:nb_mag, p in 1:length(paths)))

# 约束:每个工厂选一条路径
for i in 1:nb_mag
    @constraint(model, sum(y[i, p] for p in 1:length(paths)) == 1)
end

# 保留其他约束...

选择建议

  • 如果路径数量较多(比如节点数超过10),优先用弧流建模,虽然变量数量多,但求解器的线性规划/整数规划求解器能高效处理这类结构清晰的约束。
  • 如果路径数量很少,枚举路径的方式更直观,变量数量也更少。

内容的提问来源于stack exchange,提问作者anni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:27:12