Reputation: 1794
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.
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
Reputation: 27312
Do all these:
previousStandstill
(= var) on null and it's nextCustomer
(= inverse shadow var) also on null and it's vehicle
(= anchor shadow var) also on null.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