在 OptaPlanner 中使用 PDPTW 并行求解

Posted

技术标签:

【中文标题】在 OptaPlanner 中使用 PDPTW 并行求解【英文标题】:Parallel Solving with PDPTW in OptaPlanner 【发布时间】:2021-12-23 06:15:18 【问题描述】:

我正在尝试使用并行方法提高 OptaPlanner 的性能,但我不确定最佳策略。

我有 PDPTW:

车辆路线 时间窗口(1 小时窗口) 提货和送货

当一位新客户想要添加送货服务时,我试图找出一种快速的方法(不到一秒)向他们展示一天中有哪些时间段(上午 8 点、上午 9 点、上午 10 点等)。每个时间段都有不同的得分结果。有些效率很高,有些则无法预订,具体取决于驾驶时间增加的时间/情况。

为了性能,我不想按顺序尝试每个小时的时间,因为它太慢了。

如何在所有时间段内同时尝试客户的交付?在添加客户的潜在交付窗口之前先运行求解器,然后与独立求解的所有不同添加的交付时间段共享已解决的原始状态是有意义的。

有没有直观的方法来做到这一点?例如:

    重用一些原始求解计算(添加新交付之前的状态)。也许这甚至可以提前缓存? 也许在不同的服务器(或至少多个线程)上运行所有时隙求解实例。

这样的推荐设置是什么?在一秒钟内返回 HTTP 响应会很棒。这适用于大约 100-200 次交付和 10-20 辆卡车。

谢谢!

【问题讨论】:

关于 pdptw:出租车问题(= 非混合接送)在 OptaPlanner 中很简单。叫车问题(= 混合接送)很困难(需要自定义动作)。 【参考方案1】:

A) 如果您优化将 1 个客户分配到 1 个车辆中的 1 个索引,同时固定所有其他已分配的客户,那么您将放弃所有优化优势.这不是NP难的。 您仍然可以为此使用 OptaPlanner <constructionHeuristic/><localSearch/> 不会提高分数),无论是否使用 moveThreadCount 将其分布在内核之间,尽管主要好处只是增量分数计算,而不是 AI 算法。

B) 优化将所有客户分配到车辆索引。当添加新客户允许移动现有客户分配时,真正的业务收益 - 例如减少 25% 的驾驶时间 - 就来了。问题是那些现有客户已经收到了他们在议程中排除的时间窗口。但是,如果这些时间窗口足够宽,那就不必成为问题:这些只是硬约束。 更宽的时间窗口 = 更多的驾驶时间优化机会(= 更多的 $$$,更少的 CO² 排放)。


一分钟内的回复呢?

此时,您无需发布(= 与客户分享信息)哪辆车将在何时以何种顺序到达。无论您是否接受时间窗口,您只需要发布。有两种方法可以做到这一点:

C) 基于决策表(放松):每辆车每天不超过 5 个客户。

陷阱:如果它在国家/州的 5 个角落有 5 个客户,那么它可能仍然不可行。影响决策的任何两个客户位置对之间的平均欧氏距离因素。

D) 通过运行 optaplanner 直到终止可行=true,从上一个计划的热启动开始。如果在 1000ms 内没有找到这样的可行解,则拒绝时间窗提议。

D) 的陷阱:如果 2 个请求同时进入,并且您并行运行它们,因此两者都没有考虑另一个,那么它们可能单独可行但一起不可行。

【讨论】:

谢谢!澄清一下,业务案例实际上是垃圾清除,因此在必须在转运站卸货之前有几次取货。这非常具有挑战性,因为混合了容量问题,而且,根据客户所拥有的垃圾类型,这可以确定该垃圾的卸载位置。这对于时间窗口(更大的窗口,更好的优化潜力)是有意义的。所以你建议自定义移动(哪些是最好的?),但在添加增量客户时,大多数收益来自构建启发式而不是本地搜索? 如果可以的话,我会避免自定义动作。只取垃圾,直到容量满了,然后去最近的卸货地点。一个影子变量可以在每次垃圾拾取后决定是否该卸货,然后再开往下一个。 谢谢 - 与太多客户预订是我试图解决的主要挑战(客户迟到时会生气等)。是的,我希望不需要自定义动作,但目前分数的提高要到近一分钟才会稳定下来,所以我真的需要以某种方式进行优化。 恐怕自定义动作是为了逃离高原,而不是为了更快地到达它们。分数计算速度(见信息记录)超过 10 000 有助于更快地达到高原。

以上是关于在 OptaPlanner 中使用 PDPTW 并行求解的主要内容,如果未能解决你的问题,请参考以下文章

Optaplanner逐步学习 : 基本概念 - Optaplanner,规划问题, 约束,方

Optaplanner规划引擎的工作原理及简单示例

Optaplanner规划引擎的工作原理及简单示例

使用 Optaplanner 解决 VRPTWPD

Optaplanner:检查链式规划变量是不是有锚

在 IntelliJ 中运行 OptaPlanner 示例