From 289b7a0f772b94675c794a9a4fe7acb878febdbb Mon Sep 17 00:00:00 2001 From: Stefan Schroeder <4sschroeder@gmail.com> Date: Tue, 8 Oct 2013 15:34:33 +0200 Subject: [PATCH] relax API --- .../main/java/algorithms/ActivityVisitor.java | 2 +- .../main/java/algorithms/BestInsertion.java | 22 + .../java/algorithms/BestInsertionBuilder.java | 51 +- ... BestInsertionInitialSolutionFactory.java} | 8 +- .../CalculatesServiceInsertion.java | 7 +- ...tesServiceInsertionConsideringFixCost.java | 2 - .../CalculatesVehTypeDepServiceInsertion.java | 1 - .../{CalcUtils.java => CalculationUtils.java} | 4 +- .../java/algorithms/CalculatorBuilder.java | 2 +- .../algorithms/FiniteFleetManagerFactory.java | 21 + .../main/java/algorithms/HardConstraints.java | 311 --------- .../InfiniteFleetManagerFactory.java | 21 + .../java/algorithms/InfiniteVehicles.java | 10 +- .../algorithms/InitialSolutionFactory.java | 4 +- .../java/algorithms/InsertionContext.java | 2 +- .../java/algorithms/InsertionFactory.java | 21 +- .../java/algorithms/InsertionStrategy.java | 26 - .../MarginalsCalculusTriangleInequality.java | 4 +- .../java/algorithms/RemoveEmptyVehicles.java | 4 +- .../algorithms/ReverseActivityVisitor.java | 2 +- .../ReverseRouteActivityVisitor.java | 2 +- .../java/algorithms/RouteActivityVisitor.java | 2 +- .../main/java/algorithms/RouteVisitor.java | 2 +- .../src/main/java/algorithms/RuinRadial.java | 1 + .../src/main/java/algorithms/RuinRandom.java | 1 + .../main/java/algorithms/StateManager.java | 36 - .../java/algorithms/StateManagerImpl.java | 79 ++- .../src/main/java/algorithms/StateTypes.java | 18 +- .../main/java/algorithms/StateUpdates.java | 636 ------------------ .../java/algorithms/VehicleFleetManager.java | 61 +- .../VehicleFleetManagerFactory.java | 7 + .../algorithms/VehicleFleetManagerImpl.java | 24 +- .../algorithms/VehicleRoutingAlgorithms.java | 71 +- .../main/java/algorithms/VehicleTypeKey.java | 48 ++ .../constraints/ConstraintManager.java | 30 + .../HardActivityLevelConstraint.java | 10 + .../HardActivityLevelConstraintManager.java | 27 + .../constraints/HardConstraints.java | 44 ++ .../constraints/HardLoadConstraint.java | 26 + ...kupAndDeliveryActivityLevelConstraint.java | 50 ++ ...liveryBackhaulActivityLevelConstraint.java | 54 ++ .../HardPickupAndDeliveryLoadConstraint.java | 42 ++ .../constraints/HardRouteLevelConstraint.java | 9 + .../HardRouteLevelConstraintManager.java | 26 + ...HardTimeWindowActivityLevelConstraint.java | 49 ++ .../{ => states}/ActivityTimeTracker.java | 3 +- ...StartAndEndOfRouteWhenInsertionStarts.java | 64 ++ .../java/algorithms/states/StateUpdates.java | 162 +++++ .../states/UpdateActivityTimes.java | 63 ++ .../states/UpdateCostsAtAllLevels.java | 118 ++++ .../states/UpdateCostsAtRouteLevel.java | 65 ++ ...EarliestStartTimeWindowAtActLocations.java | 38 ++ .../UpdateFuturePickupsAtActivityLevel.java | 42 ++ ...atestOperationStartTimeAtActLocations.java | 53 ++ .../states/UpdateLoadAtActivityLevel.java | 68 ++ .../states/UpdateLoadAtAllLevels.java | 41 ++ .../states/UpdateLoadAtRouteLevel.java | 56 ++ ...rtAndEndOfRouteWhenJobHasBeenInserted.java | 54 ++ ...pdateOccuredDeliveriesAtActivityLevel.java | 41 ++ .../java/basics/algo/InsertionListeners.java | 42 ++ .../basics/algo/InsertionStartsListener.java | 1 + .../algo}/RuinListeners.java | 17 +- jsprit-core/src/main/java/util/Solutions.java | 11 + .../BuildCVRPAlgoFromScratchTest.java | 11 +- .../BuildPDVRPAlgoFromScratchTest.java | 46 +- .../java/algorithms/GendreauPostOptTest.java | 6 +- .../TestCalculatesServiceInsertion.java | 6 +- ...alculatesServiceInsertionOnRouteLevel.java | 2 +- .../TestIterateRouteForwardInTime.java | 8 +- .../TestTourStateUpdaterWithService.java | 2 +- 70 files changed, 1674 insertions(+), 1226 deletions(-) rename jsprit-core/src/main/java/algorithms/{CreateInitialSolution.java => BestInsertionInitialSolutionFactory.java} (90%) rename jsprit-core/src/main/java/algorithms/{CalcUtils.java => CalculationUtils.java} (92%) create mode 100644 jsprit-core/src/main/java/algorithms/FiniteFleetManagerFactory.java delete mode 100644 jsprit-core/src/main/java/algorithms/HardConstraints.java create mode 100644 jsprit-core/src/main/java/algorithms/InfiniteFleetManagerFactory.java delete mode 100644 jsprit-core/src/main/java/algorithms/StateUpdates.java create mode 100644 jsprit-core/src/main/java/algorithms/VehicleFleetManagerFactory.java create mode 100644 jsprit-core/src/main/java/algorithms/VehicleTypeKey.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/ConstraintManager.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardActivityLevelConstraint.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardActivityLevelConstraintManager.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardConstraints.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardLoadConstraint.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryActivityLevelConstraint.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryBackhaulActivityLevelConstraint.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryLoadConstraint.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardRouteLevelConstraint.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardRouteLevelConstraintManager.java create mode 100644 jsprit-core/src/main/java/algorithms/constraints/HardTimeWindowActivityLevelConstraint.java rename jsprit-core/src/main/java/algorithms/{ => states}/ActivityTimeTracker.java (97%) create mode 100644 jsprit-core/src/main/java/algorithms/states/InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts.java create mode 100644 jsprit-core/src/main/java/algorithms/states/StateUpdates.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateActivityTimes.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateCostsAtAllLevels.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateCostsAtRouteLevel.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateEarliestStartTimeWindowAtActLocations.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateFuturePickupsAtActivityLevel.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateLatestOperationStartTimeAtActLocations.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateLoadAtActivityLevel.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateLoadAtAllLevels.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateLoadAtRouteLevel.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted.java create mode 100644 jsprit-core/src/main/java/algorithms/states/UpdateOccuredDeliveriesAtActivityLevel.java create mode 100644 jsprit-core/src/main/java/basics/algo/InsertionListeners.java rename jsprit-core/src/main/java/{algorithms => basics/algo}/RuinListeners.java (79%) diff --git a/jsprit-core/src/main/java/algorithms/ActivityVisitor.java b/jsprit-core/src/main/java/algorithms/ActivityVisitor.java index 2891d085..076fd552 100644 --- a/jsprit-core/src/main/java/algorithms/ActivityVisitor.java +++ b/jsprit-core/src/main/java/algorithms/ActivityVisitor.java @@ -3,7 +3,7 @@ package algorithms; import basics.route.TourActivity; import basics.route.VehicleRoute; -interface ActivityVisitor { +public interface ActivityVisitor { public void begin(VehicleRoute route); diff --git a/jsprit-core/src/main/java/algorithms/BestInsertion.java b/jsprit-core/src/main/java/algorithms/BestInsertion.java index bee3394b..a768a4fd 100644 --- a/jsprit-core/src/main/java/algorithms/BestInsertion.java +++ b/jsprit-core/src/main/java/algorithms/BestInsertion.java @@ -38,6 +38,28 @@ import basics.route.VehicleRoute; final class BestInsertion implements InsertionStrategy{ + class Insertion { + + private final VehicleRoute route; + + private final InsertionData insertionData; + + public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) { + super(); + this.route = vehicleRoute; + this.insertionData = insertionData; + } + + public VehicleRoute getRoute() { + return route; + } + + public InsertionData getInsertionData() { + return insertionData; + } + + } + private static Logger logger = Logger.getLogger(BestInsertion.class); private Random random = RandomNumberGeneration.getRandom(); diff --git a/jsprit-core/src/main/java/algorithms/BestInsertionBuilder.java b/jsprit-core/src/main/java/algorithms/BestInsertionBuilder.java index 9d415afa..ac12ad9d 100644 --- a/jsprit-core/src/main/java/algorithms/BestInsertionBuilder.java +++ b/jsprit-core/src/main/java/algorithms/BestInsertionBuilder.java @@ -1,8 +1,10 @@ package algorithms; +import algorithms.constraints.ConstraintManager; +import algorithms.constraints.HardActivityLevelConstraint; +import algorithms.constraints.HardRouteLevelConstraint; import basics.VehicleRoutingProblem; -import algorithms.HardConstraints.HardActivityLevelConstraint; -import algorithms.HardConstraints.HardRouteLevelConstraint; +import basics.VehicleRoutingProblem.FleetSize; public class BestInsertionBuilder implements InsertionStrategyBuilder{ @@ -10,25 +12,58 @@ public class BestInsertionBuilder implements InsertionStrategyBuilder{ private StateManager stateManager; + private boolean local = true; + + private ConstraintManager constraintManager; + + private VehicleFleetManager fleetManager; + public BestInsertionBuilder(VehicleRoutingProblem vrp, StateManager stateManager) { super(); this.vrp = vrp; this.stateManager = stateManager; + this.constraintManager = new ConstraintManager(); } - public void addConstraint(HardActivityLevelConstraint hardActvitiyLevelConstraint){}; + public void addConstraint(HardActivityLevelConstraint hardActvitiyLevelConstraint){ + constraintManager.addConstraint(hardActvitiyLevelConstraint); + }; - public void addConstraint(HardRouteLevelConstraint hardRouteLevelConstraint){}; + public void addConstraint(HardRouteLevelConstraint hardRouteLevelConstraint){ + constraintManager.addConstraint(hardRouteLevelConstraint); + }; - public void setRouteLevel(int forwardLooking, int memory){}; + //public void setRouteLevel(int forwardLooking, int memory){}; - public void setLocalLevel(){}; + public void setLocalLevel(){ + local = true; + }; - public void setActivityInsertionCostCalculator(ActivityInsertionCostCalculator costCalc){}; + public void setFleetManager(VehicleFleetManager fleetManager){ + this.fleetManager = fleetManager; + } + + //public void setActivityInsertionCostCalculator(ActivityInsertionCostCalculator costCalc){}; @Override public InsertionStrategy build() { - return null; + CalculatorBuilder calcBuilder = new CalculatorBuilder(null, null); + if(local){ + calcBuilder.setLocalLevel(); + } + calcBuilder.setConstraintManager(constraintManager); + calcBuilder.setStates(stateManager); + calcBuilder.setVehicleRoutingProblem(vrp); + calcBuilder.setVehicleFleetManager(fleetManager); + JobInsertionCalculator jobInsertions = calcBuilder.build(); + return new BestInsertion(jobInsertions); + } + + private VehicleFleetManager createFleetManager(VehicleRoutingProblem vrp) { + if(vrp.getFleetSize().equals(FleetSize.INFINITE)){ + return new InfiniteVehicles(vrp.getVehicles()); + } + else return new VehicleFleetManagerImpl(vrp.getVehicles()); } } diff --git a/jsprit-core/src/main/java/algorithms/CreateInitialSolution.java b/jsprit-core/src/main/java/algorithms/BestInsertionInitialSolutionFactory.java similarity index 90% rename from jsprit-core/src/main/java/algorithms/CreateInitialSolution.java rename to jsprit-core/src/main/java/algorithms/BestInsertionInitialSolutionFactory.java index e0b1cd6d..927cff55 100644 --- a/jsprit-core/src/main/java/algorithms/CreateInitialSolution.java +++ b/jsprit-core/src/main/java/algorithms/BestInsertionInitialSolutionFactory.java @@ -47,9 +47,9 @@ import basics.route.VehicleRoute; -final class CreateInitialSolution implements InitialSolutionFactory { +public final class BestInsertionInitialSolutionFactory implements InitialSolutionFactory { - private static final Logger logger = Logger.getLogger(CreateInitialSolution.class); + private static final Logger logger = Logger.getLogger(BestInsertionInitialSolutionFactory.class); private final InsertionStrategy insertion; @@ -59,13 +59,13 @@ final class CreateInitialSolution implements InitialSolutionFactory { this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist; } - public CreateInitialSolution(InsertionStrategy insertionStrategy) { + public BestInsertionInitialSolutionFactory(InsertionStrategy insertionStrategy) { super(); this.insertion = insertionStrategy; } @Override - public VehicleRoutingProblemSolution createInitialSolution(final VehicleRoutingProblem vrp) { + public VehicleRoutingProblemSolution createSolution(final VehicleRoutingProblem vrp) { logger.info("create initial solution."); List vehicleRoutes = new ArrayList(); if(generateAsMuchAsRoutesAsVehiclesExist){ diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java index e14b2277..79465800 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java @@ -15,18 +15,17 @@ package algorithms; import org.apache.log4j.Logger; import util.Neighborhood; -import algorithms.HardConstraints.HardRouteLevelConstraint; import algorithms.ActivityInsertionCostCalculator.Marginals; +import algorithms.constraints.HardRouteLevelConstraint; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingTransportCosts; +import basics.route.DefaultTourActivityFactory; import basics.route.Driver; import basics.route.End; -import basics.route.ServiceActivity; import basics.route.Start; import basics.route.TourActivity; import basics.route.TourActivityFactory; -import basics.route.DefaultTourActivityFactory; import basics.route.Vehicle; import basics.route.VehicleImpl.NoVehicle; import basics.route.VehicleRoute; @@ -117,7 +116,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{ } double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle); - double nextActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, nextAct); + double nextActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct); prevActStartTime = nextActEndTime; diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java index 1961ec84..7a03913e 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java @@ -23,8 +23,6 @@ package algorithms; import org.apache.log4j.Logger; import algorithms.InsertionData.NoInsertionFound; -import algorithms.StateManager.State; -import algorithms.StateManager.States; import basics.Job; import basics.route.Driver; import basics.route.Vehicle; diff --git a/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java b/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java index 264ee753..1977fa02 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java @@ -26,7 +26,6 @@ import java.util.Collection; import org.apache.log4j.Logger; import algorithms.InsertionData.NoInsertionFound; -import algorithms.VehicleFleetManager.TypeKey; import basics.Job; import basics.route.Driver; import basics.route.Vehicle; diff --git a/jsprit-core/src/main/java/algorithms/CalcUtils.java b/jsprit-core/src/main/java/algorithms/CalculationUtils.java similarity index 92% rename from jsprit-core/src/main/java/algorithms/CalcUtils.java rename to jsprit-core/src/main/java/algorithms/CalculationUtils.java index 67da5ffc..bfa26b14 100644 --- a/jsprit-core/src/main/java/algorithms/CalcUtils.java +++ b/jsprit-core/src/main/java/algorithms/CalculationUtils.java @@ -22,7 +22,7 @@ package algorithms; import basics.route.TourActivity; -class CalcUtils { +public class CalculationUtils { /** @@ -32,7 +32,7 @@ class CalcUtils { * @param act * @return */ - static double getActivityEndTime(double actArrTime, TourActivity act){ + public static double getActivityEndTime(double actArrTime, TourActivity act){ return Math.max(actArrTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime(); } } diff --git a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java index 95859ce8..c69fa971 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java +++ b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java @@ -23,7 +23,7 @@ package algorithms; import java.util.ArrayList; import java.util.List; -import algorithms.HardConstraints.ConstraintManager; +import algorithms.constraints.ConstraintManager; import basics.VehicleRoutingProblem; import basics.algo.InsertionListener; import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener; diff --git a/jsprit-core/src/main/java/algorithms/FiniteFleetManagerFactory.java b/jsprit-core/src/main/java/algorithms/FiniteFleetManagerFactory.java new file mode 100644 index 00000000..68a6c693 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/FiniteFleetManagerFactory.java @@ -0,0 +1,21 @@ +package algorithms; + +import java.util.Collection; + +import basics.route.Vehicle; + +public class FiniteFleetManagerFactory implements VehicleFleetManagerFactory{ + + private Collection vehicles; + + public FiniteFleetManagerFactory(Collection vehicles) { + super(); + this.vehicles = vehicles; + } + + @Override + public VehicleFleetManager createFleetManager() { + return new VehicleFleetManagerImpl(vehicles); + } + +} diff --git a/jsprit-core/src/main/java/algorithms/HardConstraints.java b/jsprit-core/src/main/java/algorithms/HardConstraints.java deleted file mode 100644 index ec2533b9..00000000 --- a/jsprit-core/src/main/java/algorithms/HardConstraints.java +++ /dev/null @@ -1,311 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: - * Stefan Schroeder - initial API and implementation - ******************************************************************************/ -package algorithms; - -import java.util.ArrayList; -import java.util.Collection; - -import org.apache.log4j.Logger; - -import basics.Delivery; -import basics.Pickup; -import basics.Service; -import basics.costs.VehicleRoutingTransportCosts; -import basics.route.DeliveryActivity; -import basics.route.PickupActivity; -import basics.route.ServiceActivity; -import basics.route.Start; -import basics.route.TourActivity; - -/** - * collection of hard constrainters bot at activity and at route level. - * - *

HardPickupAndDeliveryLoadConstraint requires LOAD_AT_DEPOT and LOAD (i.e. load at end) at route-level - * - *

HardTimeWindowConstraint requires LATEST_OPERATION_START_TIME - * - *

HardPickupAndDeliveryConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level - * - *

HardPickupAndDeliveryBackhaulConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level - * - * @author stefan - * - */ -class HardConstraints { - - interface HardRouteLevelConstraint { - - public boolean fulfilled(InsertionContext insertionContext); - - } - - interface HardActivityLevelConstraint { - - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime); - - } - - static class HardRouteLevelConstraintManager implements HardRouteLevelConstraint { - - private Collection hardConstraints = new ArrayList(); - - public void addConstraint(HardRouteLevelConstraint constraint){ - hardConstraints.add(constraint); - } - - @Override - public boolean fulfilled(InsertionContext insertionContext) { - for(HardRouteLevelConstraint constraint : hardConstraints){ - if(!constraint.fulfilled(insertionContext)){ - return false; - } - } - return true; - } - - } - - static class ConstraintManager implements HardActivityLevelConstraint, HardRouteLevelConstraint{ - - private HardActivityLevelConstraintManager actLevelConstraintManager = new HardActivityLevelConstraintManager(); - - private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager(); - - public void addConstraint(HardActivityLevelConstraint actLevelConstraint){ - actLevelConstraintManager.addConstraint(actLevelConstraint); - } - - public void addConstraint(HardRouteLevelConstraint routeLevelConstraint){ - routeLevelConstraintManager.addConstraint(routeLevelConstraint); - } - - @Override - public boolean fulfilled(InsertionContext insertionContext) { - return routeLevelConstraintManager.fulfilled(insertionContext); - } - - @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) { - return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime); - } - - } - - static class HardActivityLevelConstraintManager implements HardActivityLevelConstraint { - - private Collection hardConstraints = new ArrayList(); - - public void addConstraint(HardActivityLevelConstraint constraint){ - hardConstraints.add(constraint); - } - - @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { - for(HardActivityLevelConstraint constraint : hardConstraints){ - if(!constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime)){ - return false; - } - } - return true; - } - - } - - static class HardLoadConstraint implements HardRouteLevelConstraint{ - - private StateManager states; - - public HardLoadConstraint(StateManager states) { - super(); - this.states = states; - } - - @Override - public boolean fulfilled(InsertionContext insertionContext) { - int currentLoad = (int) states.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble(); - Service service = (Service) insertionContext.getJob(); - if(currentLoad + service.getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){ - return false; - } - return true; - } - } - - /** - * lsjdfjsdlfjsa - * - * @author stefan - * - */ - static class HardPickupAndDeliveryLoadConstraint implements HardRouteLevelConstraint { - - private StateManager stateManager; - - public HardPickupAndDeliveryLoadConstraint(StateManager stateManager) { - super(); - this.stateManager = stateManager; - } - - @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 || insertionContext.getJob() instanceof Service){ - int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble(); - if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){ - return false; - } - } - return true; - } - - } - - /** - * ljsljslfjs - * @author stefan - * - */ - public static class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint { - - private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class); - - private StateManager states; - - private VehicleRoutingTransportCosts routingCosts; - - public HardTimeWindowActivityLevelConstraint(StateManager states, VehicleRoutingTransportCosts routingCosts) { - super(); - this.states = states; - this.routingCosts = routingCosts; - } - - @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { -// log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime); - double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); - double latestArrTimeAtNewAct = states.getActivityState(newAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble(); - if(arrTimeAtNewAct > latestArrTimeAtNewAct){ - return false; - } -// log.info(newAct + " arrTime=" + arrTimeAtNewAct); - double endTimeAtNewAct = CalcUtils.getActivityEndTime(arrTimeAtNewAct, newAct); - double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle()); - double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble(); - if(arrTimeAtNextAct > latestArrTimeAtNextAct){ - return false; - } -// log.info(nextAct + " arrTime=" + arrTimeAtNextAct); - return true; - } - } - - static class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint { - - private StateManager stateManager; - - public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) { - super(); - this.stateManager = stateManager; - } - - @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { - 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(); - futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble(); - pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble(); - } - if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){ - 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; - } - - } - - static class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint { - - private StateManager stateManager; - - public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateManager stateManager) { - super(); - this.stateManager = stateManager; - } - - @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 ServiceActivity && nextAct instanceof DeliveryActivity){ return false; } - if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return false; } - if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ 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(); - futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble(); - pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble(); - } - if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){ - 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; - } - - } - - - -} diff --git a/jsprit-core/src/main/java/algorithms/InfiniteFleetManagerFactory.java b/jsprit-core/src/main/java/algorithms/InfiniteFleetManagerFactory.java new file mode 100644 index 00000000..8439a97d --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/InfiniteFleetManagerFactory.java @@ -0,0 +1,21 @@ +package algorithms; + +import java.util.Collection; + +import basics.route.Vehicle; + +public class InfiniteFleetManagerFactory implements VehicleFleetManagerFactory{ + + private Collection vehicles; + + public InfiniteFleetManagerFactory(Collection vehicles) { + super(); + this.vehicles = vehicles; + } + + @Override + public VehicleFleetManager createFleetManager() { + return new InfiniteVehicles(vehicles); + } + +} diff --git a/jsprit-core/src/main/java/algorithms/InfiniteVehicles.java b/jsprit-core/src/main/java/algorithms/InfiniteVehicles.java index 84da957b..bca7368b 100644 --- a/jsprit-core/src/main/java/algorithms/InfiniteVehicles.java +++ b/jsprit-core/src/main/java/algorithms/InfiniteVehicles.java @@ -45,9 +45,9 @@ class InfiniteVehicles implements VehicleFleetManager{ private static Logger logger = Logger.getLogger(InfiniteVehicles.class); - private Map types = new HashMap(); + private Map types = new HashMap(); - private List sortedTypes = new ArrayList(); + private List sortedTypes = new ArrayList(); public InfiniteVehicles(Collection vehicles){ extractTypes(vehicles); @@ -61,7 +61,7 @@ class InfiniteVehicles implements VehicleFleetManager{ private void extractTypes(Collection vehicles) { for(Vehicle v : vehicles){ - TypeKey typeKey = new TypeKey(v.getType().getTypeId(),v.getLocationId()); + VehicleTypeKey typeKey = new VehicleTypeKey(v.getType().getTypeId(),v.getLocationId()); types.put(typeKey,v); sortedTypes.add(typeKey); @@ -99,8 +99,8 @@ class InfiniteVehicles implements VehicleFleetManager{ @Override public Collection getAvailableVehicles(String withoutThisType, String locationId) { Collection vehicles = new ArrayList(); - TypeKey thisKey = new TypeKey(withoutThisType,locationId); - for(TypeKey key : types.keySet()){ + VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType,locationId); + for(VehicleTypeKey key : types.keySet()){ if(!key.equals(thisKey)){ vehicles.add(types.get(key)); } diff --git a/jsprit-core/src/main/java/algorithms/InitialSolutionFactory.java b/jsprit-core/src/main/java/algorithms/InitialSolutionFactory.java index ed1a1d8c..b41d719f 100644 --- a/jsprit-core/src/main/java/algorithms/InitialSolutionFactory.java +++ b/jsprit-core/src/main/java/algorithms/InitialSolutionFactory.java @@ -17,8 +17,8 @@ import basics.VehicleRoutingProblemSolution; -interface InitialSolutionFactory { +public interface InitialSolutionFactory { - public VehicleRoutingProblemSolution createInitialSolution(VehicleRoutingProblem vrp); + public VehicleRoutingProblemSolution createSolution(VehicleRoutingProblem vrp); } diff --git a/jsprit-core/src/main/java/algorithms/InsertionContext.java b/jsprit-core/src/main/java/algorithms/InsertionContext.java index 8b3b2593..fe0a1abc 100644 --- a/jsprit-core/src/main/java/algorithms/InsertionContext.java +++ b/jsprit-core/src/main/java/algorithms/InsertionContext.java @@ -25,7 +25,7 @@ import basics.route.Driver; import basics.route.Vehicle; import basics.route.VehicleRoute; -class InsertionContext { +public class InsertionContext { private VehicleRoute route; private Job job; diff --git a/jsprit-core/src/main/java/algorithms/InsertionFactory.java b/jsprit-core/src/main/java/algorithms/InsertionFactory.java index 182efa0f..34bf9097 100644 --- a/jsprit-core/src/main/java/algorithms/InsertionFactory.java +++ b/jsprit-core/src/main/java/algorithms/InsertionFactory.java @@ -27,8 +27,7 @@ import java.util.concurrent.ExecutorService; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.log4j.Logger; -import algorithms.HardConstraints.ConstraintManager; -import algorithms.StateUpdates.UpdateStates; +import algorithms.constraints.ConstraintManager; import basics.VehicleRoutingProblem; import basics.algo.InsertionListener; import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener; @@ -39,8 +38,7 @@ class InsertionFactory { public static InsertionStrategy createInsertion(VehicleRoutingProblem vrp, HierarchicalConfiguration config, VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){ - boolean concurrentInsertion = false; - if(executorService != null) concurrentInsertion = true; + if(config.containsKey("[@name]")){ String insertionName = config.getString("[@name]"); if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){ @@ -100,21 +98,8 @@ class InsertionFactory { if(insertionName.equals("bestInsertion")){ insertionStrategy = new BestInsertion(jic); } -// else if(insertionName.equals("regretInsertion")){ -// insertionStrategy = RegretInsertion.newInstance(routeAlgorithm); -// } - -// insertionStrategy.addListener(new RemoveEmptyVehicles(vehicleFleetManager)); -// insertionStrategy.addListener(new ResetAndIniFleetManager(vehicleFleetManager)); -// insertionStrategy.addListener(new VehicleSwitched(vehicleFleetManager)); - -// insertionStrategy.addListener(new UpdateLoadAtRouteLevel(routeStates)); - -// insertionStrategy.addListener(new UpdateStates(routeStates, vrp.getTransportCosts(), vrp.getActivityCosts())); for(InsertionListener l : insertionListeners) insertionStrategy.addListener(l); -// insertionStrategy.addListener(new FindCheaperVehicle( -// new FindCheaperVehicleAlgoNew(vehicleFleetManager, tourStateCalculator, auxCalculator))); - + algorithmListeners.addAll(algoListeners); return insertionStrategy; diff --git a/jsprit-core/src/main/java/algorithms/InsertionStrategy.java b/jsprit-core/src/main/java/algorithms/InsertionStrategy.java index 50b1e160..890bfdad 100644 --- a/jsprit-core/src/main/java/algorithms/InsertionStrategy.java +++ b/jsprit-core/src/main/java/algorithms/InsertionStrategy.java @@ -29,32 +29,6 @@ import basics.route.VehicleRoute; public interface InsertionStrategy { - class Insertion { - - private final VehicleRoute route; - - private final InsertionData insertionData; - - public Insertion(VehicleRoute vehicleRoute, InsertionData insertionData) { - super(); - this.route = vehicleRoute; - this.insertionData = insertionData; - } - - public VehicleRoute getRoute() { - return route; - } - - public InsertionData getInsertionData() { - return insertionData; - } - - } - - - - - /** * Assigns the unassigned jobs to service-providers * diff --git a/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java b/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java index 6eb0c245..b2a67442 100644 --- a/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java +++ b/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java @@ -20,7 +20,7 @@ ******************************************************************************/ package algorithms; -import algorithms.HardConstraints.HardActivityLevelConstraint; +import algorithms.constraints.HardActivityLevelConstraint; import basics.costs.VehicleRoutingActivityCosts; import basics.costs.VehicleRoutingTransportCosts; import basics.route.TourActivity; @@ -50,7 +50,7 @@ class MarginalsCalculusTriangleInequality implements ActivityInsertionCostCalcul double newAct_arrTime = depTimeAtPrevAct + tp_time_prevAct_newAct; - double newAct_endTime = CalcUtils.getActivityEndTime(newAct_arrTime, newAct); + double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct); double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); diff --git a/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java b/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java index 3a1e7f0b..27b5adcd 100644 --- a/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java +++ b/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java @@ -31,13 +31,13 @@ import basics.algo.InsertionEndsListener; import basics.algo.InsertionStartsListener; import basics.route.VehicleRoute; -class RemoveEmptyVehicles implements InsertionEndsListener{ +public class RemoveEmptyVehicles implements InsertionEndsListener{ private static Logger log = Logger.getLogger(RemoveEmptyVehicles.class); private VehicleFleetManager fleetManager; - RemoveEmptyVehicles(VehicleFleetManager fleetManager) { + public RemoveEmptyVehicles(VehicleFleetManager fleetManager) { super(); this.fleetManager = fleetManager; } diff --git a/jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java b/jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java index dbe7ed2c..4d1374d0 100644 --- a/jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java +++ b/jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java @@ -3,7 +3,7 @@ package algorithms; import basics.route.TourActivity; import basics.route.VehicleRoute; -interface ReverseActivityVisitor { +public interface ReverseActivityVisitor { public void begin(VehicleRoute route); diff --git a/jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java b/jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java index 7550f0cb..4de31f39 100644 --- a/jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java +++ b/jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java @@ -7,7 +7,7 @@ import java.util.Iterator; import basics.route.TourActivity; import basics.route.VehicleRoute; -class ReverseRouteActivityVisitor implements RouteVisitor{ +public class ReverseRouteActivityVisitor implements RouteVisitor{ private Collection visitors = new ArrayList(); diff --git a/jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java b/jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java index a7353c72..bcd13f4c 100644 --- a/jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java +++ b/jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java @@ -6,7 +6,7 @@ import java.util.Collection; import basics.route.TourActivity; import basics.route.VehicleRoute; -class RouteActivityVisitor implements RouteVisitor{ +public class RouteActivityVisitor implements RouteVisitor{ private Collection visitors = new ArrayList(); diff --git a/jsprit-core/src/main/java/algorithms/RouteVisitor.java b/jsprit-core/src/main/java/algorithms/RouteVisitor.java index 2aad9d3f..a4014197 100644 --- a/jsprit-core/src/main/java/algorithms/RouteVisitor.java +++ b/jsprit-core/src/main/java/algorithms/RouteVisitor.java @@ -2,7 +2,7 @@ package algorithms; import basics.route.VehicleRoute; -interface RouteVisitor { +public interface RouteVisitor { public void visit(VehicleRoute route); diff --git a/jsprit-core/src/main/java/algorithms/RuinRadial.java b/jsprit-core/src/main/java/algorithms/RuinRadial.java index bf7704f4..76184ec9 100644 --- a/jsprit-core/src/main/java/algorithms/RuinRadial.java +++ b/jsprit-core/src/main/java/algorithms/RuinRadial.java @@ -30,6 +30,7 @@ import util.StopWatch; import basics.Job; import basics.VehicleRoutingProblem; import basics.algo.RuinListener; +import basics.algo.RuinListeners; import basics.route.VehicleRoute; diff --git a/jsprit-core/src/main/java/algorithms/RuinRandom.java b/jsprit-core/src/main/java/algorithms/RuinRandom.java index c4e5dfe3..98f88e8c 100644 --- a/jsprit-core/src/main/java/algorithms/RuinRandom.java +++ b/jsprit-core/src/main/java/algorithms/RuinRandom.java @@ -24,6 +24,7 @@ import util.RandomNumberGeneration; import basics.Job; import basics.VehicleRoutingProblem; import basics.algo.RuinListener; +import basics.algo.RuinListeners; import basics.route.VehicleRoute; diff --git a/jsprit-core/src/main/java/algorithms/StateManager.java b/jsprit-core/src/main/java/algorithms/StateManager.java index 5bb9fc4d..e39f6a4d 100644 --- a/jsprit-core/src/main/java/algorithms/StateManager.java +++ b/jsprit-core/src/main/java/algorithms/StateManager.java @@ -29,42 +29,6 @@ public interface StateManager { double toDouble(); } - class StateImpl implements State{ - double state; - - public StateImpl(double state) { - super(); - this.state = state; - } - - @Override - public double toDouble() { - return state; - } - -// public void setState(double val){ -// state=val; -// } - } - - interface States { - -// void putState(String key, State state); - - State getState(String key); - - } - - - -// Map getRouteStates(); - -// void put(VehicleRoute route, States states); - -// Map getActivityStates(); - -// void put(TourActivity act, States states); - State getActivityState(TourActivity act, String stateType); State getRouteState(VehicleRoute route, String stateType); diff --git a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java index c72a1108..72edd57c 100644 --- a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java +++ b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java @@ -25,21 +25,45 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import algorithms.StateManager.State; import basics.Job; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblemSolution; import basics.algo.InsertionEndsListener; import basics.algo.InsertionListener; +import basics.algo.InsertionListeners; import basics.algo.InsertionStartsListener; import basics.algo.IterationStartsListener; import basics.algo.JobInsertedListener; import basics.algo.RuinListener; +import basics.algo.RuinListeners; import basics.route.TourActivity; import basics.route.VehicleRoute; public class StateManagerImpl implements StateManager, IterationStartsListener, RuinListener, InsertionStartsListener, JobInsertedListener, InsertionEndsListener { - static class StatesImpl implements States{ + private interface States { + + State getState(String key); + + } + + public static class StateImpl implements State{ + double state; + + public StateImpl(double state) { + super(); + this.state = state; + } + + @Override + public double toDouble() { + return state; + } + + } + + private static class StatesImpl implements States{ private Map states = new HashMap(); @@ -54,9 +78,9 @@ public class StateManagerImpl implements StateManager, IterationStartsListener, } - private Map vehicleRouteStates = new HashMap(); + private Map vehicleRouteStates = new HashMap(); - private Map activityStates = new HashMap(); + private Map activityStates = new HashMap(); private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); @@ -64,6 +88,27 @@ public class StateManagerImpl implements StateManager, IterationStartsListener, private Collection routeVisitors = new ArrayList(); + private RuinListeners ruinListeners = new RuinListeners(); + + private InsertionListeners insertionListeners = new InsertionListeners(); + + public void addListener(RuinListener ruinListener){ + ruinListeners.addListener(ruinListener); + } + + public void removeListener(RuinListener ruinListener){ + ruinListeners.removeListener(ruinListener); + } + + public void addListener(InsertionListener insertionListener){ + insertionListeners.addListener(insertionListener); + } + + public void removeListener(InsertionListener insertionListener){ + insertionListeners.removeListener(insertionListener); + } + + public void clear(){ vehicleRouteStates.clear(); activityStates.clear(); @@ -133,6 +178,7 @@ public class StateManagerImpl implements StateManager, IterationStartsListener, @Override public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { + insertionListeners.jobInserted(job2insert, inRoute, additionalCosts, additionalTime); for(RouteVisitor v : routeVisitors){ v.visit(inRoute); } routeActivityVisitor.visit(inRoute); revRouteActivityVisitor.visit(inRoute); @@ -140,6 +186,7 @@ public class StateManagerImpl implements StateManager, IterationStartsListener, @Override public void informInsertionStarts(Collection vehicleRoutes,Collection unassignedJobs) { + insertionListeners.insertionStarts(vehicleRoutes, unassignedJobs); for(VehicleRoute route : vehicleRoutes){ for(RouteVisitor v : routeVisitors){ v.visit(route); } routeActivityVisitor.visit(route); @@ -147,10 +194,24 @@ public class StateManagerImpl implements StateManager, IterationStartsListener, } } + /** + * Adds an activityVisitor. + *

This visitor visits all activities in a route subsequently in two cases. First, if insertionStart (after ruinStrategies have removed activities from routes) + * and, second, if a job has been inserted and thus if a route has changed. + * + * @param activityVistor + */ public void addActivityVisitor(ActivityVisitor activityVistor){ routeActivityVisitor.addActivityVisitor(activityVistor); } + /** + * Adds an reverseActivityVisitor. + *

This reverseVisitor visits all activities in a route subsequently (starting from the end of the route) in two cases. First, if insertionStart (after ruinStrategies have removed activities from routes) + * and, second, if a job has been inserted and thus if a route has changed. + * + * @param reverseActivityVistor + */ public void addActivityVisitor(ReverseActivityVisitor activityVistor){ revRouteActivityVisitor.addActivityVisitor(activityVistor); } @@ -166,25 +227,21 @@ public class StateManagerImpl implements StateManager, IterationStartsListener, @Override public void ruinStarts(Collection routes) { - // TODO Auto-generated method stub - + ruinListeners.ruinStarts(routes); } @Override public void ruinEnds(Collection routes, Collection unassignedJobs) { - // TODO Auto-generated method stub - + ruinListeners.ruinEnds(routes, unassignedJobs); } @Override public void removed(Job job, VehicleRoute fromRoute) { - // TODO Auto-generated method stub - + ruinListeners.removed(job, fromRoute); } @Override public void informInsertionEnds(Collection vehicleRoutes) { - // TODO Auto-generated method stub - + insertionListeners.insertionEnds(vehicleRoutes); } } diff --git a/jsprit-core/src/main/java/algorithms/StateTypes.java b/jsprit-core/src/main/java/algorithms/StateTypes.java index 812a4ea8..0b824f05 100644 --- a/jsprit-core/src/main/java/algorithms/StateTypes.java +++ b/jsprit-core/src/main/java/algorithms/StateTypes.java @@ -20,20 +20,20 @@ ******************************************************************************/ package algorithms; -class StateTypes { - final static String LOAD = "load"; +public class StateTypes { + public final static String LOAD = "load"; - final static String LOAD_AT_DEPOT = "loadAtDepot"; + public final static String LOAD_AT_DEPOT = "loadAtDepot"; - final static String DURATION = "duration"; + public final static String DURATION = "duration"; - final static String LATEST_OPERATION_START_TIME = "latestOST"; + public final static String LATEST_OPERATION_START_TIME = "latestOST"; - final static String EARLIEST_OPERATION_START_TIME = "earliestOST"; + public final static String EARLIEST_OPERATION_START_TIME = "earliestOST"; - static final String COSTS = "costs"; + public static final String COSTS = "costs"; - final static String FUTURE_PICKS = "futurePicks"; + public final static String FUTURE_PICKS = "futurePicks"; - final static String PAST_DELIVERIES = "pastDeliveries"; + public final static String PAST_DELIVERIES = "pastDeliveries"; } diff --git a/jsprit-core/src/main/java/algorithms/StateUpdates.java b/jsprit-core/src/main/java/algorithms/StateUpdates.java deleted file mode 100644 index ca899ae2..00000000 --- a/jsprit-core/src/main/java/algorithms/StateUpdates.java +++ /dev/null @@ -1,636 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributors: - * Stefan Schroeder - initial API and implementation - ******************************************************************************/ -package algorithms; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -import algorithms.BackwardInTimeListeners.BackwardInTimeListener; -import algorithms.ForwardInTimeListeners.ForwardInTimeListener; -import algorithms.StateManager.StateImpl; -import basics.Delivery; -import basics.Job; -import basics.Pickup; -import basics.Service; -import basics.VehicleRoutingProblem; -import basics.VehicleRoutingProblemSolution; -import basics.algo.InsertionEndsListener; -import basics.algo.InsertionStartsListener; -import basics.algo.IterationEndsListener; -import basics.algo.IterationStartsListener; -import basics.algo.JobInsertedListener; -import basics.algo.RuinListener; -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 UpdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{ - - private StateManagerImpl states; - - private VehicleRoutingTransportCosts tpCosts; - - private VehicleRoutingActivityCosts actCosts; - - public UpdateCostsAtRouteLevel(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) { - super(); - this.states = states; - this.tpCosts = tpCosts; - this.actCosts = actCosts; - } - - @Override - public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { -// inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts); - double oldCosts = states.getRouteState(inRoute, StateTypes.COSTS).toDouble(); - oldCosts += additionalCosts; - states.putRouteState(inRoute, StateTypes.COSTS, new StateImpl(oldCosts)); - } - - @Override - public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) { - RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(actCosts, tpCosts, states)); - for(VehicleRoute route : vehicleRoutes){ - forwardInTime.visit(route); - } - - } - - @Override - public void informInsertionEnds(Collection vehicleRoutes) { - -// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts); -// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states)); - for(VehicleRoute route : vehicleRoutes){ - if(route.isEmpty()) continue; - route.getVehicleRouteCostCalculator().reset(); - route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble()); - route.getVehicleRouteCostCalculator().price(route.getVehicle()); -// forwardInTime.iterate(route); - } - - } - - } - - static class UpdateActivityTimes implements ActivityVisitor{ - - private Logger log = Logger.getLogger(UpdateActivityTimes.class); - - private ActivityTimeTracker timeTracker; - - private VehicleRoute route; - - public UpdateActivityTimes(ForwardTransportTime transportTime) { - super(); - timeTracker = new ActivityTimeTracker(transportTime); - } - - @Override - public void begin(VehicleRoute route) { - timeTracker.begin(route); - this.route = route; - route.getStart().setEndTime(timeTracker.getActEndTime()); - } - - @Override - 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 ActivityVisitor{ - - private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class); - - private VehicleRoutingActivityCosts activityCost; - - private ForwardTransportCost transportCost; - - private StateManagerImpl states; - - private double totalOperationCost = 0.0; - - private VehicleRoute vehicleRoute = null; - - private TourActivity prevAct = null; - - private double startTimeAtPrevAct = 0.0; - - 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 begin(VehicleRoute route) { - vehicleRoute = route; - vehicleRoute.getVehicleRouteCostCalculator().reset(); - timeTracker.begin(route); - prevAct = route.getStart(); - startTimeAtPrevAct = timeTracker.getActEndTime(); - } - - @Override - 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, timeTracker.getActArrTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle()); - - vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost); - vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost); - - totalOperationCost += transportCost; - totalOperationCost += actCost; - - states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost)); - - prevAct = act; - startTimeAtPrevAct = timeTracker.getActEndTime(); - } - - @Override - 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); - - totalOperationCost += transportCost; - totalOperationCost += actCost; - - states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost)); - - //this is rather strange and likely to change - vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver()); - vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle()); - vehicleRoute.getVehicleRouteCostCalculator().finish(); - - startTimeAtPrevAct = 0.0; - prevAct = null; - vehicleRoute = null; - totalOperationCost = 0.0; - } - - } - - static class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor{ - - private StateManagerImpl states; - - private ActivityTimeTracker timeTracker; - - public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts transportCosts) { - super(); - this.states = states; - timeTracker = new ActivityTimeTracker(transportCosts); - } - - @Override - public void begin(VehicleRoute route) { - timeTracker.begin(route); - } - - @Override - 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 ReverseActivityVisitor{ - - private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class); - - private 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 begin(VehicleRoute route) { - this.route = route; - latestArrTimeAtPrevAct = route.getEnd().getTheoreticalLatestOperationStartTime(); - prevAct = route.getEnd(); - } - - @Override - 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 ActivityVisitor{ - - private double load = 0.0; - - private StateManagerImpl states; - - private VehicleRoute vehicleRoute; - - public UpdateLoadAtAllLevels(StateManagerImpl states) { - super(); - this.states = states; - } - - @Override - public void begin(VehicleRoute route) { - vehicleRoute = route; - } - - @Override - 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; - } - - } - - static class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{ - - private StateManagerImpl states; - - public UpdateLoadAtRouteLevel(StateManagerImpl states) { - super(); - this.states = states; - } - - @Override - public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { - if(!(job2insert instanceof Service)){ - return; - } - double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble(); - states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand())); - } - - @Override - public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) { - for(VehicleRoute route : vehicleRoutes){ - int load = 0; - for(Job j : route.getTourActivities().getJobs()){ - load += j.getCapacityDemand(); - } - states.putRouteState(route, StateTypes.LOAD, new StateImpl(load)); - } - - } - - } - - static class UpdateStates implements JobInsertedListener, RuinListener{ - - private RouteActivityVisitor routeActivityVisitor; - - 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)); - - revRouteActivityVisitor = new ReverseRouteActivityVisitor(); - revRouteActivityVisitor.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(states, routingCosts)); - - } - - public void update(VehicleRoute route){ - routeActivityVisitor.visit(route); - revRouteActivityVisitor.visit(route); - } - - @Override - public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { - routeActivityVisitor.visit(inRoute); - revRouteActivityVisitor.visit(inRoute); - } - - @Override - public void ruinStarts(Collection routes) {} - - @Override - public void ruinEnds(Collection routes,Collection unassignedJobs) { - for(VehicleRoute route : routes) { - routeActivityVisitor.visit(route); - revRouteActivityVisitor.visit(route); - } - } - - @Override - public void removed(Job job, VehicleRoute fromRoute) {} - - } - - static class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor { - private StateManagerImpl stateManager; - private int futurePicks = 0; - private VehicleRoute route; - - public UpdateFuturePickupsAtActivityLevel(StateManagerImpl stateManager) { - super(); - this.stateManager = stateManager; - } - - @Override - public void begin(VehicleRoute route) { - this.route = route; - } - - @Override - public void visit(TourActivity act) { - stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks)); - if(act instanceof PickupActivity || act instanceof ServiceActivity){ - futurePicks += act.getCapacityDemand(); - } - assert futurePicks <= route.getVehicle().getCapacity() : "sum of pickups must not be > vehicleCap"; - assert futurePicks >= 0 : "sum of pickups must not < 0"; - } - - @Override - public void finish() { - futurePicks = 0; - route = null; - } - } - - static class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor { - private StateManagerImpl stateManager; - private int deliveries = 0; - private VehicleRoute route; - - public UpdateOccuredDeliveriesAtActivityLevel(StateManagerImpl stateManager) { - super(); - this.stateManager = stateManager; - } - - @Override - public void begin(VehicleRoute route) { - this.route = route; - } - - @Override - public void visit(TourActivity act) { - if(act instanceof DeliveryActivity){ - deliveries += Math.abs(act.getCapacityDemand()); - } - stateManager.putActivityState(act, StateTypes.PAST_DELIVERIES, new StateImpl(deliveries)); - assert deliveries >= 0 : "deliveries < 0"; - assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap"; - } - - @Override - public void finish() { - deliveries = 0; - route = null; - } - } - - /** - * Updates load at activity level. Note that this assumed that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT. - * If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot. - * - * @author stefan - * - */ - static class UpdateLoadAtActivityLevel implements ActivityVisitor { - private StateManagerImpl stateManager; - private int currentLoad = 0; - private VehicleRoute route; - - public UpdateLoadAtActivityLevel(StateManagerImpl stateManager) { - super(); - this.stateManager = stateManager; - } - - @Override - public void begin(VehicleRoute route) { - currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble(); - this.route = route; - } - - @Override - 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 finish() { - currentLoad = 0; - } - } - - static class ResetStateManager implements IterationStartsListener { - - private StateManagerImpl stateManager; - - public ResetStateManager(StateManagerImpl stateManager) { - super(); - this.stateManager = stateManager; - } - - @Override - public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection solutions) { - stateManager.clear(); - } - } - - static interface InsertionStarts { - - void insertionStarts(VehicleRoute route); - - } - - static class UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStarts { - - private StateManagerImpl stateManager; - - public UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManagerImpl stateManager) { - super(); - this.stateManager = stateManager; - } - - @Override - public void insertionStarts(VehicleRoute route) { - int loadAtDepot = 0; - int loadAtEnd = 0; - for(Job j : route.getTourActivities().getJobs()){ - if(j instanceof Delivery){ - loadAtDepot += j.getCapacityDemand(); - } - else if(j instanceof Pickup || j instanceof Service){ - loadAtEnd += j.getCapacityDemand(); - } - } - stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot)); - stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd)); - } - - } - - static class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener { - - private StateManagerImpl stateManager; - - public UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(StateManagerImpl stateManager) { - super(); - this.stateManager = stateManager; - } - - @Override - public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { - if(job2insert instanceof Delivery){ - int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble(); -// log.info("loadAtDepot="+loadAtDepot); - stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand())); - } - else if(job2insert instanceof Pickup || job2insert instanceof Service){ - int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble(); -// log.info("loadAtEnd="+loadAtEnd); - stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand())); - } - } - - } - - static class UpdateRouteStatesOnceTheRouteHasBeenChanged implements InsertionStartsListener, JobInsertedListener { - - private RouteActivityVisitor forwardInTimeIterator; - - private ReverseRouteActivityVisitor backwardInTimeIterator; - - private Collection insertionStartsListeners; - - private Collection jobInsertionListeners; - - public UpdateRouteStatesOnceTheRouteHasBeenChanged(VehicleRoutingTransportCosts routingCosts) { - forwardInTimeIterator = new RouteActivityVisitor(); - backwardInTimeIterator = new ReverseRouteActivityVisitor(); - insertionStartsListeners = new ArrayList(); - jobInsertionListeners = new ArrayList(); - } - - void addVisitor(ActivityVisitor vis){ - forwardInTimeIterator.addActivityVisitor(vis); - } - - void addVisitor(ReverseActivityVisitor revVis){ - backwardInTimeIterator.addActivityVisitor(revVis); - } - - void addInsertionStartsListener(InsertionStarts insertionStartListener){ - insertionStartsListeners.add(insertionStartListener); - } - - void addJobInsertedListener(JobInsertedListener jobInsertedListener){ - jobInsertionListeners.add(jobInsertedListener); - } - - @Override - public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { - for(JobInsertedListener l : jobInsertionListeners){ l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); } - forwardInTimeIterator.visit(inRoute); - backwardInTimeIterator.visit(inRoute); - } - - @Override - public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) { - for(VehicleRoute route : vehicleRoutes){ - for(InsertionStarts insertionsStartsHandler : insertionStartsListeners){ - insertionsStartsHandler.insertionStarts(route); - } - forwardInTimeIterator.visit(route); - backwardInTimeIterator.visit(route); - } - } - - } -} diff --git a/jsprit-core/src/main/java/algorithms/VehicleFleetManager.java b/jsprit-core/src/main/java/algorithms/VehicleFleetManager.java index b70094e3..ff72ee0e 100644 --- a/jsprit-core/src/main/java/algorithms/VehicleFleetManager.java +++ b/jsprit-core/src/main/java/algorithms/VehicleFleetManager.java @@ -24,65 +24,18 @@ import java.util.Collection; import basics.route.Vehicle; -interface VehicleFleetManager { +public interface VehicleFleetManager { - static class TypeKey { - - public final String type; - public final String locationId; - - public TypeKey(String typeId, String locationId) { - super(); - this.type = typeId; - this.locationId = locationId; - } + public abstract void lock(Vehicle vehicle); - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((locationId == null) ? 0 : locationId.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - return result; - } + public abstract void unlock(Vehicle vehicle); - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - TypeKey other = (TypeKey) obj; - if (locationId == null) { - if (other.locationId != null) - return false; - } else if (!locationId.equals(other.locationId)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - return true; - } + public abstract boolean isLocked(Vehicle vehicle); - - - } + public abstract void unlockAll(); - abstract void lock(Vehicle vehicle); + public abstract Collection getAvailableVehicles(); - abstract void unlock(Vehicle vehicle); - - abstract boolean isLocked(Vehicle vehicle); - - abstract void unlockAll(); - - abstract Collection getAvailableVehicles(); - - Collection getAvailableVehicles(String withoutThisType, String locationId); + public Collection getAvailableVehicles(String withoutThisType, String locationId); } diff --git a/jsprit-core/src/main/java/algorithms/VehicleFleetManagerFactory.java b/jsprit-core/src/main/java/algorithms/VehicleFleetManagerFactory.java new file mode 100644 index 00000000..1c119d1f --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/VehicleFleetManagerFactory.java @@ -0,0 +1,7 @@ +package algorithms; + +public interface VehicleFleetManagerFactory { + + public VehicleFleetManager createFleetManager(); + +} diff --git a/jsprit-core/src/main/java/algorithms/VehicleFleetManagerImpl.java b/jsprit-core/src/main/java/algorithms/VehicleFleetManagerImpl.java index 752e2e62..286fc895 100644 --- a/jsprit-core/src/main/java/algorithms/VehicleFleetManagerImpl.java +++ b/jsprit-core/src/main/java/algorithms/VehicleFleetManagerImpl.java @@ -58,11 +58,11 @@ class VehicleFleetManagerImpl implements VehicleFleetManager { static class TypeContainer { - private TypeKey type; + private VehicleTypeKey type; private ArrayList vehicleList; - public TypeContainer(TypeKey type) { + public TypeContainer(VehicleTypeKey type) { super(); this.type = type; vehicleList = new ArrayList(); @@ -96,9 +96,9 @@ class VehicleFleetManagerImpl implements VehicleFleetManager { private Set lockedVehicles; - private Map typeMapOfAvailableVehicles; + private Map typeMapOfAvailableVehicles; - private Map penaltyVehicles = new HashMap(); + private Map penaltyVehicles = new HashMap(); // private Map typeMapOfAvailablePenaltyVehicles; @@ -126,8 +126,8 @@ class VehicleFleetManagerImpl implements VehicleFleetManager { } private void makeMap() { - typeMapOfAvailableVehicles = new HashMap(); - penaltyVehicles = new HashMap(); + typeMapOfAvailableVehicles = new HashMap(); + penaltyVehicles = new HashMap(); for(Vehicle v : vehicles){ addVehicle(v); } @@ -139,11 +139,11 @@ class VehicleFleetManagerImpl implements VehicleFleetManager { } String typeId = v.getType().getTypeId(); if(v.getType() instanceof PenaltyVehicleType){ - TypeKey typeKey = new TypeKey(typeId,v.getLocationId()); + VehicleTypeKey typeKey = new VehicleTypeKey(typeId,v.getLocationId()); penaltyVehicles.put(typeKey, v); } else{ - TypeKey typeKey = new TypeKey(v.getType().getTypeId(),v.getLocationId()); + VehicleTypeKey typeKey = new VehicleTypeKey(v.getType().getTypeId(),v.getLocationId()); if(!typeMapOfAvailableVehicles.containsKey(typeKey)){ typeMapOfAvailableVehicles.put(typeKey, new TypeContainer(typeKey)); } @@ -154,7 +154,7 @@ class VehicleFleetManagerImpl implements VehicleFleetManager { private void removeVehicle(Vehicle v){ //it might be better to introduce a class PenaltyVehicle if(!(v.getType() instanceof PenaltyVehicleType)){ - TypeKey key = new TypeKey(v.getType().getTypeId(),v.getLocationId()); + VehicleTypeKey key = new VehicleTypeKey(v.getType().getTypeId(),v.getLocationId()); if(typeMapOfAvailableVehicles.containsKey(key)){ typeMapOfAvailableVehicles.get(key).remove(v); } @@ -171,7 +171,7 @@ class VehicleFleetManagerImpl implements VehicleFleetManager { @Override public Collection getAvailableVehicles() { List vehicles = new ArrayList(); - for(TypeKey key : typeMapOfAvailableVehicles.keySet()){ + for(VehicleTypeKey key : typeMapOfAvailableVehicles.keySet()){ if(!typeMapOfAvailableVehicles.get(key).isEmpty()){ vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle()); } @@ -197,8 +197,8 @@ class VehicleFleetManagerImpl implements VehicleFleetManager { @Override public Collection getAvailableVehicles(String withoutThisType, String withThisLocationId) { List vehicles = new ArrayList(); - TypeKey thisKey = new TypeKey(withoutThisType,withThisLocationId); - for(TypeKey key : typeMapOfAvailableVehicles.keySet()){ + VehicleTypeKey thisKey = new VehicleTypeKey(withoutThisType,withThisLocationId); + for(VehicleTypeKey key : typeMapOfAvailableVehicles.keySet()){ if(key.equals(thisKey)) continue; if(!typeMapOfAvailableVehicles.get(key).isEmpty()){ vehicles.add(typeMapOfAvailableVehicles.get(key).getVehicle()); diff --git a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java index 3831069d..bd7db3bd 100644 --- a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java +++ b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java @@ -35,13 +35,6 @@ import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.XMLConfiguration; import org.apache.log4j.Logger; -import algorithms.HardConstraints.ConstraintManager; -import algorithms.HardConstraints.HardTimeWindowActivityLevelConstraint; -import algorithms.StateUpdates.UpdateActivityTimes; -import algorithms.StateUpdates.UpdateCostsAtAllLevels; -import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations; -import algorithms.StateUpdates.UpdateLatestOperationStartTimeAtActLocations; -import algorithms.StateUpdates.UpdateStates; import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey; import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey; import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey; @@ -52,9 +45,22 @@ import algorithms.acceptors.AcceptNewIfBetterThanWorst; import algorithms.acceptors.AcceptNewRemoveFirst; import algorithms.acceptors.SchrimpfAcceptance; import algorithms.acceptors.SolutionAcceptor; +import algorithms.constraints.ConstraintManager; +import algorithms.constraints.HardPickupAndDeliveryActivityLevelConstraint; +import algorithms.constraints.HardPickupAndDeliveryBackhaulActivityLevelConstraint; +import algorithms.constraints.HardPickupAndDeliveryLoadConstraint; +import algorithms.constraints.HardTimeWindowActivityLevelConstraint; import algorithms.selectors.SelectBest; import algorithms.selectors.SelectRandomly; import algorithms.selectors.SolutionSelector; +import algorithms.states.InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts; +import algorithms.states.UpdateActivityTimes; +import algorithms.states.UpdateCostsAtAllLevels; +import algorithms.states.UpdateFuturePickupsAtActivityLevel; +import algorithms.states.UpdateLatestOperationStartTimeAtActLocations; +import algorithms.states.UpdateLoadAtActivityLevel; +import algorithms.states.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted; +import algorithms.states.UpdateOccuredDeliveriesAtActivityLevel; import basics.VehicleRoutingAlgorithm; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblem.Constraint; @@ -451,16 +457,16 @@ public class VehicleRoutingAlgorithms { */ //constraint manager ConstraintManager constraintManager = new ConstraintManager(); - constraintManager.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts())); + constraintManager.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts())); if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){ - constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager)); + constraintManager.addConstraint(new HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager)); } else{ - constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager)); + constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager)); } - constraintManager.addConstraint(new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager)); + constraintManager.addConstraint(new HardPickupAndDeliveryLoadConstraint(stateManager)); //construct initial solution creator AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager); @@ -498,23 +504,38 @@ public class VehicleRoutingAlgorithms { */ //reset stateManager - algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager))); +// algorithmListeners.add(new PrioritizedVRAListener(Priority.LOW, new StateUpdates.ResetStateManager(stateManager))); //update states // metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateStates(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts())); - StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts()); +// UpdateRouteStatesOnceTheRouteHasBeenChanged routeChangedListener = new StateUpdates.UpdateRouteStatesOnceTheRouteHasBeenChanged(vrp.getTransportCosts()); +// +// routeChangedListener.addInsertionStartsListener(new InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager)); +// routeChangedListener.addJobInsertedListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(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.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager)); +// routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); +// routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager)); - routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager)); - routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager)); + stateManager.addListener(new InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager)); + stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager)); + + stateManager.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts())); + stateManager.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager)); - routeChangedListener.addVisitor(new StateUpdates.UpdateActivityTimes(vrp.getTransportCosts())); - routeChangedListener.addVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager)); - routeChangedListener.addVisitor(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); + stateManager.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); - routeChangedListener.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager)); - routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); - routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager)); + stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager)); + stateManager.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); + stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager)); + + + metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager); + metaAlgorithm.getAlgorithmListeners().addListener(stateManager); - metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(routeChangedListener); metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(vehicleFleetManager)); metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new ResetAndIniFleetManager(vehicleFleetManager)); metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new VehicleSwitched(vehicleFleetManager)); @@ -637,9 +658,9 @@ public class VehicleRoutingAlgorithms { @Override public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection solutions) { - CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy); + BestInsertionInitialSolutionFactory createInitialSolution = new BestInsertionInitialSolutionFactory(finalInsertionStrategy); createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false); - VehicleRoutingProblemSolution vrpSol = createInitialSolution.createInitialSolution(vrp); + VehicleRoutingProblemSolution vrpSol = createInitialSolution.createSolution(vrp); solutions.add(vrpSol); } @@ -834,6 +855,8 @@ public class VehicleRoutingAlgorithms { InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads, constraintManager); return insertion; } + + } diff --git a/jsprit-core/src/main/java/algorithms/VehicleTypeKey.java b/jsprit-core/src/main/java/algorithms/VehicleTypeKey.java new file mode 100644 index 00000000..c37c5bfd --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/VehicleTypeKey.java @@ -0,0 +1,48 @@ +package algorithms; + +class VehicleTypeKey { + + public final String type; + public final String locationId; + + VehicleTypeKey(String typeId, String locationId) { + super(); + this.type = typeId; + this.locationId = locationId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((locationId == null) ? 0 : locationId.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + VehicleTypeKey other = (VehicleTypeKey) obj; + if (locationId == null) { + if (other.locationId != null) + return false; + } else if (!locationId.equals(other.locationId)) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + + + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/ConstraintManager.java b/jsprit-core/src/main/java/algorithms/constraints/ConstraintManager.java new file mode 100644 index 00000000..0f7834c8 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/ConstraintManager.java @@ -0,0 +1,30 @@ +package algorithms.constraints; + +import algorithms.InsertionContext; +import basics.route.TourActivity; + +public class ConstraintManager implements HardActivityLevelConstraint, HardRouteLevelConstraint{ + + private HardActivityLevelConstraintManager actLevelConstraintManager = new HardActivityLevelConstraintManager(); + + private HardRouteLevelConstraintManager routeLevelConstraintManager = new HardRouteLevelConstraintManager(); + + public void addConstraint(HardActivityLevelConstraint actLevelConstraint){ + actLevelConstraintManager.addConstraint(actLevelConstraint); + } + + public void addConstraint(HardRouteLevelConstraint routeLevelConstraint){ + routeLevelConstraintManager.addConstraint(routeLevelConstraint); + } + + @Override + public boolean fulfilled(InsertionContext insertionContext) { + return routeLevelConstraintManager.fulfilled(insertionContext); + } + + @Override + public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime); + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardActivityLevelConstraint.java b/jsprit-core/src/main/java/algorithms/constraints/HardActivityLevelConstraint.java new file mode 100644 index 00000000..cb2a6067 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardActivityLevelConstraint.java @@ -0,0 +1,10 @@ +package algorithms.constraints; + +import algorithms.InsertionContext; +import basics.route.TourActivity; + +public interface HardActivityLevelConstraint { + + public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime); + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardActivityLevelConstraintManager.java b/jsprit-core/src/main/java/algorithms/constraints/HardActivityLevelConstraintManager.java new file mode 100644 index 00000000..d921d7c3 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardActivityLevelConstraintManager.java @@ -0,0 +1,27 @@ +package algorithms.constraints; + +import java.util.ArrayList; +import java.util.Collection; + +import algorithms.InsertionContext; +import basics.route.TourActivity; + +class HardActivityLevelConstraintManager implements HardActivityLevelConstraint { + + private Collection hardConstraints = new ArrayList(); + + public void addConstraint(HardActivityLevelConstraint constraint){ + hardConstraints.add(constraint); + } + + @Override + public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + for(HardActivityLevelConstraint constraint : hardConstraints){ + if(!constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime)){ + return false; + } + } + return true; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardConstraints.java b/jsprit-core/src/main/java/algorithms/constraints/HardConstraints.java new file mode 100644 index 00000000..7a71b10e --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardConstraints.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (C) 2013 Stefan Schroeder + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * Stefan Schroeder - initial API and implementation + ******************************************************************************/ +package algorithms.constraints; + + + + +/** + * collection of hard constrainters bot at activity and at route level. + * + *

HardPickupAndDeliveryLoadConstraint requires LOAD_AT_DEPOT and LOAD (i.e. load at end) at route-level + * + *

HardTimeWindowConstraint requires LATEST_OPERATION_START_TIME + * + *

HardPickupAndDeliveryConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level + * + *

HardPickupAndDeliveryBackhaulConstraint requires LOAD_AT_DEPOT and LOAD at route-level and FUTURE_PICKS and PAST_DELIVIERS on activity-level + * + * @author stefan + * + */ +class HardConstraints { + + + +} diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardLoadConstraint.java b/jsprit-core/src/main/java/algorithms/constraints/HardLoadConstraint.java new file mode 100644 index 00000000..d62f1f47 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardLoadConstraint.java @@ -0,0 +1,26 @@ +package algorithms.constraints; + +import algorithms.InsertionContext; +import algorithms.StateManager; +import algorithms.StateTypes; +import basics.Service; + +public class HardLoadConstraint implements HardRouteLevelConstraint{ + + private StateManager states; + + public HardLoadConstraint(StateManager states) { + super(); + this.states = states; + } + + @Override + public boolean fulfilled(InsertionContext insertionContext) { + int currentLoad = (int) states.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble(); + Service service = (Service) insertionContext.getJob(); + if(currentLoad + service.getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){ + return false; + } + return true; + } +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryActivityLevelConstraint.java b/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryActivityLevelConstraint.java new file mode 100644 index 00000000..97749776 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryActivityLevelConstraint.java @@ -0,0 +1,50 @@ +package algorithms.constraints; + +import algorithms.InsertionContext; +import algorithms.StateManager; +import algorithms.StateTypes; +import basics.route.DeliveryActivity; +import basics.route.PickupActivity; +import basics.route.ServiceActivity; +import basics.route.Start; +import basics.route.TourActivity; + +public class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint { + + private StateManager stateManager; + + public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + 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(); + futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble(); + pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble(); + } + if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){ + 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; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryBackhaulActivityLevelConstraint.java b/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryBackhaulActivityLevelConstraint.java new file mode 100644 index 00000000..d2190b98 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryBackhaulActivityLevelConstraint.java @@ -0,0 +1,54 @@ +package algorithms.constraints; + +import algorithms.InsertionContext; +import algorithms.StateManager; +import algorithms.StateTypes; +import basics.route.DeliveryActivity; +import basics.route.PickupActivity; +import basics.route.ServiceActivity; +import basics.route.Start; +import basics.route.TourActivity; + +public class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint { + + private StateManager stateManager; + + public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateManager stateManager) { + super(); + this.stateManager = stateManager; + } + + @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 ServiceActivity && nextAct instanceof DeliveryActivity){ return false; } + if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return false; } + if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ 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(); + futurePicks = (int) stateManager.getActivityState(prevAct, StateTypes.FUTURE_PICKS).toDouble(); + pastDeliveries = (int) stateManager.getActivityState(prevAct, StateTypes.PAST_DELIVERIES).toDouble(); + } + if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){ + 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; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryLoadConstraint.java b/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryLoadConstraint.java new file mode 100644 index 00000000..0cae5f95 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardPickupAndDeliveryLoadConstraint.java @@ -0,0 +1,42 @@ +package algorithms.constraints; + +import algorithms.InsertionContext; +import algorithms.StateManager; +import algorithms.StateTypes; +import basics.Delivery; +import basics.Pickup; +import basics.Service; + +/** + * lsjdfjsdlfjsa + * + * @author stefan + * + */ +public class HardPickupAndDeliveryLoadConstraint implements HardRouteLevelConstraint { + + private StateManager stateManager; + + public HardPickupAndDeliveryLoadConstraint(StateManager stateManager) { + super(); + this.stateManager = stateManager; + } + + @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 || insertionContext.getJob() instanceof Service){ + int loadAtEnd = (int) stateManager.getRouteState(insertionContext.getRoute(), StateTypes.LOAD).toDouble(); + if(loadAtEnd + insertionContext.getJob().getCapacityDemand() > insertionContext.getNewVehicle().getCapacity()){ + return false; + } + } + return true; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardRouteLevelConstraint.java b/jsprit-core/src/main/java/algorithms/constraints/HardRouteLevelConstraint.java new file mode 100644 index 00000000..8a1ee1c0 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardRouteLevelConstraint.java @@ -0,0 +1,9 @@ +package algorithms.constraints; + +import algorithms.InsertionContext; + +public interface HardRouteLevelConstraint { + + public boolean fulfilled(InsertionContext insertionContext); + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardRouteLevelConstraintManager.java b/jsprit-core/src/main/java/algorithms/constraints/HardRouteLevelConstraintManager.java new file mode 100644 index 00000000..681f816c --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardRouteLevelConstraintManager.java @@ -0,0 +1,26 @@ +package algorithms.constraints; + +import java.util.ArrayList; +import java.util.Collection; + +import algorithms.InsertionContext; + +class HardRouteLevelConstraintManager implements HardRouteLevelConstraint { + + private Collection hardConstraints = new ArrayList(); + + public void addConstraint(HardRouteLevelConstraint constraint){ + hardConstraints.add(constraint); + } + + @Override + public boolean fulfilled(InsertionContext insertionContext) { + for(HardRouteLevelConstraint constraint : hardConstraints){ + if(!constraint.fulfilled(insertionContext)){ + return false; + } + } + return true; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/constraints/HardTimeWindowActivityLevelConstraint.java b/jsprit-core/src/main/java/algorithms/constraints/HardTimeWindowActivityLevelConstraint.java new file mode 100644 index 00000000..ac3059a5 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/constraints/HardTimeWindowActivityLevelConstraint.java @@ -0,0 +1,49 @@ +package algorithms.constraints; + +import org.apache.log4j.Logger; + +import algorithms.CalculationUtils; +import algorithms.InsertionContext; +import algorithms.StateManager; +import algorithms.StateTypes; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.TourActivity; + +/** + * ljsljslfjs + * @author stefan + * + */ + public class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint { + + private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class); + + private StateManager states; + + private VehicleRoutingTransportCosts routingCosts; + + public HardTimeWindowActivityLevelConstraint(StateManager states, VehicleRoutingTransportCosts routingCosts) { + super(); + this.states = states; + this.routingCosts = routingCosts; + } + + @Override + public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { +// log.info("check insertion of " + newAct + " between " + prevAct + " and " + nextAct + ". prevActDepTime=" + prevActDepTime); + double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); + double latestArrTimeAtNewAct = states.getActivityState(newAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble(); + if(arrTimeAtNewAct > latestArrTimeAtNewAct){ + return false; + } +// log.info(newAct + " arrTime=" + arrTimeAtNewAct); + double endTimeAtNewAct = CalculationUtils.getActivityEndTime(arrTimeAtNewAct, newAct); + double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle()); + double latestArrTimeAtNextAct = states.getActivityState(nextAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble(); + if(arrTimeAtNextAct > latestArrTimeAtNextAct){ + return false; + } +// log.info(nextAct + " arrTime=" + arrTimeAtNextAct); + return true; + } + } \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java b/jsprit-core/src/main/java/algorithms/states/ActivityTimeTracker.java similarity index 97% rename from jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java rename to jsprit-core/src/main/java/algorithms/states/ActivityTimeTracker.java index 1cb0e5b6..7c99d6ac 100644 --- a/jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java +++ b/jsprit-core/src/main/java/algorithms/states/ActivityTimeTracker.java @@ -1,5 +1,6 @@ -package algorithms; +package algorithms.states; +import algorithms.ActivityVisitor; import basics.costs.ForwardTransportTime; import basics.route.Driver; import basics.route.TourActivity; diff --git a/jsprit-core/src/main/java/algorithms/states/InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts.java b/jsprit-core/src/main/java/algorithms/states/InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts.java new file mode 100644 index 00000000..0ad81e61 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts.java @@ -0,0 +1,64 @@ +package algorithms.states; + +import java.util.Collection; + +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.Delivery; +import basics.Job; +import basics.Pickup; +import basics.Service; +import basics.algo.InsertionStartsListener; +import basics.route.VehicleRoute; + +/** + * Initializes the load of each route/vehicle at start- and end-location before insertion starts. + * + *

StateTypes.LOAD_AT_DEPOT and StateTypes.LOAD are modified for each route + *

These states can be retrieved by
+ * stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT) for LOAD_AT_DEPOT and
+ * stateManager.getRouteState(route, StateTypes.LOAD) for LOAD (i.e. load at end) + * + * @param stateManager + */ +public class InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStartsListener { + + private StateManagerImpl stateManager; + + /** + * Initializes the load of each route/vehicle at start- and end-location before insertion starts. + * + *

StateTypes.LOAD_AT_DEPOT and StateTypes.LOAD are modified for each route + *

These states can be retrieved by
+ * stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT) for LOAD_AT_DEPOT and
+ * stateManager.getRouteState(route, StateTypes.LOAD) for LOAD (i.e. load at end) + * + * @param stateManager + */ + public InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManagerImpl stateManager) { + super(); + this.stateManager = stateManager; + } + + void insertionStarts(VehicleRoute route) { + int loadAtDepot = 0; + int loadAtEnd = 0; + for(Job j : route.getTourActivities().getJobs()){ + if(j instanceof Delivery){ + loadAtDepot += j.getCapacityDemand(); + } + else if(j instanceof Pickup || j instanceof Service){ + loadAtEnd += j.getCapacityDemand(); + } + } + stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot)); + stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd)); + } + + @Override + public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) { + for(VehicleRoute route : vehicleRoutes){ insertionStarts(route); } + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/StateUpdates.java b/jsprit-core/src/main/java/algorithms/states/StateUpdates.java new file mode 100644 index 00000000..22d715b0 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/StateUpdates.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (C) 2013 Stefan Schroeder + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * Stefan Schroeder - initial API and implementation + ******************************************************************************/ +package algorithms.states; + +import java.util.ArrayList; +import java.util.Collection; + + +import algorithms.ActivityVisitor; +import algorithms.ReverseActivityVisitor; +import algorithms.ReverseRouteActivityVisitor; +import algorithms.RouteActivityVisitor; +import algorithms.StateManagerImpl; +import basics.Job; +import basics.VehicleRoutingProblem; +import basics.VehicleRoutingProblemSolution; +import basics.algo.InsertionStartsListener; +import basics.algo.IterationStartsListener; +import basics.algo.JobInsertedListener; +import basics.algo.RuinListener; +import basics.costs.VehicleRoutingActivityCosts; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.VehicleRoute; + +public class StateUpdates { + + public static class UpdateStates implements JobInsertedListener, RuinListener{ + + private RouteActivityVisitor routeActivityVisitor; + + 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)); + + revRouteActivityVisitor = new ReverseRouteActivityVisitor(); + revRouteActivityVisitor.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(states, routingCosts)); + + } + + public void update(VehicleRoute route){ + routeActivityVisitor.visit(route); + revRouteActivityVisitor.visit(route); + } + + @Override + public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { + routeActivityVisitor.visit(inRoute); + revRouteActivityVisitor.visit(inRoute); + } + + @Override + public void ruinStarts(Collection routes) {} + + @Override + public void ruinEnds(Collection routes,Collection unassignedJobs) { + for(VehicleRoute route : routes) { + routeActivityVisitor.visit(route); + revRouteActivityVisitor.visit(route); + } + } + + @Override + public void removed(Job job, VehicleRoute fromRoute) {} + + } + + static class ResetStateManager implements IterationStartsListener { + + private StateManagerImpl stateManager; + + public ResetStateManager(StateManagerImpl stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection solutions) { + stateManager.clear(); + } + } + + static interface InsertionStarts { + + void insertionStarts(VehicleRoute route); + + } + + static class UpdateRouteStatesOnceTheRouteHasBeenChanged implements InsertionStartsListener, JobInsertedListener { + + private RouteActivityVisitor forwardInTimeIterator; + + private ReverseRouteActivityVisitor backwardInTimeIterator; + + private Collection insertionStartsListeners; + + private Collection jobInsertionListeners; + + public UpdateRouteStatesOnceTheRouteHasBeenChanged(VehicleRoutingTransportCosts routingCosts) { + forwardInTimeIterator = new RouteActivityVisitor(); + backwardInTimeIterator = new ReverseRouteActivityVisitor(); + insertionStartsListeners = new ArrayList(); + jobInsertionListeners = new ArrayList(); + } + + void addVisitor(ActivityVisitor vis){ + forwardInTimeIterator.addActivityVisitor(vis); + } + + void addVisitor(ReverseActivityVisitor revVis){ + backwardInTimeIterator.addActivityVisitor(revVis); + } + + void addInsertionStartsListener(InsertionStarts insertionStartListener){ + insertionStartsListeners.add(insertionStartListener); + } + + void addJobInsertedListener(JobInsertedListener jobInsertedListener){ + jobInsertionListeners.add(jobInsertedListener); + } + + @Override + public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { + for(JobInsertedListener l : jobInsertionListeners){ l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); } + forwardInTimeIterator.visit(inRoute); + backwardInTimeIterator.visit(inRoute); + } + + @Override + public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) { + for(VehicleRoute route : vehicleRoutes){ + for(InsertionStarts insertionsStartsHandler : insertionStartsListeners){ + insertionsStartsHandler.insertionStarts(route); + } + forwardInTimeIterator.visit(route); + backwardInTimeIterator.visit(route); + } + } + + } +} diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateActivityTimes.java b/jsprit-core/src/main/java/algorithms/states/UpdateActivityTimes.java new file mode 100644 index 00000000..62ea3952 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateActivityTimes.java @@ -0,0 +1,63 @@ +package algorithms.states; + +import org.apache.log4j.Logger; + +import algorithms.ActivityVisitor; +import basics.costs.ForwardTransportTime; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +/** + * Updates arrival and end times of activities. + * + *

Note that this modifies arrTime and endTime of each activity in a route. + * + * @author stefan + * + */ +public class UpdateActivityTimes implements ActivityVisitor{ + + private Logger log = Logger.getLogger(UpdateActivityTimes.class); + + private ActivityTimeTracker timeTracker; + + private VehicleRoute route; + + /** + * Updates arrival and end times of activities. + * + *

Note that this modifies arrTime and endTime of each activity in a route. + * + *

ArrTimes and EndTimes can be retrieved by
+ * activity.getArrTime() and + * activity.getEndTime() + * + * @author stefan + * + */ + public UpdateActivityTimes(ForwardTransportTime transportTime) { + super(); + timeTracker = new ActivityTimeTracker(transportTime); + } + + @Override + public void begin(VehicleRoute route) { + timeTracker.begin(route); + this.route = route; + route.getStart().setEndTime(timeTracker.getActEndTime()); + } + + @Override + 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()); + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateCostsAtAllLevels.java b/jsprit-core/src/main/java/algorithms/states/UpdateCostsAtAllLevels.java new file mode 100644 index 00000000..22830629 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateCostsAtAllLevels.java @@ -0,0 +1,118 @@ +package algorithms.states; + +import org.apache.log4j.Logger; + +import algorithms.ActivityVisitor; +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.costs.ForwardTransportCost; +import basics.costs.VehicleRoutingActivityCosts; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +/** + * Updates total costs (i.e. transport and activity costs) at route and activity level. + * + *

Thus it modifies stateManager.getRouteState(route, StateTypes.COSTS) and
+ * stateManager.getActivityState(activity, StateTypes.COSTS) + * + * + * @param activityCost + * @param transportCost + * @param states + */ +public class UpdateCostsAtAllLevels implements ActivityVisitor{ + + private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class); + + private VehicleRoutingActivityCosts activityCost; + + private ForwardTransportCost transportCost; + + private StateManagerImpl states; + + private double totalOperationCost = 0.0; + + private VehicleRoute vehicleRoute = null; + + private TourActivity prevAct = null; + + private double startTimeAtPrevAct = 0.0; + + private ActivityTimeTracker timeTracker; + + /** + * Updates total costs (i.e. transport and activity costs) at route and activity level. + * + *

Thus it modifies stateManager.getRouteState(route, StateTypes.COSTS) and
+ * stateManager.getActivityState(activity, StateTypes.COSTS) + * + * + * @param activityCost + * @param transportCost + * @param states + */ + 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 begin(VehicleRoute route) { + vehicleRoute = route; + vehicleRoute.getVehicleRouteCostCalculator().reset(); + timeTracker.begin(route); + prevAct = route.getStart(); + startTimeAtPrevAct = timeTracker.getActEndTime(); + } + + @Override + 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, timeTracker.getActArrTime(), vehicleRoute.getDriver(), vehicleRoute.getVehicle()); + + vehicleRoute.getVehicleRouteCostCalculator().addTransportCost(transportCost); + vehicleRoute.getVehicleRouteCostCalculator().addActivityCost(actCost); + + totalOperationCost += transportCost; + totalOperationCost += actCost; + + states.putActivityState(act, StateTypes.COSTS, new StateImpl(totalOperationCost)); + + prevAct = act; + startTimeAtPrevAct = timeTracker.getActEndTime(); + } + + @Override + 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); + + totalOperationCost += transportCost; + totalOperationCost += actCost; + + states.putRouteState(vehicleRoute, StateTypes.COSTS, new StateImpl(totalOperationCost)); + + //this is rather strange and likely to change + vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getDriver()); + vehicleRoute.getVehicleRouteCostCalculator().price(vehicleRoute.getVehicle()); + vehicleRoute.getVehicleRouteCostCalculator().finish(); + + startTimeAtPrevAct = 0.0; + prevAct = null; + vehicleRoute = null; + totalOperationCost = 0.0; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateCostsAtRouteLevel.java b/jsprit-core/src/main/java/algorithms/states/UpdateCostsAtRouteLevel.java new file mode 100644 index 00000000..2a56897a --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateCostsAtRouteLevel.java @@ -0,0 +1,65 @@ +package algorithms.states; + +import java.util.Collection; + +import algorithms.RouteActivityVisitor; +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.Job; +import basics.algo.InsertionEndsListener; +import basics.algo.InsertionStartsListener; +import basics.algo.JobInsertedListener; +import basics.costs.VehicleRoutingActivityCosts; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.VehicleRoute; + +public class UpdateCostsAtRouteLevel implements JobInsertedListener, InsertionStartsListener, InsertionEndsListener{ + + private StateManagerImpl states; + + private VehicleRoutingTransportCosts tpCosts; + + private VehicleRoutingActivityCosts actCosts; + + public UpdateCostsAtRouteLevel(StateManagerImpl states, VehicleRoutingTransportCosts tpCosts, VehicleRoutingActivityCosts actCosts) { + super(); + this.states = states; + this.tpCosts = tpCosts; + this.actCosts = actCosts; + } + + @Override + public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { +// inRoute.getVehicleRouteCostCalculator().addTransportCost(additionalCosts); + double oldCosts = states.getRouteState(inRoute, StateTypes.COSTS).toDouble(); + oldCosts += additionalCosts; + states.putRouteState(inRoute, StateTypes.COSTS, new StateImpl(oldCosts)); + } + + @Override + public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) { + RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); + forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(actCosts, tpCosts, states)); + for(VehicleRoute route : vehicleRoutes){ + forwardInTime.visit(route); + } + + } + + @Override + public void informInsertionEnds(Collection vehicleRoutes) { + +// IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(tpCosts); +// forwardInTime.addListener(new UpdateCostsAtAllLevels(actCosts, tpCosts, states)); + for(VehicleRoute route : vehicleRoutes){ + if(route.isEmpty()) continue; + route.getVehicleRouteCostCalculator().reset(); + route.getVehicleRouteCostCalculator().addOtherCost(states.getRouteState(route, StateTypes.COSTS).toDouble()); + route.getVehicleRouteCostCalculator().price(route.getVehicle()); +// forwardInTime.iterate(route); + } + + } + + } \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateEarliestStartTimeWindowAtActLocations.java b/jsprit-core/src/main/java/algorithms/states/UpdateEarliestStartTimeWindowAtActLocations.java new file mode 100644 index 00000000..f72e9023 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateEarliestStartTimeWindowAtActLocations.java @@ -0,0 +1,38 @@ +package algorithms.states; + +import algorithms.ActivityVisitor; +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +public class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor{ + + private StateManagerImpl states; + + private ActivityTimeTracker timeTracker; + + public UpdateEarliestStartTimeWindowAtActLocations(StateManagerImpl states, VehicleRoutingTransportCosts transportCosts) { + super(); + this.states = states; + timeTracker = new ActivityTimeTracker(transportCosts); + } + + @Override + public void begin(VehicleRoute route) { + timeTracker.begin(route); + } + + @Override + 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() {} + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateFuturePickupsAtActivityLevel.java b/jsprit-core/src/main/java/algorithms/states/UpdateFuturePickupsAtActivityLevel.java new file mode 100644 index 00000000..98bf99bf --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateFuturePickupsAtActivityLevel.java @@ -0,0 +1,42 @@ +package algorithms.states; + +import algorithms.ReverseActivityVisitor; +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.route.PickupActivity; +import basics.route.ServiceActivity; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +public class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor { + private StateManagerImpl stateManager; + private int futurePicks = 0; + private VehicleRoute route; + + public UpdateFuturePickupsAtActivityLevel(StateManagerImpl stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public void begin(VehicleRoute route) { + this.route = route; + } + + @Override + public void visit(TourActivity act) { + stateManager.putActivityState(act, StateTypes.FUTURE_PICKS, new StateImpl(futurePicks)); + if(act instanceof PickupActivity || act instanceof ServiceActivity){ + futurePicks += act.getCapacityDemand(); + } + assert futurePicks <= route.getVehicle().getCapacity() : "sum of pickups must not be > vehicleCap"; + assert futurePicks >= 0 : "sum of pickups must not < 0"; + } + + @Override + public void finish() { + futurePicks = 0; + route = null; + } +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateLatestOperationStartTimeAtActLocations.java b/jsprit-core/src/main/java/algorithms/states/UpdateLatestOperationStartTimeAtActLocations.java new file mode 100644 index 00000000..0ba402e4 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateLatestOperationStartTimeAtActLocations.java @@ -0,0 +1,53 @@ +package algorithms.states; + +import org.apache.log4j.Logger; + +import algorithms.ReverseActivityVisitor; +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +public class UpdateLatestOperationStartTimeAtActLocations implements ReverseActivityVisitor{ + + private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class); + + private 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 begin(VehicleRoute route) { + this.route = route; + latestArrTimeAtPrevAct = route.getEnd().getTheoreticalLatestOperationStartTime(); + prevAct = route.getEnd(); + } + + @Override + 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() {} +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtActivityLevel.java b/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtActivityLevel.java new file mode 100644 index 00000000..18333da0 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtActivityLevel.java @@ -0,0 +1,68 @@ +package algorithms.states; + +import algorithms.ActivityVisitor; +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +/** + * Updates load at activity level. + * + *

Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT. + * If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot. + * + *

Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT + * + * @author stefan + * + */ +public class UpdateLoadAtActivityLevel implements ActivityVisitor { + private StateManagerImpl stateManager; + private int currentLoad = 0; + private VehicleRoute route; + + /** + * Updates load at activity level. + * + *

Note that this assumes that StateTypes.LOAD_AT_DEPOT is already updated, i.e. it starts by setting loadAtDepot to StateTypes.LOAD_AT_DEPOT. + * If StateTypes.LOAD_AT_DEPOT is not set, it starts with 0 load at depot. + * + *

Thus it DEPENDS on StateTypes.LOAD_AT_DEPOT + * + *

If you want to update StateTypes.LOAD_AT_DEPOT see {@link InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted} + * + *

The loads can be retrieved by
+ * stateManager.getActivityState(activity,StateTypes.LOAD); + * + * + * + * @see {@link InitializeLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted} + * @author stefan + * + */ + public UpdateLoadAtActivityLevel(StateManagerImpl stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public void begin(VehicleRoute route) { + currentLoad = (int) stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT).toDouble(); + this.route = route; + } + + @Override + 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 finish() { + currentLoad = 0; + } +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtAllLevels.java b/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtAllLevels.java new file mode 100644 index 00000000..cbd18d36 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtAllLevels.java @@ -0,0 +1,41 @@ +package algorithms.states; + +import algorithms.ActivityVisitor; +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +public class UpdateLoadAtAllLevels implements ActivityVisitor{ + + private double load = 0.0; + + private StateManagerImpl states; + + private VehicleRoute vehicleRoute; + + public UpdateLoadAtAllLevels(StateManagerImpl states) { + super(); + this.states = states; + } + + @Override + public void begin(VehicleRoute route) { + vehicleRoute = route; + } + + @Override + 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; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtRouteLevel.java b/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtRouteLevel.java new file mode 100644 index 00000000..717d57fe --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateLoadAtRouteLevel.java @@ -0,0 +1,56 @@ +package algorithms.states; + +import java.util.Collection; + +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.Job; +import basics.Service; +import basics.algo.InsertionStartsListener; +import basics.algo.JobInsertedListener; +import basics.route.VehicleRoute; + +/** + * Updates load at route level, i.e. modifies StateTypes.LOAD for each route. + * + * @author stefan + * + */ +public class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener{ + + private StateManagerImpl states; + + /** + * Updates load at route level, i.e. modifies StateTypes.LOAD for each route. + * + * @author stefan + * + */ + public UpdateLoadAtRouteLevel(StateManagerImpl states) { + super(); + this.states = states; + } + + @Override + public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { + if(!(job2insert instanceof Service)){ + return; + } + double oldLoad = states.getRouteState(inRoute, StateTypes.LOAD).toDouble(); + states.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(oldLoad + job2insert.getCapacityDemand())); + } + + @Override + public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs) { + for(VehicleRoute route : vehicleRoutes){ + int load = 0; + for(Job j : route.getTourActivities().getJobs()){ + load += j.getCapacityDemand(); + } + states.putRouteState(route, StateTypes.LOAD, new StateImpl(load)); + } + + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted.java b/jsprit-core/src/main/java/algorithms/states/UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted.java new file mode 100644 index 00000000..3d510ff1 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted.java @@ -0,0 +1,54 @@ +package algorithms.states; + +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.Delivery; +import basics.Job; +import basics.Pickup; +import basics.Service; +import basics.algo.JobInsertedListener; +import basics.route.VehicleRoute; + +/** + * Updates loads at start and end of a route if a job has been inserted in that route. + * + *

These states can be retrieved by
+ * stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT) for LOAD_AT_DEPOT and
+ * stateManager.getRouteState(route, StateTypes.LOAD) for LOAD (i.e. load at end) + * + * @param stateManager + */ +public class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener { + + private StateManagerImpl stateManager; + + /** + * Updates loads at start and end of a route if a job has been inserted in that route. + * + *

These states can be retrieved by
+ * stateManager.getRouteState(route, StateTypes.LOAD_AT_DEPOT) for LOAD_AT_DEPOT and
+ * stateManager.getRouteState(route, StateTypes.LOAD) for LOAD (i.e. load at end) + * + * @param stateManager + */ + public UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(StateManagerImpl stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { + if(job2insert instanceof Delivery){ + int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble(); +// log.info("loadAtDepot="+loadAtDepot); + stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand())); + } + else if(job2insert instanceof Pickup || job2insert instanceof Service){ + int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble(); +// log.info("loadAtEnd="+loadAtEnd); + stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand())); + } + } + + } \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/states/UpdateOccuredDeliveriesAtActivityLevel.java b/jsprit-core/src/main/java/algorithms/states/UpdateOccuredDeliveriesAtActivityLevel.java new file mode 100644 index 00000000..3a4f7ce2 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/states/UpdateOccuredDeliveriesAtActivityLevel.java @@ -0,0 +1,41 @@ +package algorithms.states; + +import algorithms.ActivityVisitor; +import algorithms.StateManagerImpl; +import algorithms.StateManagerImpl.StateImpl; +import algorithms.StateTypes; +import basics.route.DeliveryActivity; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +public class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor { + private StateManagerImpl stateManager; + private int deliveries = 0; + private VehicleRoute route; + + public UpdateOccuredDeliveriesAtActivityLevel(StateManagerImpl stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public void begin(VehicleRoute route) { + this.route = route; + } + + @Override + public void visit(TourActivity act) { + if(act instanceof DeliveryActivity){ + deliveries += Math.abs(act.getCapacityDemand()); + } + stateManager.putActivityState(act, StateTypes.PAST_DELIVERIES, new StateImpl(deliveries)); + assert deliveries >= 0 : "deliveries < 0"; + assert deliveries <= route.getVehicle().getCapacity() : "deliveries > vehicleCap"; + } + + @Override + public void finish() { + deliveries = 0; + route = null; + } +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/basics/algo/InsertionListeners.java b/jsprit-core/src/main/java/basics/algo/InsertionListeners.java new file mode 100644 index 00000000..63afa67b --- /dev/null +++ b/jsprit-core/src/main/java/basics/algo/InsertionListeners.java @@ -0,0 +1,42 @@ +package basics.algo; + +import java.util.ArrayList; +import java.util.Collection; + +import basics.Job; +import basics.route.VehicleRoute; + +public class InsertionListeners { + + private Collection startListeners = new ArrayList(); + + private Collection jobInsertedListeners = new ArrayList(); + + private Collection endListeners = new ArrayList(); + + public void addListener(InsertionListener insertionListener){ + if(insertionListener instanceof InsertionStartsListener) startListeners.add((InsertionStartsListener) insertionListener); + else if(insertionListener instanceof JobInsertedListener) jobInsertedListeners.add((JobInsertedListener) insertionListener); + else if(insertionListener instanceof InsertionEndsListener) endListeners.add((InsertionEndsListener) insertionListener); + else throw new IllegalStateException("cannot add this type of insertionListener"); + } + + public void removeListener(InsertionListener insertionListener){ + if(insertionListener instanceof InsertionStartsListener) startListeners.remove((InsertionStartsListener) insertionListener); + else if(insertionListener instanceof JobInsertedListener) jobInsertedListeners.remove((JobInsertedListener) insertionListener); + else if(insertionListener instanceof InsertionEndsListener) endListeners.remove((InsertionEndsListener) insertionListener); + else throw new IllegalStateException("cannot remove this type of insertionListener"); + } + + public void insertionStarts(Collection vehicleRoutes, Collection unassignedJobs){ + for(InsertionStartsListener l : startListeners) l.informInsertionStarts(vehicleRoutes, unassignedJobs); + } + + public void jobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime){ + for(JobInsertedListener l : jobInsertedListeners) l.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); + } + + public void insertionEnds(Collection vehicleRoutes){ + for(InsertionEndsListener l : endListeners){ l.informInsertionEnds(vehicleRoutes); } + } +} diff --git a/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java b/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java index 8f8ea757..5035b123 100644 --- a/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java +++ b/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java @@ -29,4 +29,5 @@ import basics.route.VehicleRoute; public interface InsertionStartsListener extends InsertionListener { public void informInsertionStarts(Collection vehicleRoutes, Collection unassignedJobs); + } diff --git a/jsprit-core/src/main/java/algorithms/RuinListeners.java b/jsprit-core/src/main/java/basics/algo/RuinListeners.java similarity index 79% rename from jsprit-core/src/main/java/algorithms/RuinListeners.java rename to jsprit-core/src/main/java/basics/algo/RuinListeners.java index ca885c5f..fc442cc9 100644 --- a/jsprit-core/src/main/java/algorithms/RuinListeners.java +++ b/jsprit-core/src/main/java/basics/algo/RuinListeners.java @@ -18,41 +18,40 @@ * Contributors: * Stefan Schroeder - initial API and implementation ******************************************************************************/ -package algorithms; +package basics.algo; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import basics.Job; -import basics.algo.RuinListener; import basics.route.VehicleRoute; -class RuinListeners { +public class RuinListeners { private Collection ruinListeners = new ArrayList(); - void ruinStarts(Collection routes){ + public void ruinStarts(Collection routes){ for(RuinListener l : ruinListeners) l.ruinStarts(routes); } - void ruinEnds(Collection routes, Collection unassignedJobs){ + public void ruinEnds(Collection routes, Collection unassignedJobs){ for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs); } - void removed(Job job, VehicleRoute fromRoute){ + public void removed(Job job, VehicleRoute fromRoute){ for(RuinListener l : ruinListeners) l.removed(job, fromRoute); } - void addListener(RuinListener ruinListener){ + public void addListener(RuinListener ruinListener){ ruinListeners.add(ruinListener); } - void removeListener(RuinListener ruinListener){ + public void removeListener(RuinListener ruinListener){ ruinListeners.remove(ruinListener); } - Collection getListeners(){ + public Collection getListeners(){ return Collections.unmodifiableCollection(ruinListeners); } } diff --git a/jsprit-core/src/main/java/util/Solutions.java b/jsprit-core/src/main/java/util/Solutions.java index 7af2493b..9b6c0c68 100644 --- a/jsprit-core/src/main/java/util/Solutions.java +++ b/jsprit-core/src/main/java/util/Solutions.java @@ -26,6 +26,7 @@ import basics.VehicleRoutingProblemSolution; public class Solutions { + @Deprecated public static VehicleRoutingProblemSolution getBest(Collection solutions){ VehicleRoutingProblemSolution best = null; for(VehicleRoutingProblemSolution s : solutions){ @@ -34,5 +35,15 @@ public class Solutions { } return best; } + + + public static VehicleRoutingProblemSolution bestOf(Collection solutions){ + VehicleRoutingProblemSolution best = null; + for(VehicleRoutingProblemSolution s : solutions){ + if(best == null) best = s; + else if(s.getCost() < best.getCost()) best = s; + } + return best; + } } diff --git a/jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java b/jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java index f5e8b452..a0a4765b 100644 --- a/jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java +++ b/jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java @@ -28,11 +28,12 @@ import org.junit.Before; import org.junit.Test; import util.Solutions; -import algorithms.HardConstraints.HardActivityLevelConstraint; -import algorithms.StateUpdates.UpdateCostsAtRouteLevel; -import algorithms.StateUpdates.UpdateLoadAtRouteLevel; import algorithms.acceptors.AcceptNewIfBetterThanWorst; +import algorithms.constraints.HardActivityLevelConstraint; +import algorithms.constraints.HardLoadConstraint; import algorithms.selectors.SelectBest; +import algorithms.states.UpdateCostsAtRouteLevel; +import algorithms.states.UpdateLoadAtRouteLevel; import basics.VehicleRoutingAlgorithm; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblemSolution; @@ -63,7 +64,7 @@ public class BuildCVRPAlgoFromScratchTest { } }; ActivityInsertionCostCalculator marginalCalculus = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), hardActLevelConstraint); - CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager)); + CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardLoadConstraint(stateManager)); VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles()); JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, serviceInsertion); @@ -101,7 +102,7 @@ public class BuildCVRPAlgoFromScratchTest { vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateCostsAtRouteLevel(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts())); vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateLoadAtRouteLevel(stateManager)); - VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion).createInitialSolution(vrp); + VehicleRoutingProblemSolution iniSolution = new BestInsertionInitialSolutionFactory(bestInsertion).createSolution(vrp); // System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size()); vra.addInitialSolution(iniSolution); diff --git a/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java b/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java index 8da91d96..3314d4e3 100644 --- a/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java +++ b/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java @@ -26,17 +26,20 @@ import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; -import util.Solutions; -import algorithms.BackwardInTimeListeners.BackwardInTimeListener; -import algorithms.ForwardInTimeListeners.ForwardInTimeListener; -import algorithms.HardConstraints.HardActivityLevelConstraintManager; -import algorithms.StateManager.StateImpl; -import algorithms.StateUpdates.UpdateActivityTimes; -import algorithms.StateUpdates.UpdateCostsAtAllLevels; -import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations; -import algorithms.StateUpdates.UpdateLatestOperationStartTimeAtActLocations; +import algorithms.StateManagerImpl.StateImpl; import algorithms.acceptors.AcceptNewIfBetterThanWorst; +import algorithms.constraints.ConstraintManager; +import algorithms.constraints.HardPickupAndDeliveryActivityLevelConstraint; +import algorithms.constraints.HardPickupAndDeliveryLoadConstraint; +import algorithms.constraints.HardTimeWindowActivityLevelConstraint; import algorithms.selectors.SelectBest; +import algorithms.states.UpdateActivityTimes; +import algorithms.states.UpdateCostsAtAllLevels; +import algorithms.states.UpdateEarliestStartTimeWindowAtActLocations; +import algorithms.states.UpdateFuturePickupsAtActivityLevel; +import algorithms.states.UpdateLatestOperationStartTimeAtActLocations; +import algorithms.states.UpdateLoadAtActivityLevel; +import algorithms.states.UpdateOccuredDeliveriesAtActivityLevel; import basics.Delivery; import basics.Job; import basics.Pickup; @@ -44,17 +47,10 @@ import basics.VehicleRoutingAlgorithm; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblemSolution; import basics.algo.InsertionStartsListener; -import basics.algo.IterationStartsListener; import basics.algo.JobInsertedListener; import basics.algo.SearchStrategy; import basics.algo.SearchStrategyManager; 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; public class BuildPDVRPAlgoFromScratchTest { @@ -74,13 +70,13 @@ public class BuildPDVRPAlgoFromScratchTest { final StateManagerImpl stateManager = new StateManagerImpl(); - HardActivityLevelConstraintManager actLevelConstraintAccumulator = new HardActivityLevelConstraintManager(); - actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager)); - actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts())); + ConstraintManager actLevelConstraintAccumulator = new ConstraintManager(); + actLevelConstraintAccumulator.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager)); + actLevelConstraintAccumulator.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts())); ActivityInsertionCostCalculator 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 HardPickupAndDeliveryLoadConstraint(stateManager)); // CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager)); VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles()); @@ -105,7 +101,7 @@ public class BuildPDVRPAlgoFromScratchTest { vra = new VehicleRoutingAlgorithm(vrp, strategyManager); - vra.getAlgorithmListeners().addListener(new StateUpdates.ResetStateManager(stateManager)); + vra.getAlgorithmListeners().addListener(stateManager); final RouteActivityVisitor iterateForward = new RouteActivityVisitor(); @@ -113,12 +109,12 @@ public class BuildPDVRPAlgoFromScratchTest { iterateForward.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, vrp.getTransportCosts())); iterateForward.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); - iterateForward.addActivityVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager)); - iterateForward.addActivityVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager)); + iterateForward.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager)); + iterateForward.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager)); final ReverseRouteActivityVisitor iterateBackward = new ReverseRouteActivityVisitor(); iterateBackward.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); - iterateBackward.addActivityVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager)); + iterateBackward.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager)); InsertionStartsListener loadVehicleInDepot = new InsertionStartsListener() { @@ -171,7 +167,7 @@ public class BuildPDVRPAlgoFromScratchTest { bestInsertion.addListener(loadVehicleInDepot); bestInsertion.addListener(updateLoadAfterJobHasBeenInserted); - VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion).createInitialSolution(vrp); + VehicleRoutingProblemSolution iniSolution = new BestInsertionInitialSolutionFactory(bestInsertion).createSolution(vrp); // System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size()); vra.addInitialSolution(iniSolution); diff --git a/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java b/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java index 7642b043..5f823ea2 100644 --- a/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java +++ b/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java @@ -33,7 +33,9 @@ import org.junit.Test; import util.Coordinate; import util.ManhattanDistanceCalculator; import util.RouteUtils; -import algorithms.StateUpdates.UpdateStates; +import algorithms.constraints.HardLoadConstraint; +import algorithms.constraints.HardTimeWindowActivityLevelConstraint; +import algorithms.states.StateUpdates.UpdateStates; import basics.Job; import basics.Service; import basics.VehicleRoutingProblem; @@ -152,7 +154,7 @@ public class GendreauPostOptTest { activityCosts = new ExampleActivityCostFunction(); - CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, new MarginalsCalculusTriangleInequality(cost, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, cost)), new HardConstraints.HardLoadConstraint(states)); + CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, new MarginalsCalculusTriangleInequality(cost, activityCosts, new HardTimeWindowActivityLevelConstraint(states, cost)), new HardLoadConstraint(states)); CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states); withFixCost.setWeightOfFixCost(1.2); diff --git a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java index 8ab72ed7..9cd7c56b 100644 --- a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java +++ b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java @@ -32,7 +32,9 @@ import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; -import algorithms.StateUpdates.UpdateStates; +import algorithms.constraints.HardLoadConstraint; +import algorithms.constraints.HardTimeWindowActivityLevelConstraint; +import algorithms.states.StateUpdates.UpdateStates; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingTransportCosts; @@ -157,7 +159,7 @@ public class TestCalculatesServiceInsertion { ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction(); - serviceInsertion = new CalculatesServiceInsertion(costs, new MarginalsCalculusTriangleInequality(costs, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, costs)), new HardConstraints.HardLoadConstraint(states)); + serviceInsertion = new CalculatesServiceInsertion(costs, new MarginalsCalculusTriangleInequality(costs, activityCosts, new HardTimeWindowActivityLevelConstraint(states, costs)), new HardLoadConstraint(states)); stateUpdater = new UpdateStates(states, costs, activityCosts); diff --git a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java index 7798a263..71f5d8a8 100644 --- a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java +++ b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java @@ -34,7 +34,7 @@ import org.junit.Test; import util.Coordinate; import util.ManhattanDistanceCalculator; -import algorithms.StateUpdates.UpdateStates; +import algorithms.states.StateUpdates.UpdateStates; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingTransportCosts; diff --git a/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java b/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java index 99de138d..1525b4c2 100644 --- a/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java +++ b/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java @@ -30,10 +30,10 @@ import org.junit.Test; import util.Coordinate; import util.ManhattanDistanceCalculator; -import algorithms.StateUpdates.UpdateActivityTimes; -import algorithms.StateUpdates.UpdateCostsAtAllLevels; -import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations; -import algorithms.StateUpdates.UpdateLoadAtAllLevels; +import algorithms.states.UpdateActivityTimes; +import algorithms.states.UpdateCostsAtAllLevels; +import algorithms.states.UpdateEarliestStartTimeWindowAtActLocations; +import algorithms.states.UpdateLoadAtAllLevels; import basics.Job; import basics.Service; import basics.costs.DefaultVehicleRoutingActivityCosts; diff --git a/jsprit-core/src/test/java/algorithms/TestTourStateUpdaterWithService.java b/jsprit-core/src/test/java/algorithms/TestTourStateUpdaterWithService.java index 1ded2d91..f2e1c3bc 100644 --- a/jsprit-core/src/test/java/algorithms/TestTourStateUpdaterWithService.java +++ b/jsprit-core/src/test/java/algorithms/TestTourStateUpdaterWithService.java @@ -27,7 +27,7 @@ import org.junit.Test; import util.Coordinate; import util.ManhattanDistanceCalculator; -import algorithms.StateUpdates.UpdateStates; +import algorithms.states.StateUpdates.UpdateStates; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingTransportCosts;