
optaplanner 的构造启发式(ch)阶段默认仅在结束时触发一次分数更新,以避免频繁克隆解决方案带来的性能开销;该行为属设计使然,但旧版本存在未及时派发最终分数的 bug,已在 timefold 0.8.39/0.9.39 中修复。
optaplanner 的构造启发式(ch)阶段默认仅在结束时触发一次分数更新,以避免频繁克隆解决方案带来的性能开销;该行为属设计使然,但旧版本存在未及时派发最终分数的 bug,已在 timefold 0.8.39/0.9.39 中修复。
在使用 HardMediumSoftLongScore 并允许规划变量(如 timeslot)为 null 的过约束(over-constrained)场景中,理解构造阶段的分数行为至关重要。构造启发式旨在快速生成一个可行(或尽可能可行)的初始解,而非实时优化——因此它不会在每一步赋值后都计算并派发分数。这是出于性能考量:每次分数计算均需克隆当前工作解决方案(Working Solution),而 CH 阶段可能涉及成百上千次变量赋值,频繁克隆将显著拖慢初始化速度。
✅ 正确行为是:CH 完成全部赋值后,统一执行一次分数计算,并向监听器(如 BestSolutionChangedEventListener)派发最终分数事件。
⚠️ 历史问题(已修复):在 Timefold(OptaPlanner 衍生版)
关于初始化分数趋势(initializingScoreTrend):
-
可以且推荐设置,尤其在过约束场景下。例如:
<!-- 在 solverConfig.xml 中 --> <constructionheuristic><initializingscoretrend>ONLY_DOWN</initializingscoretrend></constructionheuristic>
或通过 Java API:
SolverFactory<mysolution> factory = SolverFactory.create(...); SolverConfig config = factory.getSolverConfig(); config.getConstructionHeuristicConfig() .setInitializingScoreTrend("ONLY_DOWN");</mysolution> - ONLY_DOWN 表示分数只会恶化(如硬约束从 -1→-2),适用于“先满足硬约束,再优化软约束”的典型过约束逻辑;若允许硬约束逐步修复,可选 ONLY_UP 或 ANY。该配置帮助后续局部搜索更智能地评估移动价值,与 CH 是否派发中间分数无关,但能提升整体求解效率和稳定性。
? 注意事项:
- 不要依赖 CH 阶段的中间分数事件做实时监控或 UI 更新;如需可视化进度,建议结合 PhaseLifecycleListener 监听 phaseEnded();
- 确保 @PlanningVariable(nullable = true) 的 @ValueRangeProvider 返回的值范围包含 null,且 HardMediumSoftLongScore 的 hardScore 能准确惩罚未分配任务(如 penalize(..., HardMediumSoftLongScore.ONE_HARD));
- 若仍遇无分数更新,请检查是否误用 SolverManager.solveAndListen() 的回调时机——它默认在 bestSolutionChanged 时触发,而 CH 结束事件必须由修复后的版本正确派发。
综上,CH 阶段无中间分数更新是合理设计,而非缺陷;启用并正确配置 initializingScoreTrend 是提升过约束问题求解质量的关键实践。











