得分的VRP取决于optaplanner中的多个作业



我们正在尝试使用Optaplanner解决VRP。分数计算通过约束流运行。

现在我有两辆车(A和B(,想安排两项工作(J1和J2(。构造启发式(FIRST_FIT_DECREASING(将J1调度到A,将J2调度到B,这是迄今为止正确的。

现在,这两个作业还具有属性";客户";,如果两项工作的客户相同,但车辆不同,我想指定一个处罚。

为此,我在ConstraintProvider中创建了一个约束,该约束通过groupBy过滤所有具有相同客户但不同车辆的作业。

如果我现在打开FULL_ASSERT_MODE,则在调度J2之后会发生IllegalStateException,因为增量计算的分数与完整计算的分数不同。我怀疑这是因为重新计算作业时间的VariableListener只告诉ScoreDirector我的影子变量对作业J2的更改,因此只更改与之相关的分数部分

我如何告诉Optaplanner J1的分数也必须重新计算?我无法通过VariableListener到达作业J1,告诉ScoreDirector必须在此处更改分数。

还是这个问题需要一种不同的方法?

这是一个有点难以完全解释的问题。TLDR版本:约束流仅对来自from()join()ifExists()的对象的更改作出反应。未通过这些语句的对象的更改将不会被捕获,因此会导致分数损坏。下面是更详细的解释。

考虑这样一个假设的约束流:

constraintFactory.from(Shift.class)
.join(Shift.class)
.filter((shift1, shift2) -> shift1.getEmployee() == shift2.getEmployee())
...

这个约束流可以正常工作,因为如果您通过设置不同的员工来更改Shift,则会重新评估Shift。它们通过from()join()进入流,这就是CS知道在它们改变时重新评估Shifts的方式。

现在考虑这个约束流:

constraintFactory.from(Shift.class)
.filter(shift -> shift.getEmployee().getName() == "Lukas")
...

如果Shift发生变化,将重新评估此约束流。但当Employeename发生变化时,约束流将不会被重新评估;Employee既不在from()中,也不在join()中,对Employee的更改不会触发对约束流的重新评估。

在您的特定情况下,您需要确保以下几点:

  • 变量侦听器将所有实际更改的内容标记为已更改
  • 如果您修改问题事实,您需要确保您的变量监听器也能处理它
  • 您希望约束流对其作出反应的对象是通过from()join()传入的

最新更新