0

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.

1 Answers1

0

I can't answer your question fully but I did find a problem in your Listener implementation. The lines

scoreDirector.beforeVariableChanged(shadowCustomer, "vehicle");
scoreDirector.afterVariableChanged(shadowCustomer, "vehicle");

must surround any line that modifies your planning variables such as:

 nextVehicle.setCurrentDemand(currentDemand);

I think what Geoff suggested is that if your capacity hits 0 your vehicle.getDistanceToPreviousStandstill function would add the distance to the depot to the calculation. (This is just my guess I didn't read too far into Geoff's design comment).

  • Thank you for clearing up the listener implementation. Will definitely try to implement this. I've been a bit stuck on this:) – Daniel Mouris Jun 06 '18 at 16:39