CPLEX Java API自动Benders分解变量标注报错及相关问题咨询
CPLEX用户自定义Benders分解标注问题解答
问题背景
使用CPLEX 20.10版本,尝试通过USER策略实现自动Benders分解,自定义变量标注划分主问题与子问题。初始化Benders策略与标注后,创建整数变量并尝试标注为主问题变量(值=0)时,触发如下错误:
ilog.cplex.IloCplex$UnknownObjectException: CPLEX Error: object is unknown to IloCplex at ilog.cplex.IloCplex.getIndexOrException(IloCplex.java:11470) at ilog.cplex.IloCplex.access$7400(IloCplex.java:453) at ilog.cplex.IloCplex$AnnotationList.getIndexAndType(IloCplex.java:22273) at ilog.cplex.IloCplex$AnnotationList.setAnnotation(IloCplex.java:22302) at ilog.cplex.IloCplex.setAnnotation(IloCplex.java:22851)
错误代码片段:
cplex.setParam(IloCplex.Param.Benders.Strategy, IloCplex.BendersStrategy.User); IloCplex.LongAnnotation benders = cplex.newLongAnnotation("cpxBendersPartition"); IloIntVar [] x = new IloIntVar[NumofX]; //integer for(int k=0; k < x.length; k++) { x[k] = cplex.intVar(0,UB,"x_"+k); cplex.setAnnotation(benders, x[k], 0); }
问题解答
1. 错误原因
CPLEX仅能识别已添加到模型中的对象。你创建变量x[k]后直接调用setAnnotation设置标注,但此时变量还未被加入CPLEX的模型实例,CPLEX无法识别该变量对象,因此抛出UnknownObjectException。
2. 正确的变量标注方法
必须先将变量添加到CPLEX模型,再设置Benders分区标注。有两种常见实现方式:
- 方式一:创建变量后直接调用
addVar加入模型,再设置标注
cplex.setParam(IloCplex.Param.Benders.Strategy, IloCplex.BendersStrategy.User); IloCplex.LongAnnotation benders = cplex.newLongAnnotation("cpxBendersPartition"); IloIntVar [] x = new IloIntVar[NumofX]; for(int k=0; k < x.length; k++) { x[k] = cplex.intVar(0,UB,"x_"+k); cplex.addVar(x[k]); // 将变量加入模型 cplex.setAnnotation(benders, x[k], 0); // 标注为主问题变量(值=0) } // 子问题变量标注示例:将y变量标注为子问题1的变量(值=1) IloNumVar[] y = new IloNumVar[NumofY]; for(int j=0; j < y.length; j++) { y[j] = cplex.numVar(LB, UB, "y_"+j); cplex.addVar(y[j]); cplex.setAnnotation(benders, y[j], 1); }
- 方式二:通过构建并添加约束间接将变量关联到模型,之后再设置标注(变量会在约束添加时自动被CPLEX识别)
3. 导出主问题与子问题的LP文件
可以通过设置CPLEX的Benders.WriteLevel参数实现:
// 设置参数:2表示导出主问题和所有子问题的LP文件 cplex.setParam(IloCplex.Param.Benders.WriteLevel, 2); cplex.solve(); // 求解过程中,CPLEX会自动在工作目录生成对应的LP文件
参数说明:
- 值为1:仅导出主问题LP文件
- 值为2:导出主问题和所有子问题LP文件
内容的提问来源于stack exchange,提问作者CHE
相关产品推荐
相关产品推荐

