允许与 OptaPlanner 和 TSPTW 重叠

Allowing overlap with OptaPlanner and TSPTW

我目前使用 OptaPlanner 解决 TSPTW 问题。对于以下内容,将目的地视为任务会有所帮助。

每个任务当前都有一个名为 previousTask 的链式规划变量。任务可以分为A类或B类。我现在要做的是让B类任务有选择地重叠A类任务,让OptaPlanner决定是否重叠是正确的选择。

例如,给定任务 A1、A2、B1,OptaPlanner 可能会决定 A1 -> B1 -> A2 是最好的,或者 A1 ->(A2 与 B1 重叠)是最好的。

我认为我可以实现的方法是:

  1. 给每个 A 类任务一个名为 overlappingTask 的第二个(非链式)规划变量。
  2. 将当前的 "tasks" ValueRangeProvider 拆分为两个 ValueRangeProvider,"typeATasks" 和 "typeBTasks".
  3. 将 previousTask 的 ValueRangeProviders 注释为 typeATasks 和 typeBTasks。
  4. 将 overlappingTask 的 ValueRangeProviders 注释为仅类型 BTasks。

我正在解决的问题总是至少有一个 A 类任务,但可能没有任何 B 类任务。这导致我提出的解决方案出现问题,因为 "typeBTasks" ValueRangeProvider 有时为空,这会为 previousTask 计划变量抛出 IllegalStateException。

有没有更好的方法来解决这个问题?有没有办法解决空的 ValueRangeProvider 问题?鉴于 ValueRangeProviders 的组合不为空,对 previousTask 的空洞抱怨似乎很奇怪。看来OptaPlanner检查组合是否为空会更好,而不是每个输入都单独检查。

这里有一些代码片段来阐明当前的设计:

public Solution
{
    @PlanningEntityCollectionProperty
    @ValueRangeProvider(id = "typeATasks")
    public List<TypeA> getTypeATasks)

    @PlanningEntityCollectionProperty
    @ValueRangeProvider(id = "typeBTasks")
    public List<TypeB> getTypeBTasks()
}

public class Task
{
    @PlanningVariable(valueRangeProviderRefs = { "typeATasks", "typeBTasks" },
                      graphType = PlanningVariableGraphType.CHAINED)
    public Task getPreviousTask()
}

public class TaskB extends Task {}

public class TaskA extends Task
{
    @PlanningVariable(valueRangeProviderRefs = { "typeBTasks" }, nullable = true)
    public TaskB getOverlappingTask()
}

并不是说你的模型不好,我们称你的提案为 C)。请参阅我上面的评论,这是一个错误,optaplanner 6.4.0.Beta2 在该模型上快速失败。

但是我在想这样的模型,建议A):

@PlanningEntity class TaskAssignment {
    TaskDef taskDef;
    @PlanningVariable TaskAssignment previousTaskAssignment;
    @PlanningVariable Boolean overlapPreviousIfPossible;

    boolean isOverLappingPrevious {
        return taskDef.isTypeB() && overlapPreviousIfPossible;
    }
}

在这种情况下,值范围提供程序将 return 所有 TaskAssignments。

但我也在考虑另一种模型,我们称其为提案B),如考试示例中:计划实体AbstractTaskAssignment,由TypeATaskAssigement 和TaskBTaskAssignment 扩展。这是一个更好的域模型(类型 A 赋值没有重叠变量),但配置要痛苦得多(尤其是移动更难)。