我有以下问题:我使用集成了启发式组件的CPLEX解决了具有许多同步约束的大型VRP,以改善现有设备。通用算法如下:如果在CPLEX中找到了新任职者,或者达到了时间限制,那么我将进行启发式尝试,并尝试改善当前任职者。前者使用现任回调完成,后者使用启发式回调完成。虽然我可以查询现有回调中的所有变量,但在启发式回调中却得到了一些奇怪的行为:当我查询
this.getStatus().toString()
这将返回“ Optimal”,即使解决方案还不是最优的(现有的,但仍然存在较大的完整性差距)。我确保模型通过查询目标值和当前完整性差距来查询正确的cplex对象,它们与对数匹配。然后,
this.getIncumbentValue(v[n][i][j]);
失败(如果我使用this.getIncumbentValues(v[n][i]);
查询值,也会失败)。
[当我检入模型时(使用cplex.exportModel(String filename)
,所有变量都存在。
我以为这可能与我将CPLEX用作单例的事实有关,但是当我第一次使用单例时,状态已经是“最佳”的(但是在第一次迭代中,可以查询所有变量。 ,此问题仅在第二次迭代中存在)。
我这样创建单例:
public static IloCplex getCplex() {
if (cplex == null) {
try {
cplex = new IloCplex();
} catch (IloException e) {
e.printStackTrace();
}
} else {
try {
cplex.clearModel();
cplex.setDefaults();
} catch (IloException e) {
e.printStackTrace();
}
}
return cplex;
}
我可能在这里做错了吗?
编辑:包括回溯的确切错误消息是:
ilog.cplex.IloCplex$UnknownObjectException: CPLEX Error: object is unknown to IloCplex
at ilog.cplex.CpxNumVar.getVarIndexValue(CpxNumVar.java:295)
at ilog.cplex.IloCplex$MIPInfoCallback.getIndex(IloCplex.java:13648)
at ilog.cplex.IloCplex$MIPInfoCallback.getIncumbentValues(IloCplex.java:13807)
at ilog.cplex.IloCplex$MIPInfoCallback.getIncumbentValues(IloCplex.java:13785)
at SolverHybridCRP$InsertSolution.getV(SolverHybridCRP.java:2091)
at SolverHybridCRP$InsertSolution.improveIncumbent(SolverHybridCRP.java:2054)
at SolverHybridCRP$InsertSolution.main(SolverHybridCRP.java:2024)
at ilog.cplex.CpxCallback.callmain(CpxCallback.java:160)
at ilog.cplex.CpxHeuristicCallbackFunction.callIt(CpxHeuristicCallbackFunction.java:48)
at ilog.cplex.Cplex.CPXmipopt(Native Method)
at ilog.cplex.CplexI$SolveHandle.start(CplexI.java:2837)
at ilog.cplex.CplexI.solve(CplexI.java:2963)
at ilog.cplex.IloCplex.solve(IloCplex.java:10254)
at SolverHybridCRP.solveModel(SolverHybridCRP.java:1525)
at AppHelp.runtimeTest4(AppHelp.java:1218)
at AppHelp.main(AppHelp.java:61)
它在查询ANY变量时发生,但仅在第二次查询cplex对象之后才发生。 (因此:我启动程序,在很多实例上进行迭代,第一个实例很好,所有启发式回调均有效,在所有后续迭代中,我最终都在catch块中并获得了上面的异常跟踪。)这就是为什么我认为单例可能无法按预期工作的原因,并且并不是所有内容都从第一次迭代中删除。
查看reference documentation可以看到的IloCplex.HeuristicCallback.getStatus()
返回当前节点的解决方案状态。
此方法返回实例找到的解决方案的状态 在最后一次调用该方法期间,当前节点上的IloCplex数量 IloCplex.HeuristicCallback.solve(可能已直接调用 在回调中或通过IloCplex处理节点之前 回调被调用)。
换句话说,该函数不返回全局状态,而仅返回本地节点状态。预计在调用回调时,当前可将节点求解到最佳状态。
关于回调中的异常:您正在尝试访问不在要解决的模型中的变量对象。发生这种情况的典型情况是:
cplex.add()
来强制其使用。