价值范围提供者依赖于计划变量

时间:2018-04-09 21:31:40

标签: optaplanner

问题

是否可以创建动态ValueRangeProvider,其值范围取决于计划变量的当前值?或者是否有其他方法可以达到预期效果?

背景

我正在尝试进行类似于护士名单示例的调度优化。以下是一些差异:

  • 班次需要分配员工,以便尽可能多地涵盖班次的持续时间
  • 员工只能在每个班次特有的特定时间内开始,并且每个员工都是唯一的
  • 员工及其开始时间都需要优化为严格的硬约束(员工不能安排在没有可用性的班次中,也不能将开始时间超出员工可用的班次)
  • 贪婪地选择员工工作的持续时间以尽可能多地填充班次(当开始时间改变时由阴影变量控制)。
  • 移位间隔不均匀,持续时间也不同。他们可以有任何开始/结束时间,并且可能重叠(员工不能在不同班次之间轻松交换)
  • 员工仍然可以分配到多个班次,甚至可以在不同的时间分配到同一班次,只要员工的分配时间不超过为其定义的固定最大值的任何其他分配时间。雇员。大多数员工的固定最大值为1(即在重叠时间内不能处理两个重叠的班次)。

规划实体的数量是可变的,但这是一个不同的问题。当前的解决方法是生成与每个班次的持续时间一样多的计划实体,但这将很快创建数百万个实体,这些实体最终将具有空分配。

尝试

我尝试在ShiftAssignment(PlanningEntity)上设置ValueRangeProvider,它根据当前分配的Employee的可用时间返回可数值范围,但似乎这对于分配的第一个Employee是静态的。我的下一次尝试是让ValueRangeProvider返回@CustomShadowVariable的实例,该实例会在设置新的Employee时更改可用性,但这似乎与第一种方式没有任何不同的效果。

另一个想法是创建一个自定义移动工厂,它只生成当前Employee可以启动的有效时间,但这仍然不能阻止Employee中的更改在其无效时间上打破硬约束。看起来更像是这种方法需要一个额外的自定义移动工厂来更改Employees,只要它发生变化,就会明确地将startTime变量更改为该Employee的有效时间。

另一种尝试是使开始时间成为更新为Employee的第一个可用时间的影子变量,同时具有真正的变量“offset”,该变量将是0到移位持续时间之间的静态值范围。这似乎可以解决问题,但假设每当Employee更改时,偏移量可以重置为0,这需要自定义移动工厂才能实现。这似乎最终与自定义移动工厂相同,只是将开始时间规划为真正的规划变量,但也许它比尝试动态更改ValueRangeProvider更好。

当前解决方案

现在,我忽略了无法在ValueRangeProvider中强制执行约束,只返回由shift的开始/结束时间设置的ValueRange(对于每个不同的班次都是固定的)。这会增加搜索空间,并在Employee无法在更改后选择的时间启动时生成许多具有破坏硬约束的解决方案。它似乎永远找不到更好的解决方案,因为它没有机会改善开始时间变量。这可以通过改变求解器参数(我不是很擅长)来部分缓解,但搜索空间仍然会比必要的要大很多。

非常感谢任何帮助或正确方向的观点。谢谢!

2 个答案:

答案 0 :(得分:2)

我最终为每个Employee和Employee可用的每个时间范围创建了一个ShiftAssignment实体的新实例,这样每个实体上的ValueRangeProvider都是静态的,这似乎对我的目的起作用。而不是让员工和开始时间都是计划变量,只是开始时间现在是一个变量,但可以为空,表示特定的员工/班次/可用性实体未分配给班次。

答案 1 :(得分:2)

您可以参考章节"4.3.5.2.3. ValueRangeProvider on the Planning Entity。。值范围可以放在解决方案类或计划实体类上。您可以在计划实体类中创建一个getter,以获取基于当前计划实体实例的值范围,过滤范围以减少计划变量的可能值,以减少搜索空间。