簡體   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