From a32d8c1c6a1a2f25b02697681a5fb1c6fac541d9 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Mon, 7 Oct 2013 11:02:39 +0200 Subject: [PATCH] Switch to Activity- and RouteVisitor --- .../java/algorithms/ActivityTimeTracker.java | 82 +++++ .../main/java/algorithms/ActivityVisitor.java | 14 + .../algorithms/ReverseActivityVisitor.java | 14 + .../ReverseRouteActivityVisitor.java | 49 +++ .../java/algorithms/RouteActivityVisitor.java | 46 +++ .../main/java/algorithms/RouteVisitor.java | 9 + .../java/algorithms/StateManagerImpl.java | 42 ++- .../main/java/algorithms/StateUpdates.java | 320 ++++++++---------- .../algorithms/VehicleRoutingAlgorithms.java | 12 +- .../BuildPDVRPAlgoFromScratchTest.java | 26 +- .../TestIterateRouteForwardInTime.java | 44 +-- .../examples/PickupAndDeliveryExample2.java | 2 +- .../examples/VRPWithBackhaulsExample.java | 9 +- .../examples/VRPWithBackhaulsExample2.java | 4 +- 14 files changed, 447 insertions(+), 226 deletions(-) create mode 100644 jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java create mode 100644 jsprit-core/src/main/java/algorithms/ActivityVisitor.java create mode 100644 jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java create mode 100644 jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java create mode 100644 jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java create mode 100644 jsprit-core/src/main/java/algorithms/RouteVisitor.java diff --git a/jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java b/jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java new file mode 100644 index 00000000..1cb0e5b6 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java @@ -0,0 +1,82 @@ +package algorithms; + +import basics.costs.ForwardTransportTime; +import basics.route.Driver; +import basics.route.TourActivity; +import basics.route.Vehicle; +import basics.route.VehicleRoute; + +class ActivityTimeTracker implements ActivityVisitor{ + + private ForwardTransportTime transportTime; + + private TourActivity prevAct = null; + + private double startAtPrevAct; + + private VehicleRoute route; + + private boolean beginFirst = false; + + private double actArrTime; + + private double actEndTime; + + public ActivityTimeTracker(ForwardTransportTime transportTime) { + super(); + this.transportTime = transportTime; + } + + public double getActArrTime(){ + return actArrTime; + } + + public double getActEndTime(){ + return actEndTime; + } + + @Override + public void begin(VehicleRoute route) { + prevAct = route.getStart(); + startAtPrevAct = prevAct.getEndTime(); + + actEndTime = startAtPrevAct; + + this.route = route; + + beginFirst = true; + } + + @Override + public void visit(TourActivity activity) { + if(!beginFirst) throw new IllegalStateException("never called begin. this however is essential here"); + double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), activity.getLocationId(), startAtPrevAct, route.getDriver(), route.getVehicle()); + double arrivalTimeAtCurrAct = startAtPrevAct + transportTime; + + actArrTime = arrivalTimeAtCurrAct; + + double operationStartTime = Math.max(activity.getTheoreticalEarliestOperationStartTime(), arrivalTimeAtCurrAct); + double operationEndTime = operationStartTime + activity.getOperationTime(); + + actEndTime = operationEndTime; + + prevAct = activity; + startAtPrevAct = operationEndTime; + + } + + @Override + public void finish() { + double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), route.getEnd().getLocationId(), startAtPrevAct, route.getDriver(), route.getVehicle()); + double arrivalTimeAtCurrAct = startAtPrevAct + transportTime; + + actArrTime = arrivalTimeAtCurrAct; + actEndTime = arrivalTimeAtCurrAct; + + beginFirst = false; + } + + + + +} diff --git a/jsprit-core/src/main/java/algorithms/ActivityVisitor.java b/jsprit-core/src/main/java/algorithms/ActivityVisitor.java new file mode 100644 index 00000000..2891d085 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/ActivityVisitor.java @@ -0,0 +1,14 @@ +package algorithms; + +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +interface ActivityVisitor { + + public void begin(VehicleRoute route); + + public void visit(TourActivity activity); + + public void finish(); + +} diff --git a/jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java b/jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java new file mode 100644 index 00000000..dbe7ed2c --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java @@ -0,0 +1,14 @@ +package algorithms; + +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +interface ReverseActivityVisitor { + + public void begin(VehicleRoute route); + + public void visit(TourActivity activity); + + public void finish(); + +} diff --git a/jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java b/jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java new file mode 100644 index 00000000..7550f0cb --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java @@ -0,0 +1,49 @@ +package algorithms; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +class ReverseRouteActivityVisitor implements RouteVisitor{ + + private Collection visitors = new ArrayList(); + + @Override + public void visit(VehicleRoute route) { + if(visitors.isEmpty()) return; + begin(route); + Iterator revIterator = route.getTourActivities().reverseActivityIterator(); + while(revIterator.hasNext()){ + TourActivity act = revIterator.next(); + visit(act); + } + finish(route); + } + + private void finish(VehicleRoute route) { + for(ReverseActivityVisitor visitor : visitors){ + visitor.finish(); + } + + } + + private void visit(TourActivity act) { + for(ReverseActivityVisitor visitor : visitors){ + visitor.visit(act); + } + } + + private void begin(VehicleRoute route) { + for(ReverseActivityVisitor visitor : visitors){ + visitor.begin(route); + } + + } + + public void addActivityVisitor(ReverseActivityVisitor activityVisitor){ + visitors.add(activityVisitor); + } +} diff --git a/jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java b/jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java new file mode 100644 index 00000000..a7353c72 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java @@ -0,0 +1,46 @@ +package algorithms; + +import java.util.ArrayList; +import java.util.Collection; + +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +class RouteActivityVisitor implements RouteVisitor{ + + private Collection visitors = new ArrayList(); + + @Override + public void visit(VehicleRoute route) { + if(visitors.isEmpty()) return; + begin(route); + for(TourActivity act : route.getTourActivities().getActivities()){ + visit(act); + } + end(route); + } + + private void end(VehicleRoute route) { + for(ActivityVisitor visitor : visitors){ + visitor.finish(); + } + + } + + private void visit(TourActivity act) { + for(ActivityVisitor visitor : visitors){ + visitor.visit(act); + } + } + + private void begin(VehicleRoute route) { + for(ActivityVisitor visitor : visitors){ + visitor.begin(route); + } + + } + + public void addActivityVisitor(ActivityVisitor activityVisitor){ + visitors.add(activityVisitor); + } +} diff --git a/jsprit-core/src/main/java/algorithms/RouteVisitor.java b/jsprit-core/src/main/java/algorithms/RouteVisitor.java new file mode 100644 index 00000000..2aad9d3f --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/RouteVisitor.java @@ -0,0 +1,9 @@ +package algorithms; + +import basics.route.VehicleRoute; + +interface RouteVisitor { + + public void visit(VehicleRoute route); + +} diff --git a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java index fc4af220..e0383803 100644 --- a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java +++ b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java @@ -20,13 +20,18 @@ ******************************************************************************/ package algorithms; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Map; +import basics.Job; +import basics.algo.InsertionStartsListener; +import basics.algo.JobInsertedListener; import basics.route.TourActivity; import basics.route.VehicleRoute; -class StateManagerImpl implements StateManager{ +class StateManagerImpl implements StateManager, InsertionStartsListener, JobInsertedListener { static class StatesImpl implements States{ @@ -47,6 +52,12 @@ class StateManagerImpl implements StateManager{ private Map activityStates = new HashMap(); + private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); + + private ReverseRouteActivityVisitor revRouteActivityVisitor = new ReverseRouteActivityVisitor(); + + private Collection routeVisitors = new ArrayList(); + public void clear(){ vehicleRouteStates.clear(); activityStates.clear(); @@ -113,7 +124,32 @@ class StateManagerImpl implements StateManager{ StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route); routeStates.putState(stateType, state); } - - + @Override + public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { + for(RouteVisitor v : routeVisitors){ v.visit(inRoute); } + routeActivityVisitor.visit(inRoute); + revRouteActivityVisitor.visit(inRoute); + } + + @Override + public void informInsertionStarts(Collection vehicleRoutes,Collection unassignedJobs) { + for(VehicleRoute route : vehicleRoutes){ + for(RouteVisitor v : routeVisitors){ v.visit(route); } + routeActivityVisitor.visit(route); + revRouteActivityVisitor.visit(route); + } + } + + public void addActivityVisitor(ActivityVisitor activityVistor){ + routeActivityVisitor.addActivityVisitor(activityVistor); + } + + public void addActivityVisitor(ReverseActivityVisitor activityVistor){ + revRouteActivityVisitor.addActivityVisitor(activityVistor); + } + + public void addRouteVisitor(RouteVisitor routeVisitor){ + routeVisitors.add(routeVisitor); + } } diff --git a/jsprit-core/src/main/java/algorithms/StateUpdates.java b/jsprit-core/src/main/java/algorithms/StateUpdates.java index 92d7927f..a0cdf286 100644 --- a/jsprit-core/src/main/java/algorithms/StateUpdates.java +++ b/jsprit-core/src/main/java/algorithms/StateUpdates.java @@ -44,95 +44,21 @@ import basics.algo.IterationStartsListener; import basics.algo.JobInsertedListener; import basics.algo.VehicleRoutingAlgorithmListener; import basics.costs.ForwardTransportCost; +import basics.costs.ForwardTransportTime; import basics.costs.VehicleRoutingActivityCosts; import basics.costs.VehicleRoutingTransportCosts; import basics.route.DeliveryActivity; +import basics.route.Driver; import basics.route.End; import basics.route.PickupActivity; import basics.route.ServiceActivity; import basics.route.Start; import basics.route.TourActivity; +import basics.route.Vehicle; import basics.route.VehicleRoute; class StateUpdates { - static class VRAListenersManager implements IterationStartsListener, IterationEndsListener, InsertionStartsListener, InsertionEndsListener, JobInsertedListener, RuinListener{ - - private Map,Collection> listeners = new HashMap,Collection>(); - - public void addListener(VehicleRoutingAlgorithmListener vraListener){ - if(!listeners.containsKey(vraListener.getClass())){ - listeners.put(vraListener.getClass(), new ArrayList()); - } - listeners.get(vraListener.getClass()).add(vraListener); - } - - @Override - public void ruinStarts(Collection routes) { - if(listeners.containsKey(RuinListener.class)){ - for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){ - ((RuinListener)l).ruinStarts(routes); - } - } - } - - @Override - public void ruinEnds(Collection routes,Collection unassignedJobs) { - if(listeners.containsKey(RuinListener.class)){ - for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){ - ((RuinListener)l).ruinEnds(routes,unassignedJobs); - } - } - } - - @Override - public void removed(Job job, VehicleRoute fromRoute) { - if(listeners.containsKey(RuinListener.class)){ - for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){ - ((RuinListener)l).removed(job, fromRoute); - } - } - } - - @Override - public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { - if(listeners.containsKey(JobInsertedListener.class)){ - for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){ - ((JobInsertedListener)l).informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); - } - } - - } - - @Override - public void informInsertionEnds(Collection vehicleRoutes) { -// if(listeners.containsKey(JobInsertedListener.class)){ -// for(VehicleRoutingAlgorithmListener l : listeners.get(RuinListener.class)){ -// ((JobInsertedListener)l).informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); -// } -// } - } - - @Override - public void informInsertionStarts(Collection vehicleRoutes,Collection unassignedJobs) { - // TODO Auto-generated method stub - - } - - @Override - public void informIterationEnds(int i, VehicleRoutingProblem problem,Collection solutions) { - // TODO Auto-generated method stub - - } - - @Override - public void informIterationStarts(int i, VehicleRoutingProblem problem,Collection solutions) { - // TODO Auto-generated method stub - - } - - } - static class UpdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{ private StateManagerImpl states; @@ -158,10 +84,10 @@ class StateUpdates { @Override public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) { - IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts); - forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states)); + RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); + forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(actCosts, tpCosts, states)); for(VehicleRoute route : vehicleRoutes){ - forwardInTime.iterate(route); + forwardInTime.visit(route); } } @@ -183,29 +109,42 @@ class StateUpdates { } - static class UpdateActivityTimes implements ForwardInTimeListener{ + static class UpdateActivityTimes implements ActivityVisitor{ private Logger log = Logger.getLogger(UpdateActivityTimes.class); - @Override - public void start(VehicleRoute route, Start start, double departureTime) { - start.setEndTime(departureTime); + private ActivityTimeTracker timeTracker; + + private VehicleRoute route; + + public UpdateActivityTimes(ForwardTransportTime transportTime) { + super(); + timeTracker = new ActivityTimeTracker(transportTime); } @Override - public void nextActivity(TourActivity act, double arrTime, double endTime) { - act.setArrTime(arrTime); - act.setEndTime(endTime); + public void begin(VehicleRoute route) { + timeTracker.begin(route); + this.route = route; + route.getStart().setEndTime(timeTracker.getActEndTime()); } @Override - public void end(End end, double arrivalTime) { - end.setArrTime(arrivalTime); + public void visit(TourActivity activity) { + timeTracker.visit(activity); + activity.setArrTime(timeTracker.getActArrTime()); + activity.setEndTime(timeTracker.getActEndTime()); + } + + @Override + public void finish() { + timeTracker.finish(); + route.getEnd().setArrTime(timeTracker.getActArrTime()); } } - static class UpdateCostsAtAllLevels implements ForwardInTimeListener{ + static class UpdateCostsAtAllLevels implements ActivityVisitor{ private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class); @@ -223,27 +162,31 @@ class StateUpdates { private double startTimeAtPrevAct = 0.0; - public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, ForwardTransportCost transportCost, StateManagerImpl states) { + private ActivityTimeTracker timeTracker; + + public UpdateCostsAtAllLevels(VehicleRoutingActivityCosts activityCost, VehicleRoutingTransportCosts transportCost, StateManagerImpl states) { super(); this.activityCost = activityCost; this.transportCost = transportCost; this.states = states; + timeTracker = new ActivityTimeTracker(transportCost); } @Override - public void start(VehicleRoute route, Start start, double departureTime) { + public void begin(VehicleRoute route) { vehicleRoute = route; vehicleRoute.getVehicleRouteCostCalculator().reset(); - prevAct = start; - startTimeAtPrevAct = departureTime; -// log.info(start + " depTime=" + departureTime); + timeTracker.begin(route); + prevAct = route.getStart(); + startTimeAtPrevAct = timeTracker.getActEndTime(); } @Override - public void nextActivity(TourActivity act, double arrTime, double endTime) { -// log.info(act + " job " + ((JobActivity)act).getJob().getId() + " arrTime=" + arrTime + " endTime=" + endTime); + public void visit(TourActivity act) { + timeTracker.visit(act); + double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), act.getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle()); - double actCost = activityCost.getActivityCost(act, arrTime, vehicleRoute.getDriver(), vehicleRoute.getVehicle()); + double actCost = activityCost.getActivityCost(act, timeTracker.getActArrTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle()); vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost); vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost); @@ -254,14 +197,14 @@ class StateUpdates { states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost)); prevAct = act; - startTimeAtPrevAct = endTime; + startTimeAtPrevAct = timeTracker.getActEndTime(); } @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()); + public void finish() { + timeTracker.finish(); + double transportCost = this.transportCost.getTransportCost(prevAct.getLocationId(), vehicleRoute.getEnd().getLocationId(), startTimeAtPrevAct, vehicleRoute.getDriver(), vehicleRoute.getVehicle()); + double actCost = activityCost.getActivityCost(vehicleRoute.getEnd(), timeTracker.getActEndTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle()); vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost); vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost); @@ -284,56 +227,78 @@ class StateUpdates { } - static class UpdateEarliestStartTimeWindowAtActLocations implements ForwardInTimeListener{ + static class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor{ private StateManagerImpl states; - public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states) { + private ActivityTimeTracker timeTracker; + + public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts transportCosts) { super(); this.states = states; + timeTracker = new ActivityTimeTracker(transportCosts); } @Override - public void start(VehicleRoute route, Start start, double departureTime) {} - - @Override - public void nextActivity(TourActivity act, double arrTime, double endTime) { - states.putActivityState(act, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(arrTime, act.getTheoreticalEarliestOperationStartTime()))); + public void begin(VehicleRoute route) { + timeTracker.begin(route); } @Override - public void end(End end, double arrivalTime) {} + public void visit(TourActivity activity) { + timeTracker.visit(activity); + states.putActivityState(activity, StateTypes.EARLIEST_OPERATION_START_TIME, new StateImpl(Math.max(timeTracker.getActArrTime(), activity.getTheoreticalEarliestOperationStartTime()))); + + } + + @Override + public void finish() {} } - static class UpdateLatestOperationStartTimeAtActLocations implements BackwardInTimeListener{ + static class UpdateLatestOperationStartTimeAtActLocations implements ReverseActivityVisitor{ private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class); private StateManagerImpl states; - public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states) { + private VehicleRoute route; + + private VehicleRoutingTransportCosts transportCosts; + + private double latestArrTimeAtPrevAct; + + private TourActivity prevAct; + + public UpdateLatestOperationStartTimeAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts) { super(); this.states = states; + this.transportCosts = tpCosts; } @Override - public void start(VehicleRoute route, End end, double latestArrivalTime) {} - - @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)); + public void begin(VehicleRoute route) { + this.route = route; + latestArrTimeAtPrevAct = route.getEnd().getTheoreticalLatestOperationStartTime(); + prevAct = route.getEnd(); } @Override - public void end(Start start, double latestDepartureTime) {} - - + public void visit(TourActivity activity) { + double potentialLatestArrivalTimeAtCurrAct = latestArrTimeAtPrevAct - transportCosts.getBackwardTransportTime(activity.getLocationId(), prevAct.getLocationId(), latestArrTimeAtPrevAct, route.getDriver(),route.getVehicle()) - activity.getOperationTime(); + double latestArrivalTime = Math.min(activity.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct); + + states.putActivityState(activity, StateTypes.LATEST_OPERATION_START_TIME, new StateImpl(latestArrivalTime)); + + latestArrTimeAtPrevAct = latestArrivalTime; + prevAct = activity; + } + @Override + public void finish() {} } - static class UpdateLoadAtAllLevels implements ForwardInTimeListener{ + static class UpdateLoadAtAllLevels implements ActivityVisitor{ private double load = 0.0; @@ -347,16 +312,18 @@ class StateUpdates { } @Override - public void start(VehicleRoute route, Start start, double departureTime) { vehicleRoute = route; } - - @Override - public void nextActivity(TourActivity act, double arrTime, double endTime) { - load += (double)act.getCapacityDemand(); - states.putActivityState(act, StateTypes.LOAD, new StateImpl(load)); + public void begin(VehicleRoute route) { + vehicleRoute = route; } @Override - public void end(End end, double arrivalTime) { + public void visit(TourActivity activity) { + load += (double)activity.getCapacityDemand(); + states.putActivityState(activity, StateTypes.LOAD, new StateImpl(load)); + } + + @Override + public void finish() { states.putRouteState(vehicleRoute, StateTypes.LOAD, new StateImpl(load)); load=0; vehicleRoute = null; @@ -398,31 +365,30 @@ class StateUpdates { static class UpdateStates implements JobInsertedListener, RuinListener{ - private IterateRouteForwardInTime iterateForward; + private RouteActivityVisitor routeActivityVisitor; - private IterateRouteBackwardInTime iterateBackward; + private ReverseRouteActivityVisitor revRouteActivityVisitor; public UpdateStates(StateManagerImpl states, VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts) { + routeActivityVisitor = new RouteActivityVisitor(); + routeActivityVisitor.addActivityVisitor(new UpdateActivityTimes(routingCosts)); + routeActivityVisitor.addActivityVisitor(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states)); + routeActivityVisitor.addActivityVisitor(new UpdateLoadAtAllLevels(states)); - iterateForward = new IterateRouteForwardInTime(routingCosts); - iterateForward.addListener(new UpdateActivityTimes()); - iterateForward.addListener(new UpdateCostsAtAllLevels(activityCosts, routingCosts, states)); - iterateForward.addListener(new UpdateLoadAtAllLevels(states)); -// iterateForward.addListener(new UpdateEarliestStartTimeWindowAtActLocations(states)); - - iterateBackward = new IterateRouteBackwardInTime(routingCosts); - iterateBackward.addListener(new UpdateLatestOperationStartTimeAtActLocations(states)); + revRouteActivityVisitor = new ReverseRouteActivityVisitor(); + revRouteActivityVisitor.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(states, routingCosts)); + } public void update(VehicleRoute route){ - iterateForward.iterate(route); - iterateBackward.iterate(route); + routeActivityVisitor.visit(route); + revRouteActivityVisitor.visit(route); } @Override public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { - iterateForward.iterate(inRoute); - iterateBackward.iterate(inRoute); + routeActivityVisitor.visit(inRoute); + revRouteActivityVisitor.visit(inRoute); } @Override @@ -431,8 +397,8 @@ class StateUpdates { @Override public void ruinEnds(Collection routes,Collection unassignedJobs) { for(VehicleRoute route : routes) { - iterateForward.iterate(route); - iterateBackward.iterate(route); + routeActivityVisitor.visit(route); + revRouteActivityVisitor.visit(route); } } @@ -441,7 +407,7 @@ class StateUpdates { } - static class UpdateFuturePickupsAtActivityLevel implements BackwardInTimeListener { + static class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor { private StateManagerImpl stateManager; private int futurePicks = 0; private VehicleRoute route; @@ -452,12 +418,12 @@ class StateUpdates { } @Override - public void start(VehicleRoute route, End end, double latestArrivalTime) { + public void begin(VehicleRoute route) { this.route = route; } - + @Override - public void prevActivity(TourActivity act, double latestDepartureTime, double latestOperationStartTime) { + public void visit(TourActivity act) { stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks)); if(act instanceof PickupActivity || act instanceof ServiceActivity){ futurePicks += act.getCapacityDemand(); @@ -465,15 +431,15 @@ class StateUpdates { assert futurePicks <= route.getVehicle().getCapacity() : "sum of pickups must not be > vehicleCap"; assert futurePicks >= 0 : "sum of pickups must not < 0"; } - + @Override - public void end(Start start, double latestDepartureTime) { + public void finish() { futurePicks = 0; route = null; } } - static class UpdateOccuredDeliveriesAtActivityLevel implements ForwardInTimeListener { + static class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor { private StateManagerImpl stateManager; private int deliveries = 0; private VehicleRoute route; @@ -484,12 +450,12 @@ class StateUpdates { } @Override - public void start(VehicleRoute route, Start start, double departureTime) { + public void begin(VehicleRoute route) { this.route = route; } - + @Override - public void nextActivity(TourActivity act, double arrTime, double endTime) { + public void visit(TourActivity act) { if(act instanceof DeliveryActivity){ deliveries += Math.abs(act.getCapacityDemand()); } @@ -497,9 +463,9 @@ class StateUpdates { assert deliveries >= 0 : "deliveries < 0"; assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap"; } - + @Override - public void end(End end, double arrivalTime) { + public void finish() { deliveries = 0; route = null; } @@ -512,7 +478,7 @@ class StateUpdates { * @author stefan * */ - static class UpdateLoadAtActivityLevel implements ForwardInTimeListener { + static class UpdateLoadAtActivityLevel implements ActivityVisitor { private StateManagerImpl stateManager; private int currentLoad = 0; private VehicleRoute route; @@ -521,23 +487,23 @@ class StateUpdates { super(); this.stateManager = stateManager; } - + @Override - public void start(VehicleRoute route, Start start, double departureTime) { + public void begin(VehicleRoute route) { currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble(); this.route = route; } - + @Override - public void nextActivity(TourActivity act, double arrTime, double endTime) { + public void visit(TourActivity act) { currentLoad += act.getCapacityDemand(); stateManager.putActivityState(act, StateTypes.LOAD, new StateImpl(currentLoad)); assert currentLoad <= route.getVehicle().getCapacity() : "currentLoad at activity must not be > vehicleCapacity"; assert currentLoad >= 0 : "currentLoad at act must not be < 0"; } - + @Override - public void end(End end, double arrivalTime) { + public void finish() { currentLoad = 0; } } @@ -617,27 +583,27 @@ class StateUpdates { static class UpdateRouteStatesOnceTheRouteHasBeenChanged implements InsertionStartsListener, JobInsertedListener { - private IterateRouteForwardInTime forwardInTimeIterator; + private RouteActivityVisitor forwardInTimeIterator; - private IterateRouteBackwardInTime backwardInTimeIterator; + private ReverseRouteActivityVisitor backwardInTimeIterator; private Collection insertionStartsListeners; private Collection jobInsertionListeners; public UpdateRouteStatesOnceTheRouteHasBeenChanged(VehicleRoutingTransportCosts routingCosts) { - forwardInTimeIterator = new IterateRouteForwardInTime(routingCosts); - backwardInTimeIterator = new IterateRouteBackwardInTime(routingCosts); + forwardInTimeIterator = new RouteActivityVisitor(); + backwardInTimeIterator = new ReverseRouteActivityVisitor(); insertionStartsListeners = new ArrayList(); jobInsertionListeners = new ArrayList(); } - void addListener(ForwardInTimeListener l){ - forwardInTimeIterator.addListener(l); + void addVisitor(ActivityVisitor vis){ + forwardInTimeIterator.addActivityVisitor(vis); } - void addListener(BackwardInTimeListener l){ - backwardInTimeIterator.addListener(l); + void addVisitor(ReverseActivityVisitor revVis){ + backwardInTimeIterator.addActivityVisitor(revVis); } void addInsertionStartsListener(InsertionStarts insertionStartListener){ @@ -651,8 +617,8 @@ class StateUpdates { @Override public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { for(JobInsertedListener l : jobInsertionListeners){ l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); } - forwardInTimeIterator.iterate(inRoute); - backwardInTimeIterator.iterate(inRoute); + forwardInTimeIterator.visit(inRoute); + backwardInTimeIterator.visit(inRoute); } @Override @@ -661,8 +627,8 @@ class StateUpdates { for(InsertionStarts insertionsStartsHandler : insertionStartsListeners){ insertionsStartsHandler.insertionStarts(route); } - forwardInTimeIterator.iterate(route); - backwardInTimeIterator.iterate(route); + forwardInTimeIterator.visit(route); + backwardInTimeIterator.visit(route); } } diff --git a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java index d3c77390..3831069d 100644 --- a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java +++ b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java @@ -506,13 +506,13 @@ public class VehicleRoutingAlgorithms { routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager)); routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager)); - routeChangedListener.addListener(new StateUpdates.UpdateActivityTimes()); - routeChangedListener.addListener(new StateUpdates.UpdateLoadAtActivityLevel(stateManager)); - routeChangedListener.addListener(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); + routeChangedListener.addVisitor(new StateUpdates.UpdateActivityTimes(vrp.getTransportCosts())); + routeChangedListener.addVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager)); + routeChangedListener.addVisitor(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); - routeChangedListener.addListener(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager)); - routeChangedListener.addListener(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager)); - routeChangedListener.addListener(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager)); + routeChangedListener.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager)); + routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); + routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager)); metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(routeChangedListener); metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager)); diff --git a/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java b/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java index 7279b242..65933e82 100644 --- a/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java +++ b/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java @@ -108,18 +108,18 @@ public class BuildPDVRPAlgoFromScratchTest { vra.getAlgorithmListeners().addListener(new StateUpdates.ResetStateManager(stateManager)); - final IterateRouteForwardInTime iterateForward = new IterateRouteForwardInTime(vrp.getTransportCosts()); + final RouteActivityVisitor iterateForward = new RouteActivityVisitor(); - iterateForward.addListener(new UpdateActivityTimes()); - iterateForward.addListener(new UpdateEarliestStartTimeWindowAtActLocations(stateManager)); - iterateForward.addListener(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); + iterateForward.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts())); + iterateForward.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, vrp.getTransportCosts())); + iterateForward.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); - iterateForward.addListener(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager)); - iterateForward.addListener(new StateUpdates.UpdateLoadAtActivityLevel(stateManager)); + iterateForward.addActivityVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager)); + iterateForward.addActivityVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager)); - final IterateRouteBackwardInTime iterateBackward = new IterateRouteBackwardInTime(vrp.getTransportCosts()); - iterateBackward.addListener(new UpdateLatestOperationStartTimeAtActLocations(stateManager)); - iterateBackward.addListener(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager)); + final ReverseRouteActivityVisitor iterateBackward = new ReverseRouteActivityVisitor(); + iterateBackward.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); + iterateBackward.addActivityVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager)); InsertionStartsListener loadVehicleInDepot = new InsertionStartsListener() { @@ -139,8 +139,8 @@ public class BuildPDVRPAlgoFromScratchTest { } stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot)); stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd)); - iterateForward.iterate(route); - iterateBackward.iterate(route); + iterateForward.visit(route); + iterateBackward.visit(route); } } @@ -164,8 +164,8 @@ public class BuildPDVRPAlgoFromScratchTest { // log.info("loadAtEnd="+loadAtEnd); stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand())); } - iterateForward.iterate(inRoute); - iterateBackward.iterate(inRoute); + iterateForward.visit(inRoute); + iterateBackward.visit(inRoute); } }; diff --git a/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java b/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java index 98f37f69..99de138d 100644 --- a/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java +++ b/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java @@ -139,9 +139,9 @@ public class TestIterateRouteForwardInTime { @Test public void whenIteratingWithActivityTimeUpdater_itShouldUpdateActivityTimes() { - IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost); - forwardInTime.addListener(new UpdateActivityTimes()); - forwardInTime.iterate(vehicleRoute); + RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); + forwardInTime.addActivityVisitor(new UpdateActivityTimes(cost)); + forwardInTime.visit(vehicleRoute); assertEquals(10.0,firstAct.getArrTime(),0.1); assertEquals(10.0,firstAct.getEndTime(),0.1); @@ -152,9 +152,9 @@ public class TestIterateRouteForwardInTime { @Test public void whenIteratingWithLoadUpdateAtActLocations_itShouldUpdateLoad() { - IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost); - forwardInTime.addListener(new UpdateLoadAtAllLevels(stateManager)); - forwardInTime.iterate(vehicleRoute); + RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); + forwardInTime.addActivityVisitor(new UpdateLoadAtAllLevels(stateManager)); + forwardInTime.visit(vehicleRoute); assertEquals(5.0, stateManager.getActivityState(firstAct,StateTypes.LOAD).toDouble(), 0.01); assertEquals(10.0, stateManager.getActivityState(secondAct,StateTypes.LOAD).toDouble(), 0.01); @@ -163,8 +163,8 @@ public class TestIterateRouteForwardInTime { @Test public void testStatesOfAct0(){ - IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost); - forwardInTime.iterate(vehicleRoute); + RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); + forwardInTime.visit(vehicleRoute); assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05); assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId()); @@ -175,11 +175,11 @@ public class TestIterateRouteForwardInTime { @Test public void testStatesOfAct1(){ - IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost); - forwardInTime.addListener(new UpdateLoadAtAllLevels(stateManager)); - forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(stateManager)); - forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); - forwardInTime.iterate(vehicleRoute); + RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); + forwardInTime.addActivityVisitor(new UpdateLoadAtAllLevels(stateManager)); + forwardInTime.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, cost)); + forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); + forwardInTime.visit(vehicleRoute); assertEquals(10.0, stateManager.getActivityState(firstAct, StateTypes.COSTS).toDouble(),0.05); assertEquals(5.0, stateManager.getActivityState(firstAct, StateTypes.LOAD).toDouble(),0.05); @@ -189,12 +189,12 @@ public class TestIterateRouteForwardInTime { @Test public void testStatesOfAct2(){ - IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost); + RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - forwardInTime.addListener(new UpdateLoadAtAllLevels(stateManager)); - forwardInTime.addListener(new UpdateEarliestStartTimeWindowAtActLocations(stateManager)); - forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); - forwardInTime.iterate(vehicleRoute); + forwardInTime.addActivityVisitor(new UpdateLoadAtAllLevels(stateManager)); + forwardInTime.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, cost)); + forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); + forwardInTime.visit(vehicleRoute); assertEquals(30.0, stateManager.getActivityState(secondAct, StateTypes.COSTS).toDouble(),0.05); assertEquals(10.0, stateManager.getActivityState(secondAct, StateTypes.LOAD).toDouble(),0.05); @@ -204,11 +204,11 @@ public class TestIterateRouteForwardInTime { @Test public void testStatesOfAct3(){ - IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost); + RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - forwardInTime.addListener(new UpdateActivityTimes()); - forwardInTime.addListener(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); - forwardInTime.iterate(vehicleRoute); + forwardInTime.addActivityVisitor(new UpdateActivityTimes(cost)); + forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); + forwardInTime.visit(vehicleRoute); assertEquals(40.0, stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(), 0.05); assertEquals(40.0, vehicleRoute.getEnd().getArrTime(),0.05); diff --git a/jsprit-examples/src/main/java/examples/PickupAndDeliveryExample2.java b/jsprit-examples/src/main/java/examples/PickupAndDeliveryExample2.java index 573e62b4..7ae5e5e6 100644 --- a/jsprit-examples/src/main/java/examples/PickupAndDeliveryExample2.java +++ b/jsprit-examples/src/main/java/examples/PickupAndDeliveryExample2.java @@ -104,7 +104,7 @@ public class PickupAndDeliveryExample2 { Plotter plotter = new Plotter(vrp, solution); plotter.setLabel(Label.SIZE); plotter.setShowFirstActivity(true); - plotter.plot("output/pd_christophides_vrpnc1.png","pd_vrpnc1"); + plotter.plot("output/pd_christophides_vrpnc1_solution.png","pd_vrpnc1"); diff --git a/jsprit-examples/src/main/java/examples/VRPWithBackhaulsExample.java b/jsprit-examples/src/main/java/examples/VRPWithBackhaulsExample.java index e4782681..9676f16a 100644 --- a/jsprit-examples/src/main/java/examples/VRPWithBackhaulsExample.java +++ b/jsprit-examples/src/main/java/examples/VRPWithBackhaulsExample.java @@ -35,7 +35,11 @@ import basics.VehicleRoutingAlgorithm; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblemSolution; import basics.VehicleRoutingProblem.Constraint; +import basics.costs.VehicleRoutingActivityCosts; import basics.io.VrpXMLReader; +import basics.route.Driver; +import basics.route.TourActivity; +import basics.route.Vehicle; public class VRPWithBackhaulsExample { @@ -68,9 +72,10 @@ public class VRPWithBackhaulsExample { * Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances). */ vrpBuilder.addProblemConstraint(Constraint.DELIVERIES_FIRST); + VehicleRoutingProblem vrp = vrpBuilder.build(); - SolutionPlotter.plotVrpAsPNG(vrp, "output/pd_solomon_r101.png", "pd_r101"); +// SolutionPlotter.plotVrpAsPNG(vrp, "output/vrpwbh_solomon_r101.png", "pd_r101"); /* * Define the required vehicle-routing algorithms to solve the above problem. @@ -103,7 +108,7 @@ public class VRPWithBackhaulsExample { Plotter plotter = new Plotter(vrp, solution); plotter.setLabel(Label.SIZE); plotter.setShowFirstActivity(true); - plotter.plot("output/pd_withBackhauls_solomon_r101_solution.png","pd_withBackhauls_r101"); + plotter.plot("output/vrpwbh_solomon_r101_solution.png","vrpwbh_r101"); } diff --git a/jsprit-examples/src/main/java/examples/VRPWithBackhaulsExample2.java b/jsprit-examples/src/main/java/examples/VRPWithBackhaulsExample2.java index a36b852d..26221ce3 100644 --- a/jsprit-examples/src/main/java/examples/VRPWithBackhaulsExample2.java +++ b/jsprit-examples/src/main/java/examples/VRPWithBackhaulsExample2.java @@ -74,7 +74,7 @@ public class VRPWithBackhaulsExample2 { */ VehicleRoutingProblem vrp = vrpBuilder.build(); - SolutionPlotter.plotVrpAsPNG(vrp, "output/pd_christophides_vrpnc1.png", "pd_vrpnc1"); + SolutionPlotter.plotVrpAsPNG(vrp, "output/vrpwbh_christophides_vrpnc1.png", "pd_vrpnc1"); /* * Define the required vehicle-routing algorithms to solve the above problem. @@ -107,7 +107,7 @@ public class VRPWithBackhaulsExample2 { Plotter plotter = new Plotter(vrp, solution); plotter.setLabel(Label.SIZE); plotter.setShowFirstActivity(true); - plotter.plot("output/vrpwbh_christophides_vrpnc1.png","vrpwbh_vrpnc1"); + plotter.plot("output/vrpwbh_christophides_vrpnc1_solution.png","vrpwbh_vrpnc1");