首页 > 解决方案 > CPLEX+JAVA:在启发式回调中检索解决方案行为异常

问题描述

我有以下问题:我使用与启发式组件集成的 CPLEX 来解决具有许多同步约束的大型 VRP,以改进现有人员。一般算法如下:如果在 CPLEX 中找到新的现任者,或者如果达到时间限制,我会转向启发式算法,并尝试改进当前的现任者。前者使用 Incumbent Callback 完成,后者使用 Heuristic Callback。虽然我能够查询现有回调中的所有变量,但我在启发式回调中得到了一些奇怪的行为:当我查询时

this.getStatus().toString()

这将返回“最优”,即使解决方案还不是最优的(有一个现任者,但仍然存在相当大的完整性差距)。我通过查看目标值和当前完整性差距来确保模型实际上查询了正确的 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)

它发生在我查询任何变量时,但仅在我第二次查询 cplex 对象之后。(所以:我启动程序,它迭代了很多实例,第一个实例很好,所有启发式回调都工作,在所有进一步的迭代中,我最终进入 catch-block 并获得上述异常跟踪。)那是为什么我假设单例可能无法完全按照预期工作,并且并非所有内容都从第一次迭代中删除。

标签: javacplex

解决方案


查看您可以看到的参考文档IloCplex.HeuristicCallback.getStatus()

返回当前节点的解决方案状态。

此方法返回在最后一次调用方法 IloCplex.HeuristicCallback.solve 期间由当前节点上的 IloCplex 实例找到的解决方案的状态(可能已在回调中直接调用,或者在处理节点之前的节点时由 IloCplex 调用)。回调被调用)。

换句话说,该函数不返回全局状态,而仅返回节点本地状态。预计在调用回调时节点当前已解决到最优。

关于回调中的异常:您正在尝试访问不在正在解决的模型中的变量对象。发生这种情况的典型情况是:

  1. 您创建了变量,但它没有出现在任何约束或目标中,即它没有在任何地方使用。cplex.add()您可以通过将变量作为参数显式调用来强制使用它。
  2. 该变量是在先前的迭代中创建的,并且在当前迭代中不再是模型的一部分。调试此问题的一个好方法是为每个变量分配一个名称,并让该名称包含迭代索引。然后在异常处理程序中打印有问题的变量的名称。这应该很好地暗示出了什么问题。

推荐阅读