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

如何在OptaPlanner中优化含学生子组(选修课)的课程表?

OptaPlanner 班级选修子组课程表建模方案

核心建模思路

不拆分主班级,通过学生选修子组和课程受众范围两个维度,区分主干课(全员参与)和选修课(特定子组参与),在约束中控制课程冲突与受众匹配逻辑。

实体类设计

1. Student(学生实体)

包含两个核心属性:

  • mainClass:主班级标识(如"四年级"),用于关联主干课的受众范围
  • electiveGroup:选修子组标识(如"4S"、"4E"),用于匹配选修课的受众

2. Course(课程定义)

区分课程类型并指定受众:

  • isCore:布尔值,标记是否为主干课程
  • targetElectiveGroups:集合类型,存储该课程面向的选修子组
    • 主干课:集合包含主班级下所有选修子组(如{"4S", "4E"})
    • 选修课:集合仅包含对应子组(如science+对应{"4S"},economics+对应{"4E"})

3. Lesson(规划实体)

作为OptaPlanner的核心规划实体,代表一次具体授课,包含:

  • 关联的Course实例
  • 规划变量:timeSlot(时间槽)、room(教室)
  • 辅助属性:teacher(授课教师)等

约束配置

硬约束(必须满足)

  • 学生时间冲突约束:确保同一学生在同一时间没有两门需参与的课程
    实现逻辑:对每个学生,检查同一时间槽内的所有Lesson,若Lesson的targetElectiveGroups包含该学生的electiveGroup,则不允许存在多个这样的Lesson。
  • 选修课受众匹配约束:禁止选修子组外的学生被分配到对应选修课(通过课程的targetElectiveGroups与学生electiveGroup的匹配实现)
  • 主干课完整性约束:主干课的Lesson必须覆盖主班级所有学生,不能拆分(通过将主干课的targetElectiveGroups设为主班级所有子组来保证)

软约束(优化目标)

  • 选修课尽量集中安排在连续时间段,减少学生切换场地的成本
  • 教师授课时间分布均匀,避免连续多节授课
  • 同一子组的选修课尽量使用同一教室,减少资源浪费

代码示例(约束实现)

用OptaPlanner的Constraint Streams实现学生时间冲突约束:

import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory;
import org.optaplanner.core.api.score.stream.Joiners;

public class TimetableConstraintProvider {

    public Constraint studentConflict(ConstraintFactory factory) {
        return factory.from(Student.class)
                // 关联学生需要参与的所有课程
                .join(Lesson.class, Joiners.filtering((student, lesson) ->
                        lesson.getCourse().getTargetElectiveGroups().contains(student.getElectiveGroup())))
                // 关联同一学生同一时间的另一门课程
                .join(Lesson.class,
                        Joiners.equal((student, lesson1) -> student),
                        Joiners.equal((student, lesson1) -> lesson1.getTimeSlot()),
                        Joiners.lessThan(Lesson::getId)) // 避免重复配对
                // 检查另一门课程是否也属于该学生的受众范围
                .filter((student, lesson1, lesson2) ->
                        lesson2.getCourse().getTargetElectiveGroups().contains(student.getElectiveGroup()))
                .penalize("Student has conflicting lessons", HardSoftScore.ONE_HARD);
    }
}

额外注意事项

  • 生成Lesson时,主干课仅需创建1个实例(覆盖所有子组),选修课需为每个目标子组创建独立实例(如4E的science-和economics+各对应1个Lesson)
  • 若教室资源有限,可添加软约束:同一时间槽内,同一子组的选修课尽量使用相同教室,避免资源浪费

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 01:40:30