java - 如何在 OptaPlanner 中为每组的最小和最大计数添加 HardConstraint?

标签 java optaplanner

我是 OptaPlanner 的新用户。

我需要在员工之间划分工作列表,但一名员工执行的工作数量不应少于或多于指定值。 例如,一名员工每天不能执行少于 10 项和超过 30 项工作。

源代码

@Data
@NoArgsConstructor
@PlanningEntity
public class Job {

    @PlanningId
    private Long id;

    @PlanningVariable(valueRangeProviderRefs = "employeeRange")
    private Employee employee;

}

@Data
@NoArgsConstructor
@AllArgsConstructor
@PlanningEntity
public class Inspector {

    @PlanningId
    private Long id;

    @InverseRelationShadowVariable(sourceVariableName = "employee")
    private List<Job> jobs;

}

@Data
@NoArgsConstructor
@PlanningSolution
public class Plan {

    @ProblemFactCollectionProperty
    @ValueRangeProvider(id = "employeeRange")
    private List<Employee> employees;

    @PlanningEntityCollectionProperty
    private List<Job> jobs;

    @PlanningScore
    private HardSoftScore score;

}

还有一个问题:

如何将多个约束合并为一个。 例如,一名员工每天可以执行 10 到 30 项工作。一次出差持续2天,因此在此期间他总共可以完成20到60份工作。

我阅读了文档,但我不确定 count() countDistinct() min() max() 是否适合此目的

最佳答案

在您的域中,我没有看到任何用于确定作业日期的字段,因此我假设所有作业共享相同的日期。使用Constraint Streams ,您可以对最小和最大工作限制进行建模,如下所示:

public class MyConstraintProvider implements ConstraintProvider {

    @Override
    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[] {
                minimumJobsPerDay(constraintFactory),
                maximumJobsPerDay(constraintFactory)
        };
    }

    Constraint minimumJobsPerDay(ConstraintFactory constraintFactory) {
        return constraintFactory.forEach(Inspector.class)
                            .filter(inspector -> inspector.getJobs().size() < 10)
                            .penalize("Employee performing less than minimum jobs per day",
                                      HardSoftScore.ONE_HARD,
                                      inspector -> 10 - inspector.getJobs().size());
    }

    Constraint maximumJobsPerDay(ConstraintFactory constraintFactory) {
        return constraintFactory.forEach(Inspector.class)
                            .filter(inspector -> inspector.getJobs().size() > 30)
                            .penalize("Employee performing more than maximum jobs per day",
                                      HardSoftScore.ONE_HARD,
                                      inspector -> inspector.getJobs().size() - 30);
    }
}

对于你的第二个问题,Compose Constraint Collector对于组合约束非常有用(尽管您的示例不需要)。对于您的示例(带有附加问题事实类 BusinessTrip):

@Data
@AllArgsConstructor
public class BusinessTrip {
    private Employee employee;
    private LocalDate start;
    private LocalDate end;
}

并更改工作,使其具有日期:

@Data
@NoArgsConstructor
@PlanningEntity
public class Job {

    @PlanningId
    private Long id;

    private LocalDate date;

    @PlanningVariable(valueRangeProviderRefs = "employeeRange")
    private Employee employee;

}

约束可以像这样建模:

Constraint jobsDuringBusinessTrip(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(BusinessTrip.class)
        .join(Employee.class, Joiners.equal(BusinessTrip::getEmployee, employee -> employee))
        .join(Job.class, Joiners.overlapping(
              (trip, employee) -> trip.getStart().atStartOfDay(),
              (trip, employee) -> trip.getEnd().atStartOfDay(),
              job -> job.getDate().atStartOfDay(),
              job -> job.getDate().plusDays(1).atStartOfDay()),
              Joiners.equal((trip, employee) -> employee, Job::getEmployee))
        .groupBy((trip,employee,job) -> trip,
                 (trip,employee,job) -> employee,
                 ConstraintCollectors.countTri())
        .filter((trip, employee, jobCount) -> jobCount < 20 || jobCount > 60)
        .penalize("Over or under job count during business trip",
                  HardSoftScore.ONE_HARD);
}

关于java - 如何在 OptaPlanner 中为每组的最小和最大计数添加 HardConstraint?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72858723/

相关文章:

java - 如何更好地在OptaPlanner中应用过度约束规划?

c++ - 在 c++/c# 中替代 drools-planner/optaplanner?

java - 在 Optaplanner 中使用@PlanningPin 时如何解决 “Bailing out of neverEnding selector to avoid infinite loop” 错误?

java - Web 应用程序 [VehicleRouting] 似乎启动了一个名为 [drools-worker-4] 的线程,但未能停止它

javascript - 使用 MySQL Community Server 和 jQuery AJAX 的 RESTful Web 服务

java - Class$S7119 在 GWT 中代表什么?

java - 序列中唯一的随机整数

java - 单击菜单链接时获取元素不可单击异常

java - Optaplanner 解决过程中出现空指针异常 - 交叉引用对象和 ReflectionPropertyAccessor 类

java - 当JAV中包含WAV时,如何在Java中播放WAV