如何使用 Spring Boot 在 Timefold Solver 中为时间表应用程序编写教师偏好约束?

问题描述 投票:0回答:1

假设我有一份生成大学时间表的申请,并且我有一个限制,即某些教师只在特定日期的某些时段进行教学。如何在 Timefold 中实现这种类型的约束?在 Spring Boot/Java 的调度算法中添加此类情况的最佳实践是什么?

我在 Timefold 的 GitHub Repo 上看到了以下场景的示例,可能与我需要的类似:老师更喜欢按顺序教授课程,不喜欢课程之间的间隙。这个约束的代码如下所示:

Constraint teacherTimeEfficiency(ConstraintFactory constraintFactory) {
    // A teacher prefers to teach sequential lessons and dislikes gaps between lessons.
    return constraintFactory
            .forEachUniquePair(Lesson.class,
                    Joiners.equal(Lesson::getTeacher),
                    Joiners.equal((lesson) -> lesson.getTimeslot().getDayOfWeek()))
            .filter((lesson1, lesson2) -> {
                Duration between = Duration.between(lesson1.getTimeslot().getEndTime(),
                        lesson2.getTimeslot().getStartTime());
                return !between.isNegative() && between.compareTo(Duration.ofMinutes(30)) <= 0;
            })
            .reward(HardSoftScore.ONE_SOFT)
            .justifyWith((lesson1, lesson2, score) -> new TeacherTimeEfficiencyJustification(lesson1.getTeacher(), lesson1, lesson2))
            .asConstraint("Teacher time efficiency");
}
java spring spring-boot constraints timefold
1个回答
0
投票

您知道首选的确切

Timeslots
吗?如果是这样,我会像这样建模
Teacher

// preferredTimeslots is nullable
public record Teacher(String name, List<Timeslot> preferredTimeslots) {}

那么约束就是

Constraint maximizePreferredTimeslotAssignments(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(Lesson.class)
               .join(Teacher.class, Joiners.equal(Lesson::getTeacher, Function.identity()))
               .filter((lesson, teacher) -> teacher.preferredTimeslots() != null && !teacher.preferredTimeslots().contains(lesson.getTimeslot()))
               .penalize(HardSoftScore.ONE_SOFT)
               .asConstraint("Teacher was assigned unpreferred timeslot");
}

这将惩罚

Teacher
的所有非首选时隙分配(前提是
Teacher
有首选时隙)。如果
Teacher
在周一没有首选时间段,并且您不想对该老师的所有周一作业进行处罚,则您需要将
List<Timeslot>
更改为
Map<DayOfWeek, List<Timeslot>>
(在过滤器中进行相应的更改):

(lesson, teacher) -> teacher.preferredTimeslots().get(lesson.getTimeslot().getDayOfWeek()) != null && !teacher.preferredTimeslots().get(lesson.getTimeslot().getDayOfWeek()).contains(lesson.getTimeslot())
© www.soinside.com 2019 - 2024. All rights reserved.