【发布时间】:2017-11-30 22:38:15
【问题描述】:
我正在使用 OptaPlanner 开发 VRPTW 问题的求解器,当需要为大量客户提供服务时,我遇到了问题。我所说的数量庞大,是指多达 10,000 名客户。我已经尝试运行求解器大约 48 小时,但没有找到可行的解决方案。
我使用了一个高度定制的 VRPTW 域模型,它引入了额外的计划实体,即所谓的“Workbreak”。工间休息就像客户,但他们可以有一个实际上是另一个规划价值的位置——因为每天工人都可以回家或去酒店。工间休息有固定的出发时间(通常是第二天早上)和可变的到达时间(因为它取决于链中的前一个实体)。硬约束关心的是不允许在某个时间点之后“到达”Workbreak。还有其他硬性约束,例如:
- 每位客户有多个服务时间窗口
- 每周最后一位链上客户必须是特殊客户“仓储空间访问”(工人需要在下周之前收集材料)
- 长时间的工作管理(当客户需要的服务时间超过指定时间时,应在一天中的特定时间之前提供服务)
- 每个工作日的最大作业数
- 每个工作日的最长总工作时间(因为工人的工作时间不能超过指定时间)
- 工间休息的酒店位置不能离工人家太近。
- 周日无法提供工作服务
... 等等 - 总共有 19 个硬约束必须应用。也有 3 个软约束。
所有上述约束最初都是作为 Drools 规则编写的,但由于许多基于累积的约束(每天最多工作、每天最多工作时间、每周加班时间),求解器的总体速度(基准)约为 400步/秒。
起初我认为求解器的速度太慢,无法在合理的时间内得出可行的解决方案,所以我将所有规则改写成简易分数计算器,它的速度还不错——大约 4600 步/秒。我知道这只会对极少数客户表现最好,但我想知道 Drools 是否是导致性能不佳的原因。然后我将所有这些规则重写为增量分数计算器(并在分数错误损坏的痛苦中幸存下来,直到所有这些都被成功修复)。与简单的分数计算器相比,对于少数客户而言,令人惊讶的是增量分数计算要慢一些,但这不是问题,因为总体速度约为 4000 步/秒 - 无论我有多少实体。
最让我烦恼的是,超过一定数量的客户(问题从 1000 个客户开始),求解器无法得出可行的解决方案。目前我正在使用延迟接受和计步算法,因为它们在这类问题上表现得非常好(至少对于较少数量的客户而言)。我也使用了模拟退火,但没有成功,主要是因为我找不到算法特定参数的好值。
我也实现了一些自定义动作:
- 使用更改/交换移动等其他移动更改同级实体时更改工作中断位置的复合移动(它有助于避免许多得分陷阱,因为改进步骤通常需要在一个步骤中执行至少两个移动)
- 为了更好地分配长期工作而搬迁工厂(它会尝试将服务时间较长的客户置于工作日链的前端)
- 工间休息分配移动工厂(它生成的移动有助于将工间休息按正确的顺序排列)
现在我摸不着头脑,想知道我应该怎么做才能诊断出问题的根源。我怀疑它可能遇到了分数陷阱,但我已经修改了求解器,因此它每分钟保存最佳分数的快照。在阅读了这些快照后,我意识到分数仍在下降。硬约束的数量能起到作用吗?我怀疑需要执行许多动作才能找出提高分数的动作。事实是,对于这类问题,也许 48 小时并不算多,它应该进行一整周的计算?不幸的是,我没有什么可比的。
我想知道如何确定这仅仅是性能问题,还是求解器(算法、自定义动作、硬/软分数)配置问题。
我真的很抱歉我的英语不好。
【问题讨论】:
标签: optaplanner