简体   繁体   English

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

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

Each job has own location (city).每个工作都有自己的位置(城市)。 Each employee can take jobs only in one location.每个员工只能在一个地点工作。 If an employee took a job in one location, he cannot take orders from another location.如果员工在一个地点工作,他就不能从另一个地点接受订单。 How I can do this?我怎么能做到这一点? Given:鉴于:

@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;
    }
}

Here is constraint for considering the location:这是考虑位置的约束:

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

the another constraint (location is not considered): But it's not working另一个约束(不考虑位置):但它不起作用

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);
}

Thanks in advance!提前致谢!

I think I have found a solution.我想我已经找到了解决办法。

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);
}

I'm afraid that what you're trying to solve here is actually two distinct planning problems.恐怕您在这里要解决的实际上是两个不同的规划问题。 Assigning employees to locations, and then assigning jobs to employees in those locations.将员工分配到位置,然后将工作分配给这些位置的员工。 The outcome of the latter depends on the outcome of the former;后者的结果取决于前者的结果; if the outcome of the former changes, the entire outcome for the latter needs to be significantly recomputed.如果前者的结果发生变化,则需要对后者的整个结果进行大量重新计算。

Attempting to solve both of these issues in a single solver is bound to cause issues.试图在一个求解器中解决这两个问题必然会导致问题。 Once you assign an employee to a location, and you assign some jobs to that employee, reassigning the employee to another location is then guaranteed to break hard constraints, and so are moves that try to assign jobs from a different city - therefore no move will actually get you anywhere, unless you write a custom move that reassigns all employee jobs when the location moves, plus a whole bunch of move filters eliminating useless moves.一旦您将员工分配到一个位置,并且您将一些工作分配给该员工,那么将保证将员工重新分配到另一个位置可以保证打破硬约束,尝试从不同城市分配工作的移动也是如此 - 因此不会移动实际上可以让您到任何地方,除非您编写一个自定义移动,当位置移动时重新分配所有员工工作,再加上一大堆移动过滤器,消除无用的移动。 Although this problem will not prevent the solver from working, the solver will not be too efficient.虽然这个问题不会妨碍求解器的工作,但求解器的效率不会太高。

A better approach would be to implement multi-stage planning .更好的方法是实施多阶段规划 Solve the problem of assigning employees to cities first.先解决员工进城问题。 If it's a simple enough problem, use brute force;如果这是一个足够简单的问题,请使用蛮力; if it's hard, use OptaPlanner.如果很难,请使用 OptaPlanner。 Once you have an allocation, use OptaPlanner to assign jobs to those employees, with their cities now immutable.一旦你有了分配,使用 OptaPlanner 将工作分配给这些员工,他们的城市现在是不可变的。 This will bring its own inefficiencies, but it will be relatively simple to implement and understand.这会带来其自身的低效率,但实施和理解起来会相对简单。

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

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