From 6cf67f7ba06b423a952ae6667c177ce09de3fc82 Mon Sep 17 00:00:00 2001 From: Stefan Schroeder <4sschroeder@gmail.com> Date: Fri, 30 Aug 2013 10:52:31 +0200 Subject: [PATCH] refinements to incorporate pickup and deliveries --- .../java/algorithms/StateManagerImpl.java | 26 +--- .../src/main/java/algorithms/StateTypes.java | 6 +- .../algorithms/UpdateCostsAtAllLevels.java | 16 +++ ...atestOperationStartTimeAtActLocations.java | 6 + .../java/basics/VehicleRoutingProblem.java | 4 + .../BuildPDVRPAlgoFromScratchTest.java | 121 ++++++------------ 6 files changed, 69 insertions(+), 110 deletions(-) diff --git a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java index 2292ac97..fc31b947 100644 --- a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java +++ b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java @@ -27,30 +27,6 @@ class StateManagerImpl implements StateManager{ private Map activityStates = new HashMap(); -// Map getRouteStates() { -// return Collections.unmodifiableMap(vehicleRouteStates); -// } -// -// States getRouteStates(VehicleRoute route){ -// return vehicleRouteStates.get(route); -// } -// -// void put(VehicleRoute route, States states) { -// vehicleRouteStates.put(route, states); -// } -// -// Map getActivityStates() { -// return Collections.unmodifiableMap(activityStates); -// } -// -// States getActivityStates(TourActivity act){ -// return activityStates.get(act); -// } -// -// void put(TourActivity act, States states) { -// activityStates.put(act, states); -// } - public void clear(){ vehicleRouteStates.clear(); activityStates.clear(); @@ -84,6 +60,8 @@ class StateManagerImpl implements StateManager{ if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0); if(stateType.equals(StateTypes.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime()); if(stateType.equals(StateTypes.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime()); + if(stateType.equals(StateTypes.FUTURE_PICKS)) return new StateImpl(0); + if(stateType.equals(StateTypes.PAST_DELIVERIES)) return new StateImpl(0); return null; } diff --git a/jsprit-core/src/main/java/algorithms/StateTypes.java b/jsprit-core/src/main/java/algorithms/StateTypes.java index d7c03523..e2dbd4e7 100644 --- a/jsprit-core/src/main/java/algorithms/StateTypes.java +++ b/jsprit-core/src/main/java/algorithms/StateTypes.java @@ -11,5 +11,9 @@ class StateTypes { final static String EARLIEST_OPERATION_START_TIME = "earliestOST"; - public static final String COSTS = "costs"; + static final String COSTS = "costs"; + + final static String FUTURE_PICKS = "futurePicks"; + + final static String PAST_DELIVERIES = "pastDeliveries"; } diff --git a/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java b/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java index 2cc6bcf7..b7852a83 100644 --- a/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java +++ b/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java @@ -1,5 +1,7 @@ package algorithms; +import org.apache.log4j.Logger; + import algorithms.ForwardInTimeListeners.ForwardInTimeListener; import algorithms.StateManager.StateImpl; import basics.costs.ForwardTransportCost; @@ -7,10 +9,13 @@ import basics.costs.VehicleRoutingActivityCosts; import basics.route.End; import basics.route.Start; import basics.route.TourActivity; +import basics.route.TourActivity.JobActivity; import basics.route.VehicleRoute; class UpdateCostsAtAllLevels implements ForwardInTimeListener{ + private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class); + private VehicleRoutingActivityCosts activityCost; private ForwardTransportCost transportCost; @@ -38,16 +43,22 @@ class UpdateCostsAtAllLevels implements ForwardInTimeListener{ vehicleRoute.getVehicleRouteCostCalculator().reset(); prevAct = start; startTimeAtPrevAct = departureTime; +// log.info(start + " depTime=" + departureTime); } @Override public void nextActivity(TourActivity act, double arrTime, double endTime) { +// log.info(act + " job " + ((JobActivity)act).getJob().getId() + " arrTime=" + arrTime + " endTime=" + endTime); double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle()); double actCost = activityCost.getActivityCost(act, arrTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle()); vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost); vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost); + if(transportCost > 10000 || actCost > 100000){ + throw new IllegalStateException("aaaääähh"); + } + totalOperationCost += transportCost; totalOperationCost += actCost; @@ -59,12 +70,17 @@ class UpdateCostsAtAllLevels implements ForwardInTimeListener{ @Override public void end(End end, double arrivalTime) { +// log.info(end + " arrTime=" + arrivalTime); double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), end.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle()); double actCost = activityCost.getActivityCost(end, arrivalTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle()); vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost); vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost); + if(transportCost > 10000 || actCost > 100000){ + throw new IllegalStateException("aaaääähh"); + } + totalOperationCost += transportCost; totalOperationCost += actCost; diff --git a/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java b/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java index 6c65282e..6607bd50 100644 --- a/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java +++ b/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java @@ -1,14 +1,19 @@ package algorithms; +import org.apache.log4j.Logger; + import algorithms.BackwardInTimeListeners.BackwardInTimeListener; import algorithms.StateManager.StateImpl; import basics.route.End; import basics.route.Start; import basics.route.TourActivity; +import basics.route.TourActivity.JobActivity; import basics.route.VehicleRoute; class UpdateLatestOperationStartTimeAtActLocations implements BackwardInTimeListener{ + private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class); + private StateManagerImpl states; public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states) { @@ -21,6 +26,7 @@ class UpdateLatestOperationStartTimeAtActLocations implements BackwardInTimeList @Override public void prevActivity(TourActivity act,double latestDepartureTime, double latestOperationStartTime) { +// log.info(act + " jobId=" + ((JobActivity)act).getJob().getId() + " " + latestOperationStartTime); states.putActivityState(act, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestOperationStartTime)); } diff --git a/jsprit-core/src/main/java/basics/VehicleRoutingProblem.java b/jsprit-core/src/main/java/basics/VehicleRoutingProblem.java index 0fc612f2..71c13a50 100644 --- a/jsprit-core/src/main/java/basics/VehicleRoutingProblem.java +++ b/jsprit-core/src/main/java/basics/VehicleRoutingProblem.java @@ -49,6 +49,10 @@ import basics.route.VehicleTypeImpl; */ public class VehicleRoutingProblem { + public static class VehicleRoutingProblemType { + + } + /** * Builder to build the routing-problem. * diff --git a/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java b/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java index c998dfd5..04fddd9d 100644 --- a/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java +++ b/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java @@ -9,8 +9,7 @@ import org.junit.Test; import util.Solutions; import algorithms.BackwardInTimeListeners.BackwardInTimeListener; import algorithms.ForwardInTimeListeners.ForwardInTimeListener; -import algorithms.HardConstraints.HardActivityLevelConstraint; -import algorithms.StateManager.State; +import algorithms.HardConstraints.HardActivityLevelConstraintAccumulator; import algorithms.StateManager.StateImpl; import algorithms.acceptors.AcceptNewIfBetterThanWorst; import algorithms.selectors.SelectBest; @@ -29,7 +28,6 @@ import basics.io.VrpXMLReader; import basics.io.VrpXMLWriter; import basics.route.DeliveryActivity; import basics.route.End; -import basics.route.PickupActivity; import basics.route.Start; import basics.route.TourActivity; import basics.route.VehicleRoute; @@ -46,80 +44,19 @@ public class BuildPDVRPAlgoFromScratchTest { public void setup(){ VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance(); - new VrpXMLReader(builder).read("src/test/resources/pdVRP_vrpnc1_jsprit.xml"); + new VrpXMLReader(builder).read("src/test/resources/pd_solomon_r101.xml"); vrp = builder.build(); final StateManagerImpl stateManager = new StateManagerImpl(); - HardActivityLevelConstraint hardActLevelConstraint = new HardActivityLevelConstraint() { - - @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { -// if(newAct instanceof PickupActivity && nextAct instanceof DeliveryActivity){ return false; } -// if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return false; } - int loadAtPrevAct; - int futurePicks; - int pastDeliveries; - if(prevAct instanceof Start){ - loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble(); - futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateTypes.LOAD).toDouble(); - pastDeliveries = 0; - } - else{ - loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateTypes.LOAD).toDouble(); - State futurePickState = stateManager.getActivityState(prevAct, "futurePicks"); - if(futurePickState == null) { - futurePicks = 0; - } - else { - futurePicks = (int) futurePickState.toDouble(); - } - State pastDeliveryState = stateManager.getActivityState(prevAct, "pastDeliveries"); - if(pastDeliveryState == null){ - pastDeliveries = 0; - } - else { - pastDeliveries = (int) pastDeliveryState.toDouble(); - } - } - if(newAct instanceof PickupActivity){ - if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){ - return false; - } - } - if(newAct instanceof DeliveryActivity){ - if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){ - return false; - } - - } - return true; - } - - }; + HardActivityLevelConstraintAccumulator actLevelConstraintAccumulator = new HardActivityLevelConstraintAccumulator(); + actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardPickupAndDeliveryConstraint(stateManager)); + actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardTimeWindowConstraint(stateManager, vrp.getTransportCosts())); - MarginalsCalculus marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), hardActLevelConstraint); - CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardRouteLevelConstraint() { - - @Override - public boolean fulfilled(InsertionContext insertionContext) { - if(insertionContext.getJob() instanceof Delivery){ - int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD_AT_DEPOT).toDouble(); - if(loadAtDepot + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){ - return false; - } - } - else if(insertionContext.getJob() instanceof Pickup){ - int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble(); - if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){ - return false; - } - } - else throw new IllegalStateException("ähh"); - return true; - } - - }); + MarginalsCalculus marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), actLevelConstraintAccumulator); + + CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager)); +// CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager)); VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles()); JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, serviceInsertion); @@ -156,16 +93,23 @@ public class BuildPDVRPAlgoFromScratchTest { final IterateRouteForwardInTime iterateForward = new IterateRouteForwardInTime(vrp.getTransportCosts()); + iterateForward.addListener(new UpdateActivityTimes()); + iterateForward.addListener(new UpdateEarliestStartTimeWindowAtActLocations(stateManager)); iterateForward.addListener(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); + +// iterateForward.addListener(new UpdateLoadAtAllLevels(stateManager)); + iterateForward.addListener(new ForwardInTimeListener() { private int currentLoad = 0; - private int deliveries = 0; + private int deliveries = 0; + private VehicleRoute route; @Override public void start(VehicleRoute route, Start start, double departureTime) { // log.info("iterate forward"); currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble(); + this.route = route; // log.info("currentLoad="+currentLoad); } @@ -177,11 +121,12 @@ public class BuildPDVRPAlgoFromScratchTest { deliveries += Math.abs(act.getCapacityDemand()); } stateManager.putActivityState(act, StateTypes.LOAD, new StateImpl(currentLoad)); - stateManager.putActivityState(act, "pastDeliveries", new StateImpl(deliveries)); + stateManager.putActivityState(act, StateTypes.PAST_DELIVERIES, new StateImpl(deliveries)); if(currentLoad < 0) throw new IllegalStateException("currentload < 0"); - if(currentLoad > 50){ - throw new IllegalStateException("currentload="+currentLoad+" wich is > 50"); + if(currentLoad > route.getVehicle().getCapacity()){ + throw new IllegalStateException("currentload="+currentLoad+" wich is > " + route.getVehicle().getCapacity()); } + } @Override @@ -190,10 +135,12 @@ public class BuildPDVRPAlgoFromScratchTest { // stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(currentLoad)); currentLoad = 0; deliveries = 0; + route = null; } }); - +// final IterateRouteBackwardInTime iterateBackward = new IterateRouteBackwardInTime(vrp.getTransportCosts()); + iterateBackward.addListener(new UpdateLatestOperationStartTimeAtActLocations(stateManager)); iterateBackward.addListener(new BackwardInTimeListener() { int futurePicks = 0; @@ -205,7 +152,7 @@ public class BuildPDVRPAlgoFromScratchTest { @Override public void prevActivity(TourActivity act, double latestDepartureTime, double latestOperationStartTime) { - stateManager.putActivityState(act, "futurePicks", new StateImpl(futurePicks)); + stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks)); if(act.getCapacityDemand() > 0){ futurePicks += act.getCapacityDemand(); } @@ -220,7 +167,6 @@ public class BuildPDVRPAlgoFromScratchTest { }); - InsertionStartsListener loadVehicleInDepot = new InsertionStartsListener() { @Override @@ -246,14 +192,16 @@ public class BuildPDVRPAlgoFromScratchTest { }; vra.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager)); - vra.getSearchStrategyManager().addSearchStrategyModuleListener(loadVehicleInDepot); + +// vra.getSearchStrategyManager().addSearchStrategyModuleListener(loadVehicleInDepot); JobInsertedListener updateLoadAfterJobHasBeenInserted = new JobInsertedListener() { @Override public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { -// log.info("insert job " + job2insert.getClass().toString() + " " + job2insert.getCapacityDemand() + " in route " + inRoute.getTourActivities()); +// log.info("insert job " + job2insert.getClass().toString() + " job " + job2insert + "" + job2insert.getCapacityDemand() + " in route " + inRoute.getTourActivities()); + if(job2insert instanceof Delivery){ int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble(); // log.info("loadAtDepot="+loadAtDepot); @@ -270,14 +218,17 @@ public class BuildPDVRPAlgoFromScratchTest { } }; - vra.getSearchStrategyManager().addSearchStrategyModuleListener(updateLoadAfterJobHasBeenInserted); +// vra.getSearchStrategyManager().addSearchStrategyModuleListener(updateLoadAfterJobHasBeenInserted); + + bestInsertion.addListener(loadVehicleInDepot); + bestInsertion.addListener(updateLoadAfterJobHasBeenInserted); VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion).createInitialSolution(vrp); // System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size()); vra.addInitialSolution(iniSolution); - vra.setNuOfIterations(2000); -// vra.setPrematureBreak(200); + vra.setNuOfIterations(10000); + vra.setPrematureBreak(1000); } @@ -285,7 +236,7 @@ public class BuildPDVRPAlgoFromScratchTest { public void test(){ Collection solutions = vra.searchSolutions(); System.out.println(Solutions.getBest(solutions).getCost()); - new VrpXMLWriter(vrp, solutions).write("output/pdvrp_sol.xml"); + new VrpXMLWriter(vrp, solutions).write("output/pd_solomon_r101.xml"); }