diff --git a/Changelog.md b/Changelog.md deleted file mode 100644 index 1a8c1bc5..00000000 --- a/Changelog.md +++ /dev/null @@ -1,21 +0,0 @@ -Change-log -========== -**v0.0.4** @ 2013-10-17 - -- A number of internal improvements -- License change from GPLv2 to LGPLv3 -- Add premature algorithm termination: PrematureAlgorithmBreaker.java and its implementations -- SearchStrategy.java: public SearchStrategy(SolutionSelector,SolutionAcceptor) --> public SearchStratgy(SolutionSelector,SolutionAcceptor,SolutionCostCalculator) -- SearchStrategy.java: public boolean run(...) --> public DiscoveredSolution run(...) -- VehicleImpl.VehicleType.Builder --> VehicleTypeImpl.Builder -- VehicleImpl.VehicleBuilder --> VehicleImpl.Builder - -**v0.0.3** @ 2013-06-04 - -- Bug fix - access resources in jar - -**v0.0.2** @ 2013-06-03 - -- Bug fix - access resources in jar - -**v0.0.1** @ 2013-06-02 diff --git a/jsprit-analysis/src/main/java/analysis/AlgorithmSearchProgressChartListener.java b/jsprit-analysis/src/main/java/analysis/AlgorithmSearchProgressChartListener.java index c31b6e51..af7962d2 100644 --- a/jsprit-analysis/src/main/java/analysis/AlgorithmSearchProgressChartListener.java +++ b/jsprit-analysis/src/main/java/analysis/AlgorithmSearchProgressChartListener.java @@ -118,8 +118,10 @@ public class AlgorithmSearchProgressChartListener implements IterationEndsListen XYPlot plot = chart.getXYPlot(); NumberAxis yAxis = (NumberAxis) plot.getRangeAxis(); - Range rangeY = new Range(minValue-0.05*minValue,maxValue + 0.05*maxValue); - yAxis.setRange(rangeY); + Range rangeBounds = coll.getRangeBounds(true); + double upper = Math.min(rangeBounds.getUpperBound(), rangeBounds.getLowerBound()*5); + if(upper == 0.0){ upper = 10000; } + yAxis.setRangeWithMargins(rangeBounds.getLowerBound(),upper); try { ChartUtilities.saveChartAsJPEG(new File(filename), chart, 1000, 600); @@ -143,9 +145,9 @@ public class AlgorithmSearchProgressChartListener implements IterationEndsListen double best = Double.MAX_VALUE; double sum = 0.0; for(VehicleRoutingProblemSolution sol : solutions){ - if(sol.getCost() > worst) worst = sol.getCost(); + if(sol.getCost() > worst) worst = Math.min(sol.getCost(),Double.MAX_VALUE); if(sol.getCost() < best) best = sol.getCost(); - sum += sol.getCost(); + sum += Math.min(sol.getCost(),Double.MAX_VALUE); } bestResultList.add(best); worstResultList.add(worst); diff --git a/jsprit-core/src/main/java/algorithms/ActivityInsertionCostsCalculator.java b/jsprit-core/src/main/java/algorithms/ActivityInsertionCostsCalculator.java index 4a72322b..bed0a9c5 100644 --- a/jsprit-core/src/main/java/algorithms/ActivityInsertionCostsCalculator.java +++ b/jsprit-core/src/main/java/algorithms/ActivityInsertionCostsCalculator.java @@ -22,9 +22,9 @@ package algorithms; import basics.route.TourActivity; -interface ActivityInsertionCostsCalculator { +public interface ActivityInsertionCostsCalculator { - class ActivityInsertionCosts { + public class ActivityInsertionCosts { private double additionalCosts; private double additionalTime; @@ -50,6 +50,6 @@ interface ActivityInsertionCostsCalculator { } - ActivityInsertionCosts calculate(InsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct); + public ActivityInsertionCosts getCosts(InsertionContext iContext, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct); } diff --git a/jsprit-core/src/main/java/algorithms/AvgJobDistance.java b/jsprit-core/src/main/java/algorithms/AvgJobDistance.java index 0425aeca..eaa9c6a8 100644 --- a/jsprit-core/src/main/java/algorithms/AvgJobDistance.java +++ b/jsprit-core/src/main/java/algorithms/AvgJobDistance.java @@ -52,7 +52,7 @@ class AvgJobDistance implements JobDistance { *

If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs. */ @Override - public double calculateDistance(Job i, Job j) { + public double getDistance(Job i, Job j) { if (i.equals(j)) return 0.0; if (i instanceof Service && j instanceof Service) { diff --git a/jsprit-core/src/main/java/algorithms/BestInsertion.java b/jsprit-core/src/main/java/algorithms/BestInsertion.java index ca3f8241..d86173ba 100644 --- a/jsprit-core/src/main/java/algorithms/BestInsertion.java +++ b/jsprit-core/src/main/java/algorithms/BestInsertion.java @@ -42,6 +42,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(); @@ -56,7 +78,7 @@ final class BestInsertion implements InsertionStrategy{ private Inserter inserter; - private JobInsertionCalculator bestInsertionCostCalculator; + private JobInsertionCostsCalculator bestInsertionCostCalculator; private boolean minVehiclesFirst = false; @@ -64,7 +86,7 @@ final class BestInsertion implements InsertionStrategy{ this.random = random; } - public BestInsertion(JobInsertionCalculator jobInsertionCalculator) { + public BestInsertion(JobInsertionCostsCalculator jobInsertionCalculator) { super(); this.insertionsListeners = new InsertionListeners(); inserter = new Inserter(insertionsListeners); @@ -86,7 +108,7 @@ final class BestInsertion implements InsertionStrategy{ Insertion bestInsertion = null; double bestInsertionCost = Double.MAX_VALUE; for(VehicleRoute vehicleRoute : vehicleRoutes){ - InsertionData iData = bestInsertionCostCalculator.calculate(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost); + InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost); if(iData instanceof NoInsertionFound) { continue; } @@ -97,7 +119,7 @@ final class BestInsertion implements InsertionStrategy{ } if(!minVehiclesFirst){ VehicleRoute newRoute = VehicleRoute.emptyRoute(); - InsertionData newIData = bestInsertionCostCalculator.calculate(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost); + InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost); if(newIData.getInsertionCost() < bestInsertionCost){ bestInsertion = new Insertion(newRoute,newIData); bestInsertionCost = newIData.getInsertionCost(); @@ -106,7 +128,7 @@ final class BestInsertion implements InsertionStrategy{ } if(bestInsertion == null){ VehicleRoute newRoute = VehicleRoute.emptyRoute(); - InsertionData bestI = bestInsertionCostCalculator.calculate(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE); + InsertionData bestI = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE); if(bestI instanceof InsertionData.NoInsertionFound){ throw new IllegalStateException(getErrorMsg(unassignedJob)); } diff --git a/jsprit-core/src/main/java/algorithms/BestInsertionBuilder.java b/jsprit-core/src/main/java/algorithms/BestInsertionBuilder.java new file mode 100644 index 00000000..b13773ff --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/BestInsertionBuilder.java @@ -0,0 +1,129 @@ +package algorithms; + +import java.util.ArrayList; +import java.util.List; + +import basics.VehicleRoutingProblem; +import basics.VehicleRoutingProblem.Constraint; +import basics.algo.InsertionListener; +import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener; +import basics.route.VehicleFleetManager; + +public class BestInsertionBuilder implements InsertionStrategyBuilder{ + + private VehicleRoutingProblem vrp; + + private StateManager stateManager; + + private boolean local = true; + + private ConstraintManager constraintManager; + + private VehicleFleetManager fleetManager; + + private double weightOfFixedCosts; + + private boolean considerFixedCosts = false; + + private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null; + + private int forwaredLooking; + + private int memory; + + public BestInsertionBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager) { + super(); + this.vrp = vrp; + this.stateManager = stateManager; + this.constraintManager = new ConstraintManager(); + this.fleetManager = vehicleFleetManager; + addCoreStateUpdaters(); + } + + private void addCoreStateUpdaters(){ + stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager)); + stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager)); + + stateManager.addActivityVisitor(new UpdateMaxLoad(stateManager)); + stateManager.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts())); + stateManager.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); + } + + public BestInsertionBuilder addHardLoadConstraints(){ + constraintManager.addConstraint(new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager)); + if(vrp.getProblemConstraints().contains(Constraint.DELIVERIES_FIRST)){ + constraintManager.addConstraint(new HardPickupAndDeliveryBackhaulActivityLevelConstraint(stateManager)); + } + else{ + constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager)); + } + stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager)); + stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager)); + return this; + } + + public BestInsertionBuilder addHardTimeWindowConstraint(){ + constraintManager.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts())); +// stateManager.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, vrp.getTransportCosts())); + stateManager.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); + return this; + } + + + public BestInsertionBuilder addConstraint(HardActivityLevelConstraint hardActvitiyLevelConstraint){ + constraintManager.addConstraint(hardActvitiyLevelConstraint); + return this; + }; + + public BestInsertionBuilder addConstraint(HardRouteLevelConstraint hardRouteLevelConstraint){ + constraintManager.addConstraint(hardRouteLevelConstraint); + return this; + }; + + public void setRouteLevel(int forwardLooking, int memory){ + local = false; + this.forwaredLooking = forwardLooking; + this.memory = memory; + }; + + public BestInsertionBuilder setLocalLevel(){ + local = true; + return this; + }; + + public BestInsertionBuilder considerFixedCosts(double weightOfFixedCosts){ + this.weightOfFixedCosts = weightOfFixedCosts; + this.considerFixedCosts = true; + return this; + } + + public void setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){ + this.actInsertionCostsCalculator = activityInsertionCostsCalculator; + }; + + @Override + public InsertionStrategy build() { + List iListeners = new ArrayList(); + List algorithmListeners = new ArrayList(); + CalculatorBuilder calcBuilder = new CalculatorBuilder(iListeners, algorithmListeners); + if(local){ + calcBuilder.setLocalLevel(); + } + else { + calcBuilder.setRouteLevel(forwaredLooking, memory); + } + calcBuilder.setConstraintManager(constraintManager); + calcBuilder.setStates(stateManager); + calcBuilder.setVehicleRoutingProblem(vrp); + calcBuilder.setVehicleFleetManager(fleetManager); + calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator); + if(considerFixedCosts) { + calcBuilder.considerFixedCosts(weightOfFixedCosts); + } + JobInsertionCostsCalculator jobInsertions = calcBuilder.build(); + BestInsertion bestInsertion = new BestInsertion(jobInsertions); + for(InsertionListener l : iListeners) bestInsertion.addListener(l); + return bestInsertion; + } + +} diff --git a/jsprit-core/src/main/java/algorithms/BestInsertionStrategyFactory.java b/jsprit-core/src/main/java/algorithms/BestInsertionStrategyFactory.java new file mode 100644 index 00000000..beb92f46 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/BestInsertionStrategyFactory.java @@ -0,0 +1,19 @@ +package algorithms; + +import basics.VehicleRoutingProblem; + +public class BestInsertionStrategyFactory implements InsertionStrategyFactory{ + + private JobInsertionCostsCalculator jobInsertionCalculator; + + public BestInsertionStrategyFactory(JobInsertionCostsCalculator jobInsertionCalculator) { + super(); + this.jobInsertionCalculator = jobInsertionCalculator; + } + + @Override + public InsertionStrategy createStrategy(VehicleRoutingProblem vrp) { + return new BestInsertion(jobInsertionCalculator); + } + +} diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTimeScheduling.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTimeScheduling.java index b96999ec..f8ef9064 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTimeScheduling.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTimeScheduling.java @@ -27,11 +27,11 @@ import basics.route.Driver; import basics.route.Vehicle; import basics.route.VehicleRoute; -class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalculator{ +class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{ private static Logger log = Logger.getLogger(CalculatesServiceInsertionWithTimeScheduling.class); - private JobInsertionCalculator jic; + private JobInsertionCostsCalculator jic; private Random random = new Random(); @@ -39,7 +39,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul private double timeSlice = 900.0; - public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCalculator jic, double timeSlice, int neighbors) { + public CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double timeSlice, int neighbors) { super(); this.jic = jic; this.timeSlice = timeSlice; @@ -53,7 +53,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul } @Override - public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) { + public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore) { List vehicleDepartureTimes = new ArrayList(); double currentStart; if(currentRoute.getStart() == null){ @@ -74,7 +74,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCalcul InsertionData bestIData = null; for(Double departureTime : vehicleDepartureTimes){ - InsertionData iData = jic.calculate(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore); + InsertionData iData = jic.getInsertionData(currentRoute, jobToInsert, newVehicle, departureTime, newDriver, bestKnownScore); if(bestIData == null) bestIData = iData; else if(iData.getInsertionCost() < bestIData.getInsertionCost()){ iData.setVehicleDepartureTime(departureTime); diff --git a/jsprit-core/src/main/java/algorithms/CalculationUtils.java b/jsprit-core/src/main/java/algorithms/CalculationUtils.java new file mode 100644 index 00000000..d584578c --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/CalculationUtils.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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 basics.route.TourActivity; + +class CalculationUtils { + + + /** + * Calculates actEndTime assuming that activity can at earliest start at act.getTheoreticalEarliestOperationStartTime(). + * + * @param actArrTime + * @param act + * @return + */ + 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 47be6346..612977cb 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java +++ b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java @@ -19,10 +19,10 @@ package algorithms; import java.util.ArrayList; import java.util.List; -import algorithms.HardConstraints.ConstraintManager; import basics.VehicleRoutingProblem; import basics.algo.InsertionListener; import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener; +import basics.route.VehicleFleetManager; @@ -30,16 +30,16 @@ class CalculatorBuilder { private static class CalculatorPlusListeners { - private JobInsertionCalculator calculator; + private JobInsertionCostsCalculator calculator; - public JobInsertionCalculator getCalculator() { + public JobInsertionCostsCalculator getCalculator() { return calculator; } private List algorithmListener = new ArrayList(); private List insertionListener = new ArrayList(); - public CalculatorPlusListeners(JobInsertionCalculator calculator) { + public CalculatorPlusListeners(JobInsertionCostsCalculator calculator) { super(); this.calculator = calculator; } @@ -59,7 +59,7 @@ class CalculatorBuilder { private VehicleRoutingProblem vrp; - private StateManager states; + private StateGetter states; private boolean local = true; @@ -80,6 +80,8 @@ class CalculatorBuilder { private int neighbors; private ConstraintManager constraintManager; + + private ActivityInsertionCostsCalculator activityInsertionCostCalculator = null; /** * Constructs the builder. @@ -102,7 +104,7 @@ class CalculatorBuilder { * * @return */ - public CalculatorBuilder setStates(StateManager states){ + public CalculatorBuilder setStates(StateGetter states){ this.states = states; return this; } @@ -137,6 +139,10 @@ class CalculatorBuilder { public void setLocalLevel(){ local = true; } + + public void setActivityInsertionCostsCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator){ + this.activityInsertionCostCalculator = activityInsertionCostsCalculator; + } /** * Sets a flag to build a calculator that evaluates job insertion on route-level. @@ -173,11 +179,11 @@ class CalculatorBuilder { * @return jobInsertionCalculator. * @throws IllegalStateException if vrp == null or activityStates == null or fleetManager == null. */ - public JobInsertionCalculator build(){ + public JobInsertionCostsCalculator build(){ if(vrp == null) throw new IllegalStateException("vehicle-routing-problem is null, but it must be set (this.setVehicleRoutingProblem(vrp))"); if(states == null) throw new IllegalStateException("states is null, but is must be set (this.setStates(states))"); if(fleetManager == null) throw new IllegalStateException("fleetManager is null, but it must be set (this.setVehicleFleetManager(fleetManager))"); - JobInsertionCalculator baseCalculator = null; + JobInsertionCostsCalculator baseCalculator = null; CalculatorPlusListeners standardLocal = null; if(local){ standardLocal = createStandardLocal(vrp, states); @@ -212,40 +218,58 @@ class CalculatorBuilder { } } - private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager statesManager){ + private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateGetter statesManager){ if(constraintManager == null) throw new IllegalStateException("constraint-manager is null"); - ActivityInsertionCostsCalculator defaultCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager); - JobInsertionCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), defaultCalc, constraintManager); - +//<<<<<<< HEAD +// ActivityInsertionCostsCalculator defaultCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager); +// JobInsertionCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), defaultCalc, constraintManager); +// +//======= + ActivityInsertionCostsCalculator actInsertionCalc; + if(activityInsertionCostCalculator == null){ + actInsertionCalc = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts()); + } + else{ + actInsertionCalc = activityInsertionCostCalculator; + } + + JobInsertionCostsCalculator standardServiceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), actInsertionCalc, constraintManager, constraintManager); +//>>>>>>> refs/remotes/choose_remote_name/relaxAPI ((ServiceInsertionCalculator) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood()); CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion); return calcPlusListeners; } - private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCalculator baseCalculator, StateManager activityStates2, double weightOfFixedCosts){ - final CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(baseCalculator, activityStates2); + private CalculatorPlusListeners createCalculatorConsideringFixedCosts(VehicleRoutingProblem vrp, JobInsertionCostsCalculator baseCalculator, StateGetter activityStates2, double weightOfFixedCosts){ + final JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(baseCalculator, activityStates2); withFixCost.setWeightOfFixCost(weightOfFixedCosts); CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(withFixCost); calcPlusListeners.getInsertionListener().add(new ConfigureFixCostCalculator(vrp, withFixCost)); return calcPlusListeners; } - private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateManager activityStates2, int forwardLooking, int solutionMemory){ + private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateGetter activityStates2, int forwardLooking, int solutionMemory){ int after = forwardLooking; - ActivityInsertionCostsCalculator routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, activityStates2); - JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts(), constraintManager, routeLevelCostEstimator); - ((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNuOfActsForwardLooking(after); - ((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setMemorySize(solutionMemory); - ((CalculatesServiceInsertionOnRouteLevel)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood()); - ((CalculatesServiceInsertionOnRouteLevel) jobInsertionCalculator).setStates(activityStates2); + ActivityInsertionCostsCalculator routeLevelCostEstimator; + if(activityInsertionCostCalculator == null){ + routeLevelCostEstimator = new RouteLevelActivityInsertionCostsEstimator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityStates2); + } + else{ + routeLevelCostEstimator = activityInsertionCostCalculator; + } + JobInsertionCostsCalculator jobInsertionCalculator = new ServiceInsertionOnRouteLevelCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), routeLevelCostEstimator, constraintManager, constraintManager); + ((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNuOfActsForwardLooking(after); + ((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setMemorySize(solutionMemory); + ((ServiceInsertionOnRouteLevelCalculator)jobInsertionCalculator).setNeighborhood(vrp.getNeighborhood()); + ((ServiceInsertionOnRouteLevelCalculator) jobInsertionCalculator).setStates(activityStates2); CalculatorPlusListeners calcPlusListener = new CalculatorPlusListeners(jobInsertionCalculator); return calcPlusListener; } - private JobInsertionCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCalculator baseCalc, StateManager activityStates2){ - return new CalculatesVehTypeDepServiceInsertion(fleetManager, baseCalc); + private JobInsertionCostsCalculator createFinalInsertion(VehicleFleetManager fleetManager, JobInsertionCostsCalculator baseCalc, StateGetter activityStates2){ + return new VehicleTypeDependentJobInsertionCalculator(fleetManager, baseCalc); } public void setConstraintManager(ConstraintManager constraintManager) { diff --git a/jsprit-core/src/main/java/algorithms/ConfigureFixCostCalculator.java b/jsprit-core/src/main/java/algorithms/ConfigureFixCostCalculator.java index 80b06a15..ed9fb977 100644 --- a/jsprit-core/src/main/java/algorithms/ConfigureFixCostCalculator.java +++ b/jsprit-core/src/main/java/algorithms/ConfigureFixCostCalculator.java @@ -37,11 +37,11 @@ final class ConfigureFixCostCalculator implements InsertionStartsListener, JobIn VehicleRoutingProblem vrp; - CalculatesServiceInsertionConsideringFixCost calcConsideringFix; + JobInsertionConsideringFixCostsCalculator calcConsideringFix; private int nuOfJobsToRecreate; - public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, CalculatesServiceInsertionConsideringFixCost calcConsideringFix) { + public ConfigureFixCostCalculator(VehicleRoutingProblem vrp, JobInsertionConsideringFixCostsCalculator calcConsideringFix) { super(); this.vrp = vrp; this.calcConsideringFix = calcConsideringFix; diff --git a/jsprit-core/src/main/java/algorithms/ConstraintManager.java b/jsprit-core/src/main/java/algorithms/ConstraintManager.java new file mode 100644 index 00000000..d7713776 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/ConstraintManager.java @@ -0,0 +1,29 @@ +package algorithms; + +import basics.route.TourActivity; + +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 ConstraintsStatus 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/EuclideanServiceDistance.java b/jsprit-core/src/main/java/algorithms/EuclideanServiceDistance.java index 5dc11af3..0f4641b3 100644 --- a/jsprit-core/src/main/java/algorithms/EuclideanServiceDistance.java +++ b/jsprit-core/src/main/java/algorithms/EuclideanServiceDistance.java @@ -27,7 +27,7 @@ class EuclideanServiceDistance implements JobDistance { } @Override - public double calculateDistance(Job i, Job j) { + public double getDistance(Job i, Job j) { double avgCost = 0.0; if (i instanceof Service && j instanceof Service) { if (i.equals(j)) { diff --git a/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java b/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java index 7354398c..abbfb90a 100644 --- a/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java +++ b/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java @@ -24,6 +24,7 @@ import org.apache.log4j.Logger; import basics.route.TourActivities; import basics.route.TourActivity; import basics.route.Vehicle; +import basics.route.VehicleFleetManager; import basics.route.VehicleImpl.NoVehicle; import basics.route.VehicleRoute; @@ -41,13 +42,13 @@ final class FindCheaperVehicleAlgo { private double weightFixCosts = 1.0; - private StateManager states; + private StateGetter states; public void setWeightFixCosts(double weightFixCosts) { this.weightFixCosts = weightFixCosts; } - public void setStates(StateManager states) { + public void setStates(StateGetter states) { this.states = states; } @@ -79,11 +80,11 @@ final class FindCheaperVehicleAlgo { if(vehicle.getType().getTypeId().equals(vehicleRoute.getVehicle().getType().getTypeId())){ continue; } - if(states.getRouteState(vehicleRoute,StateTypes.LOAD).toDouble() <= vehicle.getCapacity()){ + if(states.getRouteState(vehicleRoute,StateFactory.LOAD).toDouble() <= vehicle.getCapacity()){ double fixCostSaving = vehicleRoute.getVehicle().getType().getVehicleCostParams().fix - vehicle.getType().getVehicleCostParams().fix; double departureTime = vehicleRoute.getStart().getEndTime(); double newCost = auxilliaryCostCalculator.costOfPath(path, departureTime, vehicleRoute.getDriver(), vehicle); - double varCostSaving = states.getRouteState(vehicleRoute, StateTypes.COSTS).toDouble() - newCost; + double varCostSaving = states.getRouteState(vehicleRoute, StateFactory.COSTS).toDouble() - newCost; double totalCostSaving = varCostSaving + weightFixCosts*fixCostSaving; if(totalCostSaving > bestSaving){ bestSaving = totalCostSaving; diff --git a/jsprit-core/src/main/java/algorithms/Gendreau.java b/jsprit-core/src/main/java/algorithms/Gendreau.java index 951314ff..7c46473d 100644 --- a/jsprit-core/src/main/java/algorithms/Gendreau.java +++ b/jsprit-core/src/main/java/algorithms/Gendreau.java @@ -28,14 +28,15 @@ import java.util.Set; import org.apache.log4j.Logger; import util.RandomNumberGeneration; -import algorithms.RuinStrategy.RuinListener; import basics.Job; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblemSolution; import basics.algo.InsertionListener; +import basics.algo.RuinListener; import basics.algo.SearchStrategyModule; import basics.algo.SearchStrategyModuleListener; import basics.route.TourActivity; +import basics.route.VehicleFleetManager; import basics.route.TourActivity.JobActivity; import basics.route.VehicleRoute; diff --git a/jsprit-core/src/main/java/algorithms/HardActivityLevelConstraint.java b/jsprit-core/src/main/java/algorithms/HardActivityLevelConstraint.java new file mode 100644 index 00000000..fc3e878c --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardActivityLevelConstraint.java @@ -0,0 +1,15 @@ +package algorithms; + +import basics.route.TourActivity; + +public interface HardActivityLevelConstraint { + + static enum ConstraintsStatus { + + NOT_FULFILLED_BREAK, NOT_FULFILLED, FULFILLED; + + } + + public ConstraintsStatus 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/HardActivityLevelConstraintManager.java b/jsprit-core/src/main/java/algorithms/HardActivityLevelConstraintManager.java new file mode 100644 index 00000000..da5dc409 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardActivityLevelConstraintManager.java @@ -0,0 +1,27 @@ +package algorithms; + +import java.util.ArrayList; +import java.util.Collection; + +import basics.route.TourActivity; + +class HardActivityLevelConstraintManager implements HardActivityLevelConstraint { + + private Collection hardConstraints = new ArrayList(); + + public void addConstraint(HardActivityLevelConstraint constraint){ + hardConstraints.add(constraint); + } + + @Override + public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + for(HardActivityLevelConstraint constraint : hardConstraints){ + ConstraintsStatus status = constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime); + if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK) || status.equals(ConstraintsStatus.NOT_FULFILLED)){ + return status; + } + } + return ConstraintsStatus.FULFILLED; + } + +} \ No newline at end of file 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 1fc26fd5..00000000 --- a/jsprit-core/src/main/java/algorithms/HardConstraints.java +++ /dev/null @@ -1,382 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -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.DeliverService; -import basics.route.DeliverShipment; -import basics.route.DeliveryActivity; -import basics.route.PickupActivity; -import basics.route.PickupService; -import basics.route.PickupShipment; -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; - - private boolean backhaul = false; - - public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager) { - super(); - this.stateManager = stateManager; - } - - public HardPickupAndDeliveryActivityLevelConstraint(StateManager stateManager, boolean backhaul) { - super(); - this.stateManager = stateManager; - this.backhaul = backhaul; - } - - @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { - if(!(newAct instanceof PickupService) && !(newAct instanceof DeliverService)){ - return true; - } - if(backhaul){ - if(newAct instanceof PickupService && nextAct instanceof DeliverService){ return false; } - if(newAct instanceof DeliverService && prevAct instanceof PickupService){ 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 PickupService){ - if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){ - return false; - } - } - if(newAct instanceof DeliverService){ - if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){ - return false; - } - - } - return true; - } - - } - - static class HardPickupAndDeliveryShipmentActivityLevelConstraint implements HardActivityLevelConstraint { - - private StateManager stateManager; - - private boolean backhaul = false; - - public HardPickupAndDeliveryShipmentActivityLevelConstraint(StateManager stateManager) { - super(); - this.stateManager = stateManager; - } - - public HardPickupAndDeliveryShipmentActivityLevelConstraint(StateManager stateManager, boolean backhaul) { - super(); - this.stateManager = stateManager; - this.backhaul = backhaul; - } - - @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { - if(!(newAct instanceof PickupShipment) && !(newAct instanceof DeliverShipment)){ - return true; - } - if(backhaul){ -// if(newAct instanceof PickupShipment && nextAct instanceof DeliverShipment){ return false; } - if(newAct instanceof DeliverShipment && prevAct instanceof PickupShipment){ 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 PickupShipment){ - if(loadAtPrevAct + newAct.getCapacityDemand() > iFacts.getNewVehicle().getCapacity()){ - return false; - } - } - if(newAct instanceof DeliverShipment){ - if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) > 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 PickupService && nextAct instanceof DeliverService){ return false; } -// if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return false; } - if(newAct instanceof DeliverService && prevAct instanceof PickupService){ 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/HardLoadConstraint.java b/jsprit-core/src/main/java/algorithms/HardLoadConstraint.java new file mode 100644 index 00000000..0cc1dbd2 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardLoadConstraint.java @@ -0,0 +1,23 @@ +package algorithms; + +import basics.Service; + +class HardLoadConstraint implements HardRouteLevelConstraint{ + + private StateGetter states; + + public HardLoadConstraint(StateGetter states) { + super(); + this.states = states; + } + + @Override + public boolean fulfilled(InsertionContext insertionContext) { + int currentLoad = (int) states.getRouteState(insertionContext.getRoute(), StateFactory.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/HardPickupAndDeliveryActivityLevelConstraint.java b/jsprit-core/src/main/java/algorithms/HardPickupAndDeliveryActivityLevelConstraint.java new file mode 100644 index 00000000..f7b9e06c --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardPickupAndDeliveryActivityLevelConstraint.java @@ -0,0 +1,47 @@ +package algorithms; + +import basics.route.DeliveryActivity; +import basics.route.PickupActivity; +import basics.route.ServiceActivity; +import basics.route.Start; +import basics.route.TourActivity; + +class HardPickupAndDeliveryActivityLevelConstraint implements HardActivityLevelConstraint { + + private StateGetter stateManager; + + public HardPickupAndDeliveryActivityLevelConstraint(StateGetter stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public ConstraintsStatus 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(), StateFactory.LOAD_AT_BEGINNING).toDouble(); + futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_END).toDouble(); + pastDeliveries = 0; + } + else{ + loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateFactory.LOAD).toDouble(); + futurePicks = (int) stateManager.getActivityState(prevAct, StateFactory.FUTURE_PICKS).toDouble(); + pastDeliveries = (int) stateManager.getActivityState(prevAct, StateFactory.PAST_DELIVERIES).toDouble(); + } + if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){ + if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){ + return ConstraintsStatus.NOT_FULFILLED; + } + } + if(newAct instanceof DeliveryActivity){ + if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){ + return ConstraintsStatus.NOT_FULFILLED; + } + + } + return ConstraintsStatus.FULFILLED; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/HardPickupAndDeliveryBackhaulActivityLevelConstraint.java b/jsprit-core/src/main/java/algorithms/HardPickupAndDeliveryBackhaulActivityLevelConstraint.java new file mode 100644 index 00000000..007912f2 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardPickupAndDeliveryBackhaulActivityLevelConstraint.java @@ -0,0 +1,51 @@ +package algorithms; + +import basics.route.DeliveryActivity; +import basics.route.PickupActivity; +import basics.route.ServiceActivity; +import basics.route.Start; +import basics.route.TourActivity; + +class HardPickupAndDeliveryBackhaulActivityLevelConstraint implements HardActivityLevelConstraint { + + private StateGetter stateManager; + + public HardPickupAndDeliveryBackhaulActivityLevelConstraint(StateGetter stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + if(newAct instanceof PickupActivity && nextAct instanceof DeliveryActivity){ return ConstraintsStatus.NOT_FULFILLED; } + if(newAct instanceof ServiceActivity && nextAct instanceof DeliveryActivity){ return ConstraintsStatus.NOT_FULFILLED; } + if(newAct instanceof DeliveryActivity && prevAct instanceof PickupActivity){ return ConstraintsStatus.NOT_FULFILLED; } + if(newAct instanceof DeliveryActivity && prevAct instanceof ServiceActivity){ return ConstraintsStatus.NOT_FULFILLED; } + int loadAtPrevAct; + int futurePicks; + int pastDeliveries; + if(prevAct instanceof Start){ + loadAtPrevAct = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_BEGINNING).toDouble(); + futurePicks = (int)stateManager.getRouteState(iFacts.getRoute(), StateFactory.LOAD_AT_END).toDouble(); + pastDeliveries = 0; + } + else{ + loadAtPrevAct = (int) stateManager.getActivityState(prevAct, StateFactory.LOAD).toDouble(); + futurePicks = (int) stateManager.getActivityState(prevAct, StateFactory.FUTURE_PICKS).toDouble(); + pastDeliveries = (int) stateManager.getActivityState(prevAct, StateFactory.PAST_DELIVERIES).toDouble(); + } + if(newAct instanceof PickupActivity || newAct instanceof ServiceActivity){ + if(loadAtPrevAct + newAct.getCapacityDemand() + futurePicks > iFacts.getNewVehicle().getCapacity()){ + return ConstraintsStatus.NOT_FULFILLED; + } + } + if(newAct instanceof DeliveryActivity){ + if(loadAtPrevAct + Math.abs(newAct.getCapacityDemand()) + pastDeliveries > iFacts.getNewVehicle().getCapacity()){ + return ConstraintsStatus.NOT_FULFILLED; + } + + } + return ConstraintsStatus.FULFILLED; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/HardPickupAndDeliveryLoadRouteLevelConstraint.java b/jsprit-core/src/main/java/algorithms/HardPickupAndDeliveryLoadRouteLevelConstraint.java new file mode 100644 index 00000000..b5281620 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardPickupAndDeliveryLoadRouteLevelConstraint.java @@ -0,0 +1,39 @@ +package algorithms; + +import basics.Delivery; +import basics.Pickup; +import basics.Service; + +/** + * lsjdfjsdlfjsa + * + * @author stefan + * + */ +class HardPickupAndDeliveryLoadRouteLevelConstraint implements HardRouteLevelConstraint { + + private StateGetter stateManager; + + public HardPickupAndDeliveryLoadRouteLevelConstraint(StateGetter stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public boolean fulfilled(InsertionContext insertionContext) { + if(insertionContext.getJob() instanceof Delivery){ + int loadAtDepot = (int) stateManager.getRouteState(insertionContext.getRoute(), StateFactory.LOAD_AT_BEGINNING).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(), StateFactory.LOAD_AT_END).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/HardRouteLevelConstraint.java b/jsprit-core/src/main/java/algorithms/HardRouteLevelConstraint.java new file mode 100644 index 00000000..9cbd6258 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardRouteLevelConstraint.java @@ -0,0 +1,8 @@ +package algorithms; + + +public interface HardRouteLevelConstraint { + + public boolean fulfilled(InsertionContext insertionContext); + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/HardRouteLevelConstraintManager.java b/jsprit-core/src/main/java/algorithms/HardRouteLevelConstraintManager.java new file mode 100644 index 00000000..c9fe37fb --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardRouteLevelConstraintManager.java @@ -0,0 +1,25 @@ +package algorithms; + +import java.util.ArrayList; +import java.util.Collection; + + +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/HardTimeWindowActivityLevelConstraint.java b/jsprit-core/src/main/java/algorithms/HardTimeWindowActivityLevelConstraint.java new file mode 100644 index 00000000..137b0a81 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/HardTimeWindowActivityLevelConstraint.java @@ -0,0 +1,51 @@ +package algorithms; + +import org.apache.log4j.Logger; + +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.TourActivity; + +/** + * ljsljslfjs + * @author stefan + * + */ + class HardTimeWindowActivityLevelConstraint implements HardActivityLevelConstraint { + + private static Logger log = Logger.getLogger(HardTimeWindowActivityLevelConstraint.class); + + private StateGetter states; + + private VehicleRoutingTransportCosts routingCosts; + + public HardTimeWindowActivityLevelConstraint(StateGetter states, VehicleRoutingTransportCosts routingCosts) { + super(); + this.states = states; + this.routingCosts = routingCosts; + } + + @Override + public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + if(newAct.getTheoreticalLatestOperationStartTime() < prevAct.getTheoreticalEarliestOperationStartTime()){ + return ConstraintsStatus.NOT_FULFILLED_BREAK; + } + if(newAct.getTheoreticalEarliestOperationStartTime() > nextAct.getTheoreticalLatestOperationStartTime()){ + return ConstraintsStatus.NOT_FULFILLED; + } + // 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, StateFactory.LATEST_OPERATION_START_TIME).toDouble(); + + if(arrTimeAtNewAct > latestArrTimeAtNewAct){ + return ConstraintsStatus.NOT_FULFILLED; + } +// 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, StateFactory.LATEST_OPERATION_START_TIME).toDouble(); + if(arrTimeAtNextAct > latestArrTimeAtNextAct){ + return ConstraintsStatus.NOT_FULFILLED; + } + return ConstraintsStatus.FULFILLED; + } + } \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/InitialSolutionFactory.java b/jsprit-core/src/main/java/algorithms/InitialSolutionFactory.java index 1bc2e612..0942bddd 100644 --- a/jsprit-core/src/main/java/algorithms/InitialSolutionFactory.java +++ b/jsprit-core/src/main/java/algorithms/InitialSolutionFactory.java @@ -21,8 +21,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 150ea6cf..16c5c377 100644 --- a/jsprit-core/src/main/java/algorithms/InsertionContext.java +++ b/jsprit-core/src/main/java/algorithms/InsertionContext.java @@ -21,7 +21,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/InsertionData.java b/jsprit-core/src/main/java/algorithms/InsertionData.java index c06be526..e033684d 100644 --- a/jsprit-core/src/main/java/algorithms/InsertionData.java +++ b/jsprit-core/src/main/java/algorithms/InsertionData.java @@ -19,9 +19,14 @@ package algorithms; import basics.route.Driver; import basics.route.Vehicle; - - -class InsertionData { +/** + * Data object that collects insertion information. It collects insertionCosts, insertionIndeces, vehicle and driver to be employed + * and departureTime of vehicle at vehicle's start location (e.g. depot). + * + * @author stefan + * + */ +public class InsertionData { static class NoInsertionFound extends InsertionData{ @@ -33,7 +38,15 @@ class InsertionData { private static InsertionData noInsertion = new NoInsertionFound(); - public static InsertionData noInsertionFound(){ + /** + * Returns an instance of InsertionData that represents an EmptyInsertionData (which might indicate + * that no insertion has been found). It is internally instantiated as follows:
+ * new InsertionData(Double.MAX_VALUE, NO_INDEX, NO_INDEX, null, null);
+ * where NO_INDEX=-1. + * + * @return + */ + public static InsertionData createEmptyInsertionData(){ return noInsertion; } @@ -80,22 +93,47 @@ class InsertionData { return "[iCost="+insertionCost+"][iIndex="+deliveryInsertionIndex+"][depTime="+departureTime+"][vehicle="+selectedVehicle+"][driver="+selectedDriver+"]"; } + /** + * Returns insertionIndex of deliveryActivity. If no insertionPosition is found, it returns NO_INDEX (=-1). + * + * @return + */ public int getDeliveryInsertionIndex(){ return deliveryInsertionIndex; } + /** + * Returns insertionIndex of pickkupActivity. If no insertionPosition is found, it returns NO_INDEX (=-1). + * + * @return + */ public int getPickupInsertionIndex(){ return pickupInsertionIndex; } + /** + * Returns insertion costs (which might be the additional costs of inserting the corresponding job). + * + * @return + */ public double getInsertionCost() { return insertionCost; } + /** + * Returns the vehicle to be employed. + * + * @return + */ public Vehicle getSelectedVehicle() { return selectedVehicle; } + /** + * Returns the vehicle to be employed. + * + * @return + */ public Driver getSelectedDriver(){ return selectedDriver; } diff --git a/jsprit-core/src/main/java/algorithms/InsertionFactory.java b/jsprit-core/src/main/java/algorithms/InsertionFactory.java index 9dae4a80..64ec876e 100644 --- a/jsprit-core/src/main/java/algorithms/InsertionFactory.java +++ b/jsprit-core/src/main/java/algorithms/InsertionFactory.java @@ -23,19 +23,18 @@ import java.util.concurrent.ExecutorService; import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.log4j.Logger; -import algorithms.HardConstraints.ConstraintManager; import basics.VehicleRoutingProblem; import basics.algo.InsertionListener; import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener; +import basics.route.VehicleFleetManager; class InsertionFactory { private static Logger log = Logger.getLogger(InsertionFactory.class); 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; + VehicleFleetManager vehicleFleetManager, StateManager routeStates, List algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager){ + if(config.containsKey("[@name]")){ String insertionName = config.getString("[@name]"); if(!insertionName.equals("bestInsertion") && !insertionName.equals("regretInsertion")){ @@ -89,27 +88,14 @@ class InsertionFactory { calcBuilder.experimentalTimeScheduler(Double.parseDouble(timeSliceString),Integer.parseInt(neighbors)); } - JobInsertionCalculator jic = calcBuilder.build(); + JobInsertionCostsCalculator jic = calcBuilder.build(); 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/CreateInitialSolution.java b/jsprit-core/src/main/java/algorithms/InsertionInitialSolutionFactory.java similarity index 52% rename from jsprit-core/src/main/java/algorithms/CreateInitialSolution.java rename to jsprit-core/src/main/java/algorithms/InsertionInitialSolutionFactory.java index b2e9655b..39e990ce 100644 --- a/jsprit-core/src/main/java/algorithms/CreateInitialSolution.java +++ b/jsprit-core/src/main/java/algorithms/InsertionInitialSolutionFactory.java @@ -1,18 +1,14 @@ /******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder + * Copyright (c) 2011 Stefan Schroeder. + * eMail: stefan.schroeder@kit.edu * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v2.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . + * Contributors: + * Stefan Schroeder - initial API and implementation ******************************************************************************/ /* *********************************************************************** * * project: org.matsim.* @@ -45,48 +41,34 @@ import basics.Job; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblemSolution; import basics.algo.SolutionCostCalculator; -import basics.route.DriverImpl; -import basics.route.TourActivities; -import basics.route.Vehicle; import basics.route.VehicleRoute; -final class CreateInitialSolution implements InitialSolutionFactory { +public final class InsertionInitialSolutionFactory implements InitialSolutionFactory { - private static final Logger logger = Logger.getLogger(CreateInitialSolution.class); + private static final Logger logger = Logger.getLogger(InsertionInitialSolutionFactory.class); private final InsertionStrategy insertion; - - private SolutionCostCalculator solutionCostCalculator; - - private boolean generateAsMuchAsRoutesAsVehiclesExist = false; - - public void setGenerateAsMuchAsRoutesAsVehiclesExist(boolean generateAsMuchAsRoutesAsVehiclesExist) { - this.generateAsMuchAsRoutesAsVehiclesExist = generateAsMuchAsRoutesAsVehiclesExist; - } - public CreateInitialSolution(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) { + private SolutionCostCalculator solutionCostsCalculator; + + public InsertionInitialSolutionFactory(InsertionStrategy insertionStrategy, SolutionCostCalculator solutionCostCalculator) { super(); this.insertion = insertionStrategy; - this.solutionCostCalculator = solutionCostCalculator; + this.solutionCostsCalculator = solutionCostCalculator; } @Override - public VehicleRoutingProblemSolution createInitialSolution(final VehicleRoutingProblem vrp) { + public VehicleRoutingProblemSolution createSolution(final VehicleRoutingProblem vrp) { logger.info("create initial solution."); List vehicleRoutes = new ArrayList(); - if(generateAsMuchAsRoutesAsVehiclesExist){ - for(Vehicle vehicle : vrp.getVehicles()){ - vehicleRoutes.add(VehicleRoute.newInstance(TourActivities.emptyTour(), DriverImpl.noDriver(), vehicle)); - } - } insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp)); -// double totalCost = getTotalCost(vehicleRoutes); + VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, Double.MAX_VALUE); + double costs = solutionCostsCalculator.getCosts(solution); + solution.setCost(costs); logger.info("creation done"); - VehicleRoutingProblemSolution vehicleRoutingProblemSolution = new VehicleRoutingProblemSolution(vehicleRoutes, 0.0); - solutionCostCalculator.calculateCosts(vehicleRoutingProblemSolution); - return vehicleRoutingProblemSolution; + return solution; } private List getUnassignedJobs(VehicleRoutingProblem vrp) { diff --git a/jsprit-core/src/main/java/algorithms/InsertionStrategy.java b/jsprit-core/src/main/java/algorithms/InsertionStrategy.java index 239e1c61..17c84fad 100644 --- a/jsprit-core/src/main/java/algorithms/InsertionStrategy.java +++ b/jsprit-core/src/main/java/algorithms/InsertionStrategy.java @@ -31,33 +31,7 @@ import basics.route.VehicleRoute; * */ -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; - } - - } - - - - +public interface InsertionStrategy { /** * Assigns the unassigned jobs to service-providers diff --git a/jsprit-core/src/main/java/algorithms/InsertionStrategyBuilder.java b/jsprit-core/src/main/java/algorithms/InsertionStrategyBuilder.java new file mode 100644 index 00000000..04e34208 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/InsertionStrategyBuilder.java @@ -0,0 +1,7 @@ +package algorithms; + +public interface InsertionStrategyBuilder { + + public InsertionStrategy build(); + +} diff --git a/jsprit-core/src/main/java/algorithms/IterateRouteBackwardInTime.java b/jsprit-core/src/main/java/algorithms/IterateRouteBackwardInTime.java deleted file mode 100644 index 4204c943..00000000 --- a/jsprit-core/src/main/java/algorithms/IterateRouteBackwardInTime.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package algorithms; - -import java.util.Iterator; - -import org.apache.log4j.Logger; - -import algorithms.BackwardInTimeListeners.BackwardInTimeListener; -import basics.costs.BackwardTransportTime; -import basics.route.TourActivity; -import basics.route.VehicleRoute; - - -/** - * - * @author stefan schroeder - * - */ - -class IterateRouteBackwardInTime implements VehicleRouteUpdater{ - - private static Logger log = Logger.getLogger(IterateRouteBackwardInTime.class); - - private BackwardTransportTime transportTime; - - private BackwardInTimeListeners listeners; - - public IterateRouteBackwardInTime(BackwardTransportTime transportTime) { - super(); - this.transportTime = transportTime; - listeners = new BackwardInTimeListeners(); - } - - /* - * - */ - public void iterate(VehicleRoute vehicleRoute) { - if(listeners.isEmpty()) return; - if(vehicleRoute.isEmpty()) return; - listeners.start(vehicleRoute, vehicleRoute.getEnd(), vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime()); - - Iterator reverseActIter = vehicleRoute.getTourActivities().reverseActivityIterator(); - TourActivity prevAct; - prevAct = vehicleRoute.getEnd(); - double latestArrivalTimeAtPrevAct = prevAct.getTheoreticalLatestOperationStartTime(); - - while(reverseActIter.hasNext()){ - TourActivity currAct = reverseActIter.next(); - double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle()); - double potentialLatestArrivalTimeAtCurrAct = latestDepTimeAtCurrAct - currAct.getOperationTime(); - double latestArrivalTime = Math.min(currAct.getTheoreticalLatestOperationStartTime(), potentialLatestArrivalTimeAtCurrAct); - - listeners.prevActivity(currAct, latestDepTimeAtCurrAct, latestArrivalTime); - - prevAct = currAct; - latestArrivalTimeAtPrevAct = latestArrivalTime; - } - - TourActivity currAct = vehicleRoute.getStart(); - double latestDepTimeAtCurrAct = latestArrivalTimeAtPrevAct - transportTime.getBackwardTransportTime(currAct.getLocationId(), prevAct.getLocationId(), latestArrivalTimeAtPrevAct, vehicleRoute.getDriver(),vehicleRoute.getVehicle()); - - listeners.end(vehicleRoute.getStart(), latestDepTimeAtCurrAct); - } - - public void addListener(BackwardInTimeListener l){ listeners.addListener(l); } - -} diff --git a/jsprit-core/src/main/java/algorithms/IterateRouteForwardInTime.java b/jsprit-core/src/main/java/algorithms/IterateRouteForwardInTime.java deleted file mode 100644 index dd507fb6..00000000 --- a/jsprit-core/src/main/java/algorithms/IterateRouteForwardInTime.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package algorithms; - -import org.apache.log4j.Logger; - -import algorithms.ForwardInTimeListeners.ForwardInTimeListener; -import basics.costs.ForwardTransportTime; -import basics.route.Driver; -import basics.route.End; -import basics.route.TourActivity; -import basics.route.Vehicle; -import basics.route.VehicleRoute; - - -/** - * - * @author sschroeder - * - */ - -class IterateRouteForwardInTime implements VehicleRouteUpdater{ - - private static Logger log = Logger.getLogger(IterateRouteForwardInTime.class); - - private ForwardTransportTime transportTime; - - private ForwardInTimeListeners listeners; - - public IterateRouteForwardInTime(ForwardTransportTime transportTime) { - super(); - this.transportTime = transportTime; - listeners = new ForwardInTimeListeners(); - } - - /** - * - * - */ - public void iterate(VehicleRoute vehicleRoute) { - if(listeners.isEmpty()) return; - if(vehicleRoute.isEmpty()) return; - listeners.start(vehicleRoute, vehicleRoute.getStart(), vehicleRoute.getStart().getEndTime()); - - Vehicle vehicle = vehicleRoute.getVehicle(); - Driver driver = vehicleRoute.getDriver(); - TourActivity prevAct = vehicleRoute.getStart(); - double startAtPrevAct = prevAct.getEndTime(); - - for(TourActivity currentAct : vehicleRoute.getTourActivities().getActivities()){ - double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle); - double arrivalTimeAtCurrAct = startAtPrevAct + transportTime; - double operationStartTime = Math.max(currentAct.getTheoreticalEarliestOperationStartTime(), arrivalTimeAtCurrAct); - double operationEndTime = operationStartTime + currentAct.getOperationTime(); - - listeners.nextActivity(currentAct,arrivalTimeAtCurrAct,operationEndTime); - - prevAct = currentAct; - startAtPrevAct = operationEndTime; - } - - End currentAct = vehicleRoute.getEnd(); - double transportTime = this.transportTime.getTransportTime(prevAct.getLocationId(), currentAct.getLocationId(), startAtPrevAct, driver, vehicle); - double arrivalTimeAtCurrAct = startAtPrevAct + transportTime; - - listeners.end(vehicleRoute.getEnd(), arrivalTimeAtCurrAct); - } - - public void addListener(ForwardInTimeListener l){ - listeners.addListener(l); - } - -} diff --git a/jsprit-core/src/main/java/algorithms/JobCalculatorSwitcher.java b/jsprit-core/src/main/java/algorithms/JobCalculatorSwitcher.java index 617da19d..da3485b8 100644 --- a/jsprit-core/src/main/java/algorithms/JobCalculatorSwitcher.java +++ b/jsprit-core/src/main/java/algorithms/JobCalculatorSwitcher.java @@ -8,18 +8,18 @@ import basics.route.Driver; import basics.route.Vehicle; import basics.route.VehicleRoute; -public class JobCalculatorSwitcher implements JobInsertionCalculator{ +public class JobCalculatorSwitcher implements JobInsertionCostsCalculator{ - private Map,JobInsertionCalculator> calcMap = new HashMap, JobInsertionCalculator>(); + private Map,JobInsertionCostsCalculator> calcMap = new HashMap, JobInsertionCostsCalculator>(); - void put(Class jobClass, JobInsertionCalculator jic){ + void put(Class jobClass, JobInsertionCostsCalculator jic){ calcMap.put(jobClass, jic); } - public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore){ - JobInsertionCalculator jic = calcMap.get(jobToInsert.getClass()); + public InsertionData getInsertionData(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore){ + JobInsertionCostsCalculator jic = calcMap.get(jobToInsert.getClass()); if(jic==null) throw new IllegalStateException("cannot find calculator for " + jobToInsert.getClass()); - return jic.calculate(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownScore); + return jic.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownScore); } } diff --git a/jsprit-core/src/main/java/algorithms/JobDistance.java b/jsprit-core/src/main/java/algorithms/JobDistance.java index c8da4a72..3ac28dbe 100644 --- a/jsprit-core/src/main/java/algorithms/JobDistance.java +++ b/jsprit-core/src/main/java/algorithms/JobDistance.java @@ -20,8 +20,8 @@ import basics.Job; -interface JobDistance { +public interface JobDistance { - public double calculateDistance(Job i, Job j); + public double getDistance(Job i, Job j); } diff --git a/jsprit-core/src/main/java/algorithms/JobDistanceAvgCosts.java b/jsprit-core/src/main/java/algorithms/JobDistanceAvgCosts.java index f0ef7726..66194819 100644 --- a/jsprit-core/src/main/java/algorithms/JobDistanceAvgCosts.java +++ b/jsprit-core/src/main/java/algorithms/JobDistanceAvgCosts.java @@ -49,7 +49,7 @@ class JobDistanceAvgCosts implements JobDistance { *

If the distance between two jobs cannot be calculated with input-transport costs, it tries the euclidean distance between these jobs. */ @Override - public double calculateDistance(Job i, Job j) { + public double getDistance(Job i, Job j) { double avgCost = 0.0; if (i instanceof Service && j instanceof Service) { if (i.equals(j)) { @@ -76,7 +76,7 @@ class JobDistanceAvgCosts implements JobDistance { // now try the euclidean distance between these two services } EuclideanServiceDistance euclidean = new EuclideanServiceDistance(); - distance = euclidean.calculateDistance(s_i, s_j); + distance = euclidean.getDistance(s_i, s_j); return distance; } diff --git a/jsprit-core/src/main/java/algorithms/JobDistanceBeeline.java b/jsprit-core/src/main/java/algorithms/JobDistanceBeeline.java index 21c467b0..f4287639 100644 --- a/jsprit-core/src/main/java/algorithms/JobDistanceBeeline.java +++ b/jsprit-core/src/main/java/algorithms/JobDistanceBeeline.java @@ -33,7 +33,7 @@ class JobDistanceBeeline implements JobDistance { } @Override - public double calculateDistance(Job i, Job j) { + public double getDistance(Job i, Job j) { double avgCost = 0.0; if (i instanceof Service && j instanceof Service) { if (i.equals(j)) { diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java b/jsprit-core/src/main/java/algorithms/JobInsertionConsideringFixCostsCalculator.java similarity index 75% rename from jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java rename to jsprit-core/src/main/java/algorithms/JobInsertionConsideringFixCostsCalculator.java index 68fe3a66..87c70abb 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionConsideringFixCost.java +++ b/jsprit-core/src/main/java/algorithms/JobInsertionConsideringFixCostsCalculator.java @@ -27,35 +27,35 @@ import basics.route.VehicleRoute; -final class CalculatesServiceInsertionConsideringFixCost implements JobInsertionCalculator{ +final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCostsCalculator{ - private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionConsideringFixCost.class); + private static final Logger logger = Logger.getLogger(JobInsertionConsideringFixCostsCalculator.class); - private final JobInsertionCalculator standardServiceInsertion; + private final JobInsertionCostsCalculator standardServiceInsertion; private double weight_deltaFixCost = 0.5; private double solution_completeness_ratio = 0.5; - private StateManager states; + private StateGetter stateGetter; - public CalculatesServiceInsertionConsideringFixCost(final JobInsertionCalculator standardInsertionCalculator, StateManager activityStates2) { + public JobInsertionConsideringFixCostsCalculator(final JobInsertionCostsCalculator standardInsertionCalculator, StateGetter stateGetter) { super(); this.standardServiceInsertion = standardInsertionCalculator; - this.states = activityStates2; + this.stateGetter = stateGetter; logger.info("inialise " + this); } @Override - public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) { + public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownPrice) { double relFixCost = getDeltaRelativeFixCost(currentRoute, newVehicle, jobToInsert); double absFixCost = getDeltaAbsoluteFixCost(currentRoute, newVehicle, jobToInsert); double deltaFixCost = (1-solution_completeness_ratio)*relFixCost + solution_completeness_ratio*absFixCost; double fixcost_contribution = weight_deltaFixCost*solution_completeness_ratio*deltaFixCost; if(fixcost_contribution > bestKnownPrice){ - return InsertionData.noInsertionFound(); + return InsertionData.createEmptyInsertionData(); } - InsertionData iData = standardServiceInsertion.calculate(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice); + InsertionData iData = standardServiceInsertion.getInsertionData(currentRoute, jobToInsert, newVehicle, newVehicleDepartureTime, newDriver, bestKnownPrice); if(iData instanceof NoInsertionFound){ return iData; } @@ -80,7 +80,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion } private double getDeltaAbsoluteFixCost(VehicleRoute route, Vehicle newVehicle, Job job) { - double load = getCurrentLoad(route) + job.getCapacityDemand(); + double load = getCurrentMaxLoadInRoute(route) + job.getCapacityDemand(); double currentFix = 0.0; if(route.getVehicle() != null){ if(!(route.getVehicle() instanceof NoVehicle)){ @@ -94,7 +94,7 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion } private double getDeltaRelativeFixCost(VehicleRoute route, Vehicle newVehicle, Job job) { - int currentLoad = getCurrentLoad(route); + int currentLoad = getCurrentMaxLoadInRoute(route); double load = currentLoad + job.getCapacityDemand(); double currentRelFix = 0.0; if(route.getVehicle() != null){ @@ -109,8 +109,8 @@ final class CalculatesServiceInsertionConsideringFixCost implements JobInsertion return relativeFixCost; } - private int getCurrentLoad(VehicleRoute route) { - return (int) states.getRouteState(route, StateTypes.LOAD).toDouble(); + private int getCurrentMaxLoadInRoute(VehicleRoute route) { + return (int) stateGetter.getRouteState(route, StateFactory.MAXLOAD).toDouble(); } } diff --git a/jsprit-core/src/main/java/algorithms/JobInsertionCalculator.java b/jsprit-core/src/main/java/algorithms/JobInsertionCostsCalculator.java similarity index 82% rename from jsprit-core/src/main/java/algorithms/JobInsertionCalculator.java rename to jsprit-core/src/main/java/algorithms/JobInsertionCostsCalculator.java index a8f3376f..28f908dd 100644 --- a/jsprit-core/src/main/java/algorithms/JobInsertionCalculator.java +++ b/jsprit-core/src/main/java/algorithms/JobInsertionCostsCalculator.java @@ -22,8 +22,8 @@ import basics.route.Vehicle; import basics.route.VehicleRoute; - interface JobInsertionCalculator { + public interface JobInsertionCostsCalculator { - public InsertionData calculate(VehicleRoute currentRoute, Job jobToInsert, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownScore); + public InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts); } diff --git a/jsprit-core/src/main/java/algorithms/LocalActivityInsertionCostsCalculator.java b/jsprit-core/src/main/java/algorithms/LocalActivityInsertionCostsCalculator.java index 9dd9a20b..4aac5785 100644 --- a/jsprit-core/src/main/java/algorithms/LocalActivityInsertionCostsCalculator.java +++ b/jsprit-core/src/main/java/algorithms/LocalActivityInsertionCostsCalculator.java @@ -20,38 +20,42 @@ ******************************************************************************/ package algorithms; -import algorithms.HardConstraints.HardActivityLevelConstraint; import basics.costs.VehicleRoutingActivityCosts; import basics.costs.VehicleRoutingTransportCosts; import basics.route.TourActivity; +/** + * Calculates activity insertion costs locally, i.e. by comparing the additional costs of insertion the new activity k between + * activity i (prevAct) and j (nextAct). + * Additional costs are then basically calculated as delta c = c_ik + c_kj - c_ij. + * + *

Note once time has an effect on costs this class requires activity endTimes. + * + * @author stefan + * + */ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator{ - private HardActivityLevelConstraint hardConstraint; - private VehicleRoutingTransportCosts routingCosts; private VehicleRoutingActivityCosts activityCosts; - public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) { + + public LocalActivityInsertionCostsCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts) { super(); this.routingCosts = routingCosts; this.activityCosts = actCosts; - this.hardConstraint = hardActivityLevelConstraint; } @Override - public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) { - if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){ - return null; - } + public ActivityInsertionCosts getCosts(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) { double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle()); double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), depTimeAtPrevAct, iFacts.getNewDriver(), iFacts.getNewVehicle()); 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/NeighborhoodThresholdInitialiser.java b/jsprit-core/src/main/java/algorithms/NeighborhoodThresholdInitialiser.java index 60a293d4..a9abcdfe 100644 --- a/jsprit-core/src/main/java/algorithms/NeighborhoodThresholdInitialiser.java +++ b/jsprit-core/src/main/java/algorithms/NeighborhoodThresholdInitialiser.java @@ -35,7 +35,7 @@ import basics.algo.VehicleRoutingAlgorithmFactory; import basics.route.TourActivity; import basics.route.VehicleRoute; -public class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{ +class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{ private static Logger log = Logger.getLogger(NeighborhoodThresholdInitialiser.class); diff --git a/jsprit-core/src/main/java/algorithms/RadialRuinStrategyFactory.java b/jsprit-core/src/main/java/algorithms/RadialRuinStrategyFactory.java new file mode 100644 index 00000000..c541c4c9 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/RadialRuinStrategyFactory.java @@ -0,0 +1,22 @@ +package algorithms; + +import basics.VehicleRoutingProblem; + +public class RadialRuinStrategyFactory implements RuinStrategyFactory{ + + private double fraction; + + private JobDistance jobDistance; + + public RadialRuinStrategyFactory(double fraction, JobDistance jobDistance) { + super(); + this.fraction = fraction; + this.jobDistance = jobDistance; + } + + @Override + public RuinStrategy createStrategy(VehicleRoutingProblem vrp) { + return new RuinRadial(vrp,fraction,jobDistance); + } + +} diff --git a/jsprit-core/src/main/java/algorithms/RandomRuinStrategyFactory.java b/jsprit-core/src/main/java/algorithms/RandomRuinStrategyFactory.java new file mode 100644 index 00000000..5a32c9f2 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/RandomRuinStrategyFactory.java @@ -0,0 +1,19 @@ +package algorithms; + +import basics.VehicleRoutingProblem; + +public class RandomRuinStrategyFactory implements RuinStrategyFactory{ + + private double fraction; + + public RandomRuinStrategyFactory(double fraction) { + super(); + this.fraction = fraction; + } + + @Override + public RuinStrategy createStrategy(VehicleRoutingProblem vrp) { + return new RuinRandom(vrp, fraction); + } + +} diff --git a/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java b/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java index 6e069b90..28919048 100644 --- a/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java +++ b/jsprit-core/src/main/java/algorithms/RemoveEmptyVehicles.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.log4j.Logger; import basics.algo.InsertionEndsListener; +import basics.route.VehicleFleetManager; import basics.route.VehicleRoute; class RemoveEmptyVehicles implements InsertionEndsListener{ @@ -31,7 +32,7 @@ class RemoveEmptyVehicles implements InsertionEndsListener{ private VehicleFleetManager fleetManager; - RemoveEmptyVehicles(VehicleFleetManager fleetManager) { + public RemoveEmptyVehicles(VehicleFleetManager fleetManager) { super(); this.fleetManager = fleetManager; } diff --git a/jsprit-core/src/main/java/algorithms/ResetAndIniFleetManager.java b/jsprit-core/src/main/java/algorithms/ResetAndIniFleetManager.java index d03f255d..81c68738 100644 --- a/jsprit-core/src/main/java/algorithms/ResetAndIniFleetManager.java +++ b/jsprit-core/src/main/java/algorithms/ResetAndIniFleetManager.java @@ -23,6 +23,7 @@ import org.apache.log4j.Logger; import basics.Job; import basics.algo.InsertionStartsListener; +import basics.route.VehicleFleetManager; import basics.route.VehicleRoute; class ResetAndIniFleetManager implements InsertionStartsListener{ diff --git a/jsprit-core/src/main/java/algorithms/RouteLevelActivityInsertionCostsEstimator.java b/jsprit-core/src/main/java/algorithms/RouteLevelActivityInsertionCostsEstimator.java index 2daa5e63..adc9776f 100644 --- a/jsprit-core/src/main/java/algorithms/RouteLevelActivityInsertionCostsEstimator.java +++ b/jsprit-core/src/main/java/algorithms/RouteLevelActivityInsertionCostsEstimator.java @@ -23,7 +23,6 @@ package algorithms; import java.util.ArrayList; import java.util.List; -import algorithms.HardConstraints.HardActivityLevelConstraint; import basics.costs.VehicleRoutingActivityCosts; import basics.costs.VehicleRoutingTransportCosts; import basics.route.End; @@ -33,30 +32,23 @@ import basics.route.VehicleRoute; class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCostsCalculator{ - private HardActivityLevelConstraint hardConstraint; - private VehicleRoutingActivityCosts activityCosts; private AuxilliaryCostCalculator auxilliaryPathCostCalculator; - private StateManager stateManager; + private StateGetter stateManager; private int nuOfActivities2LookForward = 0; - public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint, StateManager stateManager) { + public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, StateGetter stateManager) { super(); this.activityCosts = actCosts; - this.hardConstraint = hardActivityLevelConstraint; this.stateManager = stateManager; auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts); } @Override - public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) { - if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){ - return null; - } - + public ActivityInsertionCosts getCosts(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) { List path = new ArrayList(); path.add(prevAct); path.add(newAct); path.add(nextAct); int actIndex; @@ -77,9 +69,9 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) { if(act instanceof End){ - return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(); + return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble(); } - return stateManager.getActivityState(act,StateTypes.COSTS).toDouble(); + return stateManager.getActivityState(act,StateFactory.COSTS).toDouble(); } private List getForwardLookingPath(VehicleRoute route, int actIndex) { diff --git a/jsprit-core/src/main/java/algorithms/RuinAndRecreateModule.java b/jsprit-core/src/main/java/algorithms/RuinAndRecreateModule.java index 73c6f3a5..53703592 100644 --- a/jsprit-core/src/main/java/algorithms/RuinAndRecreateModule.java +++ b/jsprit-core/src/main/java/algorithms/RuinAndRecreateModule.java @@ -18,14 +18,14 @@ package algorithms; import java.util.Collection; -import algorithms.RuinStrategy.RuinListener; import basics.Job; import basics.VehicleRoutingProblemSolution; import basics.algo.InsertionListener; +import basics.algo.RuinListener; import basics.algo.SearchStrategyModule; import basics.algo.SearchStrategyModuleListener; -class RuinAndRecreateModule implements SearchStrategyModule{ +public class RuinAndRecreateModule implements SearchStrategyModule{ private InsertionStrategy insertion; @@ -44,9 +44,8 @@ class RuinAndRecreateModule implements SearchStrategyModule{ public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) { Collection ruinedJobs = ruin.ruin(vrpSolution.getRoutes()); insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs); -// double totalCost = RouteUtils.getTotalCost(vrpSolution.getRoutes()); -// vrpSolution.setCost(totalCost); return vrpSolution; + } @Override diff --git a/jsprit-core/src/main/java/algorithms/RuinListeners.java b/jsprit-core/src/main/java/algorithms/RuinListeners.java deleted file mode 100644 index 1b0e18b4..00000000 --- a/jsprit-core/src/main/java/algorithms/RuinListeners.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package algorithms; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; - -import algorithms.RuinStrategy.RuinListener; -import basics.Job; -import basics.route.VehicleRoute; - -class RuinListeners { - - private Collection ruinListeners = new ArrayList(); - - void ruinStarts(Collection routes){ - for(RuinListener l : ruinListeners) l.ruinStarts(routes); - } - - void ruinEnds(Collection routes, Collection unassignedJobs){ - for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs); - } - - void removed(Job job, VehicleRoute fromRoute){ - for(RuinListener l : ruinListeners) l.removed(job, fromRoute); - } - - void addListener(RuinListener ruinListener){ - ruinListeners.add(ruinListener); - } - - void removeListener(RuinListener ruinListener){ - ruinListeners.remove(ruinListener); - } - - Collection getListeners(){ - return Collections.unmodifiableCollection(ruinListeners); - } -} diff --git a/jsprit-core/src/main/java/algorithms/RuinRadial.java b/jsprit-core/src/main/java/algorithms/RuinRadial.java index 330f6a1a..c0c0fffe 100644 --- a/jsprit-core/src/main/java/algorithms/RuinRadial.java +++ b/jsprit-core/src/main/java/algorithms/RuinRadial.java @@ -33,6 +33,8 @@ import util.RandomNumberGeneration; import util.StopWatch; import basics.Job; import basics.VehicleRoutingProblem; +import basics.algo.RuinListener; +import basics.algo.RuinListeners; import basics.route.VehicleRoute; @@ -120,7 +122,7 @@ final class RuinRadial implements RuinStrategy { }); distanceNodeTree.put(i.getId(), treeSet); for (Job j : vrp.getJobs().values()) { - double distance = jobDistance.calculateDistance(i, j); + double distance = jobDistance.getDistance(i, j); ReferencedJob refNode = new ReferencedJob(j, distance); treeSet.add(refNode); nuOfDistancesStored++; diff --git a/jsprit-core/src/main/java/algorithms/RuinRandom.java b/jsprit-core/src/main/java/algorithms/RuinRandom.java index da3ab873..bbe1b2c6 100644 --- a/jsprit-core/src/main/java/algorithms/RuinRandom.java +++ b/jsprit-core/src/main/java/algorithms/RuinRandom.java @@ -27,6 +27,8 @@ import org.apache.log4j.Logger; 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/RuinStrategy.java b/jsprit-core/src/main/java/algorithms/RuinStrategy.java index b06e932d..3f03b5dc 100644 --- a/jsprit-core/src/main/java/algorithms/RuinStrategy.java +++ b/jsprit-core/src/main/java/algorithms/RuinStrategy.java @@ -19,6 +19,7 @@ package algorithms; import java.util.Collection; import basics.Job; +import basics.algo.RuinListener; import basics.route.VehicleRoute; @@ -30,41 +31,8 @@ import basics.route.VehicleRoute; * */ -interface RuinStrategy { +public interface RuinStrategy { - /** - * Listener that listens to the ruin-process. It informs whoever is interested about start, end and about a removal of a job. - * - * @author schroeder - * - */ - public static interface RuinListener { - - /** - * informs about ruin-start. - * - * @param routes - */ - public void ruinStarts(Collection routes); - - /** - * informs about ruin-end. - * - * @param routes - * @param unassignedJobs - */ - public void ruinEnds(Collection routes, Collection unassignedJobs); - - /** - * informs if a {@link Job} has been removed from a {@link VehicleRoute}. - * - * @param job - * @param fromRoute - */ - public void removed(Job job, VehicleRoute fromRoute); - - } - /** * Ruins a current solution, i.e. a collection of vehicle-routes and * returns a collection of removed and thus unassigned jobs. diff --git a/jsprit-core/src/main/java/algorithms/RuinStrategyFactory.java b/jsprit-core/src/main/java/algorithms/RuinStrategyFactory.java index 202abb54..26cf1212 100644 --- a/jsprit-core/src/main/java/algorithms/RuinStrategyFactory.java +++ b/jsprit-core/src/main/java/algorithms/RuinStrategyFactory.java @@ -18,7 +18,7 @@ package algorithms; import basics.VehicleRoutingProblem; -interface RuinStrategyFactory { +public interface RuinStrategyFactory { public RuinStrategy createStrategy(VehicleRoutingProblem vrp); diff --git a/jsprit-core/src/main/java/algorithms/ServiceInsertionCalculator.java b/jsprit-core/src/main/java/algorithms/ServiceInsertionCalculator.java index 582f395a..daa6f637 100644 --- a/jsprit-core/src/main/java/algorithms/ServiceInsertionCalculator.java +++ b/jsprit-core/src/main/java/algorithms/ServiceInsertionCalculator.java @@ -20,7 +20,8 @@ import org.apache.log4j.Logger; import util.Neighborhood; import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts; -import algorithms.HardConstraints.HardRouteLevelConstraint; + +import algorithms.HardActivityLevelConstraint.ConstraintsStatus; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingTransportCosts; @@ -36,12 +37,14 @@ import basics.route.VehicleRoute; -final class ServiceInsertionCalculator implements JobInsertionCalculator{ +final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{ private static final Logger logger = Logger.getLogger(ServiceInsertionCalculator.class); private HardRouteLevelConstraint hardRouteLevelConstraint; + private HardActivityLevelConstraint hardActivityLevelConstraint; + private Neighborhood neighborhood = new Neighborhood() { @Override @@ -61,10 +64,12 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{ logger.info("initialise neighborhood " + neighborhood); } - public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint) { + + public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint, HardActivityLevelConstraint hardActivityLevelConstraint) { super(); this.activityInsertionCostsCalculator = activityInsertionCostsCalculator; this.hardRouteLevelConstraint = hardRouteLevelConstraint; + this.hardActivityLevelConstraint = hardActivityLevelConstraint; this.transportCosts = routingCosts; activityFactory = new DefaultTourActivityFactory(); logger.info("initialise " + this); @@ -81,13 +86,13 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{ * */ @Override - public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) { + public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) { if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing."); if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing."); InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime); if(!hardRouteLevelConstraint.fulfilled(insertionContext)){ - return InsertionData.noInsertionFound(); + return InsertionData.createEmptyInsertionData(); } double bestCost = bestKnownCosts; @@ -99,17 +104,40 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{ Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival()); start.setEndTime(newVehicleDepartureTime); - End end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival()); TourActivity prevAct = start; double prevActStartTime = newVehicleDepartureTime; int actIndex = 0; - + boolean loopBroken = false; for(TourActivity nextAct : currentRoute.getTourActivities().getActivities()){ if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ - ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime); - if(mc != null){ + ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime); + if(status.equals(ConstraintsStatus.FULFILLED)){ + ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime); + if(mc.getAdditionalCosts() < bestCost){ + bestCost = mc.getAdditionalCosts(); + bestMarginals = mc; + insertionIndex = actIndex; + } + } + else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){ + loopBroken = true; + break; + } + } + double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle); + double nextActEndTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct); + prevActStartTime = nextActEndTime; + prevAct = nextAct; + actIndex++; + } + End nextAct = end; + if(!loopBroken){ + if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ + ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime); + if(status.equals(ConstraintsStatus.FULFILLED)){ + ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime); if(mc.getAdditionalCosts() < bestCost){ bestCost = mc.getAdditionalCosts(); bestMarginals = mc; @@ -117,28 +145,10 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{ } } } - double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevActStartTime, newDriver, newVehicle); - double nextActEndTime = CalcUtils.getActivityEndTime(nextActArrTime, nextAct); - - prevActStartTime = nextActEndTime; - - prevAct = nextAct; - actIndex++; } - End nextAct = end; - if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ - ActivityInsertionCosts mc = calculate(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime); - if(mc != null) { - if(mc.getAdditionalCosts() < bestCost){ - bestCost = mc.getAdditionalCosts(); - bestMarginals = mc; - insertionIndex = actIndex; - } - } - } if(insertionIndex == InsertionData.NO_INDEX) { - return InsertionData.noInsertionFound(); + return InsertionData.createEmptyInsertionData(); } InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver); insertionData.setVehicleDepartureTime(newVehicleDepartureTime); @@ -147,7 +157,6 @@ final class ServiceInsertionCalculator implements JobInsertionCalculator{ } public ActivityInsertionCosts calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double departureTimeAtPrevAct) { - return activityInsertionCostsCalculator.calculate(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct); - + return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct); } } diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java b/jsprit-core/src/main/java/algorithms/ServiceInsertionOnRouteLevelCalculator.java similarity index 77% rename from jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java rename to jsprit-core/src/main/java/algorithms/ServiceInsertionOnRouteLevelCalculator.java index 88a848a1..843f5d40 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java +++ b/jsprit-core/src/main/java/algorithms/ServiceInsertionOnRouteLevelCalculator.java @@ -27,7 +27,7 @@ import org.apache.log4j.Logger; import util.Neighborhood; import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts; -import algorithms.HardConstraints.HardRouteLevelConstraint; +import algorithms.HardActivityLevelConstraint.ConstraintsStatus; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingActivityCosts; @@ -45,9 +45,9 @@ import basics.route.VehicleRoute; -final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalculator{ +final class ServiceInsertionOnRouteLevelCalculator implements JobInsertionCostsCalculator{ - private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionOnRouteLevel.class); + private static final Logger logger = Logger.getLogger(ServiceInsertionOnRouteLevelCalculator.class); private final VehicleRoutingTransportCosts transportCosts; @@ -57,10 +57,12 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory(); - private StateManager stateManager; + private StateGetter stateManager; private HardRouteLevelConstraint hardRouteLevelConstraint; + private HardActivityLevelConstraint hardActivityLevelConstraint; + private ActivityInsertionCostsCalculator activityInsertionCostsCalculator; private int nuOfActsForwardLooking = 0; @@ -94,18 +96,19 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul logger.info("set [solutionMemory="+memorySize+"]"); } - public CalculatesServiceInsertionOnRouteLevel(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, HardRouteLevelConstraint hardRouteLevelConstraint, ActivityInsertionCostsCalculator activityInsertionCostsCalculator) { + public ServiceInsertionOnRouteLevelCalculator(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint, HardActivityLevelConstraint hardActivityLevelConstraint) { super(); this.transportCosts = vehicleRoutingCosts; this.activityCosts = costFunc; - this.hardRouteLevelConstraint = hardRouteLevelConstraint; this.activityInsertionCostsCalculator = activityInsertionCostsCalculator; + this.hardRouteLevelConstraint = hardRouteLevelConstraint; + this.hardActivityLevelConstraint = hardActivityLevelConstraint; auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts); logger.info("initialise " + this); } - public void setStates(StateManager stateManager){ + public void setStates(StateGetter stateManager){ this.stateManager = stateManager; } @@ -128,13 +131,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul * */ @Override - public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) { + public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double best_known_insertion_costs) { if(jobToInsert == null) throw new IllegalStateException("job is null. cannot calculate the insertion of a null-job."); if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("no vehicle given. set para vehicle!"); InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime); if(!hardRouteLevelConstraint.fulfilled(insertionContext)){ - return InsertionData.noInsertionFound(); + return InsertionData.createEmptyInsertionData(); } /** @@ -150,6 +153,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul TourActivities tour = currentRoute.getTourActivities(); double best_insertion_costs = best_known_insertion_costs; Service service = (Service)jobToInsert; + /** * some inis @@ -164,6 +168,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul double sumOf_prevCosts_newVehicle = 0.0; double prevActDepTime_newVehicle = start.getEndTime(); + boolean loopBroken = false; /** * inserting serviceAct2Insert in route r={0,1,...,i-1,i,j,j+1,...,n(r),n(r)+1} * i=prevAct @@ -172,12 +177,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul */ for(TourActivity nextAct : tour.getActivities()){ if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){ - /** - * builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking} - */ - InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle); - ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle); - if(actInsertionCosts != null){ + ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle); + if(status.equals(ConstraintsStatus.FULFILLED)){ + /** + * builds a path on this route forwardPath={i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking} + */ + ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle); + /** * insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle) */ @@ -190,6 +196,10 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver)); } } + else if(status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)){ + loopBroken = true; + break; + } } /** @@ -219,22 +229,25 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul actIndex++; } - End nextAct = end; - if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){ + if(!loopBroken){ + End nextAct = end; + if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){ + ConstraintsStatus status = hardActivityLevelConstraint.fulfilled(insertionContext, prevAct, serviceAct2Insert, nextAct, prevActDepTime_newVehicle); + if(status.equals(ConstraintsStatus.FULFILLED)){ + ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle); + if(actInsertionCosts != null){ + /** + * insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle) + */ + double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts(); - InsertionContext iContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, prevActDepTime_newVehicle); - ActivityInsertionCosts actInsertionCosts = activityInsertionCostsCalculator.calculate(iContext, prevAct, nextAct, serviceAct2Insert, prevActDepTime_newVehicle); - if(actInsertionCosts != null){ - /** - * insertion_cost_approximation = c({0,1,...,i},newVehicle) + c({i,k,j,j+1,j+2,...,j+nuOfActsForwardLooking},newVehicle) - c({0,1,...,i,j,j+1,...,j+nuOfActsForwardLooking},oldVehicle) - */ - double insertion_cost_approximation = sumOf_prevCosts_newVehicle - sumOf_prevCosts_oldVehicle(currentRoute,prevAct) + actInsertionCosts.getAdditionalCosts(); - - /** - * memorize it in insertion-queue - */ - if(insertion_cost_approximation < best_known_insertion_costs){ - bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver)); + /** + * memorize it in insertion-queue + */ + if(insertion_cost_approximation < best_known_insertion_costs){ + bestInsertionsQueue.add(new InsertionData(insertion_cost_approximation, InsertionData.NO_INDEX, actIndex, newVehicle, newDriver)); + } + } } } } @@ -254,6 +267,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul } } else{ + for(int i=0;i insertion_costs */ - double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateTypes.COSTS).toDouble(); + double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateFactory.COSTS).toDouble(); /** * if better than best known, make it the best known @@ -282,7 +296,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul } } } - if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.noInsertionFound(); + if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.createEmptyInsertionData(); return new InsertionData(best_insertion_costs, InsertionData.NO_INDEX, best_insertion_index, newVehicle, newDriver); } @@ -316,9 +330,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) { if(act instanceof End){ - return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(); + return stateManager.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble(); } - return stateManager.getActivityState(act,StateTypes.COSTS).toDouble(); + return stateManager.getActivityState(act,StateFactory.COSTS).toDouble(); } /** diff --git a/jsprit-core/src/main/java/algorithms/ShipmentInsertionCalculator.java b/jsprit-core/src/main/java/algorithms/ShipmentInsertionCalculator.java index a2d91f8c..21364830 100644 --- a/jsprit-core/src/main/java/algorithms/ShipmentInsertionCalculator.java +++ b/jsprit-core/src/main/java/algorithms/ShipmentInsertionCalculator.java @@ -22,7 +22,7 @@ import org.apache.log4j.Logger; import util.Neighborhood; import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts; -import algorithms.HardConstraints.HardRouteLevelConstraint; +import algorithms.HardActivityLevelConstraint.ConstraintsStatus; import basics.Job; import basics.Shipment; import basics.costs.VehicleRoutingTransportCosts; @@ -38,12 +38,14 @@ import basics.route.VehicleRoute; -final class ShipmentInsertionCalculator implements JobInsertionCalculator{ +final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{ private static final Logger logger = Logger.getLogger(ShipmentInsertionCalculator.class); private HardRouteLevelConstraint hardRouteLevelConstraint; + private HardActivityLevelConstraint hardActivityLevelConstraint; + private Neighborhood neighborhood = new Neighborhood() { @Override @@ -63,10 +65,11 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{ logger.info("initialise neighborhood " + neighborhood); } - public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint) { + public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, HardRouteLevelConstraint hardRouteLevelConstraint, HardActivityLevelConstraint hardActivityLevelConstraint) { super(); this.activityInsertionCostsCalculator = activityInsertionCostsCalculator; this.hardRouteLevelConstraint = hardRouteLevelConstraint; + this.hardActivityLevelConstraint = hardActivityLevelConstraint; this.transportCosts = routingCosts; activityFactory = new DefaultShipmentActivityFactory(); logger.info("initialise " + this); @@ -83,25 +86,24 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{ * */ @Override - public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) { + public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) { if(jobToInsert == null) throw new IllegalStateException("jobToInsert is missing."); if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing."); if(!(jobToInsert instanceof Shipment)) throw new IllegalStateException("jobToInsert should be of type Shipment!"); InsertionContext insertionContext = new InsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime); if(!hardRouteLevelConstraint.fulfilled(insertionContext)){ - return InsertionData.noInsertionFound(); + return InsertionData.createEmptyInsertionData(); } double bestCost = bestKnownCosts; Shipment shipment = (Shipment)jobToInsert; TourActivity pickupShipment = activityFactory.createPickup(shipment); - TourActivity deliveryShipment = activityFactory.createDelivery(shipment); + TourActivity deliverShipment = activityFactory.createDelivery(shipment); int pickupInsertionIndex = InsertionData.NO_INDEX; int deliveryInsertionIndex = InsertionData.NO_INDEX; -// int insertionIndex = 0; Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival()); start.setEndTime(newVehicleDepartureTime); @@ -109,23 +111,32 @@ final class ShipmentInsertionCalculator implements JobInsertionCalculator{ TourActivity prevAct = start; double prevActEndTime = newVehicleDepartureTime; + boolean pickupShipmentLoopBroken = false; //pickupShipmentLoop List activities = currentRoute.getTourActivities().getActivities(); for(int i=0;i reservedIds = Arrays.asList("maxload","load","costs","loadAtBeginning","loadAtEnd","duration","latestOST","earliestOST" + ,"futurePicks","pastDeliveries"); + + + public static StateId createId(String name){ + if(reservedIds.contains(name)){ throwException(name); } + return new StateIdImpl(name); + } + + public static State createState(double value){ + return new StateImpl(value); + } + + private static void throwException(String name) { + throw new IllegalStateException("state-id with name '" + name + "' cannot be created. it is already reserved internally."); + } + + + static class StateIdImpl implements StateId { + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + StateIdImpl other = (StateIdImpl) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + private String name; + + public StateIdImpl(String name) { + super(); + this.name = name; + } + + public String toString(){ + return name; + } + } +} diff --git a/jsprit-core/src/main/java/algorithms/CalcUtils.java b/jsprit-core/src/main/java/algorithms/StateGetter.java similarity index 71% rename from jsprit-core/src/main/java/algorithms/CalcUtils.java rename to jsprit-core/src/main/java/algorithms/StateGetter.java index c4515849..32a88e0e 100644 --- a/jsprit-core/src/main/java/algorithms/CalcUtils.java +++ b/jsprit-core/src/main/java/algorithms/StateGetter.java @@ -17,18 +17,22 @@ package algorithms; import basics.route.TourActivity; +import basics.route.VehicleRoute; -class CalcUtils { +public interface StateGetter { + + public interface StateId { + + } + + public interface State { + double toDouble(); + } - /** - * Calculates actEndTime assuming that activity can at earliest start at act.getTheoreticalEarliestOperationStartTime(). - * - * @param actArrTime - * @param act - * @return - */ - static double getActivityEndTime(double actArrTime, TourActivity act){ - return Math.max(actArrTime, act.getTheoreticalEarliestOperationStartTime()) + act.getOperationTime(); - } + State getActivityState(TourActivity act, StateId stateId); + + State getRouteState(VehicleRoute route, StateId stateId); + + } diff --git a/jsprit-core/src/main/java/algorithms/StateManager.java b/jsprit-core/src/main/java/algorithms/StateManager.java index 35d2f4f8..e83241b8 100644 --- a/jsprit-core/src/main/java/algorithms/StateManager.java +++ b/jsprit-core/src/main/java/algorithms/StateManager.java @@ -16,16 +16,42 @@ ******************************************************************************/ package algorithms; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +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.ActivityVisitor; +import basics.route.ReverseActivityVisitor; +import basics.route.ReverseRouteActivityVisitor; +import basics.route.RouteActivityVisitor; +import basics.route.RouteVisitor; import basics.route.TourActivity; import basics.route.VehicleRoute; -interface StateManager { +public class StateManager implements StateGetter, IterationStartsListener, RuinListener, InsertionStartsListener, JobInsertedListener, InsertionEndsListener { + - interface State { - double toDouble(); + + private interface States { + + State getState(StateId key); + } - class StateImpl implements State{ + static class StateImpl implements State{ double state; public StateImpl(double state) { @@ -40,14 +66,225 @@ interface StateManager { } - interface States { - - State getState(String key); - - } - - State getActivityState(TourActivity act, String stateType); - - State getRouteState(VehicleRoute route, String stateType); + private static class StatesImpl implements States{ + private Map states = new HashMap(); + + public void putState(StateId key, State state) { + states.put(key, state); + } + + @Override + public State getState(StateId key) { + return states.get(key); + } + + } + + private Map vehicleRouteStates = new HashMap(); + + private Map activityStates = new HashMap(); + + private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); + + private ReverseRouteActivityVisitor revRouteActivityVisitor = new ReverseRouteActivityVisitor(); + + private Collection routeVisitors = new ArrayList(); + + private RuinListeners ruinListeners = new RuinListeners(); + + private InsertionListeners insertionListeners = new InsertionListeners(); + + private Collection updaters = new ArrayList(); + + private Map defaultRouteStates = new HashMap(); + + private Map defaultActivityStates = new HashMap(); + + public void addDefaultRouteState(StateId stateId, State defaultState){ + defaultRouteStates.put(stateId, defaultState); + } + + public void addDefaultActivityState(StateId stateId, State defaultState){ + defaultActivityStates.put(stateId, defaultState); + } + + public void clear(){ + vehicleRouteStates.clear(); + activityStates.clear(); + } + + @Override + public State getActivityState(TourActivity act, StateId stateId) { + if(!activityStates.containsKey(act)){ + return getDefaultActState(stateId,act); + } + StatesImpl actStates = (StatesImpl) activityStates.get(act); + State state = actStates.getState(stateId); + if(state == null){ + return getDefaultActState(stateId,act); + } + return state; + } + + public void putActivityState(TourActivity act, StateId stateId, State state){ + if(!activityStates.containsKey(act)){ + activityStates.put(act, new StatesImpl()); + } + StatesImpl actStates = (StatesImpl) activityStates.get(act); + actStates.putState(stateId, state); + } + + + public void putRouteState(VehicleRoute route, StateId stateId, State state){ + if(!vehicleRouteStates.containsKey(route)){ + vehicleRouteStates.put(route, new StatesImpl()); + } + StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route); + routeStates.putState(stateId, state); + } + + @Override + public State getRouteState(VehicleRoute route, StateId stateId) { + if(!vehicleRouteStates.containsKey(route)){ + return getDefaultRouteState(stateId,route); + } + StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route); + State state = routeStates.getState(stateId); + if(state == null){ + return getDefaultRouteState(stateId, route); + } + return state; + } + + /** + * Adds state updater. + * + *

Note that a state update occurs if route and/or activity states change, i.e. if jobs are removed + * or inserted into a route. Thus here, it is assumed that a state updater is either of type InsertionListener, + * RuinListener, ActivityVisitor, ReverseActivityVisitor, RouteVisitor, ReverseRouteVisitor. + * + *

The following rule pertain for activity/route visitors:These visitors visits all activities/route 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 updater + */ + public void addStateUpdater(StateUpdater updater){ + if(updater instanceof ActivityVisitor) addActivityVisitor((ActivityVisitor) updater); + if(updater instanceof ReverseActivityVisitor) addActivityVisitor((ReverseActivityVisitor)updater); + if(updater instanceof RouteVisitor) addRouteVisitor((RouteVisitor) updater); + if(updater instanceof InsertionListener) addListener((InsertionListener) updater); + if(updater instanceof RuinListener) addListener((RuinListener) updater); + updaters.add(updater); + } + + Collection getStateUpdaters(){ + return Collections.unmodifiableCollection(updaters); + } + + /** + * 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 + */ + 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 + */ + void addActivityVisitor(ReverseActivityVisitor activityVistor){ + revRouteActivityVisitor.addActivityVisitor(activityVistor); + } + + void addRouteVisitor(RouteVisitor routeVisitor){ + routeVisitors.add(routeVisitor); + } + + void addListener(RuinListener ruinListener){ + ruinListeners.addListener(ruinListener); + } + + void removeListener(RuinListener ruinListener){ + ruinListeners.removeListener(ruinListener); + } + + void addListener(InsertionListener insertionListener){ + insertionListeners.addListener(insertionListener); + } + + void removeListener(InsertionListener insertionListener){ + insertionListeners.removeListener(insertionListener); + } + + private State getDefaultActState(StateId stateId, TourActivity act){ + if(stateId.equals(StateFactory.LOAD)) return new StateImpl(0); + if(stateId.equals(StateFactory.COSTS)) return new StateImpl(0); + if(stateId.equals(StateFactory.DURATION)) return new StateImpl(0); + if(stateId.equals(StateFactory.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime()); + if(stateId.equals(StateFactory.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime()); + if(stateId.equals(StateFactory.FUTURE_PICKS)) return new StateImpl(0); + if(stateId.equals(StateFactory.PAST_DELIVERIES)) return new StateImpl(0); + return null; + } + + private State getDefaultRouteState(StateId stateId, VehicleRoute route){ + if(stateId.equals(StateFactory.MAXLOAD)) return new StateImpl(0); + if(stateId.equals(StateFactory.LOAD)) return new StateImpl(0); + if(stateId.equals(StateFactory.LOAD_AT_END)) return new StateImpl(0); + if(stateId.equals(StateFactory.LOAD_AT_BEGINNING)) return new StateImpl(0); + if(stateId.equals(StateFactory.COSTS)) return new StateImpl(0); + if(stateId.equals(StateFactory.DURATION)) return new StateImpl(0); + return null; + } + + @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); + } + + @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); + revRouteActivityVisitor.visit(route); + } + } + + @Override + public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection solutions) { + clear(); + } + + @Override + public void ruinStarts(Collection routes) { + ruinListeners.ruinStarts(routes); + } + + @Override + public void ruinEnds(Collection routes, Collection unassignedJobs) { + ruinListeners.ruinEnds(routes, unassignedJobs); + } + + @Override + public void removed(Job job, VehicleRoute fromRoute) { + ruinListeners.removed(job, fromRoute); + } + + @Override + public void informInsertionEnds(Collection vehicleRoutes) { + insertionListeners.insertionEnds(vehicleRoutes); + } } diff --git a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java deleted file mode 100644 index cf31497d..00000000 --- a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package algorithms; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import basics.Job; -import basics.algo.InsertionStartsListener; -import basics.algo.JobInsertedListener; -import basics.route.TourActivity; -import basics.route.VehicleRoute; - -class StateManagerImpl implements StateManager, InsertionStartsListener, JobInsertedListener { - - static class StatesImpl implements States{ - - private Map states = new HashMap(); - - public void putState(String key, State state) { - states.put(key, state); - } - - @Override - public State getState(String key) { - return states.get(key); - } - - } - - private Map vehicleRouteStates = new HashMap(); - - private Map activityStates = new HashMap(); - - private RouteActivityVisitor routeActivityVisitor = new RouteActivityVisitor(); - - private ReverseRouteActivityVisitor revRouteActivityVisitor = new ReverseRouteActivityVisitor(); - - private Collection routeVisitors = new ArrayList(); - - public void clear(){ - vehicleRouteStates.clear(); - activityStates.clear(); - } - - @Override - public State getActivityState(TourActivity act, String stateType) { - if(!activityStates.containsKey(act)){ - return getDefaultActState(stateType,act); - } - StatesImpl actStates = (StatesImpl) activityStates.get(act); - State state = actStates.getState(stateType); - if(state == null){ - return getDefaultActState(stateType,act); - } - return state; - } - - public void putActivityState(TourActivity act, String stateType, State state){ - if(!activityStates.containsKey(act)){ - activityStates.put(act, new StatesImpl()); - } - StatesImpl actStates = (StatesImpl) activityStates.get(act); - actStates.putState(stateType, state); - } - - - private State getDefaultActState(String stateType, TourActivity act){ - if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0); - if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0); - if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0); - if(stateType.equals(StateTypes.EARLIEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalEarliestOperationStartTime()); - if(stateType.equals(StateTypes.LATEST_OPERATION_START_TIME)) return new StateImpl(act.getTheoreticalLatestOperationStartTime()); - if(stateType.equals(StateTypes.FUTURE_PICKS)) return new StateImpl(0); - if(stateType.equals(StateTypes.PAST_DELIVERIES)) return new StateImpl(0); - return null; - } - - private State getDefaultRouteState(String stateType, VehicleRoute route){ - if(stateType.equals(StateTypes.LOAD)) return new StateImpl(0); - if(stateType.equals(StateTypes.LOAD_AT_DEPOT)) return new StateImpl(0); - if(stateType.equals(StateTypes.COSTS)) return new StateImpl(0); - if(stateType.equals(StateTypes.DURATION)) return new StateImpl(0); - return null; - } - - @Override - public State getRouteState(VehicleRoute route, String stateType) { - if(!vehicleRouteStates.containsKey(route)){ - return getDefaultRouteState(stateType,route); - } - StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route); - State state = routeStates.getState(stateType); - if(state == null){ - return getDefaultRouteState(stateType, route); - } - return state; - } - - public void putRouteState(VehicleRoute route, String stateType, State state){ - if(!vehicleRouteStates.containsKey(route)){ - vehicleRouteStates.put(route, new StatesImpl()); - } - StatesImpl routeStates = (StatesImpl) vehicleRouteStates.get(route); - routeStates.putState(stateType, state); - } - - @Override - public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { - for(RouteVisitor v : routeVisitors){ v.visit(inRoute); } - routeActivityVisitor.visit(inRoute); - revRouteActivityVisitor.visit(inRoute); - } - - @Override - public void informInsertionStarts(Collection vehicleRoutes,Collection unassignedJobs) { - for(VehicleRoute route : vehicleRoutes){ - for(RouteVisitor v : routeVisitors){ v.visit(route); } - routeActivityVisitor.visit(route); - revRouteActivityVisitor.visit(route); - } - } - - public void addActivityVisitor(ActivityVisitor activityVistor){ - routeActivityVisitor.addActivityVisitor(activityVistor); - } - - public void addActivityVisitor(ReverseActivityVisitor activityVistor){ - revRouteActivityVisitor.addActivityVisitor(activityVistor); - } - - public void addRouteVisitor(RouteVisitor routeVisitor){ - routeVisitors.add(routeVisitor); - } -} diff --git a/jsprit-core/src/main/java/algorithms/StateUpdater.java b/jsprit-core/src/main/java/algorithms/StateUpdater.java new file mode 100644 index 00000000..9fd80a19 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/StateUpdater.java @@ -0,0 +1,5 @@ +package algorithms; + +public interface StateUpdater { + +} 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 d85f0cee..00000000 --- a/jsprit-core/src/main/java/algorithms/StateUpdates.java +++ /dev/null @@ -1,633 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package algorithms; - -import java.util.ArrayList; -import java.util.Collection; - -import org.apache.log4j.Logger; - -import algorithms.RuinStrategy.RuinListener; -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.IterationStartsListener; -import basics.algo.JobInsertedListener; -import basics.costs.ForwardTransportCost; -import basics.costs.ForwardTransportTime; -import basics.costs.VehicleRoutingActivityCosts; -import basics.costs.VehicleRoutingTransportCosts; -import basics.route.DeliveryActivity; -import basics.route.PickupActivity; -import basics.route.ServiceActivity; -import basics.route.TourActivity; -import basics.route.Vehicle; -import basics.route.VehicleRoute; -import basics.route.VehicleType; - -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; -// totalOperationCost += getFixCosts(); - - 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; - } - - private double getFixCosts() { - Vehicle vehicle = vehicleRoute.getVehicle(); - if(vehicle == null) return 0.0; - VehicleType type = vehicle.getType(); - if(type == null) return 0.0; - return type.getVehicleCostParams().fix; - } - - } - - 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/StateUtils.java b/jsprit-core/src/main/java/algorithms/StateUtils.java new file mode 100644 index 00000000..86ee258d --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/StateUtils.java @@ -0,0 +1,24 @@ +package algorithms; + +import basics.VehicleRoutingProblem; + +class StateUtils { + + public static void addCoreStateUpdaters(VehicleRoutingProblem vrp, StateManager stateManager){ + stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager)); + stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager)); + + stateManager.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts())); + stateManager.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager)); + + stateManager.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); + + stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager)); + + stateManager.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); + + stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager)); + + } + +} diff --git a/jsprit-core/src/main/java/algorithms/UpdateActivityTimes.java b/jsprit-core/src/main/java/algorithms/UpdateActivityTimes.java new file mode 100644 index 00000000..860504c0 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateActivityTimes.java @@ -0,0 +1,65 @@ +package algorithms; + +import org.apache.log4j.Logger; + +import util.ActivityTimeTracker; + +import basics.costs.ForwardTransportTime; +import basics.route.ActivityVisitor; +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 + * + */ +class UpdateActivityTimes implements ActivityVisitor, StateUpdater{ + + 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/UpdateCostsAtAllLevels.java b/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java new file mode 100644 index 00000000..a9e57c0a --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateCostsAtAllLevels.java @@ -0,0 +1,126 @@ +package algorithms; + +import org.apache.log4j.Logger; + +import util.ActivityTimeTracker; + +import algorithms.StateManager.StateImpl; +import basics.costs.ForwardTransportCost; +import basics.costs.VehicleRoutingActivityCosts; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.ActivityVisitor; +import basics.route.TourActivity; +import basics.route.Vehicle; +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 + */ +class UpdateCostsAtAllLevels implements ActivityVisitor,StateUpdater{ + + private static Logger log = Logger.getLogger(UpdateCostsAtAllLevels.class); + + private VehicleRoutingActivityCosts activityCost; + + private ForwardTransportCost transportCost; + + private StateManager 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, StateManager 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, StateFactory.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; +// totalOperationCost += getFixCosts(vehicleRoute.getVehicle()); + + states.putRouteState(vehicleRoute, StateFactory.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; + } + + private double getFixCosts(Vehicle vehicle) { + if(vehicle == null) return 0.0; + if(vehicle.getType() == null) return 0.0; + return vehicle.getType().getVehicleCostParams().fix; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/UpdateCostsAtRouteLevel.java b/jsprit-core/src/main/java/algorithms/UpdateCostsAtRouteLevel.java new file mode 100644 index 00000000..5f6392a9 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateCostsAtRouteLevel.java @@ -0,0 +1,63 @@ +package algorithms; + +import java.util.Collection; + +import algorithms.StateManager.StateImpl; +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.RouteActivityVisitor; +import basics.route.VehicleRoute; + +class UpdateCostsAtRouteLevel implements StateUpdater,JobInsertedListener, InsertionStartsListener, InsertionEndsListener{ + + private StateManager states; + + private VehicleRoutingTransportCosts tpCosts; + + private VehicleRoutingActivityCosts actCosts; + + public UpdateCostsAtRouteLevel(StateManager 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, StateFactory.COSTS).toDouble(); + oldCosts += additionalCosts; + states.putRouteState(inRoute, StateFactory.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, StateFactory.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/UpdateEarliestStartTimeWindowAtActLocations.java b/jsprit-core/src/main/java/algorithms/UpdateEarliestStartTimeWindowAtActLocations.java new file mode 100644 index 00000000..56c790dd --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateEarliestStartTimeWindowAtActLocations.java @@ -0,0 +1,37 @@ +package algorithms; + +import util.ActivityTimeTracker; +import algorithms.StateManager.StateImpl; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.ActivityVisitor; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +class UpdateEarliestStartTimeWindowAtActLocations implements ActivityVisitor,StateUpdater{ + + private StateManager states; + + private ActivityTimeTracker timeTracker; + + public UpdateEarliestStartTimeWindowAtActLocations(StateManager 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, StateFactory.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/UpdateFuturePickupsAtActivityLevel.java b/jsprit-core/src/main/java/algorithms/UpdateFuturePickupsAtActivityLevel.java new file mode 100644 index 00000000..3e402e20 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateFuturePickupsAtActivityLevel.java @@ -0,0 +1,39 @@ +package algorithms; + +import basics.route.PickupActivity; +import basics.route.ReverseActivityVisitor; +import basics.route.ServiceActivity; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +class UpdateFuturePickupsAtActivityLevel implements ReverseActivityVisitor, StateUpdater { + private StateManager stateManager; + private int futurePicks = 0; + private VehicleRoute route; + + public UpdateFuturePickupsAtActivityLevel(StateManager stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public void begin(VehicleRoute route) { + this.route = route; + } + + @Override + public void visit(TourActivity act) { + stateManager.putActivityState(act, StateFactory.FUTURE_PICKS, StateFactory.createState(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/UpdateLatestOperationStartTimeAtActLocations.java b/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java new file mode 100644 index 00000000..3e1c0d01 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateLatestOperationStartTimeAtActLocations.java @@ -0,0 +1,51 @@ +package algorithms; + +import org.apache.log4j.Logger; + +import algorithms.StateManager.StateImpl; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.ReverseActivityVisitor; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +class UpdateLatestOperationStartTimeAtActLocations implements ReverseActivityVisitor, StateUpdater{ + + private static Logger log = Logger.getLogger(UpdateLatestOperationStartTimeAtActLocations.class); + + private StateManager states; + + private VehicleRoute route; + + private VehicleRoutingTransportCosts transportCosts; + + private double latestArrTimeAtPrevAct; + + private TourActivity prevAct; + + public UpdateLatestOperationStartTimeAtActLocations(StateManager 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, StateFactory.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/UpdateLoadAtActivityLevel.java b/jsprit-core/src/main/java/algorithms/UpdateLoadAtActivityLevel.java new file mode 100644 index 00000000..73f9fb76 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateLoadAtActivityLevel.java @@ -0,0 +1,67 @@ +package algorithms; + +import algorithms.StateManager.StateImpl; +import basics.route.ActivityVisitor; +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 + * + */ +class UpdateLoadAtActivityLevel implements ActivityVisitor, StateUpdater { + private StateManager 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 UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted} + * + *

The loads can be retrieved by
+ * stateManager.getActivityState(activity,StateTypes.LOAD); + * + * + * + * @see {@link UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted} + * @author stefan + * + */ + public UpdateLoadAtActivityLevel(StateManager stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public void begin(VehicleRoute route) { + currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(); + this.route = route; + } + + @Override + public void visit(TourActivity act) { + currentLoad += act.getCapacityDemand(); + stateManager.putActivityState(act, StateFactory.LOAD, StateFactory.createState(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() { +// stateManager.putRouteState(route, StateFactory., state) + currentLoad = 0; + } +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/UpdateLoadAtAllLevels.java b/jsprit-core/src/main/java/algorithms/UpdateLoadAtAllLevels.java new file mode 100644 index 00000000..d38b3cb2 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateLoadAtAllLevels.java @@ -0,0 +1,39 @@ +package algorithms; + +import algorithms.StateManager.StateImpl; +import basics.route.ActivityVisitor; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +class UpdateLoadAtAllLevels implements ActivityVisitor,StateUpdater{ + + private double load = 0.0; + + private StateManager states; + + private VehicleRoute vehicleRoute; + + public UpdateLoadAtAllLevels(StateManager 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, StateFactory.LOAD, new StateImpl(load)); + } + + @Override + public void finish() { + states.putRouteState(vehicleRoute, StateFactory.LOAD, new StateImpl(load)); + load=0; + vehicleRoute = null; + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/UpdateLoadAtRouteLevel.java b/jsprit-core/src/main/java/algorithms/UpdateLoadAtRouteLevel.java new file mode 100644 index 00000000..a80130af --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateLoadAtRouteLevel.java @@ -0,0 +1,54 @@ +package algorithms; + +import java.util.Collection; + +import algorithms.StateManager.StateImpl; +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 + * + */ +class UpdateLoadAtRouteLevel implements JobInsertedListener, InsertionStartsListener, StateUpdater{ + + private StateManager states; + + /** + * Updates load at route level, i.e. modifies StateTypes.LOAD for each route. + * + * @author stefan + * + */ + public UpdateLoadAtRouteLevel(StateManager 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, StateFactory.LOAD).toDouble(); + states.putRouteState(inRoute, StateFactory.LOAD, StateFactory.createState(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, StateFactory.LOAD, new StateImpl(load)); + } + + } + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts.java b/jsprit-core/src/main/java/algorithms/UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts.java new file mode 100644 index 00000000..8b652430 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts.java @@ -0,0 +1,62 @@ +package algorithms; + +import java.util.Collection; + +import algorithms.StateManager.StateImpl; +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 + */ +class UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts implements InsertionStartsListener { + + private StateManager 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 UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(StateManager 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, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot)); + stateManager.putRouteState(route, StateFactory.LOAD_AT_END, StateFactory.createState(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/UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted.java b/jsprit-core/src/main/java/algorithms/UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted.java new file mode 100644 index 00000000..e73fa7b2 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted.java @@ -0,0 +1,52 @@ +package algorithms; + +import algorithms.StateManager.StateImpl; +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 + */ +class UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted implements JobInsertedListener, StateUpdater { + + private StateManager 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(StateManager 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, StateFactory.LOAD_AT_BEGINNING).toDouble(); +// log.info("loadAtDepot="+loadAtDepot); + stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot + job2insert.getCapacityDemand())); + } + else if(job2insert instanceof Pickup || job2insert instanceof Service){ + int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END).toDouble(); +// log.info("loadAtEnd="+loadAtEnd); + stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_END, StateFactory.createState(loadAtEnd + job2insert.getCapacityDemand())); + } + } + + } \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/UpdateMaxLoad.java b/jsprit-core/src/main/java/algorithms/UpdateMaxLoad.java new file mode 100644 index 00000000..9975ae8f --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateMaxLoad.java @@ -0,0 +1,69 @@ +package algorithms; + +import basics.route.ActivityVisitor; +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 + * + */ +class UpdateMaxLoad implements ActivityVisitor, StateUpdater { + private StateManager stateManager; + private int currentLoad = 0; + private VehicleRoute route; + private int maxLoad = 0; + + /** + * 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 UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted} + * + *

The loads can be retrieved by
+ * stateManager.getActivityState(activity,StateTypes.LOAD); + * + * + * + * @see {@link UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts}, {@link UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted} + * @author stefan + * + */ + public UpdateMaxLoad(StateManager stateManager) { + super(); + this.stateManager = stateManager; + } + + @Override + public void begin(VehicleRoute route) { + currentLoad = (int) stateManager.getRouteState(route, StateFactory.LOAD_AT_BEGINNING).toDouble(); + maxLoad = currentLoad; + this.route = route; + } + + @Override + public void visit(TourActivity act) { + currentLoad += act.getCapacityDemand(); + maxLoad = Math.max(maxLoad, 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() { + stateManager.putRouteState(route, StateFactory.MAXLOAD, StateFactory.createState(maxLoad)); + currentLoad = 0; + maxLoad = 0; + } +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/algorithms/UpdateOccuredDeliveriesAtActivityLevel.java b/jsprit-core/src/main/java/algorithms/UpdateOccuredDeliveriesAtActivityLevel.java new file mode 100644 index 00000000..8e58a0c8 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/UpdateOccuredDeliveriesAtActivityLevel.java @@ -0,0 +1,39 @@ +package algorithms; + +import algorithms.StateManager.StateImpl; +import basics.route.ActivityVisitor; +import basics.route.DeliveryActivity; +import basics.route.TourActivity; +import basics.route.VehicleRoute; + +class UpdateOccuredDeliveriesAtActivityLevel implements ActivityVisitor, StateUpdater { + private StateManager stateManager; + private int deliveries = 0; + private VehicleRoute route; + + public UpdateOccuredDeliveriesAtActivityLevel(StateManager 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, StateFactory.PAST_DELIVERIES, StateFactory.createState(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/algorithms/VariablePlusFixedSolutionCostCalculatorFactory.java b/jsprit-core/src/main/java/algorithms/VariablePlusFixedSolutionCostCalculatorFactory.java new file mode 100644 index 00000000..b24a5df9 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/VariablePlusFixedSolutionCostCalculatorFactory.java @@ -0,0 +1,31 @@ +package algorithms; + +import basics.VehicleRoutingProblemSolution; +import basics.algo.SolutionCostCalculator; +import basics.route.VehicleRoute; + +public class VariablePlusFixedSolutionCostCalculatorFactory { + + private StateManager stateManager; + + public VariablePlusFixedSolutionCostCalculatorFactory(StateManager stateManager) { + super(); + this.stateManager = stateManager; + } + + public SolutionCostCalculator createCalculator(){ + return new SolutionCostCalculator() { + + @Override + public double getCosts(VehicleRoutingProblemSolution solution) { + double c = 0.0; + for(VehicleRoute r : solution.getRoutes()){ + c += stateManager.getRouteState(r, StateFactory.COSTS).toDouble(); + c += r.getVehicle().getType().getVehicleCostParams().fix; + } + return c; + } + }; + } + +} diff --git a/jsprit-core/src/main/java/algorithms/VehicleFleetManager.java b/jsprit-core/src/main/java/algorithms/VehicleFleetManager.java deleted file mode 100644 index d0467077..00000000 --- a/jsprit-core/src/main/java/algorithms/VehicleFleetManager.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package algorithms; - -import java.util.Collection; - -import basics.route.Vehicle; - -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; - } - - @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; - 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; - } - - - - } - - abstract void lock(Vehicle vehicle); - - abstract void unlock(Vehicle vehicle); - - abstract boolean isLocked(Vehicle vehicle); - - abstract void unlockAll(); - - abstract Collection getAvailableVehicles(); - - Collection getAvailableVehicles(String withoutThisType, String locationId); - -} diff --git a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithmBuilder.java b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithmBuilder.java new file mode 100644 index 00000000..57800da8 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithmBuilder.java @@ -0,0 +1,44 @@ +package algorithms; + +import java.util.ArrayList; +import java.util.Collection; + +import basics.VehicleRoutingAlgorithm; +import basics.VehicleRoutingProblem; +import basics.algo.SearchStrategyManager; +import basics.algo.VehicleRoutingAlgorithmListener; +import basics.route.VehicleFleetManager; + +public class VehicleRoutingAlgorithmBuilder { + + private VehicleRoutingProblem vrp; + + private SearchStrategyManager searchStrategyManager; + + private StateManager stateManager; + + private Collection listeners = new ArrayList(); + + private VehicleFleetManager fleetManager; + + public VehicleRoutingAlgorithmBuilder(VehicleRoutingProblem vrp, SearchStrategyManager searchStrategyManager, StateManager stateManager, VehicleFleetManager vehicleFleetManager) { + super(); + this.vrp = vrp; + this.searchStrategyManager = searchStrategyManager; + this.stateManager = stateManager; + this.fleetManager = vehicleFleetManager; + } + + public void addListener(VehicleRoutingAlgorithmListener listener){ + listeners.add(listener); + } + + public VehicleRoutingAlgorithm build(){ + VehicleRoutingAlgorithm algorithm = new VehicleRoutingAlgorithm(vrp, searchStrategyManager); + algorithm.getAlgorithmListeners().addListener(stateManager); + algorithm.getSearchStrategyManager().addSearchStrategyModuleListener(stateManager); + algorithm.getSearchStrategyManager().addSearchStrategyModuleListener(new RemoveEmptyVehicles(fleetManager)); + return algorithm; + } + +} diff --git a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java index 4cd33742..bd8e6db4 100644 --- a/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java +++ b/jsprit-core/src/main/java/algorithms/VehicleRoutingAlgorithms.java @@ -31,7 +31,6 @@ import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.XMLConfiguration; import org.apache.log4j.Logger; -import algorithms.HardConstraints.ConstraintManager; import algorithms.VehicleRoutingAlgorithms.TypedMap.AbstractKey; import algorithms.VehicleRoutingAlgorithms.TypedMap.AcceptorKey; import algorithms.VehicleRoutingAlgorithms.TypedMap.InsertionStrategyKey; @@ -65,7 +64,10 @@ import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener; import basics.algo.VehicleRoutingAlgorithmListeners.Priority; import basics.io.AlgorithmConfig; import basics.io.AlgorithmConfigXmlReader; +import basics.route.FiniteFleetManagerFactory; +import basics.route.InfiniteFleetManagerFactory; import basics.route.Vehicle; +import basics.route.VehicleFleetManager; import basics.route.VehicleRoute; @@ -437,23 +439,23 @@ public class VehicleRoutingAlgorithms { final VehicleFleetManager vehicleFleetManager = createFleetManager(vrp); //create state-manager - final StateManagerImpl stateManager = new StateManagerImpl(); + final StateManager stateManager = new StateManager(); /* * define constraints */ //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 HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager)); //construct initial solution creator AlgorithmStartsListener createInitialSolution = createInitialSolution(config,vrp,vehicleFleetManager,stateManager,algorithmListeners,definedClasses,executorService,nuOfThreads,constraintManager); @@ -491,24 +493,22 @@ public class VehicleRoutingAlgorithms { * define stateUpdates */ - //reset 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()); + stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager)); + stateManager.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager)); + + stateManager.addActivityVisitor(new UpdateActivityTimes(vrp.getTransportCosts())); + stateManager.addActivityVisitor(new UpdateLoadAtActivityLevel(stateManager)); - routeChangedListener.addInsertionStartsListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(stateManager)); - routeChangedListener.addJobInsertedListener(new StateUpdates.UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(stateManager)); + stateManager.addActivityVisitor(new UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); - routeChangedListener.addVisitor(new StateUpdates.UpdateActivityTimes(vrp.getTransportCosts())); - routeChangedListener.addVisitor(new StateUpdates.UpdateLoadAtActivityLevel(stateManager)); - routeChangedListener.addVisitor(new StateUpdates.UpdateCostsAtAllLevels(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager)); + stateManager.addActivityVisitor(new UpdateOccuredDeliveriesAtActivityLevel(stateManager)); + stateManager.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); + stateManager.addActivityVisitor(new UpdateFuturePickupsAtActivityLevel(stateManager)); + - routeChangedListener.addVisitor(new StateUpdates.UpdateOccuredDeliveriesAtActivityLevel(stateManager)); - routeChangedListener.addVisitor(new StateUpdates.UpdateLatestOperationStartTimeAtActLocations(stateManager, vrp.getTransportCosts())); - routeChangedListener.addVisitor(new StateUpdates.UpdateFuturePickupsAtActivityLevel(stateManager)); + metaAlgorithm.getSearchStrategyManager().addSearchStrategyModuleListener(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)); @@ -526,16 +526,16 @@ public class VehicleRoutingAlgorithms { return metaAlgorithm; } - private static SolutionCostCalculator getCostCalculator(final StateManagerImpl stateManager) { + private static SolutionCostCalculator getCostCalculator(final StateManager stateManager) { SolutionCostCalculator calc = new SolutionCostCalculator() { @Override - public void calculateCosts(VehicleRoutingProblemSolution solution) { + public double getCosts(VehicleRoutingProblemSolution solution) { double costs = 0.0; for(VehicleRoute route : solution.getRoutes()){ - costs += stateManager.getRouteState(route, StateTypes.COSTS).toDouble() + getFixedCosts(route.getVehicle()); + costs += stateManager.getRouteState(route, StateFactory.COSTS).toDouble() + getFixedCosts(route.getVehicle()); } - solution.setCost(costs); + return costs; } private double getFixedCosts(Vehicle vehicle) { @@ -549,11 +549,11 @@ public class VehicleRoutingAlgorithms { private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) { if(vrp.getFleetSize().equals(FleetSize.INFINITE)){ - return new InfiniteVehicles(vrp.getVehicles()); + return new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager(); } else if(vrp.getFleetSize().equals(FleetSize.FINITE)){ - return new VehicleFleetManagerImpl(vrp.getVehicles()); + return new FiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager(); } throw new IllegalStateException("fleet size can only be infinite or finite. " + "makes sure your config file contains one of these options"); @@ -626,7 +626,7 @@ public class VehicleRoutingAlgorithms { metaAlgorithm.getAlgorithmListeners().addAll(algorithmListeners); } - private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManagerImpl routeStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) { + private static AlgorithmStartsListener createInitialSolution(XMLConfiguration config, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, final StateManager routeStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) { List modConfigs = config.configurationsAt("construction.insertion"); if(modConfigs == null) return null; if(modConfigs.isEmpty()) return null; @@ -651,9 +651,11 @@ public class VehicleRoutingAlgorithms { @Override public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection solutions) { - CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates)); - createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false); - VehicleRoutingProblemSolution vrpSol = createInitialSolution.createInitialSolution(vrp); + InsertionInitialSolutionFactory insertionInitialSolutionFactory = new InsertionInitialSolutionFactory(finalInsertionStrategy, getCostCalculator(routeStates)); +// CreateInitialSolution createInitialSolution = new CreateInitialSolution(finalInsertionStrategy, getCostCalculator(routeStates)); +// +// createInitialSolution.setGenerateAsMuchAsRoutesAsVehiclesExist(false); + VehicleRoutingProblemSolution vrpSol = insertionInitialSolutionFactory.createSolution(vrp); solutions.add(vrpSol); } }; @@ -721,7 +723,7 @@ public class VehicleRoutingAlgorithms { } private static SearchStrategyModule buildModule(HierarchicalConfiguration moduleConfig, final VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, - final StateManagerImpl routeStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) { + final StateManager routeStates, Set algorithmListeners, TypedMap definedClasses, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) { String moduleName = moduleConfig.getString("[@name]"); if(moduleName == null) throw new IllegalStateException("module(-name) is missing."); String moduleId = moduleConfig.getString("[@id]"); @@ -823,7 +825,7 @@ public class VehicleRoutingAlgorithms { "\n\tgendreauPostOpt"); } - private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) { + private static RuinStrategy getRadialRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin, JobDistance jobDistance) { RuinStrategyKey stratKey = new RuinStrategyKey(modKey); RuinStrategy ruin = definedClasses.get(stratKey); if(ruin == null){ @@ -833,7 +835,7 @@ public class VehicleRoutingAlgorithms { return ruin; } - private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManagerImpl routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) { + private static RuinStrategy getRandomRuin(final VehicleRoutingProblem vrp, final StateManager routeStates, TypedMap definedClasses, ModKey modKey, double shareToRuin) { RuinStrategyKey stratKey = new RuinStrategyKey(modKey); RuinStrategy ruin = definedClasses.get(stratKey); if(ruin == null){ @@ -843,10 +845,12 @@ public class VehicleRoutingAlgorithms { return ruin; } - private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManagerImpl routeStates, List algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) { + private static InsertionStrategy createInsertionStrategy(HierarchicalConfiguration moduleConfig, VehicleRoutingProblem vrp,VehicleFleetManager vehicleFleetManager, StateManager routeStates, List algorithmListeners, ExecutorService executorService, int nuOfThreads, ConstraintManager constraintManager) { InsertionStrategy insertion = InsertionFactory.createInsertion(vrp, moduleConfig, vehicleFleetManager, routeStates, algorithmListeners, executorService, nuOfThreads, constraintManager); return insertion; } + + } diff --git a/jsprit-core/src/main/java/algorithms/VehicleSwitched.java b/jsprit-core/src/main/java/algorithms/VehicleSwitched.java index 4983a4a0..a9aa86bd 100644 --- a/jsprit-core/src/main/java/algorithms/VehicleSwitched.java +++ b/jsprit-core/src/main/java/algorithms/VehicleSwitched.java @@ -17,6 +17,7 @@ package algorithms; import basics.route.Vehicle; +import basics.route.VehicleFleetManager; import basics.route.VehicleRoute; diff --git a/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java b/jsprit-core/src/main/java/algorithms/VehicleTypeDependentJobInsertionCalculator.java similarity index 73% rename from jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java rename to jsprit-core/src/main/java/algorithms/VehicleTypeDependentJobInsertionCalculator.java index 63ca251d..b729b94a 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesVehTypeDepServiceInsertion.java +++ b/jsprit-core/src/main/java/algorithms/VehicleTypeDependentJobInsertionCalculator.java @@ -25,20 +25,21 @@ import algorithms.InsertionData.NoInsertionFound; import basics.Job; import basics.route.Driver; import basics.route.Vehicle; +import basics.route.VehicleFleetManager; import basics.route.VehicleImpl.NoVehicle; import basics.route.VehicleRoute; -final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculator{ +final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCostsCalculator{ - private Logger logger = Logger.getLogger(CalculatesVehTypeDepServiceInsertion.class); + private Logger logger = Logger.getLogger(VehicleTypeDependentJobInsertionCalculator.class); private final VehicleFleetManager fleetManager; - private final JobInsertionCalculator insertionCalculator; + private final JobInsertionCostsCalculator insertionCalculator; - public CalculatesVehTypeDepServiceInsertion(final VehicleFleetManager fleetManager, final JobInsertionCalculator jobInsertionCalc) { + public VehicleTypeDependentJobInsertionCalculator(final VehicleFleetManager fleetManager, final JobInsertionCostsCalculator jobInsertionCalc) { this.fleetManager = fleetManager; this.insertionCalculator = jobInsertionCalc; logger.info("inialise " + this); @@ -49,10 +50,10 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat return "[name=vehicleTypeDependentServiceInsertion]"; } - public InsertionData calculate(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) { + public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) { Vehicle selectedVehicle = currentRoute.getVehicle(); Driver selectedDriver = currentRoute.getDriver(); - InsertionData bestIData = InsertionData.noInsertionFound(); + InsertionData bestIData = InsertionData.createEmptyInsertionData(); double bestKnownCost_ = bestKnownCost; Collection relevantVehicles = new ArrayList(); if(!(selectedVehicle instanceof NoVehicle)) { @@ -65,7 +66,7 @@ final class CalculatesVehTypeDepServiceInsertion implements JobInsertionCalculat for(Vehicle v : relevantVehicles){ double depTime = v.getEarliestDeparture(); - InsertionData iData = insertionCalculator.calculate(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_); + InsertionData iData = insertionCalculator.getInsertionData(currentRoute, jobToInsert, v, depTime, selectedDriver, bestKnownCost_); if(iData instanceof NoInsertionFound) { if(bestIData instanceof NoInsertionFound) bestIData = iData; continue; 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 7ae743f9..0923a02f 100644 --- a/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java +++ b/jsprit-core/src/main/java/basics/algo/InsertionStartsListener.java @@ -25,4 +25,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/basics/algo/RuinListener.java b/jsprit-core/src/main/java/basics/algo/RuinListener.java new file mode 100644 index 00000000..bb75ca78 --- /dev/null +++ b/jsprit-core/src/main/java/basics/algo/RuinListener.java @@ -0,0 +1,39 @@ +package basics.algo; + +import java.util.Collection; + +import basics.Job; +import basics.route.VehicleRoute; + +/** + * Listener that listens to the ruin-process. It informs whoever is interested about start, end and about a removal of a job. + * + * @author schroeder + * + */ +public interface RuinListener extends SearchStrategyModuleListener{ + + /** + * informs about ruin-start. + * + * @param routes + */ + public void ruinStarts(Collection routes); + + /** + * informs about ruin-end. + * + * @param routes + * @param unassignedJobs + */ + public void ruinEnds(Collection routes, Collection unassignedJobs); + + /** + * informs if a {@link Job} has been removed from a {@link VehicleRoute}. + * + * @param job + * @param fromRoute + */ + public void removed(Job job, VehicleRoute fromRoute); + +} \ No newline at end of file diff --git a/jsprit-core/src/main/java/basics/algo/RuinListeners.java b/jsprit-core/src/main/java/basics/algo/RuinListeners.java new file mode 100644 index 00000000..fc442cc9 --- /dev/null +++ b/jsprit-core/src/main/java/basics/algo/RuinListeners.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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 basics.algo; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import basics.Job; +import basics.route.VehicleRoute; + +public class RuinListeners { + + private Collection ruinListeners = new ArrayList(); + + public void ruinStarts(Collection routes){ + for(RuinListener l : ruinListeners) l.ruinStarts(routes); + } + + public void ruinEnds(Collection routes, Collection unassignedJobs){ + for(RuinListener l : ruinListeners) l.ruinEnds(routes, unassignedJobs); + } + + public void removed(Job job, VehicleRoute fromRoute){ + for(RuinListener l : ruinListeners) l.removed(job, fromRoute); + } + + public void addListener(RuinListener ruinListener){ + ruinListeners.add(ruinListener); + } + + public void removeListener(RuinListener ruinListener){ + ruinListeners.remove(ruinListener); + } + + public Collection getListeners(){ + return Collections.unmodifiableCollection(ruinListeners); + } +} diff --git a/jsprit-core/src/main/java/basics/algo/SearchStrategy.java b/jsprit-core/src/main/java/basics/algo/SearchStrategy.java index 3fd56556..c63ecc2e 100644 --- a/jsprit-core/src/main/java/basics/algo/SearchStrategy.java +++ b/jsprit-core/src/main/java/basics/algo/SearchStrategy.java @@ -125,7 +125,8 @@ public class SearchStrategy { VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(lastSolution); lastSolution = newSolution; } - solutionCostCalculator.calculateCosts(lastSolution); + double costs = solutionCostCalculator.getCosts(lastSolution); + lastSolution.setCost(costs); boolean solutionAccepted = solutionAcceptor.acceptSolution(solutions, lastSolution); DiscoveredSolution discoveredSolution = new DiscoveredSolution(lastSolution, solutionAccepted, getName()); return discoveredSolution; diff --git a/jsprit-core/src/main/java/basics/algo/SolutionCostCalculator.java b/jsprit-core/src/main/java/basics/algo/SolutionCostCalculator.java index f7958a0e..db67b2ca 100644 --- a/jsprit-core/src/main/java/basics/algo/SolutionCostCalculator.java +++ b/jsprit-core/src/main/java/basics/algo/SolutionCostCalculator.java @@ -21,10 +21,11 @@ import basics.VehicleRoutingProblemSolution; public interface SolutionCostCalculator { /** - * This assumes that the solution is modified by setting its costs
- * solution.setCost(costs); + * Returns costs of solution. + * * @param solution + * @return TODO */ - public void calculateCosts(VehicleRoutingProblemSolution solution); + public double getCosts(VehicleRoutingProblemSolution solution); } diff --git a/jsprit-core/src/main/java/algorithms/ActivityVisitor.java b/jsprit-core/src/main/java/basics/route/ActivityVisitor.java similarity index 89% rename from jsprit-core/src/main/java/algorithms/ActivityVisitor.java rename to jsprit-core/src/main/java/basics/route/ActivityVisitor.java index 0ac3d53f..6ad321f3 100644 --- a/jsprit-core/src/main/java/algorithms/ActivityVisitor.java +++ b/jsprit-core/src/main/java/basics/route/ActivityVisitor.java @@ -14,12 +14,10 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package basics.route; -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/basics/route/FiniteFleetManagerFactory.java b/jsprit-core/src/main/java/basics/route/FiniteFleetManagerFactory.java new file mode 100644 index 00000000..05c01461 --- /dev/null +++ b/jsprit-core/src/main/java/basics/route/FiniteFleetManagerFactory.java @@ -0,0 +1,20 @@ +package basics.route; + +import java.util.Collection; + + +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/basics/route/InfiniteFleetManagerFactory.java b/jsprit-core/src/main/java/basics/route/InfiniteFleetManagerFactory.java new file mode 100644 index 00000000..f4345b8a --- /dev/null +++ b/jsprit-core/src/main/java/basics/route/InfiniteFleetManagerFactory.java @@ -0,0 +1,20 @@ +package basics.route; + +import java.util.Collection; + + +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/basics/route/InfiniteVehicles.java similarity index 74% rename from jsprit-core/src/main/java/algorithms/InfiniteVehicles.java rename to jsprit-core/src/main/java/basics/route/InfiniteVehicles.java index aff00583..41470de7 100644 --- a/jsprit-core/src/main/java/algorithms/InfiniteVehicles.java +++ b/jsprit-core/src/main/java/basics/route/InfiniteVehicles.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package basics.route; import java.util.ArrayList; import java.util.Collection; @@ -24,26 +24,14 @@ import java.util.Map; import org.apache.log4j.Logger; -import basics.route.Vehicle; class InfiniteVehicles implements VehicleFleetManager{ - -// static class TypeKeyComparator implements Comparator{ -// -// @Override -// public int compare(TypeKey k1, TypeKey k2) { -// double k1_fix = k1.type.getVehicleCostParams().fix; -// double k2_fix = k2.type.getVehicleCostParams().fix; -// return (int)(k1_fix - k2_fix); -// } -// -// } 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); @@ -57,12 +45,11 @@ 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); } -// Collections.sort(sortedTypes, new TypeKeyComparator()); } @@ -95,8 +82,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/ReverseActivityVisitor.java b/jsprit-core/src/main/java/basics/route/ReverseActivityVisitor.java similarity index 89% rename from jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java rename to jsprit-core/src/main/java/basics/route/ReverseActivityVisitor.java index 03902866..90896cd0 100644 --- a/jsprit-core/src/main/java/algorithms/ReverseActivityVisitor.java +++ b/jsprit-core/src/main/java/basics/route/ReverseActivityVisitor.java @@ -14,12 +14,10 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package basics.route; -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/basics/route/ReverseRouteActivityVisitor.java similarity index 92% rename from jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java rename to jsprit-core/src/main/java/basics/route/ReverseRouteActivityVisitor.java index 08ead908..ddb9508c 100644 --- a/jsprit-core/src/main/java/algorithms/ReverseRouteActivityVisitor.java +++ b/jsprit-core/src/main/java/basics/route/ReverseRouteActivityVisitor.java @@ -14,16 +14,14 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package basics.route; import java.util.ArrayList; import java.util.Collection; 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/basics/route/RouteActivityVisitor.java similarity index 92% rename from jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java rename to jsprit-core/src/main/java/basics/route/RouteActivityVisitor.java index 625bbc32..cef22424 100644 --- a/jsprit-core/src/main/java/algorithms/RouteActivityVisitor.java +++ b/jsprit-core/src/main/java/basics/route/RouteActivityVisitor.java @@ -14,15 +14,13 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package basics.route; import java.util.ArrayList; 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/basics/route/RouteVisitor.java similarity index 92% rename from jsprit-core/src/main/java/algorithms/RouteVisitor.java rename to jsprit-core/src/main/java/basics/route/RouteVisitor.java index e82f6216..df7669c8 100644 --- a/jsprit-core/src/main/java/algorithms/RouteVisitor.java +++ b/jsprit-core/src/main/java/basics/route/RouteVisitor.java @@ -14,11 +14,10 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package basics.route; -import basics.route.VehicleRoute; -interface RouteVisitor { +public interface RouteVisitor { public void visit(VehicleRoute route); diff --git a/jsprit-core/src/main/java/basics/route/TourActivities.java b/jsprit-core/src/main/java/basics/route/TourActivities.java index c7a1eaf5..00c01f3f 100644 --- a/jsprit-core/src/main/java/basics/route/TourActivities.java +++ b/jsprit-core/src/main/java/basics/route/TourActivities.java @@ -113,6 +113,12 @@ public class TourActivities { return Collections.unmodifiableSet(jobs); } + /** + * Returns true if job is in jobList, otherwise false. + * + * @param job + * @return + */ public boolean servesJob(Job job) { return jobs.contains(job); } @@ -146,13 +152,24 @@ public class TourActivities { } } } - if(jobRemoved != activityRemoved) throw new IllegalStateException("job removed, but belonging activity not."); + assert jobRemoved == activityRemoved : "job removed, but belonging activity not."; return activityRemoved; } + /** + * Inserts the specified activity add the specified insertionIndex. Shifts the element currently at that position (if any) and + * any subsequent elements to the right (adds one to their indices). + *

If specified activity instanceof JobActivity, it adds job to jobList. + *

If insertionIndex > tourActivitiies.size(), it just adds the specified act at the end. + * + * @param insertionIndex + * @param act + * @throws IndexOutOfBoundsException if insertionIndex < 0; + */ public void addActivity(int insertionIndex, TourActivity act) { - assert insertionIndex >= 0 : "insertionIndex == 0, this cannot be"; - if(tourActivities.contains(act)) throw new IllegalStateException("act " + act + " already in tour. cannot add act twice."); + + assert insertionIndex >= 0 : "insertionIndex < 0, this cannot be"; + /* * if 1 --> between start and act(0) --> act(0) * if 2 && 2 <= acts.size --> between act(0) and act(1) --> act(1) @@ -166,9 +183,15 @@ public class TourActivities { } /** +<<<<<<< HEAD * adds activity. * * @throw {@link IllegalStateException} if same activity is added twice. +======= + * Adds specified activity at the end of activity-list. + *

If act instanceof JobActivity, it adds underlying job also. + * @throws IllegalStateException if activity-list already contains act. +>>>>>>> refs/remotes/choose_remote_name/relaxAPI * @param act */ public void addActivity(TourActivity act){ @@ -184,6 +207,11 @@ public class TourActivities { } } + /** + * Returns number of jobs. + * + * @return + */ public int jobSize() { return jobs.size(); } diff --git a/jsprit-core/src/main/java/algorithms/StateTypes.java b/jsprit-core/src/main/java/basics/route/VehicleFleetManager.java similarity index 62% rename from jsprit-core/src/main/java/algorithms/StateTypes.java rename to jsprit-core/src/main/java/basics/route/VehicleFleetManager.java index 1625e7ce..d71d2f7b 100644 --- a/jsprit-core/src/main/java/algorithms/StateTypes.java +++ b/jsprit-core/src/main/java/basics/route/VehicleFleetManager.java @@ -14,27 +14,23 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package basics.route; + +import java.util.Collection; -class StateTypes { +public interface VehicleFleetManager { -// final static StateId LOAD = new StateIdImpl("load"); - - final static String LOAD = "load"; - - final static String LOAD_AT_DEPOT = "loadAtDepot"; - - final static String DURATION = "duration"; - - final static String LATEST_OPERATION_START_TIME = "latestOST"; - - final static String EARLIEST_OPERATION_START_TIME = "earliestOST"; + public abstract void lock(Vehicle vehicle); + + public abstract void unlock(Vehicle vehicle); + + public abstract boolean isLocked(Vehicle vehicle); + + public abstract void unlockAll(); + + public abstract Collection getAvailableVehicles(); + + public Collection getAvailableVehicles(String withoutThisType, String locationId); - static final String COSTS = "costs"; - - final static String FUTURE_PICKS = "futurePicks"; - - final static String PAST_DELIVERIES = "pastDeliveries"; - } diff --git a/jsprit-core/src/main/java/basics/route/VehicleFleetManagerFactory.java b/jsprit-core/src/main/java/basics/route/VehicleFleetManagerFactory.java new file mode 100644 index 00000000..29a3980a --- /dev/null +++ b/jsprit-core/src/main/java/basics/route/VehicleFleetManagerFactory.java @@ -0,0 +1,7 @@ +package basics.route; + +public interface VehicleFleetManagerFactory { + + public VehicleFleetManager createFleetManager(); + +} diff --git a/jsprit-core/src/main/java/algorithms/VehicleFleetManagerImpl.java b/jsprit-core/src/main/java/basics/route/VehicleFleetManagerImpl.java similarity index 89% rename from jsprit-core/src/main/java/algorithms/VehicleFleetManagerImpl.java rename to jsprit-core/src/main/java/basics/route/VehicleFleetManagerImpl.java index 2f5c07c9..f3d8569b 100644 --- a/jsprit-core/src/main/java/algorithms/VehicleFleetManagerImpl.java +++ b/jsprit-core/src/main/java/basics/route/VehicleFleetManagerImpl.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package basics.route; import java.util.ArrayList; import java.util.Collection; @@ -27,12 +27,11 @@ import java.util.Set; import org.apache.log4j.Logger; -import basics.route.PenaltyVehicleType; -import basics.route.Vehicle; import basics.route.VehicleImpl.NoVehicle; + class VehicleFleetManagerImpl implements VehicleFleetManager { public VehicleFleetManagerImpl newInstance(Collection vehicles){ @@ -54,11 +53,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(); @@ -92,9 +91,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; @@ -122,8 +121,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); } @@ -135,11 +134,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)); } @@ -150,7 +149,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); } @@ -167,7 +166,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()); } @@ -193,8 +192,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/basics/route/VehicleTypeKey.java b/jsprit-core/src/main/java/basics/route/VehicleTypeKey.java new file mode 100644 index 00000000..56dae41c --- /dev/null +++ b/jsprit-core/src/main/java/basics/route/VehicleTypeKey.java @@ -0,0 +1,48 @@ +package basics.route; + +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/ActivityTimeTracker.java b/jsprit-core/src/main/java/util/ActivityTimeTracker.java similarity index 96% rename from jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java rename to jsprit-core/src/main/java/util/ActivityTimeTracker.java index 8c6e4aab..6c0a7361 100644 --- a/jsprit-core/src/main/java/algorithms/ActivityTimeTracker.java +++ b/jsprit-core/src/main/java/util/ActivityTimeTracker.java @@ -14,13 +14,14 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ -package algorithms; +package util; import basics.costs.ForwardTransportTime; +import basics.route.ActivityVisitor; import basics.route.TourActivity; import basics.route.VehicleRoute; -class ActivityTimeTracker implements ActivityVisitor{ +public class ActivityTimeTracker implements ActivityVisitor{ private ForwardTransportTime transportTime; diff --git a/jsprit-core/src/main/java/util/Solutions.java b/jsprit-core/src/main/java/util/Solutions.java index 12d69e0b..a206f05a 100644 --- a/jsprit-core/src/main/java/util/Solutions.java +++ b/jsprit-core/src/main/java/util/Solutions.java @@ -22,6 +22,7 @@ import basics.VehicleRoutingProblemSolution; public class Solutions { + @Deprecated public static VehicleRoutingProblemSolution getBest(Collection solutions){ VehicleRoutingProblemSolution best = null; for(VehicleRoutingProblemSolution s : solutions){ @@ -30,5 +31,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/AverageJobDistanceTest.java b/jsprit-core/src/test/java/algorithms/AverageJobDistanceTest.java index ec375f72..6a81431c 100644 --- a/jsprit-core/src/test/java/algorithms/AverageJobDistanceTest.java +++ b/jsprit-core/src/test/java/algorithms/AverageJobDistanceTest.java @@ -42,13 +42,13 @@ public class AverageJobDistanceTest { Shipment s1 = Shipment.Builder.newInstance("s1", 1).setPickupLocation("0,0").setDeliveryLocation("10,10").build(); Shipment s2 = Shipment.Builder.newInstance("s2", 1).setPickupLocation("0,0").setDeliveryLocation("10,10").build(); - double dist = new AvgJobDistance(routingCosts).calculateDistance(s1, s2); + double dist = new AvgJobDistance(routingCosts).getDistance(s1, s2); for(int i=0;i<10;i++){ for(int j=0;j<10;j++){ Shipment other1 = Shipment.Builder.newInstance("s1", 1).setPickupLocation("0,0").setDeliveryLocation(i+","+j).build(); Shipment other2 = Shipment.Builder.newInstance("s2", 1).setPickupLocation("0,0").setDeliveryLocation("10,10").build(); - double dist2 = new AvgJobDistance(routingCosts).calculateDistance(other1, other2); + double dist2 = new AvgJobDistance(routingCosts).getDistance(other1, other2); System.out.println("("+i+","+j+"), dist=" + dist + ", dist2=" + dist2); assertTrue(dist<=dist2+dist2*0.001); } @@ -62,7 +62,7 @@ public class AverageJobDistanceTest { Service s1 = Service.Builder.newInstance("s1", 1).setLocationId("10,0").build(); Service s2 = Service.Builder.newInstance("s2", 1).setLocationId("10,0").build(); - double dist = new AvgJobDistance(routingCosts).calculateDistance(s1, s2); + double dist = new AvgJobDistance(routingCosts).getDistance(s1, s2); assertEquals(0.0,dist,0.01); } } diff --git a/jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java b/jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java index 00659c2e..a21b575b 100644 --- a/jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java +++ b/jsprit-core/src/test/java/algorithms/BuildCVRPAlgoFromScratchTest.java @@ -24,9 +24,6 @@ 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.selectors.SelectBest; import basics.VehicleRoutingAlgorithm; @@ -37,7 +34,9 @@ import basics.algo.SearchStrategy; import basics.algo.SearchStrategyManager; import basics.algo.SolutionCostCalculator; import basics.io.VrpXMLReader; +import basics.route.InfiniteFleetManagerFactory; import basics.route.TourActivity; +import basics.route.VehicleFleetManager; import basics.route.VehicleRoute; public class BuildCVRPAlgoFromScratchTest { @@ -52,19 +51,21 @@ public class BuildCVRPAlgoFromScratchTest { new VrpXMLReader(builder).read("src/test/resources/vrpnc1-jsprit.xml"); vrp = builder.build(); - final StateManagerImpl stateManager = new StateManagerImpl(); + final StateManager stateManager = new StateManager(); HardActivityLevelConstraint hardActLevelConstraint = new HardActivityLevelConstraint() { @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { - return true; + public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + return ConstraintsStatus.FULFILLED; } }; - ActivityInsertionCostsCalculator marginalCalculus = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), hardActLevelConstraint); - ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager)); + + + ActivityInsertionCostsCalculator marginalCalculus = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts()); + ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), marginalCalculus, new HardLoadConstraint(stateManager), hardActLevelConstraint); - VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles()); - JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, serviceInsertion); + VehicleFleetManager fleetManager = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager(); + JobInsertionCostsCalculator finalServiceInsertion = new VehicleTypeDependentJobInsertionCalculator(fleetManager, serviceInsertion); BestInsertion bestInsertion = new BestInsertion(finalServiceInsertion); @@ -74,12 +75,12 @@ public class BuildCVRPAlgoFromScratchTest { SolutionCostCalculator solutionCostCalculator = new SolutionCostCalculator() { @Override - public void calculateCosts(VehicleRoutingProblemSolution solution) { + public double getCosts(VehicleRoutingProblemSolution solution) { double costs = 0.0; for(VehicleRoute route : solution.getRoutes()){ - costs += stateManager.getRouteState(route, StateTypes.COSTS).toDouble(); + costs += stateManager.getRouteState(route, StateFactory.COSTS).toDouble(); } - solution.setCost(costs); + return costs; } }; @@ -111,7 +112,9 @@ public class BuildCVRPAlgoFromScratchTest { vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateCostsAtRouteLevel(stateManager, vrp.getTransportCosts(), vrp.getActivityCosts())); vra.getSearchStrategyManager().addSearchStrategyModuleListener(new UpdateLoadAtRouteLevel(stateManager)); - VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion, solutionCostCalculator).createInitialSolution(vrp); + + VehicleRoutingProblemSolution iniSolution = new InsertionInitialSolutionFactory(bestInsertion, solutionCostCalculator).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 138f0e83..588d5751 100644 --- a/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java +++ b/jsprit-core/src/test/java/algorithms/BuildPDVRPAlgoFromScratchTest.java @@ -22,12 +22,8 @@ import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; -import algorithms.HardConstraints.HardActivityLevelConstraintManager; +import util.Solutions; import algorithms.StateManager.StateImpl; -import algorithms.StateUpdates.UpdateActivityTimes; -import algorithms.StateUpdates.UpdateCostsAtAllLevels; -import algorithms.StateUpdates.UpdateEarliestStartTimeWindowAtActLocations; -import algorithms.StateUpdates.UpdateLatestOperationStartTimeAtActLocations; import algorithms.acceptors.AcceptNewIfBetterThanWorst; import algorithms.selectors.SelectBest; import basics.Delivery; @@ -42,6 +38,10 @@ import basics.algo.SearchStrategy; import basics.algo.SearchStrategyManager; import basics.algo.SolutionCostCalculator; import basics.io.VrpXMLReader; +import basics.route.InfiniteFleetManagerFactory; +import basics.route.ReverseRouteActivityVisitor; +import basics.route.RouteActivityVisitor; +import basics.route.VehicleFleetManager; import basics.route.VehicleRoute; public class BuildPDVRPAlgoFromScratchTest { @@ -59,19 +59,20 @@ public class BuildPDVRPAlgoFromScratchTest { new VrpXMLReader(builder).read("src/test/resources/pd_solomon_r101.xml"); vrp = builder.build(); - final StateManagerImpl stateManager = new StateManagerImpl(); + final StateManager stateManager = new StateManager(); - 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())); - ActivityInsertionCostsCalculator marginalCalculus = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), actLevelConstraintAccumulator); + ActivityInsertionCostsCalculator marginalCalculus = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts()); + + ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), marginalCalculus, new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager), actLevelConstraintAccumulator); - ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager)); // CalculatesServiceInsertion serviceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager)); - VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles()); - JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, serviceInsertion); + VehicleFleetManager fleetManager = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager(); + JobInsertionCostsCalculator finalServiceInsertion = new VehicleTypeDependentJobInsertionCalculator(fleetManager, serviceInsertion); BestInsertion bestInsertion = new BestInsertion(finalServiceInsertion); @@ -81,12 +82,12 @@ public class BuildPDVRPAlgoFromScratchTest { SolutionCostCalculator solutionCostCalculator = new SolutionCostCalculator() { @Override - public void calculateCosts(VehicleRoutingProblemSolution solution) { + public double getCosts(VehicleRoutingProblemSolution solution) { double costs = 0.0; for(VehicleRoute route : solution.getRoutes()){ - costs += stateManager.getRouteState(route, StateTypes.COSTS).toDouble(); + costs += stateManager.getRouteState(route, StateFactory.COSTS).toDouble(); } - solution.setCost(costs); + return costs; } }; @@ -103,9 +104,8 @@ public class BuildPDVRPAlgoFromScratchTest { strategyManager.addStrategy(randomStrategy, 0.5); vra = new VehicleRoutingAlgorithm(vrp, strategyManager); - - - vra.getAlgorithmListeners().addListener(new StateUpdates.ResetStateManager(stateManager)); + + vra.getAlgorithmListeners().addListener(stateManager); final RouteActivityVisitor iterateForward = new RouteActivityVisitor(); @@ -113,12 +113,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() { @@ -136,8 +136,8 @@ public class BuildPDVRPAlgoFromScratchTest { loadAtEnd += j.getCapacityDemand(); } } - stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot)); - stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd)); + stateManager.putRouteState(route, StateFactory.LOAD_AT_BEGINNING, new StateImpl(loadAtDepot)); + stateManager.putRouteState(route, StateFactory.LOAD, new StateImpl(loadAtEnd)); iterateForward.visit(route); iterateBackward.visit(route); } @@ -154,14 +154,14 @@ public class BuildPDVRPAlgoFromScratchTest { // log.info("insert job " + job2insert.getClass().toString() + " job " + job2insert + "" + job2insert.getCapacityDemand() + " in route " + inRoute.getTourActivities()); if(job2insert instanceof Delivery){ - int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble(); + int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING).toDouble(); // log.info("loadAtDepot="+loadAtDepot); - stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand())); + stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, StateFactory.createState(loadAtDepot + job2insert.getCapacityDemand())); } if(job2insert instanceof Pickup){ - int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble(); + int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END).toDouble(); // log.info("loadAtEnd="+loadAtEnd); - stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand())); + stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_END, StateFactory.createState(loadAtEnd + job2insert.getCapacityDemand())); } iterateForward.visit(inRoute); iterateBackward.visit(inRoute); @@ -171,7 +171,8 @@ public class BuildPDVRPAlgoFromScratchTest { bestInsertion.addListener(loadVehicleInDepot); bestInsertion.addListener(updateLoadAfterJobHasBeenInserted); - VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion, solutionCostCalculator).createInitialSolution(vrp); + VehicleRoutingProblemSolution iniSolution = new InsertionInitialSolutionFactory(bestInsertion, solutionCostCalculator).createSolution(vrp); + // System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size()); vra.addInitialSolution(iniSolution); @@ -183,7 +184,7 @@ public class BuildPDVRPAlgoFromScratchTest { @Test public void test(){ Collection solutions = vra.searchSolutions(); -// System.out.println(Solutions.getBest(solutions).getCost()); + System.out.println(Solutions.getBest(solutions).getCost()); // new VrpXMLWriter(vrp, solutions).write("output/pd_solomon_r101.xml"); } diff --git a/jsprit-core/src/test/java/algorithms/BuildPDVRPWithShipmentsAlgoFromScratchTest.java b/jsprit-core/src/test/java/algorithms/BuildPDVRPWithShipmentsAlgoFromScratchTest.java index f18fbbc4..ff87f1dd 100644 --- a/jsprit-core/src/test/java/algorithms/BuildPDVRPWithShipmentsAlgoFromScratchTest.java +++ b/jsprit-core/src/test/java/algorithms/BuildPDVRPWithShipmentsAlgoFromScratchTest.java @@ -23,12 +23,7 @@ import org.junit.Before; import org.junit.Test; import util.Solutions; -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.acceptors.AcceptNewIfBetterThanWorst; import algorithms.selectors.SelectBest; import basics.Delivery; @@ -46,7 +41,11 @@ import basics.algo.SearchStrategyManager; import basics.algo.SolutionCostCalculator; import basics.io.VrpXMLReader; import basics.io.VrpXMLWriter; +import basics.route.InfiniteFleetManagerFactory; +import basics.route.ReverseRouteActivityVisitor; +import basics.route.RouteActivityVisitor; import basics.route.TourActivity; +import basics.route.VehicleFleetManager; import basics.route.VehicleRoute; public class BuildPDVRPWithShipmentsAlgoFromScratchTest { @@ -76,25 +75,26 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest { vrp = builder.build(); - final StateManagerImpl stateManager = new StateManagerImpl(); + final StateManager stateManager = new StateManager(); - HardActivityLevelConstraintManager actLevelConstraintAccumulator = new HardActivityLevelConstraintManager(); - actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts())); - actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardPickupAndDeliveryActivityLevelConstraint(stateManager)); - actLevelConstraintAccumulator.addConstraint(new HardConstraints.HardPickupAndDeliveryShipmentActivityLevelConstraint(stateManager)); + ConstraintManager constraintManager = new ConstraintManager(); + constraintManager.addConstraint(new HardTimeWindowActivityLevelConstraint(stateManager, vrp.getTransportCosts())); + constraintManager.addConstraint(new HardPickupAndDeliveryActivityLevelConstraint(stateManager)); + constraintManager.addConstraint(new HardPickupAndDeliveryShipmentActivityLevelConstraint(stateManager)); + constraintManager.addConstraint(new HardPickupAndDeliveryLoadRouteLevelConstraint(stateManager)); - ActivityInsertionCostsCalculator marginalCalculus = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), actLevelConstraintAccumulator); + ActivityInsertionCostsCalculator marginalCalculus = new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts()); - ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardPickupAndDeliveryLoadConstraint(stateManager)); + ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), marginalCalculus, constraintManager, constraintManager); - ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), marginalCalculus, new HardConstraints.HardLoadConstraint(stateManager)); + ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), marginalCalculus, constraintManager, constraintManager); JobCalculatorSwitcher switcher = new JobCalculatorSwitcher(); switcher.put(Shipment.class, shipmentInsertion); switcher.put(Service.class, serviceInsertion); - VehicleFleetManager fleetManager = new InfiniteVehicles(vrp.getVehicles()); - JobInsertionCalculator finalServiceInsertion = new CalculatesVehTypeDepServiceInsertion(fleetManager, switcher); + VehicleFleetManager fleetManager = new InfiniteFleetManagerFactory(vrp.getVehicles()).createFleetManager(); + JobInsertionCostsCalculator finalServiceInsertion = new VehicleTypeDependentJobInsertionCalculator(fleetManager, switcher); BestInsertion bestInsertion = new BestInsertion(finalServiceInsertion); @@ -104,12 +104,12 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest { SolutionCostCalculator solutionCostCalculator = new SolutionCostCalculator() { @Override - public void calculateCosts(VehicleRoutingProblemSolution solution) { + public double getCosts(VehicleRoutingProblemSolution solution) { double costs = 0.0; for(VehicleRoute route : solution.getRoutes()){ - costs += stateManager.getRouteState(route, StateTypes.COSTS).toDouble(); + costs += stateManager.getRouteState(route, StateFactory.COSTS).toDouble(); } - solution.setCost(costs); + return costs; } }; @@ -127,8 +127,7 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest { vra = new VehicleRoutingAlgorithm(vrp, strategyManager); - - vra.getAlgorithmListeners().addListener(new StateUpdates.ResetStateManager(stateManager)); + vra.getAlgorithmListeners().addListener(stateManager); final RouteActivityVisitor iterateForward = new RouteActivityVisitor(); @@ -136,12 +135,12 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest { 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() { @@ -159,8 +158,8 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest { loadAtEnd += j.getCapacityDemand(); } } - stateManager.putRouteState(route, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot)); - stateManager.putRouteState(route, StateTypes.LOAD, new StateImpl(loadAtEnd)); + stateManager.putRouteState(route, StateFactory.LOAD_AT_BEGINNING, new StateImpl(loadAtDepot)); + stateManager.putRouteState(route, StateFactory.LOAD, new StateImpl(loadAtEnd)); iterateForward.visit(route); iterateBackward.visit(route); } @@ -177,14 +176,14 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest { // log.info("insert job " + job2insert.getClass().toString() + " job " + job2insert + "" + job2insert.getCapacityDemand() + " in route " + inRoute.getTourActivities()); if(job2insert instanceof Delivery){ - int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD_AT_DEPOT).toDouble(); + int loadAtDepot = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING).toDouble(); // log.info("loadAtDepot="+loadAtDepot); - stateManager.putRouteState(inRoute, StateTypes.LOAD_AT_DEPOT, new StateImpl(loadAtDepot + job2insert.getCapacityDemand())); + stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_BEGINNING, new StateImpl(loadAtDepot + job2insert.getCapacityDemand())); } if(job2insert instanceof Pickup){ - int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateTypes.LOAD).toDouble(); + int loadAtEnd = (int) stateManager.getRouteState(inRoute, StateFactory.LOAD_AT_END).toDouble(); // log.info("loadAtEnd="+loadAtEnd); - stateManager.putRouteState(inRoute, StateTypes.LOAD, new StateImpl(loadAtEnd + job2insert.getCapacityDemand())); + stateManager.putRouteState(inRoute, StateFactory.LOAD_AT_END, new StateImpl(loadAtEnd + job2insert.getCapacityDemand())); } iterateForward.visit(inRoute); iterateBackward.visit(inRoute); @@ -194,11 +193,11 @@ public class BuildPDVRPWithShipmentsAlgoFromScratchTest { bestInsertion.addListener(loadVehicleInDepot); bestInsertion.addListener(updateLoadAfterJobHasBeenInserted); - VehicleRoutingProblemSolution iniSolution = new CreateInitialSolution(bestInsertion, solutionCostCalculator).createInitialSolution(vrp); + VehicleRoutingProblemSolution iniSolution = new InsertionInitialSolutionFactory(bestInsertion, solutionCostCalculator).createSolution(vrp); // System.out.println("ini: costs="+iniSolution.getCost()+";#routes="+iniSolution.getRoutes().size()); vra.addInitialSolution(iniSolution); - vra.setNuOfIterations(1000); + vra.setNuOfIterations(100); vra.setPrematureBreak(100); } diff --git a/jsprit-core/src/test/java/algorithms/CalcVehicleTypeDependentServiceInsertionTest.java b/jsprit-core/src/test/java/algorithms/CalcVehicleTypeDependentServiceInsertionTest.java index 46ae53a6..8a6cbd27 100644 --- a/jsprit-core/src/test/java/algorithms/CalcVehicleTypeDependentServiceInsertionTest.java +++ b/jsprit-core/src/test/java/algorithms/CalcVehicleTypeDependentServiceInsertionTest.java @@ -29,6 +29,7 @@ import org.junit.Test; import basics.Service; import basics.route.TimeWindow; import basics.route.Vehicle; +import basics.route.VehicleFleetManager; import basics.route.VehicleImpl; import basics.route.VehicleRoute; import basics.route.VehicleTypeImpl; @@ -71,28 +72,28 @@ public class CalcVehicleTypeDependentServiceInsertionTest { @Test public void whenHaving2Vehicle_calcInsertionOfCheapest(){ - JobInsertionCalculator calc = mock(JobInsertionCalculator.class); + JobInsertionCostsCalculator calc = mock(JobInsertionCostsCalculator.class); InsertionData iDataVeh1 = new InsertionData(10.0,InsertionData.NO_INDEX, 1, veh1, null); InsertionData iDataVeh2 = new InsertionData(20.0,InsertionData.NO_INDEX, 1, veh2, null); - when(calc.calculate(vehicleRoute, service, veh1, veh1.getEarliestDeparture(), null, Double.MAX_VALUE)).thenReturn(iDataVeh1); - when(calc.calculate(vehicleRoute, service, veh2, veh2.getEarliestDeparture(), null, Double.MAX_VALUE)).thenReturn(iDataVeh2); - when(calc.calculate(vehicleRoute, service, veh2, veh2.getEarliestDeparture(), null, 10.0)).thenReturn(iDataVeh2); - CalculatesVehTypeDepServiceInsertion insertion = new CalculatesVehTypeDepServiceInsertion(fleetManager,calc); - InsertionData iData = insertion.calculate(vehicleRoute, service, null, 0.0, null, Double.MAX_VALUE); + when(calc.getInsertionData(vehicleRoute, service, veh1, veh1.getEarliestDeparture(), null, Double.MAX_VALUE)).thenReturn(iDataVeh1); + when(calc.getInsertionData(vehicleRoute, service, veh2, veh2.getEarliestDeparture(), null, Double.MAX_VALUE)).thenReturn(iDataVeh2); + when(calc.getInsertionData(vehicleRoute, service, veh2, veh2.getEarliestDeparture(), null, 10.0)).thenReturn(iDataVeh2); + VehicleTypeDependentJobInsertionCalculator insertion = new VehicleTypeDependentJobInsertionCalculator(fleetManager,calc); + InsertionData iData = insertion.getInsertionData(vehicleRoute, service, null, 0.0, null, Double.MAX_VALUE); assertThat(iData.getSelectedVehicle(), is(veh1)); } @Test public void whenHaving2Vehicle_calcInsertionOfCheapest2(){ - JobInsertionCalculator calc = mock(JobInsertionCalculator.class); + JobInsertionCostsCalculator calc = mock(JobInsertionCostsCalculator.class); InsertionData iDataVeh1 = new InsertionData(20.0,InsertionData.NO_INDEX, 1, veh1, null); InsertionData iDataVeh2 = new InsertionData(10.0,InsertionData.NO_INDEX, 1, veh2, null); - when(calc.calculate(vehicleRoute, service, veh1, veh1.getEarliestDeparture(), null, Double.MAX_VALUE)).thenReturn(iDataVeh1); - when(calc.calculate(vehicleRoute, service, veh2, veh2.getEarliestDeparture(), null, Double.MAX_VALUE)).thenReturn(iDataVeh2); - when(calc.calculate(vehicleRoute, service, veh2, veh2.getEarliestDeparture(), null, 20.0)).thenReturn(iDataVeh2); - CalculatesVehTypeDepServiceInsertion insertion = new CalculatesVehTypeDepServiceInsertion(fleetManager,calc); - InsertionData iData = insertion.calculate(vehicleRoute, service, null, 0.0, null, Double.MAX_VALUE); + when(calc.getInsertionData(vehicleRoute, service, veh1, veh1.getEarliestDeparture(), null, Double.MAX_VALUE)).thenReturn(iDataVeh1); + when(calc.getInsertionData(vehicleRoute, service, veh2, veh2.getEarliestDeparture(), null, Double.MAX_VALUE)).thenReturn(iDataVeh2); + when(calc.getInsertionData(vehicleRoute, service, veh2, veh2.getEarliestDeparture(), null, 20.0)).thenReturn(iDataVeh2); + VehicleTypeDependentJobInsertionCalculator insertion = new VehicleTypeDependentJobInsertionCalculator(fleetManager,calc); + InsertionData iData = insertion.getInsertionData(vehicleRoute, service, null, 0.0, null, Double.MAX_VALUE); assertThat(iData.getSelectedVehicle(), is(veh2)); } diff --git a/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java b/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java index 01701200..481e56d4 100644 --- a/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java +++ b/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java @@ -29,7 +29,6 @@ import org.junit.Test; import util.Coordinate; import util.ManhattanDistanceCalculator; import util.RouteUtils; -import algorithms.StateUpdates.UpdateStates; import basics.Job; import basics.Service; import basics.VehicleRoutingProblem; @@ -38,10 +37,12 @@ import basics.costs.VehicleRoutingActivityCosts; import basics.costs.VehicleRoutingTransportCosts; import basics.route.Driver; import basics.route.DriverImpl; +import basics.route.FiniteFleetManagerFactory; import basics.route.ServiceActivity; import basics.route.TimeWindow; import basics.route.TourActivities; import basics.route.Vehicle; +import basics.route.VehicleFleetManager; import basics.route.VehicleImpl; import basics.route.VehicleRoute; import basics.route.VehicleTypeImpl; @@ -68,13 +69,13 @@ public class GendreauPostOptTest { Service job3; - private StateManagerImpl states; + private StateManager states; private List vehicles; - private VehicleFleetManagerImpl fleetManager; + private VehicleFleetManager fleetManager; - private JobInsertionCalculator insertionCalc; + private JobInsertionCostsCalculator insertionCalc; @Before public void setUp(){ @@ -143,17 +144,20 @@ public class GendreauPostOptTest { vehicles = Arrays.asList(lightVehicle1,lightVehicle2, heavyVehicle); // Collection vehicles = Arrays.asList(lightVehicle1,lightVehicle2, heavyVehicle); - fleetManager = new VehicleFleetManagerImpl(vehicles); - states = new StateManagerImpl(); + fleetManager = new FiniteFleetManagerFactory(vehicles).createFleetManager(); + states = new StateManager(); activityCosts = new ExampleActivityCostFunction(); - ServiceInsertionCalculator standardServiceInsertion = new ServiceInsertionCalculator(cost, new LocalActivityInsertionCostsCalculator(cost, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, cost)), new HardConstraints.HardLoadConstraint(states)); + + ServiceInsertionCalculator standardServiceInsertion = new ServiceInsertionCalculator(cost, new LocalActivityInsertionCostsCalculator(cost, activityCosts), new HardLoadConstraint(states), new HardTimeWindowActivityLevelConstraint(states, cost)); + + - CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states); + JobInsertionConsideringFixCostsCalculator withFixCost = new JobInsertionConsideringFixCostsCalculator(standardServiceInsertion, states); withFixCost.setWeightOfFixCost(1.2); - insertionCalc = new CalculatesVehTypeDepServiceInsertion(fleetManager, withFixCost); + insertionCalc = new VehicleTypeDependentJobInsertionCalculator(fleetManager, withFixCost); // updater = new TourStateUpdater(states, cost, activityCosts); @@ -182,14 +186,16 @@ public class GendreauPostOptTest { routes.add(route); // routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle())); // routes.add(new VehicleRoute(getEmptyTour(),getDriver(),getNoVehicle())); - - VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(routes, states.getRouteState(route, StateTypes.COSTS).toDouble() + getFixedCosts(routes)); + + + VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(routes, states.getRouteState(route, StateFactory.COSTS).toDouble() + getFixedCosts(routes)); + assertEquals(110.0, sol.getCost(), 0.5); RuinRadial radialRuin = new RuinRadial(vrp, 0.2, new JobDistanceAvgCosts(vrp.getTransportCosts())); - radialRuin.addListener(stateUpdater); +// radialRuin.addListener(stateUpdater); InsertionStrategy insertionStrategy = new BestInsertion(insertionCalc); insertionStrategy.addListener(stateUpdater); @@ -211,10 +217,12 @@ public class GendreauPostOptTest { return c; } - private double getCosts(VehicleRoutingProblemSolution newSolution, StateManagerImpl states) { + private double getCosts(VehicleRoutingProblemSolution newSolution, StateManager states) { double c = 0.0; for(VehicleRoute r : newSolution.getRoutes()){ - c += states.getRouteState(r, StateTypes.COSTS).toDouble() + r.getVehicle().getType().getVehicleCostParams().fix; + + c += states.getRouteState(r, StateFactory.COSTS).toDouble() + r.getVehicle().getType().getVehicleCostParams().fix; + } return c; } diff --git a/jsprit-core/src/test/java/algorithms/RefuseCollectionTest.java b/jsprit-core/src/test/java/algorithms/RefuseCollectionTest.java index 0a79471e..7af0822c 100644 --- a/jsprit-core/src/test/java/algorithms/RefuseCollectionTest.java +++ b/jsprit-core/src/test/java/algorithms/RefuseCollectionTest.java @@ -186,8 +186,8 @@ public class RefuseCollectionTest { vra.setPrematureBreak(100); Collection solutions = vra.searchSolutions(); - assertEquals(397.0,Solutions.getBest(solutions).getCost(),0.01); - assertEquals(2,Solutions.getBest(solutions).getRoutes().size()); + assertEquals(397.0,Solutions.bestOf(solutions).getCost(),0.01); + assertEquals(2,Solutions.bestOf(solutions).getRoutes().size()); } diff --git a/jsprit-core/src/test/java/algorithms/ShipmentInsertionCalculatorTest.java b/jsprit-core/src/test/java/algorithms/ShipmentInsertionCalculatorTest.java index 5dac938a..199ff6bc 100644 --- a/jsprit-core/src/test/java/algorithms/ShipmentInsertionCalculatorTest.java +++ b/jsprit-core/src/test/java/algorithms/ShipmentInsertionCalculatorTest.java @@ -8,8 +8,7 @@ import org.junit.Test; import util.Coordinate; import util.Locations; import util.ManhattanCosts; -import algorithms.HardConstraints.HardActivityLevelConstraint; -import algorithms.HardConstraints.HardRouteLevelConstraint; +import algorithms.HardActivityLevelConstraint.ConstraintsStatus; import basics.Shipment; import basics.costs.VehicleRoutingActivityCosts; import basics.costs.VehicleRoutingTransportCosts; @@ -37,8 +36,8 @@ public class ShipmentInsertionCalculatorTest { HardActivityLevelConstraint hardActivityLevelConstraint = new HardActivityLevelConstraint() { @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) { - return true; + public ConstraintsStatus fulfilled(InsertionContext iFacts, TourActivity prevAct,TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + return ConstraintsStatus.FULFILLED; } }; @@ -73,12 +72,12 @@ public class ShipmentInsertionCalculatorTest { routingCosts = new ManhattanCosts(locations); VehicleType type = VehicleTypeImpl.Builder.newInstance("t", 1).setCostPerDistance(1).build(); vehicle = VehicleImpl.Builder.newInstance("v").setLocationId("0,0").setType(type).build(); - activityInsertionCostsCalculator = new LocalActivityInsertionCostsCalculator(routingCosts, activityCosts, hardActivityLevelConstraint); + activityInsertionCostsCalculator = new LocalActivityInsertionCostsCalculator(routingCosts, activityCosts); createInsertionCalculator(hardRouteLevelConstraint); } private void createInsertionCalculator(HardRouteLevelConstraint hardRouteLevelConstraint) { - insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityInsertionCostsCalculator, hardRouteLevelConstraint); + insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityInsertionCostsCalculator, hardRouteLevelConstraint, hardActivityLevelConstraint); } @Test @@ -86,7 +85,7 @@ public class ShipmentInsertionCalculatorTest { Shipment shipment = Shipment.Builder.newInstance("s", 1).setPickupLocation("0,10").setDeliveryLocation("10,0").build(); VehicleRoute route = VehicleRoute.emptyRoute(); - InsertionData iData = insertionCalculator.calculate(route, shipment, vehicle, 0.0, null, Double.MAX_VALUE); + InsertionData iData = insertionCalculator.getInsertionData(route, shipment, vehicle, 0.0, null, Double.MAX_VALUE); assertEquals(40.0,iData.getInsertionCost(),0.05); } @@ -97,7 +96,7 @@ public class ShipmentInsertionCalculatorTest { VehicleRoute route = VehicleRoute.emptyRoute(); new Inserter(new InsertionListeners()).insertJob(shipment, new InsertionData(0,0,0,vehicle,null), route); - InsertionData iData = insertionCalculator.calculate(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE); + InsertionData iData = insertionCalculator.getInsertionData(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE); assertEquals(0.0,iData.getInsertionCost(),0.05); assertEquals(1,iData.getPickupInsertionIndex()); assertEquals(2,iData.getDeliveryInsertionIndex()); @@ -117,8 +116,8 @@ public class ShipmentInsertionCalculatorTest { } }); - InsertionData iData = insertionCalculator.calculate(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE); - assertEquals(InsertionData.noInsertionFound(),iData); + InsertionData iData = insertionCalculator.getInsertionData(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE); + assertEquals(InsertionData.createEmptyInsertionData(),iData); } @@ -134,7 +133,7 @@ public class ShipmentInsertionCalculatorTest { inserter.insertJob(shipment, new InsertionData(0,0,0,vehicle,null), route); inserter.insertJob(shipment2, new InsertionData(0,1,2,vehicle,null),route); - InsertionData iData = insertionCalculator.calculate(route, shipment3, vehicle, 0.0, null, Double.MAX_VALUE); + InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, null, Double.MAX_VALUE); assertEquals(0.0,iData.getInsertionCost(),0.05); assertEquals(0,iData.getPickupInsertionIndex()); assertEquals(1,iData.getDeliveryInsertionIndex()); @@ -151,7 +150,7 @@ public class ShipmentInsertionCalculatorTest { inserter.insertJob(shipment, new InsertionData(0,0,0,vehicle,null), route); inserter.insertJob(shipment2, new InsertionData(0,1,2,vehicle,null),route); - InsertionData iData = insertionCalculator.calculate(route, shipment3, vehicle, 0.0, null, Double.MAX_VALUE); + InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, null, Double.MAX_VALUE); assertEquals(2.0,iData.getInsertionCost(),0.05); assertEquals(0,iData.getPickupInsertionIndex()); assertEquals(1,iData.getDeliveryInsertionIndex()); diff --git a/jsprit-core/src/test/java/algorithms/StateUpdates.java b/jsprit-core/src/test/java/algorithms/StateUpdates.java new file mode 100644 index 00000000..475f3405 --- /dev/null +++ b/jsprit-core/src/test/java/algorithms/StateUpdates.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (C) 2013 Stefan Schroeder + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + ******************************************************************************/ +package algorithms; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import basics.Job; +import basics.algo.InsertionStartsListener; +import basics.algo.JobInsertedListener; +import basics.costs.VehicleRoutingActivityCosts; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.ReverseRouteActivityVisitor; +import basics.route.RouteActivityVisitor; +import basics.route.VehicleRoute; + + + +class UpdateStates implements JobInsertedListener, InsertionStartsListener{ + + private RouteActivityVisitor routeActivityVisitor; + + private ReverseRouteActivityVisitor revRouteActivityVisitor; + + private InsertionListeners insertionListeners = new InsertionListeners(); + + public UpdateStates(StateManager 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)); + routeActivityVisitor.addActivityVisitor(new UpdateMaxLoad(states)); + revRouteActivityVisitor = new ReverseRouteActivityVisitor(); + revRouteActivityVisitor.addActivityVisitor(new UpdateLatestOperationStartTimeAtActLocations(states, routingCosts)); + insertionListeners.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenInsertionStarts(states)); + insertionListeners.addListener(new UpdateLoadsAtStartAndEndOfRouteWhenJobHasBeenInserted(states)); + } + + public void update(VehicleRoute route){ + List routes = Arrays.asList(route); + insertionListeners.informInsertionStarts(routes, Collections.EMPTY_LIST); + routeActivityVisitor.visit(route); + revRouteActivityVisitor.visit(route); + } + + @Override + public void informJobInserted(Job job2insert, VehicleRoute inRoute, double additionalCosts, double additionalTime) { + insertionListeners.informJobInserted(job2insert, inRoute, additionalCosts, additionalTime); + routeActivityVisitor.visit(inRoute); + revRouteActivityVisitor.visit(inRoute); + } + + @Override + public void informInsertionStarts(Collection vehicleRoutes,Collection unassignedJobs) { + insertionListeners.informInsertionStarts(vehicleRoutes, unassignedJobs); + for(VehicleRoute route : vehicleRoutes) { + routeActivityVisitor.visit(route); + revRouteActivityVisitor.visit(route); + } + } + + } + + diff --git a/jsprit-core/src/test/java/algorithms/TestAlgorithmReader.java b/jsprit-core/src/test/java/algorithms/TestAlgorithmReader.java index 37b70a48..95ee0f54 100644 --- a/jsprit-core/src/test/java/algorithms/TestAlgorithmReader.java +++ b/jsprit-core/src/test/java/algorithms/TestAlgorithmReader.java @@ -40,6 +40,7 @@ import basics.Job; import basics.VehicleRoutingAlgorithm; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblemSolution; +import basics.algo.RuinListener; import basics.algo.SearchStrategy; import basics.algo.SearchStrategyModule; import basics.algo.SearchStrategyModuleListener; diff --git a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java index b6c3e7fd..06c53806 100644 --- a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java +++ b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java @@ -28,7 +28,6 @@ import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; -import algorithms.StateUpdates.UpdateStates; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingTransportCosts; @@ -59,7 +58,7 @@ public class TestCalculatesServiceInsertion { private Service third; - private StateManagerImpl states; + private StateManager states; private NoDriver driver; @@ -149,11 +148,13 @@ public class TestCalculatesServiceInsertion { jobs.add(second); jobs.add(third); - states = new StateManagerImpl(); + states = new StateManager(); ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction(); - serviceInsertion = new ServiceInsertionCalculator(costs, new LocalActivityInsertionCostsCalculator(costs, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, costs)), new HardConstraints.HardLoadConstraint(states)); + + serviceInsertion = new ServiceInsertionCalculator(costs, new LocalActivityInsertionCostsCalculator(costs, activityCosts), new HardLoadConstraint(states), new HardTimeWindowActivityLevelConstraint(states, costs)); + stateUpdater = new UpdateStates(states, costs, activityCosts); @@ -172,7 +173,7 @@ public class TestCalculatesServiceInsertion { VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); stateUpdater.update(route); - InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(0, iData.getDeliveryInsertionIndex()); } @@ -185,7 +186,7 @@ public class TestCalculatesServiceInsertion { VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); stateUpdater.update(route); - InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(0, iData.getDeliveryInsertionIndex()); } @@ -200,7 +201,7 @@ public class TestCalculatesServiceInsertion { stateUpdater.update(route); - InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(0.0, iData.getInsertionCost(), 0.2); assertEquals(1, iData.getDeliveryInsertionIndex()); } @@ -215,7 +216,7 @@ public class TestCalculatesServiceInsertion { stateUpdater.update(route); - InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, third, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(1, iData.getDeliveryInsertionIndex()); } @@ -229,7 +230,7 @@ public class TestCalculatesServiceInsertion { VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); stateUpdater.update(route); - InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(0.0, iData.getInsertionCost(), 0.2); assertEquals(2, iData.getDeliveryInsertionIndex()); } @@ -245,7 +246,7 @@ public class TestCalculatesServiceInsertion { // route.addActivity(states.getActivity(third,true)); stateUpdater.update(route); - InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, second, newVehicle, newVehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(2, iData.getDeliveryInsertionIndex()); } diff --git a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java index bd27da7a..6e26383f 100644 --- a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java +++ b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java @@ -30,7 +30,6 @@ import org.junit.Test; import util.Coordinate; import util.ManhattanDistanceCalculator; -import algorithms.StateUpdates.UpdateStates; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingTransportCosts; @@ -48,7 +47,7 @@ import basics.route.VehicleRoute; public class TestCalculatesServiceInsertionOnRouteLevel { - CalculatesServiceInsertionOnRouteLevel serviceInsertion; + ServiceInsertionOnRouteLevelCalculator serviceInsertion; VehicleRoutingTransportCosts costs; @@ -62,7 +61,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel { private Service third; - private StateManagerImpl states; + private StateManager states; private NoDriver driver; @@ -140,11 +139,11 @@ public class TestCalculatesServiceInsertionOnRouteLevel { jobs.add(second); jobs.add(third); - states = new StateManagerImpl(); + states = new StateManager(); ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction(); - ActivityInsertionCostsCalculator actInsertionCostCalculator = new RouteLevelActivityInsertionCostsEstimator(costs, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, costs), states); - serviceInsertion = new CalculatesServiceInsertionOnRouteLevel(costs,activityCosts, new HardConstraints.HardLoadConstraint(states), actInsertionCostCalculator); + ActivityInsertionCostsCalculator actInsertionCostCalculator = new RouteLevelActivityInsertionCostsEstimator(costs, activityCosts, states); + serviceInsertion = new ServiceInsertionOnRouteLevelCalculator(costs,activityCosts, actInsertionCostCalculator, new HardLoadConstraint(states), new HardTimeWindowActivityLevelConstraint(states, costs)); serviceInsertion.setNuOfActsForwardLooking(4); serviceInsertion.setStates(states); @@ -165,7 +164,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel { VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); updateStates.update(route); - InsertionData iData = serviceInsertion.calculate(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, first, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(20.0, iData.getInsertionCost(), 0.2); assertEquals(0, iData.getDeliveryInsertionIndex()); } @@ -179,7 +178,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel { VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); updateStates.update(route); - InsertionData iData = serviceInsertion.calculate(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, third, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(0.0, iData.getInsertionCost(), 0.2); assertEquals(1, iData.getDeliveryInsertionIndex()); } @@ -193,7 +192,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel { VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); updateStates.update(route); - InsertionData iData = serviceInsertion.calculate(route, third, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, third, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(40.0, iData.getInsertionCost(), 0.2); assertEquals(1, iData.getDeliveryInsertionIndex()); } @@ -207,7 +206,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel { VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); updateStates.update(route); - InsertionData iData = serviceInsertion.calculate(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, second, vehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(0.0, iData.getInsertionCost(), 0.2); assertEquals(2, iData.getDeliveryInsertionIndex()); } @@ -221,7 +220,7 @@ public class TestCalculatesServiceInsertionOnRouteLevel { VehicleRoute route = VehicleRoute.newInstance(tour,driver,vehicle); updateStates.update(route); - InsertionData iData = serviceInsertion.calculate(route, second, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); + InsertionData iData = serviceInsertion.getInsertionData(route, second, newVehicle, vehicle.getEarliestDeparture(), null, Double.MAX_VALUE); assertEquals(40.0, iData.getInsertionCost(), 0.2); assertEquals(2, iData.getDeliveryInsertionIndex()); } diff --git a/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java b/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java deleted file mode 100644 index 9512765d..00000000 --- a/jsprit-core/src/test/java/algorithms/TestIterateRouteForwardInTime.java +++ /dev/null @@ -1,214 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package algorithms; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Collection; - -import org.junit.Before; -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 basics.Job; -import basics.Service; -import basics.costs.DefaultVehicleRoutingActivityCosts; -import basics.costs.VehicleRoutingTransportCosts; -import basics.route.Driver; -import basics.route.DriverImpl; -import basics.route.ServiceActivity; -import basics.route.TimeWindow; -import basics.route.TourActivities; -import basics.route.Vehicle; -import basics.route.VehicleImpl; -import basics.route.VehicleRoute; -import basics.route.VehicleTypeImpl; - -public class TestIterateRouteForwardInTime { - - TourActivities tour; - - Driver driver; - - Vehicle vehicle; - - TourActivities anotherTour; - - private VehicleRoute vehicleRoute; - - private VehicleRoutingTransportCosts cost; - - ServiceActivity firstAct; - - ServiceActivity secondAct; - - StateManagerImpl stateManager; - - @Before - public void setUp(){ - cost = new VehicleRoutingTransportCosts() { - - @Override - public double getBackwardTransportTime(String fromId, String toId, - double arrivalTime, Driver driver, Vehicle vehicle) { - return getTransportCost(fromId, toId, arrivalTime, driver, vehicle); - } - - @Override - public double getBackwardTransportCost(String fromId, String toId, - double arrivalTime, Driver driver, Vehicle vehicle) { - return getTransportCost(fromId, toId, arrivalTime, driver, vehicle); - } - - @Override - public double getTransportCost(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) { - String[] fromTokens = fromId.split(","); - String[] toTokens = toId.split(","); - double fromX = Double.parseDouble(fromTokens[0]); - double fromY = Double.parseDouble(fromTokens[1]); - - double toX = Double.parseDouble(toTokens[0]); - double toY = Double.parseDouble(toTokens[1]); - - return ManhattanDistanceCalculator.calculateDistance(new Coordinate(fromX, fromY), new Coordinate(toX, toY)); - } - - @Override - public double getTransportTime(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) { - return getTransportCost(fromId, toId, departureTime, driver, vehicle); - } - }; - - Service firstService = Service.Builder.newInstance("1", 5).setLocationId("10,0").setTimeWindow(TimeWindow.newInstance(0, 20)).build(); - Service secondService = Service.Builder.newInstance("2", 5).setLocationId("0,10").setTimeWindow(TimeWindow.newInstance(0, 50)).build(); - - Collection services = new ArrayList(); - services.add(firstService); - services.add(secondService); - - VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("test", 0).build(); - vehicle = VehicleImpl.Builder.newInstance("testvehicle").setType(type).setLocationId("0,0") - .setEarliestStart(0.0).setLatestArrival(50.0).build(); - - tour = new TourActivities(); - firstAct = ServiceActivity.newInstance(firstService); - tour.addActivity(firstAct); - secondAct = ServiceActivity.newInstance(secondService); - tour.addActivity(secondAct); - - vehicleRoute = VehicleRoute.newInstance(tour,DriverImpl.noDriver(),vehicle); - - stateManager = new StateManagerImpl(); - } - - @Test - public void whenIteratingWithoutUpdate_itShouldUpdateNothing() { - IterateRouteForwardInTime forwardInTime = new IterateRouteForwardInTime(cost); - forwardInTime.iterate(vehicleRoute); - - assertEquals(0.0,firstAct.getArrTime(),0.1); - assertEquals(0.0,firstAct.getEndTime(),0.1); - - assertEquals(0.0,secondAct.getArrTime(),0.1); - assertEquals(0.0,secondAct.getEndTime(),0.1); - } - - @Test - public void whenIteratingWithActivityTimeUpdater_itShouldUpdateActivityTimes() { - RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - forwardInTime.addActivityVisitor(new UpdateActivityTimes(cost)); - forwardInTime.visit(vehicleRoute); - - assertEquals(10.0,firstAct.getArrTime(),0.1); - assertEquals(10.0,firstAct.getEndTime(),0.1); - - assertEquals(30.0,secondAct.getArrTime(),0.1); - assertEquals(30.0,secondAct.getEndTime(),0.1); - } - - @Test - public void whenIteratingWithLoadUpdateAtActLocations_itShouldUpdateLoad() { - RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - forwardInTime.addActivityVisitor(new UpdateLoadAtAllLevels(stateManager)); - forwardInTime.visit(vehicleRoute); - - assertEquals(5.0, stateManager.getActivityState(firstAct,StateTypes.LOAD).toDouble(), 0.01); - assertEquals(10.0, stateManager.getActivityState(secondAct,StateTypes.LOAD).toDouble(), 0.01); - } - - - @Test - public void testStatesOfAct0(){ - RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - forwardInTime.visit(vehicleRoute); - - assertEquals(0.0, vehicleRoute.getStart().getEndTime(),0.05); - assertEquals(vehicleRoute.getVehicle().getLocationId(), vehicleRoute.getStart().getLocationId()); - assertEquals(vehicleRoute.getVehicle().getEarliestDeparture(), vehicleRoute.getStart().getTheoreticalEarliestOperationStartTime(),0.05); - assertEquals(vehicleRoute.getVehicle().getLatestArrival(), vehicleRoute.getStart().getTheoreticalLatestOperationStartTime(),0.05); - - } - - @Test - public void testStatesOfAct1(){ - RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - forwardInTime.addActivityVisitor(new UpdateLoadAtAllLevels(stateManager)); - forwardInTime.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, cost)); - forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); - forwardInTime.visit(vehicleRoute); - - assertEquals(10.0, stateManager.getActivityState(firstAct, StateTypes.COSTS).toDouble(),0.05); - assertEquals(5.0, stateManager.getActivityState(firstAct, StateTypes.LOAD).toDouble(),0.05); - assertEquals(10.0, stateManager.getActivityState(firstAct, StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05); -// assertEquals(20.0, states.getState(tour.getActivities().get(0)).getLatestOperationStart(),0.05); - } - - @Test - public void testStatesOfAct2(){ - RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - - forwardInTime.addActivityVisitor(new UpdateLoadAtAllLevels(stateManager)); - forwardInTime.addActivityVisitor(new UpdateEarliestStartTimeWindowAtActLocations(stateManager, cost)); - forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); - forwardInTime.visit(vehicleRoute); - - assertEquals(30.0, stateManager.getActivityState(secondAct, StateTypes.COSTS).toDouble(),0.05); - assertEquals(10.0, stateManager.getActivityState(secondAct, StateTypes.LOAD).toDouble(),0.05); - assertEquals(30.0, stateManager.getActivityState(secondAct, StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05); -// assertEquals(40.0, states.getState(tour.getActivities().get(1)).getLatestOperationStart(),0.05); - } - - @Test - public void testStatesOfAct3(){ - RouteActivityVisitor forwardInTime = new RouteActivityVisitor(); - - forwardInTime.addActivityVisitor(new UpdateActivityTimes(cost)); - forwardInTime.addActivityVisitor(new UpdateCostsAtAllLevels(new DefaultVehicleRoutingActivityCosts(), cost, stateManager)); - forwardInTime.visit(vehicleRoute); - - assertEquals(40.0, stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(), 0.05); - assertEquals(40.0, vehicleRoute.getEnd().getArrTime(),0.05); - assertEquals(50.0, vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime(),0.05); - } - -} diff --git a/jsprit-core/src/test/java/algorithms/TestJobDistanceAvgCosts.java b/jsprit-core/src/test/java/algorithms/TestJobDistanceAvgCosts.java index 9f8a5216..c4caa271 100644 --- a/jsprit-core/src/test/java/algorithms/TestJobDistanceAvgCosts.java +++ b/jsprit-core/src/test/java/algorithms/TestJobDistanceAvgCosts.java @@ -56,7 +56,7 @@ public class TestJobDistanceAvgCosts { } }; JobDistanceAvgCosts c = new JobDistanceAvgCosts(costs); - c.calculateDistance(Service.Builder.newInstance("1", 1).setLocationId("foo").build(), Service.Builder.newInstance("2", 2).setLocationId("foo").build()); + c.getDistance(Service.Builder.newInstance("1", 1).setLocationId("foo").build(), Service.Builder.newInstance("2", 2).setLocationId("foo").build()); } @Test(expected=NullPointerException.class) @@ -92,7 +92,7 @@ public class TestJobDistanceAvgCosts { } }; JobDistanceAvgCosts c = new JobDistanceAvgCosts(costs); - c.calculateDistance(Service.Builder.newInstance("1", 1).setLocationId("loc").build(), Service.Builder.newInstance("2", 2).setLocationId("loc").build()); + c.getDistance(Service.Builder.newInstance("1", 1).setLocationId("loc").build(), Service.Builder.newInstance("2", 2).setLocationId("loc").build()); } } diff --git a/jsprit-core/src/test/java/algorithms/TestTourStateUpdaterWithService.java b/jsprit-core/src/test/java/algorithms/TestTourStateUpdaterWithService.java index 31014486..476167b0 100644 --- a/jsprit-core/src/test/java/algorithms/TestTourStateUpdaterWithService.java +++ b/jsprit-core/src/test/java/algorithms/TestTourStateUpdaterWithService.java @@ -26,7 +26,6 @@ import org.junit.Test; import util.Coordinate; import util.ManhattanDistanceCalculator; -import algorithms.StateUpdates.UpdateStates; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingTransportCosts; @@ -53,7 +52,7 @@ public class TestTourStateUpdaterWithService { UpdateStates updateStates; - StateManagerImpl states; + StateManager states; private VehicleRoute vehicleRoute; @@ -100,9 +99,9 @@ public class TestTourStateUpdaterWithService { services.add(firstService); services.add(secondService); - states = new StateManagerImpl(); + states = new StateManager(); - VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("test", 0).build(); + VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("test", 10).build(); vehicle = VehicleImpl.Builder.newInstance("testvehicle").setType(type).setLocationId("0,0") .setEarliestStart(0.0).setLatestArrival(50.0).build(); @@ -119,8 +118,8 @@ public class TestTourStateUpdaterWithService { @Test public void testCalculatedCost() { updateStates.update(vehicleRoute); - assertEquals(40.0, states.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(), 0.05); - assertEquals(10, states.getRouteState(vehicleRoute, StateTypes.LOAD).toDouble(), 0.05); + assertEquals(40.0, states.getRouteState(vehicleRoute,StateFactory.COSTS).toDouble(), 0.05); + assertEquals(10, states.getRouteState(vehicleRoute, StateFactory.LOAD).toDouble(), 0.05); } @Test @@ -136,27 +135,27 @@ public class TestTourStateUpdaterWithService { @Test public void testStatesOfAct1(){ updateStates.update(vehicleRoute); - assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateTypes.COSTS).toDouble(),0.05); - assertEquals(5.0, states.getActivityState(tour.getActivities().get(0), StateTypes.LOAD).toDouble(),0.05); + assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateFactory.COSTS).toDouble(),0.05); + assertEquals(5.0, states.getActivityState(tour.getActivities().get(0), StateFactory.LOAD).toDouble(),0.05); // assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05); - assertEquals(20.0, states.getActivityState(tour.getActivities().get(0), StateTypes.LATEST_OPERATION_START_TIME).toDouble(),0.05); + assertEquals(20.0, states.getActivityState(tour.getActivities().get(0), StateFactory.LATEST_OPERATION_START_TIME).toDouble(),0.05); } @Test public void testStatesOfAct2(){ updateStates.update(vehicleRoute); - assertEquals(30.0, states.getActivityState(tour.getActivities().get(1), StateTypes.COSTS).toDouble(),0.05); - assertEquals(10.0, states.getActivityState(tour.getActivities().get(1), StateTypes.LOAD).toDouble(),0.05); + assertEquals(30.0, states.getActivityState(tour.getActivities().get(1), StateFactory.COSTS).toDouble(),0.05); + assertEquals(10.0, states.getActivityState(tour.getActivities().get(1), StateFactory.LOAD).toDouble(),0.05); // assertEquals(10.0, states.getActivityState(tour.getActivities().get(0), StateTypes.EARLIEST_OPERATION_START_TIME).toDouble(),0.05); - assertEquals(40.0, states.getActivityState(tour.getActivities().get(1), StateTypes.LATEST_OPERATION_START_TIME).toDouble(),0.05); + assertEquals(40.0, states.getActivityState(tour.getActivities().get(1), StateFactory.LATEST_OPERATION_START_TIME).toDouble(),0.05); } @Test public void testStatesOfAct3(){ updateStates.update(vehicleRoute); - assertEquals(40.0, states.getRouteState(vehicleRoute, StateTypes.COSTS).toDouble(), 0.05); + assertEquals(40.0, states.getRouteState(vehicleRoute, StateFactory.COSTS).toDouble(), 0.05); assertEquals(40.0, vehicleRoute.getEnd().getArrTime(),0.05); assertEquals(50.0, vehicleRoute.getEnd().getTheoreticalLatestOperationStartTime(),0.05); } diff --git a/jsprit-core/src/test/java/algorithms/TestVehicleFleetManager.java b/jsprit-core/src/test/java/algorithms/TestVehicleFleetManager.java index c909e72d..5b6fa031 100644 --- a/jsprit-core/src/test/java/algorithms/TestVehicleFleetManager.java +++ b/jsprit-core/src/test/java/algorithms/TestVehicleFleetManager.java @@ -21,8 +21,10 @@ import java.util.Collection; import java.util.List; import junit.framework.TestCase; +import basics.route.FiniteFleetManagerFactory; import basics.route.PenaltyVehicleType; import basics.route.Vehicle; +import basics.route.VehicleFleetManager; import basics.route.VehicleImpl; import basics.route.VehicleTypeImpl; @@ -42,7 +44,7 @@ public class TestVehicleFleetManager extends TestCase{ vehicles.add(v1); vehicles.add(v2); - fleetManager = new VehicleFleetManagerImpl(vehicles); + fleetManager = new FiniteFleetManagerFactory(vehicles).createFleetManager(); } public void testGetVehicles(){ @@ -94,7 +96,7 @@ public class TestVehicleFleetManager extends TestCase{ vehicles.add(v1); vehicles.add(v2); vehicles.add(penalty4standard); - VehicleFleetManager fleetManager = new VehicleFleetManagerImpl(vehicles); + VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(vehicles).createFleetManager(); Collection availableVehicles = fleetManager.getAvailableVehicles(); assertEquals(2, availableVehicles.size()); @@ -115,7 +117,7 @@ public class TestVehicleFleetManager extends TestCase{ vehicles.add(v2); vehicles.add(penalty4standard); vehicles.add(v3); - VehicleFleetManager fleetManager = new VehicleFleetManagerImpl(vehicles); + VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(vehicles).createFleetManager(); fleetManager.lock(v1); fleetManager.lock(v2); Collection availableVehicles = fleetManager.getAvailableVehicles(); @@ -133,7 +135,7 @@ public class TestVehicleFleetManager extends TestCase{ vehicles.add(v1); vehicles.add(v2); vehicles.add(penalty4standard); - VehicleFleetManager fleetManager = new VehicleFleetManagerImpl(vehicles); + VehicleFleetManager fleetManager = new FiniteFleetManagerFactory(vehicles).createFleetManager(); fleetManager.lock(v1); fleetManager.lock(v2); Collection availableVehicles = fleetManager.getAvailableVehicles(); diff --git a/jsprit-core/src/test/resources/pd_solomon_c101_sol.xml b/jsprit-core/src/test/resources/pd_solomon_c101_sol.xml index c8bcecc8..1d5bfbc5 100644 --- a/jsprit-core/src/test/resources/pd_solomon_c101_sol.xml +++ b/jsprit-core/src/test/resources/pd_solomon_c101_sol.xml @@ -2534,83 +2534,18 @@ - 853.276595840535 + 1484.6058277010336 - 571.5178932313771 + 654.4873603381584 noDriver solomonVehicle 0.0 - - 20 - 0.0 - 0.0 - - - 21 - 0.0 - 0.0 - - - 23 - 0.0 - 0.0 - - - 28 - 0.0 - 0.0 - - - 17 - 0.0 - 0.0 - - - 15 - 0.0 - 0.0 - - - 11 - 0.0 - 0.0 - 10 0.0 0.0 - - 8 - 0.0 - 0.0 - - - 13 - 0.0 - 0.0 - - - 26 - 0.0 - 0.0 - - - 18 - 0.0 - 0.0 - - - 22 - 0.0 - 0.0 - - - 19 - 0.0 - 0.0 - 7 0.0 @@ -2622,107 +2557,72 @@ 0.0 - 75 + 22 0.0 0.0 - 95 + 21 0.0 0.0 - 92 + 20 0.0 0.0 - 4 + 50 0.0 0.0 - 96 + 52 0.0 0.0 - 2 + 42 0.0 0.0 - 93 + 41 0.0 0.0 - 94 + 45 0.0 0.0 - 98 + 48 0.0 0.0 - 97 + 44 0.0 0.0 - 99 + 46 0.0 0.0 - 1 + 40 0.0 0.0 - 3 + 51 0.0 0.0 - 9 - 0.0 - 0.0 - - - 100 - 0.0 - 0.0 - - - 6 - 0.0 - 0.0 - - - 30 - 0.0 - 0.0 - - - 36 - 0.0 - 0.0 - - - 25 - 0.0 - 0.0 - - - 27 - 0.0 - 0.0 - - - 24 + 31 0.0 0.0 @@ -2736,440 +2636,330 @@ 0.0 0.0 + + 36 + 0.0 + 0.0 + 33 0.0 0.0 - 29 + 65 0.0 0.0 - 53 + 63 0.0 0.0 - 81 + 66 0.0 0.0 - 71 + 62 0.0 0.0 - 77 + 68 0.0 0.0 - 79 + 54 0.0 0.0 - 80 + 58 0.0 0.0 - 78 - 0.0 - 0.0 - - - 70 - 0.0 - 0.0 - - - 76 - 0.0 - 0.0 - - - 73 - 0.0 - 0.0 - - - 38 - 0.0 - 0.0 - - - 39 - 0.0 - 0.0 - - - 16 - 0.0 - 0.0 - - - 14 - 0.0 - 0.0 - - - 37 - 0.0 - 0.0 - - - 35 - 0.0 - 0.0 - - - 12 + 100 0.0 0.0 - 35 + 100 38.07886552931954 38.07886552931954 - - 37 - 43.90981742416484 - 43.90981742416484 + + 92 + 76.15773105863909 + 76.15773105863909 - - 39 - 49.29498223129934 - 49.29498223129934 + + 82 + 76.15773105863909 + 76.15773105863909 - - 38 - 54.29498223129934 - 54.29498223129934 - - - 16 - 103.53927124027987 - 103.53927124027987 - - - 14 - 105.53927124027987 - 105.53927124027987 - - - 12 - 108.53927124027987 - 108.53927124027987 - - - 73 - 195.22260297135722 - 195.22260297135722 - - - 70 - 198.22260297135722 - 198.22260297135722 - - - 76 - 205.2936707832227 - 205.2936707832227 - - - 78 - 207.2936707832227 - 207.2936707832227 - - - 71 - 214.2936707832227 - 214.2936707832227 - - - 77 - 222.89599605026532 - 222.89599605026532 - - - 79 - 223.89599605026532 - 223.89599605026532 - - - 80 - 229.28116085739984 - 229.28116085739984 - - - 81 - 239.28116085739984 - 239.28116085739984 + + 53 + 76.15773105863909 + 76.15773105863909 53 - 290.084704040922 - 290.084704040922 + 121.33515905094515 + 121.33515905094515 - 32 - 338.8801956359454 - 338.8801956359454 - - - 33 - 340.8801956359454 - 340.8801956359454 - - - 36 - 346.71114753079075 - 346.71114753079075 - - - 34 - 349.71114753079075 - 349.71114753079075 - - - 29 - 362.71114753079075 - 362.71114753079075 - - - 24 - 367.71114753079075 - 367.71114753079075 - - - 25 - 369.71114753079075 - 369.71114753079075 - - - 27 - 371.71114753079075 - 371.71114753079075 - - - 30 - 375.95378821791 - 375.95378821791 - - - 9 - 399.38453724563 - 399.38453724563 - - - 6 - 401.62060522312976 - 401.62060522312976 - - - 100 - 423.55231742259105 - 423.55231742259105 - - - 97 - 428.55231742259105 - 428.55231742259105 - - - 93 - 433.55231742259105 - 433.55231742259105 + 82 + 180.16542337127606 + 180.16542337127606 92 - 435.55231742259105 - 435.55231742259105 + 211.2137727637961 + 211.2137727637961 + + + 39 + 255.4178449743968 + 255.4178449743968 + + + 35 + 255.4178449743968 + 255.4178449743968 - 94 - 439.15786869805504 - 439.15786869805504 + 35 + 293.4967105037163 + 293.4967105037163 - 95 - 442.76341997351904 - 442.76341997351904 + 39 + 304.6770503912153 + 304.6770503912153 + + + 60 + 344.988339132708 + 344.988339132708 + + + 56 + 344.988339132708 + 344.988339132708 + + + 57 + 344.988339132708 + 344.988339132708 + + + 59 + 344.988339132708 + 344.988339132708 + + + 55 + 344.988339132708 + 344.988339132708 - 96 - 444.76341997351904 - 444.76341997351904 + 55 + 380.0454354186242 + 380.0454354186242 - 99 - 449.76341997351904 - 449.76341997351904 + 59 + 384.0454354186242 + 384.0454354186242 - 98 - 455.59437186836436 - 455.59437186836436 + 57 + 386.0454354186242 + 386.0454354186242 - 2 - 469.5227601455485 - 469.5227601455485 + 56 + 396.0454354186242 + 396.0454354186242 - 1 - 471.5227601455485 - 471.5227601455485 + 60 + 401.0454354186242 + 401.0454354186242 - 75 - 474.5227601455485 - 474.5227601455485 + 58 + 404.0454354186242 + 404.0454354186242 - 4 - 478.76540083266775 - 478.76540083266775 + 54 + 410.44855965605706 + 410.44855965605706 - 7 - 481.59382795741396 - 481.59382795741396 + 68 + 430.67230807221375 + 430.67230807221375 - 3 - 483.59382795741396 - 483.59382795741396 + 62 + 437.7433758840792 + 437.7433758840792 - 5 - 484.59382795741396 - 484.59382795741396 + 66 + 440.7433758840792 + 440.7433758840792 - 8 - 489.59382795741396 - 489.59382795741396 + 63 + 446.57432777892456 + 446.57432777892456 - 10 - 493.19937923287796 - 493.19937923287796 + 65 + 448.57432777892456 + 448.57432777892456 + + + 37 + 461.38057625379025 + 461.38057625379025 + + + 38 + 461.38057625379025 + 461.38057625379025 - 11 - 496.19937923287796 - 496.19937923287796 + 38 + 502.61163250996685 + 502.61163250996685 - 13 - 510.51720029615433 - 510.51720029615433 + 37 + 504.61163250996685 + 504.61163250996685 - 15 - 515.9023651032888 - 515.9023651032888 + 33 + 510.61163250996685 + 510.61163250996685 - 19 - 520.9023651032888 - 520.9023651032888 + 36 + 516.4425844048121 + 516.4425844048121 - 18 - 525.9023651032888 - 525.9023651032888 + 34 + 519.4425844048121 + 519.4425844048121 - 17 - 528.9023651032888 - 528.9023651032888 + 32 + 524.8277492119466 + 524.8277492119466 - 28 - 549.5178932313771 - 549.5178932313771 + 31 + 529.8277492119466 + 529.8277492119466 - 26 - 551.5178932313771 - 551.5178932313771 + 51 + 545.6391375127886 + 545.6391375127886 - 23 - 554.5178932313771 - 554.5178932313771 + 40 + 555.6391375127886 + 555.6391375127886 - 22 - 557.5178932313771 - 557.5178932313771 + 46 + 561.0243023199231 + 561.0243023199231 - 21 - 559.5178932313771 - 559.5178932313771 + 44 + 563.8527294446693 + 563.8527294446693 + + + 48 + 567.8527294446693 + 567.8527294446693 + + + 45 + 569.8527294446693 + 569.8527294446693 + + + 41 + 575.2378942518038 + 575.2378942518038 + + + 42 + 577.2378942518038 + 577.2378942518038 + + + 52 + 585.7818979971214 + 585.7818979971214 + + + 50 + 588.9441756572897 + 588.9441756572897 20 - 561.5178932313771 - 561.5178932313771 + 607.3832645718755 + 607.3832645718755 - 571.5178932313771 + + 21 + 609.3832645718755 + 609.3832645718755 + + + 22 + 611.3832645718755 + 611.3832645718755 + + + 5 + 630.4882377464183 + 630.4882377464183 + + + 7 + 632.7243057239182 + 632.7243057239182 + + + 10 + 637.7243057239182 + 637.7243057239182 + + 654.4873603381584 - 281.7587026091579 + 830.1184673628752 noDriver solomonVehicle 0.0 - 45 - 0.0 - 0.0 - - - 46 - 0.0 - 0.0 - - - 41 - 0.0 - 0.0 - - - 42 - 0.0 - 0.0 - - - 48 - 0.0 - 0.0 - - - 51 - 0.0 - 0.0 - - - 49 - 0.0 - 0.0 - - - 52 - 0.0 - 0.0 - - - 40 + 67 0.0 0.0 @@ -3179,7 +2969,7 @@ 0.0 - 50 + 49 0.0 0.0 @@ -3189,142 +2979,52 @@ 0.0 - 44 + 8 0.0 0.0 - 57 + 6 0.0 0.0 - 60 + 11 0.0 0.0 - 55 + 9 0.0 0.0 - 69 + 15 0.0 0.0 - 56 + 18 0.0 0.0 - 58 + 3 0.0 0.0 - 66 + 4 0.0 0.0 - 54 + 75 0.0 0.0 - 59 - 0.0 - 0.0 - - - 68 - 0.0 - 0.0 - - - 74 - 0.0 - 0.0 - - - 65 - 0.0 - 0.0 - - - 64 - 0.0 - 0.0 - - - 63 - 0.0 - 0.0 - - - 62 - 0.0 - 0.0 - - - 72 - 0.0 - 0.0 - - - 61 - 0.0 - 0.0 - - - 67 - 0.0 - 0.0 - - - 82 - 0.0 - 0.0 - - - 85 - 0.0 - 0.0 - - - 91 - 0.0 - 0.0 - - - 86 - 0.0 - 0.0 - - - 89 - 0.0 - 0.0 - - - 87 - 0.0 - 0.0 - - - 88 - 0.0 - 0.0 - - - 84 - 0.0 - 0.0 - - - 90 + 1 0.0 0.0 @@ -3334,221 +3034,521 @@ 0.0 - 31 + 88 + 0.0 + 0.0 + + + 74 + 0.0 + 0.0 + + + 72 + 0.0 + 0.0 + + + 69 + 0.0 + 0.0 + + + 64 + 0.0 + 0.0 + + + 61 + 0.0 + 0.0 + + + 76 + 0.0 + 0.0 + + + 78 + 0.0 + 0.0 + + + 97 + 0.0 + 0.0 + + + 95 + 0.0 + 0.0 + + + 2 + 0.0 + 0.0 + + + 99 + 0.0 + 0.0 + + + 96 + 0.0 + 0.0 + + + 94 + 0.0 + 0.0 + + + 98 + 0.0 + 0.0 + + + 19 0.0 0.0 - 31 - 33.54101966249684 - 33.54101966249684 + 19 + 39.05124837953327 + 39.05124837953327 - 91 - 89.44271909999159 - 89.44271909999159 + 98 + 82.34097002336 + 82.34097002336 - 88 - 94.44271909999159 - 94.44271909999159 + 94 + 92.24046495997166 + 92.24046495997166 - 85 - 97.44271909999159 - 97.44271909999159 + 96 + 97.62562976710616 + 97.62562976710616 - 84 - 100.27114622473778 - 100.27114622473778 + 99 + 102.62562976710616 + 102.62562976710616 - 82 - 106.10209811958308 - 106.10209811958308 + 2 + 116.76776539083711 + 116.76776539083711 + + + 93 + 137.38329351892543 + 137.38329351892543 + + + 71 + 137.38329351892543 + 137.38329351892543 + + + 73 + 137.38329351892543 + 137.38329351892543 + + + 81 + 137.38329351892543 + 137.38329351892543 - 83 - 109.10209811958308 - 109.10209811958308 + 81 + 184.8174584214511 + 184.8174584214511 - 86 - 115.10209811958308 - 115.10209811958308 + 73 + 193.41978368849374 + 193.41978368849374 - 87 - 116.10209811958308 - 116.10209811958308 + 71 + 199.25073558333904 + 199.25073558333904 - 89 - 119.70764939504707 - 119.70764939504707 + 93 + 257.56025453179205 + 257.56025453179205 - 90 - 123.95029008216636 - 123.95029008216636 + 95 + 263.3912064266374 + 263.3912064266374 - 63 - 141.9780464594863 - 141.9780464594863 + 97 + 268.7763712337719 + 268.7763712337719 + + + 77 + 309.0876599752646 + 309.0876599752646 + + + 80 + 309.0876599752646 + 309.0876599752646 + + + 70 + 309.0876599752646 + 309.0876599752646 + + + 79 + 309.0876599752646 + 309.0876599752646 - 65 - 143.9780464594863 - 143.9780464594863 + 79 + 360.16603113175313 + 360.16603113175313 - 67 - 144.9780464594863 - 144.9780464594863 + 70 + 368.16603113175313 + 368.16603113175313 - 66 - 149.9780464594863 - 149.9780464594863 + 80 + 379.3463710192521 + 379.3463710192521 - 62 - 152.9780464594863 - 152.9780464594863 + 77 + 385.17732291409743 + 385.17732291409743 - 74 - 155.9780464594863 - 155.9780464594863 + 78 + 390.17732291409743 + 390.17732291409743 - 72 - 160.9780464594863 - 160.9780464594863 + 76 + 392.17732291409743 + 392.17732291409743 61 - 163.9780464594863 - 163.9780464594863 + 432.48861165559015 + 432.48861165559015 64 - 165.9780464594863 - 165.9780464594863 + 434.48861165559015 + 434.48861165559015 69 - 171.8089983543316 - 171.8089983543316 + 440.3195635504355 + 440.3195635504355 - 68 - 176.8089983543316 - 176.8089983543316 + 72 + 449.7535446824921 + 449.7535446824921 - 55 - 192.10605689510996 - 192.10605689510996 + 74 + 454.7535446824921 + 454.7535446824921 + + + 84 + 474.6029779237713 + 474.6029779237713 + + + 85 + 474.6029779237713 + 474.6029779237713 + + + 86 + 474.6029779237713 + 474.6029779237713 + + + 89 + 474.6029779237713 + 474.6029779237713 + + + 87 + 474.6029779237713 + 474.6029779237713 + + + 91 + 474.6029779237713 + 474.6029779237713 + + + 90 + 474.6029779237713 + 474.6029779237713 - 54 - 197.10605689510996 - 197.10605689510996 + 90 + 495.2185060518596 + 495.2185060518596 - 56 - 202.49122170224447 - 202.49122170224447 + 91 + 500.2185060518596 + 500.2185060518596 - 58 - 204.49122170224447 - 204.49122170224447 + 87 + 507.2895738637251 + 507.2895738637251 - 60 - 207.49122170224447 - 207.49122170224447 + 89 + 510.8951251391891 + 510.8951251391891 - 59 - 217.931528211155 - 217.931528211155 + 86 + 515.1377658263084 + 515.1377658263084 - 57 - 219.931528211155 - 219.931528211155 + 85 + 520.5229306334429 + 520.5229306334429 - 40 - 235.7429165119969 - 235.7429165119969 + 84 + 523.3513577581891 + 523.3513577581891 - 41 - 237.7429165119969 - 237.7429165119969 + 88 + 528.7365225653236 + 528.7365225653236 - 42 - 239.7429165119969 - 239.7429165119969 + 83 + 537.3388478323662 + 537.3388478323662 - 44 - 241.9789844894967 - 241.9789844894967 + 1 + 567.3054959599096 + 567.3054959599096 - 45 - 243.9789844894967 - 243.9789844894967 + 75 + 570.3054959599096 + 570.3054959599096 - 46 - 245.9789844894967 - 245.9789844894967 + 4 + 574.548136647029 + 574.548136647029 - 48 - 248.80741161424288 - 248.80741161424288 + 3 + 576.548136647029 + 576.548136647029 + + + 12 + 592.672652143626 + 592.672652143626 + + + 17 + 592.672652143626 + 592.672652143626 + + + 14 + 592.672652143626 + 592.672652143626 + + + 16 + 592.672652143626 + 592.672652143626 + + + 13 + 592.672652143626 + 592.672652143626 - 51 - 251.80741161424288 - 251.80741161424288 + 13 + 623.4784957451247 + 623.4784957451247 - 50 - 254.04347959174268 - 254.04347959174268 + 16 + 633.6765347723103 + 633.6765347723103 - 52 - 257.20575725191105 - 257.20575725191105 + 14 + 635.6765347723103 + 635.6765347723103 + + + 17 + 646.4468643865794 + 646.4468643865794 + + + 12 + 658.653420002313 + 658.653420002313 + + + 18 + 672.795555626044 + 672.795555626044 + + + 15 + 679.8666234379095 + 679.8666234379095 + + + 9 + 700.4578837198835 + 700.4578837198835 + + + 11 + 703.6201613800519 + 703.6201613800519 + + + 6 + 708.6201613800519 + 708.6201613800519 + + + 8 + 710.8562293575517 + 710.8562293575517 + + + 24 + 728.9669996338265 + 728.9669996338265 + + + 26 + 728.9669996338265 + 728.9669996338265 + + + 25 + 728.9669996338265 + 728.9669996338265 + + + 30 + 728.9669996338265 + 728.9669996338265 + + + 28 + 728.9669996338265 + 728.9669996338265 + + + 23 + 728.9669996338265 + 728.9669996338265 + + + 27 + 728.9669996338265 + 728.9669996338265 + + + 29 + 728.9669996338265 + 728.9669996338265 + + + 29 + 748.9669996338265 + 748.9669996338265 + + + 27 + 752.5725509092905 + 752.5725509092905 + + + 23 + 758.4035028041358 + 758.4035028041358 + + + 28 + 763.4035028041358 + 763.4035028041358 + + + 30 + 766.4035028041358 + 766.4035028041358 + + + 25 + 772.234454698981 + 772.234454698981 + + + 26 + 775.234454698981 + 775.234454698981 + + + 24 + 780.234454698981 + 780.234454698981 + + + 47 + 796.045842999823 + 796.045842999823 49 - 260.20575725191105 - 260.20575725191105 - - - 47 - 262.20575725191105 - 262.20575725191105 + 798.045842999823 + 798.045842999823 43 - 265.20575725191105 - 265.20575725191105 + 803.045842999823 + 803.045842999823 - 281.7587026091579 + + 67 + 817.9119117471415 + 817.9119117471415 + + 830.1184673628752 diff --git a/jsprit-examples/src/main/java/examples/SolomonExample.java b/jsprit-examples/src/main/java/examples/SolomonExample.java index 013dc833..d72997bc 100644 --- a/jsprit-examples/src/main/java/examples/SolomonExample.java +++ b/jsprit-examples/src/main/java/examples/SolomonExample.java @@ -69,7 +69,7 @@ public class SolomonExample { */ // VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp); VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_solomon.xml"); - vra.setPrematureBreak(100); +// vra.setPrematureBreak(100); // vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png")); /* * Solve the problem. diff --git a/license.txt b/license.txt deleted file mode 100644 index 4fdfe74d..00000000 --- a/license.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library.