![](/img/trans.png)
[英]Set that fires event when first element is added, or last one is removed
[英]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.