Java+LazyConstraintCallback 中的 CPLEX 未知对象异常
Java+CPLEX Unknown Object Exception in LazyConstraintCallback
我对 CPLEX+ 还很陌生Java。我尝试实现定向问题和接送问题的变体。我想使用 LazyConstraintCallback 来确保 Integer Solutions 中的 Subtour Elimination。
由于定向组件,我需要一个额外的变量 (z[q]) 用于回调,目前模型中还没有包含它。
protected void main() throws IloException {
// first: test if more than one route exists
int[][] cycles = getCycles(getLongRoute());
int count = countCycles(cycles);
IloNumVar[] z = model.boolVarArray(count);
if (count > 1) {
// add connectivity constraints
int b = 1;
for (int q = 0;q<cycles.length; q++) {
IloLinearNumExpr expr1 = model.linearNumExpr();
int[] cycle = cycles[q];
int m = 0;
for (int p = 0; p<cycle.length; p++) {
int i = ArrayHandler.getIndex(allLocations_k, cycle[p]);
for (int l = 0; l<cycle.length; l++) {
int j = ArrayHandler.getIndex(allLocations_k, cycle[l]);
if (i!=j) {
expr1.addTerm(1.0, x[i][j]);
}
}
if (ArrayHandler.contains(deliveryLocation_k, allLocations_k[i])) {
expr1.addTerm(ak[i], 1.0);
} else {
m++;
expr1.addTerm(ak[i], -1.0);
}
}
for (int p = 0; p<loc_k; p++) {
int i = allLocations_k[p];
if (!ArrayHandler.contains(cycle, i)) {
IloLinearNumExpr expr2 = model.linearNumExpr();
if (ArrayHandler.contains(deliveryLocation_k, i)) {
expr2.addTerm(ak[p], 1.0);
expr2.addTerm(z[q],-1.0);
this.add(model.le(expr2,0.0));
//this.addLe(expr2, z[q]);
} else {
expr2.addTerm(ak[p], 1.0);
expr2.addTerm(z[q], 1.0);
this.add(model.ge(expr2,1.0));
//model.addLe(1.0,expr2);
}
}
}
expr1.setConstant(m);
expr1.addTerm(z[q], -1.0);
this.add(model.le(0.0, expr1));
}
}
}
它在读取 "this.add(model.ge(expr2,z[q]));" 后抛出 "Unknown Object" 错误,这是它应该添加的第一个约束。我猜想这种行为与未知变量 z[q] 有某种联系。我必须在另一个位置添加它吗?我不知道 z[q] 的最终维度,因为在执行过程中发现的每个子路线都需要一个 z[q],这可能会呈指数级增长(这就是我希望能够动态创建它的原因)。
也许错误消息有帮助:
ilog.cplex.IloCplex$UnknownObjectException: CPLEX Error: object is unknown to IloCplex
at ilog.cplex.CpxNumVar.getVarIndexValue(CpxNumVar.java:295)
at ilog.cplex.CpxLinearExpr.removeDuplicatesSafe(CpxLinearExpr.java:476)
at ilog.cplex.CpxCutCallback.addCut(CpxCutCallback.java:75)
at ilog.cplex.IloCplex$LazyConstraintCallback.add(IloCplex.java:14920)
at PDOP$IntegerCutCallback.main(PDOP.java:334)
at ilog.cplex.CpxCallback.callmain(CpxCallback.java:160)
at ilog.cplex.CpxLazyConstraintCallbackFunction.callIt(CpxLazyConstraintCallbackFunction.java:45)
at ilog.cplex.Cplex.CPXmipopt(Native Method)
at ilog.cplex.CplexI$SolveHandle.start(CplexI.java:2786)
at ilog.cplex.CplexI.solve(CplexI.java:2912)
at ilog.cplex.IloCplex.solve(IloCplex.java:10434)
at PDOP.solveIBR(PDOP.java:193)
at Application.main(Application.java:33)
我希望这不是 "too" 愚蠢的问题,我试图在网上找到有关此行为的信息,但没有找到任何需要添加变量的示例。
我继续阅读它,似乎根本不可能在 LazyConstraint (https://www.or-exchange.org/questions/14311/adding-variables-or-modifying-existing-constraints-during-callbacks-with-cplex-c) 中添加额外的变量
我能够重新表述我的问题(它不是那么简洁易读,但有效......),它比直接在问题中包含 subtour 消除约束更快,并且仍然会导致可行解决方案。
感谢 rkersh 的帮助:)
我对 CPLEX+ 还很陌生Java。我尝试实现定向问题和接送问题的变体。我想使用 LazyConstraintCallback 来确保 Integer Solutions 中的 Subtour Elimination。
由于定向组件,我需要一个额外的变量 (z[q]) 用于回调,目前模型中还没有包含它。
protected void main() throws IloException {
// first: test if more than one route exists
int[][] cycles = getCycles(getLongRoute());
int count = countCycles(cycles);
IloNumVar[] z = model.boolVarArray(count);
if (count > 1) {
// add connectivity constraints
int b = 1;
for (int q = 0;q<cycles.length; q++) {
IloLinearNumExpr expr1 = model.linearNumExpr();
int[] cycle = cycles[q];
int m = 0;
for (int p = 0; p<cycle.length; p++) {
int i = ArrayHandler.getIndex(allLocations_k, cycle[p]);
for (int l = 0; l<cycle.length; l++) {
int j = ArrayHandler.getIndex(allLocations_k, cycle[l]);
if (i!=j) {
expr1.addTerm(1.0, x[i][j]);
}
}
if (ArrayHandler.contains(deliveryLocation_k, allLocations_k[i])) {
expr1.addTerm(ak[i], 1.0);
} else {
m++;
expr1.addTerm(ak[i], -1.0);
}
}
for (int p = 0; p<loc_k; p++) {
int i = allLocations_k[p];
if (!ArrayHandler.contains(cycle, i)) {
IloLinearNumExpr expr2 = model.linearNumExpr();
if (ArrayHandler.contains(deliveryLocation_k, i)) {
expr2.addTerm(ak[p], 1.0);
expr2.addTerm(z[q],-1.0);
this.add(model.le(expr2,0.0));
//this.addLe(expr2, z[q]);
} else {
expr2.addTerm(ak[p], 1.0);
expr2.addTerm(z[q], 1.0);
this.add(model.ge(expr2,1.0));
//model.addLe(1.0,expr2);
}
}
}
expr1.setConstant(m);
expr1.addTerm(z[q], -1.0);
this.add(model.le(0.0, expr1));
}
}
}
它在读取 "this.add(model.ge(expr2,z[q]));" 后抛出 "Unknown Object" 错误,这是它应该添加的第一个约束。我猜想这种行为与未知变量 z[q] 有某种联系。我必须在另一个位置添加它吗?我不知道 z[q] 的最终维度,因为在执行过程中发现的每个子路线都需要一个 z[q],这可能会呈指数级增长(这就是我希望能够动态创建它的原因)。 也许错误消息有帮助:
ilog.cplex.IloCplex$UnknownObjectException: CPLEX Error: object is unknown to IloCplex
at ilog.cplex.CpxNumVar.getVarIndexValue(CpxNumVar.java:295)
at ilog.cplex.CpxLinearExpr.removeDuplicatesSafe(CpxLinearExpr.java:476)
at ilog.cplex.CpxCutCallback.addCut(CpxCutCallback.java:75)
at ilog.cplex.IloCplex$LazyConstraintCallback.add(IloCplex.java:14920)
at PDOP$IntegerCutCallback.main(PDOP.java:334)
at ilog.cplex.CpxCallback.callmain(CpxCallback.java:160)
at ilog.cplex.CpxLazyConstraintCallbackFunction.callIt(CpxLazyConstraintCallbackFunction.java:45)
at ilog.cplex.Cplex.CPXmipopt(Native Method)
at ilog.cplex.CplexI$SolveHandle.start(CplexI.java:2786)
at ilog.cplex.CplexI.solve(CplexI.java:2912)
at ilog.cplex.IloCplex.solve(IloCplex.java:10434)
at PDOP.solveIBR(PDOP.java:193)
at Application.main(Application.java:33)
我希望这不是 "too" 愚蠢的问题,我试图在网上找到有关此行为的信息,但没有找到任何需要添加变量的示例。
我继续阅读它,似乎根本不可能在 LazyConstraint (https://www.or-exchange.org/questions/14311/adding-variables-or-modifying-existing-constraints-during-callbacks-with-cplex-c) 中添加额外的变量
我能够重新表述我的问题(它不是那么简洁易读,但有效......),它比直接在问题中包含 subtour 消除约束更快,并且仍然会导致可行解决方案。
感谢 rkersh 的帮助:)