Java Optaplanner将客户从工作VRP解决方案中移除

Java Optaplanner将客户从工作VRP解决方案中移除,java,optaplanner,Java,Optaplanner,基于此,我尝试了以下方法: public void doFactChange() { Location toBeRemovedLocation = customerToBeRemoved.getLocation(); Location lookUpWorkingObject = (Location) scoreDirector.lookUpWorkingObject(toBeRemovedLocation); scoreDirector.beforeProblemFact

基于此,我尝试了以下方法:

public void doFactChange() {
    Location toBeRemovedLocation = customerToBeRemoved.getLocation();
    Location lookUpWorkingObject = (Location) scoreDirector.lookUpWorkingObject(toBeRemovedLocation);
    scoreDirector.beforeProblemFactRemoved(lookUpWorkingObject);
    routingSolution.getLocationList().remove(lookUpWorkingObject);
    scoreDirector.afterProblemFactRemoved(lookUpWorkingObject);
    Customer workingCustomer = (Customer) scoreDirector.lookUpWorkingObject(customerToBeRemoved);

    for (Customer customer : routingSolution.getCustomerList()) {
        while (customer != null) {
            if (customer == workingCustomer) {
                if (customer.getPreviousStandstill() != null) {
                    scoreDirector.beforeVariableChanged(customer, "previousStandstill");
                    customer.getPreviousStandstill().setNextCustomer(customer.getNextCustomer());

                    scoreDirector.afterVariableChanged(customer, "previousStandstill");
                }

                scoreDirector.beforeVariableChanged(customer, "nextCustomer");
                customer.getNextCustomer().setPreviousStandstill(customer.getPreviousStandstill());
                scoreDirector.afterVariableChanged(customer, "nextCustomer");
            }
            customer = customer.getNextCustomer();
        }
    }

    scoreDirector.beforeEntityRemoved(workingCustomer);
    routingSolution.getCustomerList().remove(workingCustomer);
    scoreDirector.afterEntityRemoved(workingCustomer);
    scoreDirector.triggerVariableListeners();
}
注意:
customerToBeRemoved
是在调用
doFactChange()之前创建的实例对象

但我甚至在调用
scoreDirector.triggerVariableListeners

java.lang.IllegalStateException:实体(Customer--9048381398840634905)有一个值为(Customer--9070671076516032025)的变量(previousStandstill),该变量有一个值为(Customer-8518512081385427431)的sourceVariableName变量(nextCustomer),该值不是该实体。 验证该sourceVariableName变量的输入问题的一致性

另一个问题:

我尝试直接删除实体,如下所示:

public void doFactChange() {
    Location toBeRemovedLocation = customerToBeRemoved.getLocation();
    Location lookUpWorkingObject = (Location) scoreDirector.lookUpWorkingObject(toBeRemovedLocation);
    scoreDirector.beforeProblemFactRemoved(lookUpWorkingObject);
    routingSolution.getLocationList().remove(lookUpWorkingObject);
    scoreDirector.afterProblemFactRemoved(lookUpWorkingObject);
    Customer workingCustomer = (Customer) scoreDirector.lookUpWorkingObject(customerToBeRemoved);

    scoreDirector.beforeEntityRemoved(workingCustomer);
    routingSolution.getCustomerList().remove(workingCustomer);
    scoreDirector.afterEntityRemoved(workingCustomer);
    scoreDirector.triggerVariableListeners();
}

这有效吗?

此方法适用于optaplanner VRP示例,使用简单、递增和drl分数计算器:

public void removeRandomCustomer()
{
    doProblemFactChange(scoreDirector -> {
        VehicleRoutingSolution solution = scoreDirector.getWorkingSolution();
        int rnd = 4; //select a random customer
        if (solution.getCustomerList().size() > rnd)
        {
            Customer customer = solution.getCustomerList().get(rnd);
            scoreDirector.beforeEntityRemoved(customer);
            removeCustomer(solution, customer);
            scoreDirector.afterEntityRemoved(customer);
            scoreDirector.triggerVariableListeners();
        }
    });
}

private void removeCustomer(VehicleRoutingSolution solution, Customer customer)
{
    Standstill anchor = customer.getPreviousStandstill();
    Customer nextCustomer = customer.getNextCustomer();
    //anchor shouldn't be null in an initialized solution
    if (anchor != null)
        anchor.setNextCustomer(nextCustomer);
    if (nextCustomer != null)
        nextCustomer.setPreviousStandstill(anchor);
    solution.getCustomerList().remove(customer);
}
编辑:

具有简易/增量评分的影子变量替代方法:

private void removeCustomer(ScoreDirector<VehicleRoutingSolution> scoreDirector, VehicleRoutingSolution solution, Customer removeCustomer)
{
    final Customer customer = scoreDirector.lookUpWorkingObject(removeCustomer);
    Standstill anchor = customer.getPreviousStandstill();
    Customer nextCustomer = customer.getNextCustomer();

    //scoreDirector.beforeVariableChanged(anchor, "nextCustomer");
    scoreDirector.beforeVariableChanged(customer, "previousStandstill");    //sets anchor.nextCustomer=null
    customer.setPreviousStandstill(null);
    scoreDirector.afterVariableChanged(customer, "previousStandstill");
    //scoreDirector.afterVariableChanged(anchor, "nextCustomer");
    if(nextCustomer!=null)
    {
        //scoreDirector.beforeVariableChanged(customer, "nextCustomer");
        scoreDirector.beforeVariableChanged(nextCustomer, "previousStandstill");  //sets customer.nextCustomer=null
        nextCustomer.setPreviousStandstill(anchor);
        scoreDirector.afterVariableChanged(nextCustomer, "previousStandstill");
        //scoreDirector.afterVariableChanged(customer, "nextCustomer");
    }

    scoreDirector.beforeEntityRemoved(customer);
    //clone customer list
    ArrayList<Customer> changedList = new ArrayList<>(solution.getCustomerList());
    solution.setCustomerList(changedList);
    solution.getCustomerList().remove(customer);
    scoreDirector.afterEntityRemoved(customer);
    scoreDirector.triggerVariableListeners();  //sets customer.vehicle=null, sets all nextCustomer.vehicle=null

}
private void remove客户(ScoreDirector ScoreDirector,车辆路线解决方案,客户移除客户)
{
最终客户=scoreDirector.lookUpWorkingObject(removeCustomer);
Standstill anchor=customer.getPreviousStandstill();
Customer-nextCustomer=Customer.getNextCustomer();
//scoreDirector.beforeVariableChanged(锚定,“下一个客户”);
scoreDirector.beforeVariableChanged(customer,“previousStandstill”);//设置anchor.nextCustomer=null
customer.setPreviousStandstill(空);
scoreDirector.afterVariableChanged(客户,“以前的停止”);
//scoreDirector.afterVariableChanged(锚定,“下一个客户”);
if(nextCustomer!=null)
{
//scoreDirector.beforeVariableChanged(客户,“下一个客户”);
scoreDirector.beforeVariableChanged(nextCustomer,“previousStandstill”);//设置customer.nextCustomer=null
下一个客户设置上一个停止(锚);
scoreDirector.afterVariableChanged(下一个客户,“以前的停滞”);
//scoreDirector.afterVariableChanged(客户,“下一个客户”);
}
scoreDirector.在实体移除之前(客户);
//克隆客户列表
ArrayList changedList=新的ArrayList(solution.getCustomerList());
解决方案.setCustomerList(changedList);
solution.getCustomerList().remove(客户);
scoreDirector.afterEntityRemoved(客户);
scoreDirector.triggerVariableListeners();//设置customer.vehicle=null,设置所有nextCustomer.vehicle=null
}

解决方案现在应该处于有效状态,但您可能必须修复增量计分(轻松计分很好,因为
doProblemFactChange()
会自动重新计算它),可能需要删除
VehiclerOutingIncrementalCoreCalculator.beforeEntityRemoved()
中的收回。如果其他所有操作都失败,您可以首先将客户移动到链的末端并将其移除。

@Geoffrey De Smet,您的支持人员。如果不工作,则会出现以下异常:java.lang.IllegalStateException:entity(customer--9070677347168284185)有一个值为(customer--9097931491641785)的变量(以前的静止状态)其sourceVariableName变量(nextCustomer)的值(null)不是该实体。验证sourceVariableName变量的输入问题的一致性。这有点奇怪。您是否更改了其他内容,可能是在
doProblemFactChange()
方法中?发布的代码使用optaplanner-Distribution-7.5.0.Final中的VRP示例进行了测试,它与正在运行和停止的解算器一起工作。它如何在没有调用scoreDirector上的beforeVariableChanged和afterVariableChanged的情况下工作?我怀疑Grudolf的方法是正确的,但是Java播放器的IllegalStateException是他之前添加的另一个复杂性,这意味着remoteCustomer不能盲目复制粘贴(或者它也可能是存在的、不相关的无效状态)。好的Geoffrey,如果我们忽略该异常并查看该方法的结构,它有什么问题?