From 216df61db438791a11cab2256cc3165771d27510 Mon Sep 17 00:00:00 2001 From: Stefan Schroeder <4sschroeder@gmail.com> Date: Wed, 28 Aug 2013 18:24:27 +0200 Subject: [PATCH] adjustments to introducing pickup and delivery --- .../src/main/java/algorithms/CalcUtils.java | 18 ++++++- .../CalculatesServiceInsertion.java | 8 +++- ...alculatesServiceInsertionOnRouteLevel.java | 14 ++++-- .../java/algorithms/CalculatorBuilder.java | 2 +- .../algorithms/FindCheaperVehicleAlgo.java | 12 ++--- .../main/java/algorithms/HardConstraints.java | 19 ++++++-- .../src/main/java/algorithms/Inserter.java | 7 ++- .../MarginalsCalculusTriangleInequality.java | 16 +++---- .../java/algorithms/StateManagerImpl.java | 48 +++++++++---------- .../src/main/java/algorithms/StateTypes.java | 2 + 10 files changed, 90 insertions(+), 56 deletions(-) diff --git a/jsprit-core/src/main/java/algorithms/CalcUtils.java b/jsprit-core/src/main/java/algorithms/CalcUtils.java index c295881f..07872ef6 100644 --- a/jsprit-core/src/main/java/algorithms/CalcUtils.java +++ b/jsprit-core/src/main/java/algorithms/CalcUtils.java @@ -4,11 +4,25 @@ import basics.route.TourActivity; class CalcUtils { + /** + * + * @param startTimeAtPrevAct + * @param tpTime_prevAct_nextAct + * @param nextAct + * @return + */ static double getStartTimeAtAct(double startTimeAtPrevAct, double tpTime_prevAct_nextAct, TourActivity nextAct){ return Math.max(startTimeAtPrevAct + tpTime_prevAct_nextAct, nextAct.getTheoreticalEarliestOperationStartTime()) + nextAct.getOperationTime(); } - static double getStartTimeAtAct(double nextActArrTime, TourActivity nextAct){ - return Math.max(nextActArrTime, nextAct.getTheoreticalEarliestOperationStartTime()) + nextAct.getOperationTime(); + /** + * 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(); } } diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java index ed8dc4e9..445988e2 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java @@ -25,6 +25,8 @@ import basics.route.End; import basics.route.ServiceActivity; import basics.route.Start; import basics.route.TourActivity; +import basics.route.TourActivityFactory; +import basics.route.DefaultTourActivityFactory; import basics.route.Vehicle; import basics.route.VehicleImpl.NoVehicle; import basics.route.VehicleRoute; @@ -49,6 +51,8 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{ private VehicleRoutingTransportCosts transportCosts; + private TourActivityFactory activityFactory; + public void setNeighborhood(Neighborhood neighborhood) { this.neighborhood = neighborhood; logger.info("initialise neighborhood " + neighborhood); @@ -59,6 +63,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{ this.marginalCalculus = marginalsCalculus; this.hardRouteLevelConstraint = hardRouteLevelConstraint; this.transportCosts = routingCosts; + activityFactory = new DefaultTourActivityFactory(); logger.info("initialise " + this); } @@ -86,7 +91,8 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{ Marginals bestMarginals = null; Service service = (Service)jobToInsert; int insertionIndex = InsertionData.NO_INDEX; - TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service); + + TourActivity deliveryAct2Insert = activityFactory.createActivity(service); Start start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival()); start.setEndTime(newVehicleDepartureTime); diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java index 1d0d900c..fc255536 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java @@ -23,21 +23,21 @@ import java.util.PriorityQueue; import org.apache.log4j.Logger; import util.Neighborhood; - -import algorithms.RouteStates.ActivityState; import basics.Job; import basics.Service; import basics.costs.VehicleRoutingActivityCosts; import basics.costs.VehicleRoutingTransportCosts; +import basics.route.DefaultTourActivityFactory; import basics.route.Driver; import basics.route.End; import basics.route.ServiceActivity; import basics.route.Start; import basics.route.TourActivities; import basics.route.TourActivity; +import basics.route.TourActivityFactory; import basics.route.Vehicle; -import basics.route.VehicleRoute; import basics.route.VehicleImpl.NoVehicle; +import basics.route.VehicleRoute; @@ -51,6 +51,8 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul private AuxilliaryCostCalculator auxilliaryPathCostCalculator; + private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory(); + private StateManager states; private int nuOfActsForwardLooking = 0; @@ -70,7 +72,9 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul }; - + public void setTourActivityFactory(TourActivityFactory tourActivityFactory){ + this.tourActivityFactory=tourActivityFactory; + } public void setNeighborhood(Neighborhood neighborhood) { this.neighborhood = neighborhood; @@ -142,7 +146,7 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul /** * some inis */ - TourActivity serviceAct2Insert = ServiceActivity.newInstance(service); + TourActivity serviceAct2Insert = tourActivityFactory.createActivity(service); int best_insertion_index = InsertionData.NO_INDEX; initialiseStartAndEnd(newVehicle, newVehicleDepartureTime); diff --git a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java index 6ab8e4c0..97e8fba6 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java +++ b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java @@ -214,7 +214,7 @@ class CalculatorBuilder { } private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager activityStates2){ - MarginalsCalculus defaultCalc = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), new HardConstraints.HardTimeWindowConstraint(activityStates2) ); + MarginalsCalculus defaultCalc = new MarginalsCalculusTriangleInequality(vrp.getTransportCosts(), vrp.getActivityCosts(), new HardConstraints.HardTimeWindowConstraint(activityStates2, vrp.getTransportCosts()) ); JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), defaultCalc, new HardConstraints.HardLoadConstraint(activityStates2)); ((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood()); diff --git a/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java b/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java index 680a2525..0304643e 100644 --- a/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java +++ b/jsprit-core/src/main/java/algorithms/FindCheaperVehicleAlgo.java @@ -21,17 +21,15 @@ package algorithms; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import org.apache.log4j.Logger; -import algorithms.VehicleFleetManager.TypeKey; import basics.route.TourActivities; import basics.route.TourActivity; import basics.route.Vehicle; -import basics.route.VehicleRoute; import basics.route.VehicleImpl.NoVehicle; +import basics.route.VehicleRoute; @@ -47,13 +45,13 @@ final class FindCheaperVehicleAlgo { private double weightFixCosts = 1.0; - private RouteStates states; + private StateManager states; public void setWeightFixCosts(double weightFixCosts) { this.weightFixCosts = weightFixCosts; } - public void setStates(RouteStates states) { + public void setStates(StateManager states) { this.states = states; } @@ -85,11 +83,11 @@ final class FindCheaperVehicleAlgo { if(vehicle.getType().getTypeId().equals(vehicleRoute.getVehicle().getType().getTypeId())){ continue; } - if(states.getRouteState(vehicleRoute).getLoad() <= vehicle.getCapacity()){ + if(states.getRouteState(vehicleRoute,StateTypes.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).getCosts() - newCost; + double varCostSaving = states.getRouteState(vehicleRoute, StateTypes.COSTS).toDouble() - newCost; double totalCostSaving = varCostSaving + weightFixCosts*fixCostSaving; if(totalCostSaving > bestSaving){ bestSaving = totalCostSaving; diff --git a/jsprit-core/src/main/java/algorithms/HardConstraints.java b/jsprit-core/src/main/java/algorithms/HardConstraints.java index 28caccfb..878a91b9 100644 --- a/jsprit-core/src/main/java/algorithms/HardConstraints.java +++ b/jsprit-core/src/main/java/algorithms/HardConstraints.java @@ -1,6 +1,7 @@ package algorithms; import basics.Service; +import basics.costs.VehicleRoutingTransportCosts; import basics.route.TourActivity; class HardConstraints { @@ -13,7 +14,7 @@ class HardConstraints { interface HardActivityLevelConstraint { - public boolean fulfilled(InsertionContext iFacts, TourActivity act, double arrTime); + public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime); } @@ -41,19 +42,27 @@ class HardConstraints { private StateManager states; - public HardTimeWindowConstraint(StateManager states) { + private VehicleRoutingTransportCosts routingCosts; + + public HardTimeWindowConstraint(StateManager states, VehicleRoutingTransportCosts routingCosts) { super(); this.states = states; + this.routingCosts = routingCosts; } @Override - public boolean fulfilled(InsertionContext iFacts, TourActivity act, double arrTime) { - if(arrTime > states.getActivityState(act, StateTypes.LATEST_OPERATION_START_TIME).toDouble()){ + public boolean fulfilled(InsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) { + double arrTimeAtNewAct = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); + if(arrTimeAtNewAct > states.getActivityState(newAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble()){ + return false; + } + double endTimeAtNewAct = CalcUtils.getActivityEndTime(arrTimeAtNewAct, newAct); + double arrTimeAtNextAct = endTimeAtNewAct + routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), endTimeAtNewAct, iFacts.getNewDriver(), iFacts.getNewVehicle()); + if(arrTimeAtNextAct > states.getActivityState(nextAct, StateTypes.LATEST_OPERATION_START_TIME).toDouble()){ return false; } return true; } - } } diff --git a/jsprit-core/src/main/java/algorithms/Inserter.java b/jsprit-core/src/main/java/algorithms/Inserter.java index 24845c01..7902b6a5 100644 --- a/jsprit-core/src/main/java/algorithms/Inserter.java +++ b/jsprit-core/src/main/java/algorithms/Inserter.java @@ -4,14 +4,19 @@ import algorithms.InsertionData.NoInsertionFound; import basics.Job; import basics.Service; import basics.route.ServiceActivity; +import basics.route.TourActivityFactory; +import basics.route.DefaultTourActivityFactory; import basics.route.VehicleRoute; class Inserter { private InsertionListeners insertionListeners; + private TourActivityFactory activityFactory; + public Inserter(InsertionListeners insertionListeners) { this.insertionListeners = insertionListeners; + activityFactory = new DefaultTourActivityFactory(); } public void insertJob(Job job, InsertionData insertionData, VehicleRoute vehicleRoute){ @@ -25,7 +30,7 @@ class Inserter { } // if(vehicleRoute.getDepartureTime() != vehicleRoute.g) if(job instanceof Service) { - vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), ServiceActivity.newInstance((Service)job)); + vehicleRoute.getTourActivities().addActivity(insertionData.getDeliveryInsertionIndex(), activityFactory.createActivity((Service)job)); vehicleRoute.setDepartureTime(insertionData.getVehicleDepartureTime()); } else throw new IllegalStateException("neither service nor shipment. this is not supported."); diff --git a/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java b/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java index aeb6d2e5..22e6d1ab 100644 --- a/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java +++ b/jsprit-core/src/main/java/algorithms/MarginalsCalculusTriangleInequality.java @@ -21,16 +21,16 @@ class MarginalsCalculusTriangleInequality implements MarginalsCalculus{ @Override public Marginals calculate(InsertionContext iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct, double depTimeAtPrevAct) { + if(!hardConstraint.fulfilled(iFacts, prevAct, newAct, nextAct, depTimeAtPrevAct)){ + return null; + } + 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; - if(!hardConstraint.fulfilled(iFacts, newAct, newAct_arrTime)){ - return null; - } - - double newAct_endTime = CalcUtils.getStartTimeAtAct(newAct_arrTime, newAct); + double newAct_endTime = CalcUtils.getActivityEndTime(newAct_arrTime, newAct); double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); @@ -38,11 +38,7 @@ class MarginalsCalculusTriangleInequality implements MarginalsCalculus{ double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct; - - if(!hardConstraint.fulfilled(iFacts, nextAct, nextAct_arrTime)){ - return null; - } - + double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct; diff --git a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java index b16f0d2c..2292ac97 100644 --- a/jsprit-core/src/main/java/algorithms/StateManagerImpl.java +++ b/jsprit-core/src/main/java/algorithms/StateManagerImpl.java @@ -1,6 +1,5 @@ package algorithms; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -28,29 +27,29 @@ class StateManagerImpl implements StateManager{ private Map activityStates = new HashMap(); - public Map getRouteStates() { - return Collections.unmodifiableMap(vehicleRouteStates); - } - - public States getRouteStates(VehicleRoute route){ - return vehicleRouteStates.get(route); - } - - public void put(VehicleRoute route, States states) { - vehicleRouteStates.put(route, states); - } - - public Map getActivityStates() { - return Collections.unmodifiableMap(activityStates); - } - - public States getActivityStates(TourActivity act){ - return activityStates.get(act); - } - - public void put(TourActivity act, States states) { - activityStates.put(act, states); - } +// Map getRouteStates() { +// return Collections.unmodifiableMap(vehicleRouteStates); +// } +// +// States getRouteStates(VehicleRoute route){ +// return vehicleRouteStates.get(route); +// } +// +// void put(VehicleRoute route, States states) { +// vehicleRouteStates.put(route, states); +// } +// +// Map getActivityStates() { +// return Collections.unmodifiableMap(activityStates); +// } +// +// States getActivityStates(TourActivity act){ +// return activityStates.get(act); +// } +// +// void put(TourActivity act, States states) { +// activityStates.put(act, states); +// } public void clear(){ vehicleRouteStates.clear(); @@ -90,6 +89,7 @@ class StateManagerImpl implements StateManager{ 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; diff --git a/jsprit-core/src/main/java/algorithms/StateTypes.java b/jsprit-core/src/main/java/algorithms/StateTypes.java index 2306281d..d7c03523 100644 --- a/jsprit-core/src/main/java/algorithms/StateTypes.java +++ b/jsprit-core/src/main/java/algorithms/StateTypes.java @@ -3,6 +3,8 @@ package algorithms; class StateTypes { 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";