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

如何在Timefold中获取基于Timeslot的Lesson连续配对?

解决Timefold排课中连续Lesson配对的约束问题

问题核心

当前约束逻辑错误生成了非连续的Lesson配对,导致惩罚值不符合预期。需要调整约束,仅针对同一教师/学生(根据排课主体)的单日课程,按Timeslot排序后只检查相邻连续的Lesson配对。

修正步骤

1. 筛选单日同主体的课程组

首先将Lesson按dayOfWeek和排课主体(如teacher或studentGroup,根据业务需求)分组,确保只处理同一天同一教师/学生的课程。

2. 对组内课程按Timeslot排序

使用sorted()方法按Timeslot的开始时间(或时间戳、序号)排序,保证课程按时间顺序排列。

3. 仅生成相邻连续的配对

通过索引遍历获取排序后相邻的Lesson对,而非生成所有可能的配对(这是之前错误的根源)。

示例约束代码

private Constraint maxLessonGapPerDay(ConstraintFactory constraintFactory) {
    return constraintFactory.from(Lesson.class)
            // 按天和教师分组(若按学生约束,替换为studentGroup)
            .groupBy(Lesson::getDayOfWeek, Lesson::getTeacher, Collectors.toList())
            .filter((dayOfWeek, teacher, lessonList) -> lessonList.size() > 1)
            .flatMap((dayOfWeek, teacher, lessonList) -> {
                // 按Timeslot开始时间排序
                List<Lesson> sortedLessons = lessonList.stream()
                        .sorted(Comparator.comparing(lesson -> lesson.getTimeslot().getStartTime()))
                        .toList();
                // 生成相邻课程配对
                return IntStream.range(0, sortedLessons.size() - 1)
                        .mapToObj(i -> new LessonPair(sortedLessons.get(i), sortedLessons.get(i + 1)));
            })
            // 检查间隔是否超过指定时长(示例:间隔超1小时)
            .filter(pair -> {
                Duration gap = Duration.between(
                        pair.getFirst().getTimeslot().getEndTime(),
                        pair.getSecond().getTimeslot().getStartTime()
                );
                return gap.toHours() > 1; // 替换为实际时长阈值
            })
            .penalize("Max lesson gap per day", HardSoftScore.ONE_SOFT);
}

// 辅助类:存储相邻Lesson配对
private static class LessonPair {
    private final Lesson first;
    private final Lesson second;

    public LessonPair(Lesson first, Lesson second) {
        this.first = first;
        this.second = second;
    }

    public Lesson getFirst() { return first; }
    public Lesson getSecond() { return second; }
}

关键说明

  • 避免全量配对:不要用join(Lesson.class, ...)生成所有Lesson对,否则会引入非连续配对的无效检查,导致惩罚值偏高。
  • 排序的必要性:必须保证Lesson按时间顺序排列,否则相邻配对逻辑完全失效。
  • 阈值灵活调整:可将gap.toHours() > 1替换为分钟、秒等单位的限制,匹配业务需求。

测试验证

修正后,测试场景只会检查相邻的Lesson配对(如Timeslot2与3、3与6、6与7),只有当相邻课程间隔超过阈值时才产生惩罚,惩罚值将符合预期(预期1,实际1)。

内容的提问来源于stack exchange,提问作者Diallo Francis Patrick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 06:42:19