I'm having trouble tracking the on going capacity of a vehicle in a Capcity Vehicle Routing Problem with Time Windows (CVRPTW).
I'm trying to make the vehicle return to the depot when it hits the maximum capacity of the vehicle.
Based on the response I got here https://groups.google.com/forum/#!topic/optaplanner-dev/IMG_7D1JvmQ I'm currently trying to implement the n trips per day design.
I've tried to use a shadow variable on the Vehicle and use a variable listener on it.
I've modified the vehicle class as follows:
@XStreamAlias("VrpVehicle")
public class Vehicle extends AbstractPersistable implements Standstill {
...planning entities
...other shadow variables
protected Integer currentDemand;
@CustomShadowVariable(sources = {@PlanningVariableReference(variableName = "previousStandstill")})
public Integer getCurrentDemand() { return currentDemand; }
}
}
My Variable Listener is as follows:
public class VehicleCapacityReuseVariableListener implements VariableListener<Customer> {
@Override
public void afterEntityAdded(ScoreDirector scoreDirector,Customer customer) {
if (customer instanceof TimeWindowedCustomer) {
updateVehicleDemandTotal(scoreDirector, (TimeWindowedCustomer) customer);
}
}
@Override
public void afterVariableChanged(ScoreDirector scoreDirector, Customer customer) {
if (customer instanceof TimeWindowedCustomer) {
updateVehicleDemandTotal(scoreDirector, (TimeWindowedCustomer) customer);
}
}
...
protected void updateVehicleDemandTotal(ScoreDirector scoreDirector, Customer sourceCustomer) {
Standstill previousStandstill = sourceCustomer.getPreviousStandstill();
Vehicle vehicle = previousStandstill == null ? null : previousStandstill.getVehicle();
TimeWindowedCustomer shadowCustomer = (TimeWindowedCustomer) sourceCustomer;
Integer currentDemand = shadowCustomer.getDemand();
Vehicle currentVehicle = shadowCustomer.getVehicle();
Vehicle nextVehicle = currentVehicle;
while (shadowCustomer != null) {
scoreDirector.beforeVariableChanged(shadowCustomer, "vehicle");
currentVehicle = shadowCustomer.getVehicle();
scoreDirector.afterVariableChanged(shadowCustomer, "vehicle");
shadowCustomer = shadowCustomer.getNextCustomer();
if (shadowCustomer != null) {
nextVehicle = shadowCustomer.getVehicle();
if (!currentVehicle.equals(nextVehicle)){
nextVehicle.setCurrentDemand(currentDemand);
currentVehicle.setCurrentDemand(currentVehicle.getCurrentDemand() - currentDemand);
currentDemand = nextVehicle.getCurrentDemand();
}
currentDemand += shadowCustomer.getDemand();
nextVehicle.setCurrentDemand(currentDemand);
}
}
}
}
If someone could help me track the capacity, that would be so great.
I think the solution (to go back to the depot) would be to set the next Customer as a "Depot" Customer.
PS. There are other stackoverflow questions related to this, and I've tried them to no avail. For completeness sake:
Thank you for your time in looking at this as well, and much thanks to anyone who responds.