Deliver entire load before next pickup


#1

Hi,

I am using Shipments and I have everything working great except I need to prevent a mid route pickups. Consider the following route solution:

pickupShipment 1
pickupShipment 2
deliverShipment 1
pickupShipment 3
deliverShipment 2
deliverShipment 3

In the above solution I need to prevent “pickupShipment 3” until shipment 2 has been delivered since it is already loaded in the vehicle. Any advice on how to achieve this would be appreciated.

Thanks,


Preventing load "top ups"
#2

Hi, this was discussed here: https://discuss.graphhopper.com/t/preventing-load-top-ups/1967/7
However, I am trying the suggested solution, and it is not working well yet…


#3

Hi, I think I solved this issue with the following constraint

public class PreventMidRoutePickupsConstraint implements HardActivityConstraint {

    private final StateManager stateManager;
    private final StateId loadCountStateId;
    private final StateId deliveriesStartedStateId;

    public PreventMidRoutePickupsConstraint(StateManager stateManager, StateId loadCountStateId, StateId deliveriesStartedStateId) {
        this.stateManager = stateManager;
        this.loadCountStateId = loadCountStateId;
        this.deliveriesStartedStateId = deliveriesStartedStateId;
    }

    @Override
    public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
        if (!(newAct instanceof PickupShipment) && !(newAct instanceof DeliverShipment)) {
            return ConstraintsStatus.FULFILLED;
        }

        final VehicleRoute route = iFacts.getRoute();
        int loadCount = firstNonNull(stateManager.getRouteState(route, loadCountStateId, Integer.class), 0);
        Boolean deliveriesStarted = stateManager.getRouteState(route, deliveriesStartedStateId, Boolean.class);
        if (newAct instanceof PickupShipment) {
            loadCount++;
            stateManager.putRouteState(route, loadCountStateId, loadCount);
            return isTrue(deliveriesStarted) ? ConstraintsStatus.NOT_FULFILLED : ConstraintsStatus.FULFILLED;
        }

        // Must be a DeliverShipment
        deliveriesStarted = true;
        loadCount--;
        if (loadCount <= 0) {
            deliveriesStarted = false;
        }
        stateManager.putRouteState(route, loadCountStateId, loadCount);
        stateManager.putRouteState(route, deliveriesStartedStateId, deliveriesStarted);
        return ConstraintsStatus.FULFILLED;
    }
}

#4

Thank you for the update, but I get an error:

Exception in thread "main" java.lang.IllegalStateException: state-id with name 'com.graphhopper.jsprit.examples.CostMatrixExample2$1@7714e963' cannot be created. it is already reserved internally.
	at com.graphhopper.jsprit.core.algorithm.state.StateFactory.throwReservedIdException(StateFactory.java:56)
	at com.graphhopper.jsprit.core.algorithm.state.StateManager.putRouteState(StateManager.java:439)
	at com.graphhopper.jsprit.core.problem.constraint.PreventMidRoutePickupsConstraint.fulfilled(PreventMidRoutePickupsConstraint.java:63)
	at com.graphhopper.jsprit.core.algorithm.recreate.AbstractInsertionCalculator.fulfilled(AbstractInsertionCalculator.java:69)
	at com.graphhopper.jsprit.core.algorithm.recreate.ShipmentInsertionCalculator.getInsertionData(ShipmentInsertionCalculator.java:148)
	at com.graphhopper.jsprit.core.algorithm.recreate.JobCalculatorSwitcher.getInsertionData(JobCalculatorSwitcher.java:40)
	at com.graphhopper.jsprit.core.algorithm.recreate.VehicleTypeDependentJobInsertionCalculator.getInsertionData(VehicleTypeDependentJobInsertionCalculator.java:116)
	at com.graphhopper.jsprit.core.algorithm.recreate.RegretInsertion.getScoredJob(RegretInsertion.java:187)
	at com.graphhopper.jsprit.core.algorithm.recreate.RegretInsertion.nextJob(RegretInsertion.java:140)
	at com.graphhopper.jsprit.core.algorithm.recreate.RegretInsertion.insertUnassignedJobs(RegretInsertion.java:112)
	at com.graphhopper.jsprit.core.algorithm.recreate.AbstractInsertionStrategy.insertJobs(AbstractInsertionStrategy.java:91)
	at com.graphhopper.jsprit.core.algorithm.InsertionInitialSolutionFactory.createSolution(InsertionInitialSolutionFactory.java:56)
	at com.graphhopper.jsprit.core.algorithm.PrettyAlgorithmBuilder$1.informAlgorithmStarts(PrettyAlgorithmBuilder.java:116)
	at com.graphhopper.jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.algorithmStarts(VehicleRoutingAlgorithmListeners.java:128)
	at com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm.algorithmStarts(VehicleRoutingAlgorithm.java:356)
	at com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm.searchSolutions(VehicleRoutingAlgorithm.java:229)
	at com.graphhopper.jsprit.examples.CostMatrixExample2.readAndSolve(CostMatrixExample2.java:487)
	at com.graphhopper.jsprit.examples.CostMatrixExample2.main(CostMatrixExample2.java:76)