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

Timefold讲师课程负载均衡问题:unfairness始终为0的排查

课程-讲师公平分配问题

我需要实现课程到讲师的公平分配,均衡实体为Lecturer,负载值为分配给讲师的课程总时长。调用penalizeBigDecimal时,求解器输出显示:即使所有课程都分配给Faizal或Ahmad,unfairness值仍为0。

核心问题

  • 为何LoadBalance::unfairness()始终返回0?是否需要自定义不公平度计算函数?
  • 如何确保所有讲师都出现在LoadBalance::loads()中?若需自定义公平函数(如基于讲师平均时长计算),需要所有讲师的数据来计算平均值。

我尝试在.groupBy()后链式调用.complement(),但它要求传入Class<LoadBalance<Lecturer>>类型参数,不知道如何正确传递。


补充说明

将某一课程时长改为70后,求解器返回非零unfairness值:

List<Course> courses = List.of(
            new Course(String.valueOf(courseId++), "Fizik 1", 70),
            new Course(String.valueOf(courseId++), "Chem 1", 60)
        );

        List<LecturerCourseAssignment> assignments = List.of(
            new LecturerCourseAssignment(courses.get(0)),
            new LecturerCourseAssignment(courses.get(1))
        );

我认为unfairness为0是因为Faizal未出现在LoadBalance::loads()中。但添加2个时长为60的课程分配后,仍得到不平衡的解决方案:

List<Course> courses = List.of(
            new Course(String.valueOf(courseId++), "Fizik 1", 60),
            new Course(String.valueOf(courseId++), "Chem 1", 60),
            new Course(String.valueOf(courseId++), "Math 1", 60),
            new Course(String.valueOf(courseId++), "Programming 1", 60)
        );

        List<LecturerCourseAssignment> assignments = List.of(
            new LecturerCourseAssignment(courses.get(0)),
            new LecturerCourseAssignment(courses.get(1)),
            new LecturerCourseAssignment(courses.get(2)),
            new LecturerCourseAssignment(courses.get(3))
        );

相关代码

PlanningSolution类

@PlanningSolution
public class LecturerCourseBalancing {
    @ProblemFactCollectionProperty
    @ValueRangeProvider
    List<Lecturer> lecturers;

    @PlanningEntityCollectionProperty
    List<LecturerCourseAssignment> courses;

    @PlanningScore
    HardSoftBigDecimalScore score;

    public LecturerCourseBalancing() {}

    public LecturerCourseBalancing(List<Lecturer> lecturers, List<LecturerCourseAssignment> courses) {
        this.lecturers = lecturers;
        this.courses = courses;
    }

    public List<Lecturer> getLecturers() {
        return lecturers;
    }

    public List<LecturerCourseAssignment> getCourses() {
        return courses;
    }

    public HardSoftBigDecimalScore getScore() {
        return score;
    }
}

LecturerCourseAssignment(规划实体)

@PlanningEntity
public class LecturerCourseAssignment {
    @PlanningVariable
    Lecturer lecturer;
    Course course;

    public LecturerCourseAssignment() {

    }

    public LecturerCourseAssignment(Course course) {
        this.course = course;
    }

    public void setLecturer(Lecturer lecturer) {
        this.lecturer = lecturer;
    }

    public Lecturer getLecturer() {
        return lecturer;
    }

    public Course getCourse() {
        return course;
    }

    @Override
    public String toString() {
        return "LecturerCourseAssignment [lecturer=" + lecturer + ", course=" + course + "]";
    }
}

Lecturer.java(问题事实)

public class Lecturer {
    @PlanningId
    String id;
    String name;

    public Lecturer(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Lecturer [id=" + id + ", name=" + name + "]";
    }
}

Course.java

public class Course {
    @PlanningId
    String id;

    String name;
    int duration;

    public Course() {}

    public Course(String id, String name, int duration) {
        this.id = id;
        this.name = name;
        this.duration = duration;
    }

    public String getId() {
        return id;
    }

    public int getDuration() {
        return duration;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Course [id=" + id + ", name=" + name + ", duration=" + duration + "]";
    }
}

Constraint Provider

public class LecturerCourseBalancingConstraintProvider implements ConstraintProvider {
    @Override
    public Constraint @NonNull [] defineConstraints(@NonNull ConstraintFactory constraintFactory) {
        return new Constraint[] {
            fairLecturerCourseAssignment(constraintFactory),
        };
    }

    Constraint fairLecturerCourseAssignment(ConstraintFactory constraintFactory) {
        return constraintFactory.forEach(LecturerCourseAssignment.class)
            .groupBy(ConstraintCollectors.loadBalance(lca -> lca.getLecturer(), lca -> lca.getCourse().getDuration()))
            .penalizeBigDecimal(HardSoftBigDecimalScore.ONE_SOFT, (loadBalance) -> {
                System.out.println(loadBalance.loads());
                System.out.println(loadBalance.unfairness());
                return loadBalance.unfairness();
            })
            .asConstraint("fairLecturerCourseAssignment");
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 16:54:51