grudolf
grudolf

Reputation: 1794

Remove a vehicle from VRP

What is the correct way to remove (=delete) a vehicle from planning entity collection (similar to VehicleRoutingSolution.VehicleList in OptaPlanner VRP samples) via ProblemFactChange?

So far I've tried to

I'm getting IllegalStateException, either because of mismatch between prevStandstill and nextCustomer or Local Search phase start failing with an uninitialized solution.

Edit: moving the first customer in chain to another vehicle seems to be working fine.

Edit 2

I tried to reset all customers in chain with this snippet

Customer customer = vehicle.getNextCustomer();
while(customer!=null)
{
    Customer nextCustomer = customer.getNextCustomer();
    scoreDirector.beforeVariableChanged(customer, "previousStandstill");    //Exception on second customer
    customer.setPreviousStandstill(null);
    scoreDirector.afterVariableChanged(customer, "previousStandstill");
    scoreDirector.beforeVariableChanged(customer, "nextCustomer");
    customer.setNextCustomer(null);
    scoreDirector.afterVariableChanged(customer, "nextCustomer");
    customer.setVehicle(null);
    customer=nextCustomer;
}

but I'm getting hit with IllegalStateException on second run through loop

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: The entity (CUST39(after CUST39)) has a variable (previousStandstill) with value (CUST39(after null)) which has a sourceVariableName variable (nextCustomer) with a value (null) which is not that entity.
Verify the consistency of your input problem for that sourceVariableName variable.
    at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.retract(SingletonInverseVariableListener.java:82)
    at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.beforeVariableChanged(SingletonInverseVariableListener.java:44)
    at org.optaplanner.core.impl.domain.variable.listener.VariableListenerSupport.beforeVariableChanged(VariableListenerSupport.java:145)
    at org.optaplanner.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:257)
    at org.optaplanner.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:228)

It seems obvious (the state is invalid because first customer is detached from second, but second is still pointing at the first one), but I don't know what's the correct route ;) around it.

This

    Customer nextCustomer = customer.getNextCustomer();
    customer.setPreviousStandstill(null);
    customer.setNextCustomer(null);
    scoreDirector.beforeVariableChanged(customer, "previousStandstill");
    scoreDirector.beforeVariableChanged(customer, "nextCustomer");
    scoreDirector.afterVariableChanged(customer, "nextCustomer");
    scoreDirector.afterVariableChanged(customer, "previousStandstill");

seems to work - CH is fired for each of the removed customers, move count is correct, EasyScore works and the exception is avoided. But, is it bad?

Upvotes: 0

Views: 522

Answers (1)

Geoffrey De Smet
Geoffrey De Smet

Reputation: 27312

Do all these:

  • While each nextCustomer of that vehicle, set that customer's previousStandstill (= var) on null and it's nextCustomer (= inverse shadow var) also on null and it's vehicle (= anchor shadow var) also on null.
  • Remove the vehicle from the solution's vehicle list

Make sure to call the before/after methods appropriately.

The customers of that vehicle will then be uninitialized and the solver's CH will initialize them.

Upvotes: 1

Related Questions