首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >optaplanner调度AI是否适合于优化大学课程表?

optaplanner调度AI是否适合于优化大学课程表?
EN

Stack Overflow用户
提问于 2022-03-22 12:29:55
回答 1查看 98关注 0票数 0

学校时间表示例显示了与我需要解决的问题不同的问题。

问题是:

让我们上三门课:数学,英语,历史

所有这些课程都提供多个时隙(并行),学生可以从中选择一个。

让我们说:

数学:星期一: 9:00 - 10:00,星期二: 10:00 - 11:00 中文:星期一:9:00-10:00,星期二: 11:00 - 12:00,14:00 - 15:00,星期五: 16:00 - 17:00 历史:星期二: 10:00 - 11:00,星期五: 10:00 - 11:00

我想为每门课程找出最好的时间安排。我说的最好,是指差距最小的那个,更重要的是,让你有最多空闲时间的那个。

该示例问题的最佳解决方案可能如下

星期二:数学:9:00-10:00,历史: 10:00 - 11:00,英语: 11:00 - 12:00

没有空档,同时给出4天的空闲时间。

这在OptaPlanner中是可能的,还是应该使用不同的解决方法?我注意到Lesson对象只有一个TimeSlot,而不是一个列表,这使我认为这种时间表优化是不支持的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-22 16:20:21

从描述上看,你的问题似乎是“学生计划自己的时间表”(而学校时间表则是“教师为所有学生制定学校时间表”)。

我会这样做:

代码语言:javascript
运行
复制
@PlanningEntity
public class CourseSection {
    private List<TimeSlot> availableTimeslots;

    @PlanningId // needed for forEachUniquePair
    private String courseSectionIdentifier;

    @PlanningVariable(valueRangeProviderRefs = {"timeslotRange"})
    private TimeSlot selectedTimeslot;

    @ValueRangeProvider(id="timeslotRange")
    public List<TimeSlot> getTimeslotRangeForCourse() {
        return availableTimeslots;
    }
    
    // getters and setters ...
}

这利用了规划实体上的值范围提供程序,这意味着每个计划实体都有自己的值范围(并且不存在的课程TimeSlot将不会被尝试)。

我使用了CourseSection,因为课程可以分成多个部分(1次讲座+2次教程,2次讲座等等),每个部分都有一个CourseSection。(如果该课程只有一个讲座部分,那么只有一个CourseSection,如果该课程是一个讲座+教程,则有两个CourseSections等等)。

对于最小间隙约束,我将使用实验性的连续间隔约束收集器。要使用它,您要么需要将OptaPlanner实例添加为maven依赖项,要么需要添加从示例的源代码中复制它;一旦我们确定了API (它仍在试验阶段可能会发生变化),它最终将被移动到ConstraintCollectors中。对于连续的interval约束收集器,它将如下所示:

代码语言:javascript
运行
复制
Constraint minimizeGaps(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(CourseSection.class)
        .groupBy(section -> section.getSelectedTimeslot().getDayOfWeek(),
                 ExperimentalConstraintCollectors.consecutiveTemporalIntervals(
                         section -> section.getSelectedTimeslot().getStartTime(),
                         section -> section.getSelectedTimeslot().getEndTime()))
        .flattenLast(ConsecutiveIntervalInfo::getBreaks)
        .penalize("Minimize Gaps", HardMediumSoft.ONE_SOFT);
}

对于最大限度的空闲天数约束,我会将其写为“最小化工作日”,如下所示:

代码语言:javascript
运行
复制
Constraint minimizeWorkingDays(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(CourseSection.class)
        .groupBy(section -> section.getSelectedTimeslot().getDayOfWeek())
        .penalize("Minimize Working Days", HardMediumSoft.ONE_MEDIUM);
}

最后,我们需要确保没有两个课程部分重叠:

代码语言:javascript
运行
复制
Constraint noOverlappingCourseSections(ConstraintFactory constraintFactory) {
    return constraintFactory.forEachUniquePair(CourseSection.class,
               Joiners.equal(section -> section.getSelectedTimeslot().getDayOfWeek()),
               Joiners.overlapping(
                   section -> section.getSelectedTimeslot().getStartTime(),
                   section -> section.getSelectedTimeslot().getEndTime()))
        .penalize("Overlapping sections", HardMediumSoftScore.ONE_HARD);
}

注意,在我提供的约束条件中,工作时间较短的解决方案总是比工作日更多的解决方案更可取,即使解决方案的天数较少,间隔时间为8小时。您可能需要对允许的最大间隙添加一个附加约束(可以使用检查IntervalBreak.getLength()的筛选器来实现)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71572097

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档