JuMP中匹配多元组构建目标函数的索引错误与性能优化问题
解决JuMP目标函数无效索引问题及大数据量性能优化
错误根源分析
你遇到的无效索引错误,本质是字典键类型不匹配:
- 变量
flows的索引是三元组(origin_node, destination_node, coal_group)(来自flowslist) - 但成本字典
total_cash_cost_ex_transp的键是二元组(origin, destination)
直接用三元组(i,j,k)去查询这个字典,自然会触发KeyError,因为字典中不存在这类键。
修正目标函数索引匹配
基础修正写法
直接遍历flowslist中的每个三元组,提取前两个元素作为成本字典的键,对应到变量和成本的乘积求和:
@objective(model, Min, sum(flows[i,j,k] * total_cash_cost_ex_transp[(i,j)] for (i,j,k) in flowslist))
大数据量高效写法
针对499572行的规模,用dot乘积替代循环求和,性能提升更明显:
- 预计算每个变量对应的成本值,生成向量
- 直接创建与
flowslist一一对应的变量集合 - 用
dot实现目标函数的向量乘积
# 预计算成本向量:每个flowslist元素对应一个成本值 cost_vector = [total_cash_cost_ex_transp[(i,j)] for (i,j,k) in flowslist] # 仅创建flowslist中存在的变量,避免冗余 flows_vars = @variable(model, [idx in flowslist], base_name="flows", lower_bound=0) # 用dot实现高效的目标函数求和 @objective(model, Min, dot(cost_vector, flows_vars))
大数据量性能优化要点
1. 选择高效求解器
放弃Cbc这类适合小规模问题的求解器,改用:
- 商业求解器:Gurobi、CPLEX(性能最优)
- 开源高性能求解器:HiGHS(比Cbc快数倍,支持大规模线性规划)
2. 优化约束构造
原PuLP的约束逻辑转JuMP时,避免每次循环都过滤flowslist,提前分组预处理:
# 预处理:按起点分组,提前整理每个起点对应的(终点,煤种)组合 origin_flow_groups = Dict( i => [(j,k) for (i_, j, k) in flowslist if i_ == i] for i in unique(first.(flowslist)) ) # 构造供应约束 for i in keys(origin_flow_groups) @constraint(model, sum(flows_vars[(i,j,k)] for (j,k) in origin_flow_groups[i]) <= supply[i]) end
3. 减少冗余变量
不要创建所有(origin, dest, coal_group)的笛卡尔积变量,只保留flowslist中实际存在的组合——这能大幅减少模型的变量数量,降低求解器的内存占用和计算时间。
验证修正效果
修正后,目标函数不再用三元组查询成本字典,索引匹配问题解决;同时通过预计算和高效求解器,能有效处理近50万行的大规模数据,解决原PuLP的性能瓶颈。
内容的提问来源于stack exchange,提问作者Alex Turnbull
相关产品推荐
相关产品推荐

