optaplanner - 防止在链式计划中触发不必要的影子变量更新
问题描述
我们将取货和交付的车辆路线问题建模为链式规划问题。最重要的是,我们有一个自定义的移动实现,它从车队中取消一个拾取-交付对并将其插入到其他地方。
我们的链以与 optaplanner 示例中的ArrivalTimeUpdatingVariableListener类似的方式更新,从更改的计划实体开始,然后逐步进行直到链的末尾。
我们面临的问题是链条经常不必要地更新。由于我们宣布每次移动对 scoreDirector 进行 4 次计划变量更改,因此变量侦听器会从这 4 个计划实体中的每一个开始执行完整的链更新。通常所有四个实体都位于同一个链中,从第一个更改的实体开始进行一次更新就足够了。
我们已经实现了提前退出:如果在链更新期间没有更新特定的影子变量,我们将跳过链的其余部分。但是,这仅在我们偶然首先处理来自第一个实体的链时才有效。
我们如何确保每次 Move 只更新链一次,从第一个更改的实体开始?
解决方案
通过调试和迭代更改我们向分数控制器宣布变量更改的顺序,我们设法摆脱了多余的链更新。
TL;DR: Optaplanner 似乎按照向评分主管宣布计划变量更新的顺序触发链更新。
考虑一个插入动作,它将取货-交付对插入到现有的访问链中(应用Optaplanner 示例中的术语):
v1 <- v2 <- v3 <- v4
// insert p between v1&v2, d between v2&v3. Result:
v1 <- p <- v2 <- d <- v3 <- v4
此操作导致 4 个计划变量更改:
p.previousStandstill = v1
v2.previousStandstill = p
d.previousStandstill = v2
v3.previousStandstill = d
这些计划变量中的每一个更改都会向分数主管 ( scoreDirector.beforeVariableChanged(...)
, scoreDirector.afterVariableChanged(...)
) 宣布,并且无需进一步调整,Optaplanner 将从每个更改的实体调用完整的链更新。这不是必需的,因为从 开始的单个链更新p
足以更新所有相关的影子变量。
为了防止 Optaplanner 进行多余的链更新,我们需要确保:
- (链中最早接触的实体)的计划变量更新
p
需要在所有其他计划变量更新之前通知 scoreDirector - 一旦影子变量在整个过程中保持不变,迭代链更新就会立即停止
在我们的案例中,正确实施这些步骤将我们花费在更新链上的 CPU 时间减少了 50% 以上。
推荐阅读
- python - 如何制作分箱数据的二维直方图?
- amazon-web-services - 如何在 API Gateway 上以更长的间隔添加基于 ip 的速率限制?
- .net - 在 TextBox 控件中包装长文本
- javascript - 在将结果作为输入参数之前等待承诺
- lua - 对 lua 的 os.clock 精度感到困惑
- matlab - 如何在matlab中为散点图制作二维颜色图?
- windows - 命令中的数组迭代以查找子项
- oracle - oracle 查询以识别某些基于条件的重叠日期期间
- javascript - target="_blank" 在 Edge 中打开新的空白页
- javafx - 打开 fxml 文件一段时间并返回主屏幕?