OPL CPLEX数组索引越界问题求助(含循环固定变量代码)
OPL CPLEX数组索引越界问题求助(含循环固定变量代码)
嗨,我来帮你拆解下这个索引越界的问题,结合你的错误提示和代码细节来看,问题主要出在数组初始化和集合传递的逻辑上,咱们一步步分析:
首先定位错误根源
你遇到的 "Index out of bound for array "x(8)": 2." 错误,本质是代码中访问了数组/变量未定义的索引范围。结合你的代码,核心问题有两个:
output数组初始化长度严重不足
你一开始定义var output = new Array(3);,后续又给output[i][j]赋值时用到了i=1~5、j=1~7,甚至后面要存储r=6~12的结果——但Array(3)生成的数组只有0/1/2三个索引位,访问j=3及以上、i=3及以上都会直接越界。N集合的传递逻辑有问题
你每次迭代时用data.N=thisOplModel.s;,但thisOplModel.s初始是空集合,后续只添加当前iter,导致每次N集合只有单个元素;同时output无法匹配N中动态增加的索引值,进一步加剧了越界问题。
针对性修改方案
我把你的代码调整了关键部分,解决越界问题的同时优化了固定变量的逻辑:
main{ var source = new IloOplModelSource("subset.mod"); var cplex = new IloCplex(); var def = new IloOplModelDefinition(source); // 改用键值对对象存储output,彻底避免数组索引越界 var output = {}; for (var k=1; k<=5; k++) { output[k] = {}; for(var r=1; r<=12; r++) { output[k][r] = 0.0; } } // 维护累积的N集合,确保每次迭代的变量维度正确 var currentN = new IloIntSet(); var isFirstIter = true; for(var iter=6;iter<=12;iter++) { currentN.add(iter); cplex.tilim=300; var opl = new IloOplModel(def,cplex); var data= new IloOplDataElements(); data.N = currentN; data.M = thisOplModel.M; data.Links = thisOplModel.Links; opl.addDataSource(data); opl.generate(); // 第一次迭代没有上一步解,跳过固定变量逻辑 if (!isFirstIter){ for (var r in currentN){ for (var k in data.M){ if (output[k][r] === 1){ opl.x[k][r].LB = output[k][r]; opl.x[k][r].UB = output[k][r]; writeln("xds[",k,"][",r,"] = ",output[k][r]); } } } } // 增加求解判断,避免无解时访问solutionValue报错 if (cplex.solve()) { opl.postProcess(); for (var k in data.M){ for (var r in currentN){ output[k][r] = opl.x[k][r].solutionValue; } } } else { writeln("迭代", iter, "求解失败"); } data.end(); opl.end(); isFirstIter = false; } }
额外注意事项
- 请确保你的
subset.mod中x变量的定义是dvar boolean x[M][N];,这样才能匹配每次迭代中动态扩展的N集合,避免变量维度不匹配的越界。 - 用对象代替数组存储
output是OPL main函数中处理动态索引的常用技巧,比固定长度数组灵活得多,能彻底规避索引越界问题。
备注:内容来源于stack exchange,提问作者yalan
相关产品推荐
相关产品推荐

