向时间折叠时间表示例添加进一步的限制,即教师只能在特定日期工作

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

我正在尝试扩展 Timefold 'Hello World' java 示例。我已经添加了我自己的课程、班级和教师数据,现在我想添加一个额外的约束,即某些教师仅在特定日期工作。

我试过这个:

Constraint restDayConstraint(ConstraintFactory constraintFactory) {
        // teachers don't teach on their rest day
        return constraintFactory
                .forEachUniquePair(Lesson.class, Teacher.class,
                        Joiners.equal(Lesson::getTimeslot),
                        Joiners.equal(Teacher::getTeacher))
                .filter((lesson1, teacher) -> lesson1.getTimeslot().getDayOfWeek() != teacher.getRestDay())
                .penalize(HardSoftScore.ONE_HARD)
                .justifyWith(
                        (lesson1, teacher, score) -> new TeacherConflictJustification(lesson1.getTeacher(), lesson1, teacher))
                .asConstraint("Teacher conflict");
    }

并使用以下代码创建了 Teacher.java 文件:

package org.acme.schooltimetabling.domain;

import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
import ai.timefold.solver.core.api.domain.variable.PlanningVariable;

@PlanningEntity
public class Teacher {

    @PlanningId
    private Long id;

    private String subject;
    private String restDay;

    @PlanningVariable
    private Timeslot timeslot;

    @PlanningVariable
    private Room room;

    // No-arg constructor required for Timefold
    public Teacher() {
    }

    public Teacher(long id, String subject, String restDay) {
        this.id = id;
        this.subject = subject;
        this.restDay = restDay;
    }

    @Override
    public String toString() {
        return subject + "(" + id + ")";
    }

    // ************************************************************************
    // Getters and setters
    // ************************************************************************

    public Long getId() {
        return id;
    }

    public String getRestDay() {
        return restDay;
    }

    public String getSubject() {
        return subject;
    }

}

但是我收到以下错误:

The method forEachUniquePair(Class<A>, BiJoiner<A,A>, BiJoiner<A,A>) in the type ConstraintFactory is not applicable for the arguments (Class<Lesson>, BiJoiner<Lesson,Lesson>, BiJoiner<Teacher,Teacher>)

如何强制执行某些教师仅在特定日期工作的限制?

java optimization timefold
1个回答
0
投票

我认为该错误是由于您尝试在 2 个不同的实体(教师、课程)上执行 forEachUniquePair() 方法而导致的,而该方法是为单个规划实体(课程或教师)设计的。 https://javadoc.io/doc/ai.timefold.solver/timefold-solver-core-impl/latest/ai/timefold/solver/core/api/score/stream/ConstraintFactory.html#forEachUniquePair(java.lang .Class,ai.timefold.solver.core.api.score.stream.bi.BiJoiner,ai.timefold.solver.core.api.score.stream.bi.BiJoiner) 我不知道你为什么选择有两个规划实体。也许你可以告诉我更多关于你想要实现的目标。

如果您想更好地了解规划实体、规划变量和问题事实之间的区别,可以参考此文档:https://timefold.ai/docs/timefold-solver/latest/using-timefold-solver/modeling-规划问题#problemFact

我建议您按照以下示例对域进行建模:https://github.com/TimefoldAI/timefold-quickstarts/tree/stable/technology/java-spring-boot/src/main/java/org/acme /schooltimetableling/domain.

您可以像这样对课程和教师课程进行建模:

@PlanningEntity
public class Lesson {

    @PlanningId
    private Long id;

    private String subject;
    private Teacher teacher;
    private String studentGroup;

    @JsonIdentityReference
    @PlanningVariable
    private Timeslot timeslot;

    @JsonIdentityReference
    @PlanningVariable
    private Room room;

    //constructors and getters and setters

public class Teacher {

    private Long id;
    private String subject;
    private List<DayOfWeek> restDay;

    //contructors and getters and setters

然后我将按如下方式对约束进行建模:

Constraint restDayConstraint(ConstraintFactory constraintFactory) {
        // teachers don't teach on their rest day
        return constraintFactory
                .forEachUniquePair(Lesson.class,
                        Joiners.equal(Lesson::getTimeslot),
                        Joiners.equal((lesson) -> lesson.getTeacher()))
                .filter((lesson1, teacher) -> 
// check if the teacher's restDays contains the day of the lesson
teacher.getRestDay().contains(lesson1.getTimeslot().getDayOfWeek()))
                .penalize(HardSoftScore.ONE_HARD)
                .justifyWith(
                        (lesson1, teacher, score) -> new TeacherConflictJustification(lesson1.getTeacher(), lesson1, teacher))
                .asConstraint("Teacher conflict");
    }

这就是我解决问题的方法。如果有帮助请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.