CPLEX中用ILOG Script生成子集实现DFJ子回路消除的异常问题
错误原因
- ILOG Script 中集合属于引用类型,你预先定义的全局
emptySet全程指向同一个内存对象,调用subtours.add(emptySet)时存入的是该对象的引用,而非当前值的独立拷贝。 - 循环过程中你反复修改同一个
emptySet的内容(添加元素→存入集合→清空),已经存入subtours的所有条目会同步跟随emptySet的内容变化,最终仅保留了最后一次赋值的状态。
修复方法
不需要提前定义全局辅助集合,每次循环内创建独立的临时集合、构造新的subtour实例存入即可,修改后的代码如下:
execute FillSubtours { for(var i in customers) { // 每次循环新建独立的字符串集合,避免引用复用 var tempSet = new IloOplSetString(); tempSet.add(i); // 显式构造新的subtour实例存入集合 subtours.add(Opl.newSubtour(tempSet)); } writeln(subtours); }
如果后续需要生成所有大小≥2的顾客子集用于DFJ约束,你可以用位运算枚举所有非空子集:
execute FillAllSubtours { var cusArray = new Array(customers); var n = cusArray.length; // 枚举所有非空子集,i从1到2^n -1 for(var i=1; i < (1<<n); i++){ var tempSet = new IloOplSetString(); for(var j=0; j<n; j++){ if(i & (1<<j)){ tempSet.add(cusArray[j]); } } // 可选:过滤掉大小为1的子集,DFJ约束通常只需要大小≥2的子集 if(tempSet.size >=2){ subtours.add(Opl.newSubtour(tempSet)); } } }
内容的提问来源于stack exchange,提问作者arc_rudnevs
相关产品推荐
相关产品推荐

