繁体   English   中英

如何根据 OptaPlanner 中添加的第一个元素设置参数?

[英]How to set a parameter based on the first element added in OptaPlanner?

每个工作都有自己的位置(城市)。 每个员工只能在一个地点工作。 如果员工在一个地点工作,他就不能从另一个地点接受订单。 我怎么能做到这一点? 鉴于:

@Data
@PlanningEntity
public class Job {

    @PlanningId
    private Long id;

    private String location;

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

}

@Data
@PlanningEntity
public class Employee {

    @PlanningId
    private Long id;

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

}

@Data
@PlanningSolution
public class Solution {

    @PlanningEntityCollectionProperty
    @ValueRangeProvider(id = "employeeRange")
    private List<Emoloyee> employees;

    @PlanningEntityCollectionProperty
    private List<Job> jobs;

    @PlanningScore
    private HardMediumSoftScore score;

    public Solution(List<Emoloyee> employees, List<Job> jobs) {
        this.employees = employees;
        this.jobs = jobs;
    }
}

这是考虑位置的约束:

private Constraint locationIsConsidered(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(Job.class)
            .filter(job -> !job.getEmployee().getLocation()
                    .equals(job.getLocation()))
            .penalize("Location conflict", HardMediumSoftScore.ONE_HARD);
}

另一个约束(不考虑位置):但它不起作用

private Constraint directionIsNotConsidered(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(Job.class)
        .groupBy(Job::getInspector)
        .filter(employee -> employee.getJobs().stream()
            .anyMatch(job -> !Objects.equals(job.getLocation(),
                employee.getJobs().get(0).getLocation()))
        ).penalize("Location Conflict", HardMediumSoftScore.ONE_HARD);
}

提前致谢!

我想我已经找到了解决办法。

private Constraint directionIsNotConsidered(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(Job.class)
        .groupBy(Job::getInspector)
        .filter(employee -> employee.getJobs().stream()
            .anyMatch(job -> !Objects.equals(job.getLocation(),
                employee.getJobs().get(0).getLocation()))
        ).penalize("Location Conflict", HardMediumSoftScore.ONE_HARD);
}

恐怕您在这里要解决的实际上是两个不同的规划问题。 将员工分配到位置,然后将工作分配给这些位置的员工。 后者的结果取决于前者的结果; 如果前者的结果发生变化,则需要对后者的整个结果进行大量重新计算。

试图在一个求解器中解决这两个问题必然会导致问题。 一旦您将员工分配到一个位置,并且您将一些工作分配给该员工,那么将保证将员工重新分配到另一个位置可以保证打破硬约束,尝试从不同城市分配工作的移动也是如此 - 因此不会移动实际上可以让您到任何地方,除非您编写一个自定义移动,当位置移动时重新分配所有员工工作,再加上一大堆移动过滤器,消除无用的移动。 虽然这个问题不会妨碍求解器的工作,但求解器的效率不会太高。

更好的方法是实施多阶段规划 先解决员工进城问题。 如果这是一个足够简单的问题,请使用蛮力; 如果很难,请使用 OptaPlanner。 一旦你有了分配,使用 OptaPlanner 将工作分配给这些员工,他们的城市现在是不可变的。 这会带来其自身的低效率,但实施和理解起来会相对简单。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM