【发布时间】:2018-09-19 09:16:02
【问题描述】:
问题
是否可以创建一个动态 ValueRangeProvider,其值范围取决于计划变量的当前值?或者有没有其他方法可以达到这个预期的效果?
背景
我正在尝试进行类似于护士名册示例的调度优化。以下是一些区别:
- 轮班需要分配员工,以便尽可能多地覆盖轮班的持续时间
- 员工只能在每个班次和每个员工所特有的特定时间开始工作
- 员工及其开始时间都需要作为严格的硬约束进行优化(不能将员工安排在没有空闲时间的班次,开始时间也不能超出该班次的空闲时间)
- Employee 工作的持续时间被贪婪地选择以尽可能多地填补班次(当开始时间改变时由影子变量控制)。
- 班次间隔不均匀,持续时间也不相同。他们可以有任何开始/结束时间,并且可能重叠(员工不能在不同班次之间轻松调换)
- 员工仍然可以分配到多个班次,甚至可以在不同时间分配到同一个班次,只要该员工的分配时间不重叠任何其他分配时间超过为其定义的固定最大值员工。大多数员工的最大值固定为 1(即不能在重叠时间内工作两个重叠的班次)。
计划实体的数量是可变的,但这是一个不同的问题。当前的解决方法是生成与每个班次持续时间一样多的计划实体,但这将很快创建数百万个实体,这些实体最终大多会分配为空。
尝试
我尝试在 ShiftAssignment(PlanningEntity)上设置一个 ValueRangeProvider,它根据当前分配的 Employee 的可用时间返回一个可计数的值范围,但对于分配的第一个 Employee 来说,这似乎是静态的。我的下一个尝试是让 ValueRangeProvider 返回一个 @CustomShadowVariable 的实例,该实例将在设置新 Employee 时更改可用性,但这似乎与第一种方式的效果没有任何不同。
另一个想法是创建一个自定义移动工厂,它只生成当前 Employee 可以启动的有效时间,但这仍然不会阻止 Employee 中的更改打破其时间无效的硬约束。似乎这种方法需要一个额外的自定义移动工厂来更改员工,明确地将 startTime 变量更改为该员工的有效时间,只要它发生变化。
另一种尝试是使开始时间成为一个影子变量,该变量更新为员工的第一个可用时间,同时具有一个真正的变量“偏移量”,该变量将是一个介于 0 和轮班持续时间之间的静态值范围。这似乎可以解决问题,但假设每当 Employee 更改时偏移量可以重置为 0,这需要自定义移动工厂才能实现。这似乎最终与自定义移动工厂相同,仅将开始时间计划为真正的计划变量,但也许它比尝试动态更改 ValueRangeProvider 更好。
当前解决方案
现在,我忽略了无法在 ValueRangeProvider 中强制执行约束,只返回由班次的开始/结束时间设置的 ValueRange(对于每个不同的班次都是固定的)。这增加了搜索空间,并在员工更改后无法在选择的时间开始时生成许多硬约束被破坏的解决方案。似乎它永远找不到更好的解决方案,因为它没有机会改进开始时间变量。这可以通过更改求解器参数(我不太擅长)来部分缓解,但搜索空间仍然会比必要的大很多。
任何帮助或正确方向的观点将不胜感激。谢谢!
【问题讨论】:
标签: optaplanner