优化Timefold课程排课项目中全局状态约束的性能
优化Timefold全局状态约束的高效写法
你当前的约束写法通过groupBy(t->0, toList())实现了“每次Lesson变更时仅计算一次全局状态影响”的需求,但冗余的分组操作确实会带来性能开销。以下是更高效的优化方案:
优化后的约束定义
直接使用ConstraintCollectors.count()作为分组收集器,无需手动指定无意义的groupKey,同时避免了创建全量Lesson列表的开销:
factory.forEach(Lesson.class) .groupBy(ConstraintCollectors.count()) .impact(HardMediumSoft.ofHard(1), (count) -> GlobalState.getSingleton().getImpact()) .asConstraint(id);
优化原理
- 去掉冗余groupKey:使用单参数的
groupBy(Collector)会自动将所有Lesson归为单一分组,无需手动指定t->0这类无意义的分组键,彻底避免了Group1Mapping0CollectorUniNode.createGroupKey的热点调用。 - 轻量收集器替代:
count()收集器仅统计Lesson数量,相比toList()无需创建和维护全量Lesson列表,内存占用和计算开销更低。 - 保持触发逻辑不变:只要任意Lesson的
Timeslot规划变量变更,该约束仍会重新计算,确保全局状态的影响能实时反映到分数中。
为什么不能直接遍历GlobalState
你提到的factory.forEach(GlobalState.class).impact(...)写法无法满足需求,核心原因是:
Timefold的约束触发依赖于规划变量或问题事实的变更检测,GlobalState作为单例对象,Timefold无法感知到它是由Lesson变更间接更新的,因此不会在Lesson变更时重新计算该约束,导致分数与实际全局状态脱节。
内容的提问来源于stack exchange,提问作者hornisgrinde
相关产品推荐
相关产品推荐

