CPLEX OPL主流程中为多维数组赋值报错:数据元素不存在
问题分析与解决方案
你遇到的报错“Data element 'target' does not exist”,核心原因是模型中索引化参数的定义与你在main函数中赋值的格式不匹配:
- 模型里的
target是通过[a in A][b in B]声明的索引化参数,而你用JavaScript二维数组直接赋值给IloOplDataElements的方式,OPL无法将其映射到索引化参数的结构上,导致无法识别该数据元素。
下面提供两种可行的修复方案:
方案一:修改模型参数定义为二维数组格式
将test.mod中target的定义改为和value一致的二维数组形式,让OPL可以直接识别JS数组结构:
range A = 0..1; range B = 0..1; float value[A][B] = ...; // 修改为二维数组格式,和value保持一致 float target[A][B] = ...; dvar float+ x[A][B] in 0 .. 2; dvar float Z; maximize Z; subject to { Z == sum ( a in A, b in B ) ( value[a,b] * x[a, b] ) ; forall (a in A ) sum ( b in B ) x[a,b] == 2; forall (a in A, b in B ) x[a,b] >= target[a,b]; }
此时你原main函数中的代码无需大改,OPL就能正确解析newTarget这个二维数组作为target的值。
方案二:直接修改opl.data中的索引化参数(更适合循环修改场景)
不需要额外创建IloOplDataElements,而是在模型生成后,直接通过opl.data.target遍历索引赋值,完全贴合OPL的索引化参数结构,也更适合你多次修改参数运行模型的需求:
修改main_test.mod代码如下:
main { var data = new IloOplDataSource("test.dat"); var def = new IloOplModelDefinition(new IloOplModelSource("test.mod")); var cplex = new IloCplex(); var opl = new IloOplModel(def, cplex); opl.addDataSource(data); // 生成模型,初始化所有参数 opl.generate(); // 遍历索引直接修改target参数 for (var a = 0; a <= 1; a++) { for (var b = 0; b <= 1; b++) { opl.data.target[a][b] = 1; } } // 求解并输出结果 if (cplex.solve()) { writeln("目标函数值: ", cplex.getObjValue()); writeln("value参数: ", opl.data.value); writeln("target参数: ", opl.data.target); } else { writeln("求解失败"); } // 释放资源 opl.end(); cplex.end(); }
说明:
opl.generate()会根据模型定义和数据源初始化所有参数,此时opl.data.target已成为可直接访问的索引化参数对象,通过索引赋值即可完成修改。- 这种方式无需处理数据源格式问题,循环修改参数时只需重复赋值+求解步骤即可。
内容的提问来源于stack exchange,提问作者Patrik Ulvdal
相关产品推荐
相关产品推荐

