如何在CPLEX OPL主函数中迭代更新矩阵并保留历史值
CPLEX OPL迭代中保留矩阵历史值的实现方案
问题说明
需要在OPL主函数的多轮迭代中,让矩阵pa持续累积每一轮迭代的修改值,确保第3次迭代时能同时保留第1、2次迭代的更新结果。当前代码存在pa传递逻辑错误,导致无法累积历史值。
核心修改点
- 将全局矩阵
pa初始化为全0,确保初始状态有明确值 - 每次迭代前将当前
pa的状态传入OPL模型,让模型基于历史值继续计算 - 迭代求解完成后,用模型输出的更新值同步回全局
pa,实现累积 - 优化OPL模型的创建逻辑,避免重复加载资源(可选,提升效率)
修改后的完整代码
int TSlots = 96; range TRange = 1..TSlots; int ncs=6; range csrange=1..ncs; int piles=12; range np=1..piles; int nv=3; range nvrange=1..nv; main { // 全局初始化pa矩阵,全部设为0,避免undefined值 var pa = new Array(piles + 1); // 索引从1开始对应np范围 for (var i = 1; i <= piles; i++) { pa[i] = new Array(TSlots + 1); for (var t = 1; t <= TSlots; t++) { pa[i][t] = 0; } } var source = new IloOplModelSource("subvalue.mod"); var cplex = new IloCplex; var def = new IloOplModelDefinition(source); for(var v=1; v<=nv; v++) { var opl = new IloOplModel(def, cplex); var data = new IloOplDataSource("MultipleStoCS.dat"); var data2 = new IloOplDataElements(); data2.currentnv = v; // 将当前pa的全局状态传入OPL模型 data2.pa = pa; opl.addDataSource(data2); opl.addDataSource(data); opl.generate(); if (!cplex.solve()) { writeln("No solution exists. Stopping."); break; } else { opl.postProcess(); writeln("Iteration ", v, " solution = ", cplex.getObjValue()); // 将模型中更新后的pa同步回全局pa for (var i in opl.np) { for (var t in opl.TRange) { pa[i][t] = opl.pa[i][t]; } } writeln("dslot is ", opl.cslot); writeln("visted pl matrix is", opl.visitpile); writeln("The visited pl is", opl.visitedpile); writeln("The pl availability (current iteration) is", opl.pa); writeln("The pl availability (global cumulative) is", pa); } opl.end(); } cplex.end(); }
配套.mod文件调整说明
确保.mod文件中pa定义为可接收外部传入值的变量,允许主函数传递和修改:
// .mod文件中的pa定义 int pa[np][TRange]; // 移除原初始值,由主函数传入初始状态 // 决策变量定义不变 dvar int cslot[nvrange]; dvar int sreq[nvrange]; dvar int visitedpl[np];
关键逻辑解释
- 全局初始化:提前给
pa的所有元素设为0,避免迭代中出现未定义值导致的计算错误 - 双向数据传递:每次迭代前把全局
pa传给模型,模型基于历史值进行更新;求解完成后再把模型内的pa同步回全局变量,实现迭代间的状态累积 - 完整同步:使用双层循环将模型内
pa的所有元素复制到全局pa,确保所有修改都被保留
内容的提问来源于stack exchange,提问作者SUBHADARSHINI PANDA
相关产品推荐
相关产品推荐

