You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Optaplanner增量计算合理性:手动调度下硬约束预计算效率优化问询

解决方案:利用Bavet增量评分优化手动课程校验效率

针对你的课程排课场景,完全可以利用OptaPlanner 9.37的Bavet约束流增量评分能力,大幅提升单个潜在课程的校验效率,分两种需求场景说明:


场景1:需要保留用户可读的违规提示

不需要全量调用SolutionManager.explainScore(),可以通过手动操作BavetScoreDirector实现增量约束匹配计算:

  1. 初始化增量评分环境
    • 基于已完成评分的现有调度计划(原PlanningSolution),创建BavetScoreDirector,确保复用原Solution的已有分数状态,避免全量重算:
      ConstraintProvider constraintProvider = new YourConstraintProvider();
      ScoreDirectorFactory<YourPlanningSolution> scoreDirectorFactory = ScoreDirectorFactory.create(constraintProvider);
      BavetScoreDirector<YourPlanningSolution> scoreDirector = (BavetScoreDirector<YourPlanningSolution>) scoreDirectorFactory.buildScoreDirector();
      scoreDirector.setWorkingSolution(originalSolution);
      // 如果原Solution未预先评分,先执行一次全量计算(仅需执行一次)
      if (!scoreDirector.isScoreCalculated()) {
          scoreDirector.calculateScore();
      }
      
  2. 增量校验潜在课程
    • 临时添加潜在课程到工作Solution,并触发增量评分:
      Lecture newLecture = ...; // 待校验的潜在课程
      scoreDirector.beforeEntityAdded(newLecture);
      originalSolution.getLectureList().add(newLecture);
      scoreDirector.afterEntityAdded(newLecture);
      
  3. 提取违规提示
    • 从ScoreDirector中获取仅与新增课程相关的约束匹配结果,转换为用户可读提示:
      Map<Constraint, ConstraintMatchTotal<YourPlanningSolution>> constraintMatchTotalMap = scoreDirector.getConstraintMatchTotalMap();
      List<String> violationMessages = new ArrayList<>();
      for (ConstraintMatchTotal<YourPlanningSolution> matchTotal : constraintMatchTotalMap.values()) {
          // 仅关注硬约束违规
          if (matchTotal.getScore().getHardScore() < 0) {
              // 这里可以根据约束名称或自定义匹配信息生成提示
              String message = convertConstraintMatchToMessage(matchTotal);
              violationMessages.add(message);
          }
      }
      
  4. 回滚操作
    • 移除临时添加的课程,恢复原Solution状态:
      scoreDirector.beforeEntityRemoved(newLecture);
      originalSolution.getLectureList().remove(newLecture);
      scoreDirector.afterEntityRemoved(newLecture);
      

注意:定义约束流时,建议通过Constraint.as("约束名称")给每个硬约束命名,方便后续映射到用户可读提示;如果需要更精细的匹配信息,可以在约束流中使用constraintMatch(...)方法传递自定义数据。


场景2:仅需判断硬约束是否合法(无需违规提示)

这种场景效率更高,只需检查增量评分后的硬分数是否未恶化:

  1. 复用已初始化的ScoreDirector(同场景1的步骤1)
  2. 增量更新并检查分数
    boolean isValidLecture = true;
    Lecture newLecture = ...;
    scoreDirector.beforeEntityAdded(newLecture);
    originalSolution.getLectureList().add(newLecture);
    scoreDirector.afterEntityAdded(newLecture);
    
    Score score = scoreDirector.getScore();
    // 假设原计划硬分数为0(合法状态),新增后硬分数≥0则合法
    if (score.getHardScore() < 0) {
        isValidLecture = false;
    }
    
    // 回滚
    scoreDirector.beforeEntityRemoved(newLecture);
    originalSolution.getLectureList().remove(newLecture);
    scoreDirector.afterEntityRemoved(newLecture);
    

关键注意事项

  • 必须严格遵循ScoreDirector的生命周期方法(beforeEntityAdded/afterEntityAdded等),否则增量计算会出现错误。
  • 原Solution只需预先全量计算一次分数,后续所有增量校验都基于该状态,避免重复计算现有计划的约束。
  • Bavet约束流在OptaPlanner 9.37版本完全支持实体新增/移除的增量评分,无需额外配置。

内容的提问来源于stack exchange,提问作者B Myers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 12:05:28