diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java index 8b1a1c73..1f89669e 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionOnRouteLevel.java @@ -13,7 +13,6 @@ package algorithms; import java.util.ArrayList; -import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -23,6 +22,7 @@ import java.util.PriorityQueue; import org.apache.log4j.Logger; import util.Neighborhood; +import algorithms.ActivityInsertionCostsCalculator.ActivityInsertionCosts; import algorithms.HardConstraints.HardRouteLevelConstraint; import basics.Job; import basics.Service; @@ -90,11 +90,12 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul logger.info("set [solutionMemory="+memorySize+"]"); } - public CalculatesServiceInsertionOnRouteLevel(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, HardRouteLevelConstraint hardRouteLevelConstraint) { + public CalculatesServiceInsertionOnRouteLevel(VehicleRoutingTransportCosts vehicleRoutingCosts, VehicleRoutingActivityCosts costFunc, HardRouteLevelConstraint hardRouteLevelConstraint, ActivityInsertionCostsCalculator activityInsertionCostsCalculator) { super(); this.transportCosts = vehicleRoutingCosts; this.activityCosts = costFunc; this.hardRouteLevelConstraint = hardRouteLevelConstraint; + this.activityInsertionCostsCalculator = activityInsertionCostsCalculator; auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(transportCosts, activityCosts); logger.info("initialise " + this); } @@ -169,32 +170,22 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul 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} - */ - - //--------------------------- - //ActivityInsertionCostsEstimator - List path = new ArrayList(); - path.add(prevAct); path.add(serviceAct2Insert); path.add(nextAct); - if(nuOfActsForwardLooking > 0){ path.addAll(getForwardLookingPath(currentRoute,actIndex)); } + */ + 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(); - /** - * calculates the path costs with new vehicle, c(forwardPath,newVehicle). - */ - double forwardPathCost_newVehicle = auxilliaryPathCostCalculator.costOfPath(path, prevActDepTime_newVehicle, newDriver, 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) - */ - double insertion_cost_approximation = sumOf_prevCosts_newVehicle + forwardPathCost_newVehicle - pathCost_oldVehicle(currentRoute,path); - - /** - * 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)); + } } - } /** @@ -227,25 +218,20 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul End nextAct = end; if(neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(serviceAct2Insert.getLocationId(), nextAct.getLocationId())){ - //---------------------------- - //ActivityInsertionCostsEstimator - /** - * calculates the path costs with new vehicle, c(forwardPath,newVehicle). - */ - List path = Arrays.asList(prevAct,serviceAct2Insert,end); - double forwardPathCost_newVehicle = auxilliaryPathCostCalculator.costOfPath(path, prevActDepTime_newVehicle, newDriver, 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) - */ - double insertion_cost_approximation = sumOf_prevCosts_newVehicle + forwardPathCost_newVehicle - pathCost_oldVehicle(currentRoute,path); + 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)); + } } } @@ -256,39 +242,40 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul * */ - if(memorySize==0){ + if(memorySize==0){ // return bestInsertion InsertionData insertion = bestInsertionsQueue.poll(); if(insertion != null){ best_insertion_index = insertion.getDeliveryInsertionIndex(); best_insertion_costs = insertion.getInsertionCost(); } } - - for(int i=0;i wholeTour = new ArrayList(); - wholeTour.add(start); - wholeTour.addAll(currentRoute.getTourActivities().getActivities()); - wholeTour.add(end); - wholeTour.add(data.getDeliveryInsertionIndex()+1, serviceAct2Insert); - - /** - * compute cost-diff of tour with and without new activity --> insertion_costs - */ - double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateTypes.COSTS).toDouble(); - - /** - * if better than best known, make it the best known - */ - if(insertion_costs < best_insertion_costs){ - best_insertion_index = data.getDeliveryInsertionIndex(); - best_insertion_costs = insertion_costs; + else{ + for(int i=0;i wholeTour = new ArrayList(); + wholeTour.add(start); + wholeTour.addAll(currentRoute.getTourActivities().getActivities()); + wholeTour.add(end); + wholeTour.add(data.getDeliveryInsertionIndex()+1, serviceAct2Insert); + + /** + * compute cost-diff of tour with and without new activity --> insertion_costs + */ + double insertion_costs = auxilliaryPathCostCalculator.costOfPath(wholeTour, start.getEndTime(), newDriver, newVehicle) - stateManager.getRouteState(currentRoute,StateTypes.COSTS).toDouble(); + + /** + * if better than best known, make it the best known + */ + if(insertion_costs < best_insertion_costs){ + best_insertion_index = data.getDeliveryInsertionIndex(); + best_insertion_costs = insertion_costs; + } } } if(best_insertion_index == InsertionData.NO_INDEX) return InsertionData.noInsertionFound(); @@ -323,36 +310,13 @@ final class CalculatesServiceInsertionOnRouteLevel implements JobInsertionCalcul } } - private double pathCost_oldVehicle(VehicleRoute vehicleRoute, List path) { - TourActivity act = path.get(path.size()-1); + private double sumOf_prevCosts_oldVehicle(VehicleRoute vehicleRoute, TourActivity act) { if(act instanceof End){ return stateManager.getRouteState(vehicleRoute,StateTypes.COSTS).toDouble(); } return stateManager.getActivityState(act,StateTypes.COSTS).toDouble(); } - /** - * returns the path or the partial route r_partial = {j+1,j+2,...,j+nuOfActsForwardLooking} - * - * @param route - * @param actIndex - * @return - */ - private List getForwardLookingPath(VehicleRoute route, int actIndex) { - List forwardLookingPath = new ArrayList(); - int nuOfActsInPath = 0; - int index = actIndex + 1; - while(index < route.getTourActivities().getActivities().size() && nuOfActsInPath < nuOfActsForwardLooking){ - forwardLookingPath.add(route.getTourActivities().getActivities().get(index)); - index++; - nuOfActsInPath++; - } - if(nuOfActsInPath < nuOfActsForwardLooking){ - forwardLookingPath.add(route.getEnd()); - } - return forwardLookingPath; - } - /** * creates a comparator to sort insertion-data in insertionQueue in ascending order according insertion costs. * @return diff --git a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java index 621a8f27..4465baf0 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java +++ b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java @@ -238,7 +238,8 @@ class CalculatorBuilder { private CalculatorPlusListeners createStandardRoute(VehicleRoutingProblem vrp, StateManager activityStates2, int forwardLooking, int solutionMemory){ int after = forwardLooking; - JobInsertionCalculator jobInsertionCalculator = new CalculatesServiceInsertionOnRouteLevel(vrp.getTransportCosts(), vrp.getActivityCosts(), hardRouteLevelConstraint); + 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()); diff --git a/jsprit-core/src/main/java/algorithms/RouteLevelActivityInsertionCostsEstimator.java b/jsprit-core/src/main/java/algorithms/RouteLevelActivityInsertionCostsEstimator.java index 53d265fe..2daa5e63 100644 --- a/jsprit-core/src/main/java/algorithms/RouteLevelActivityInsertionCostsEstimator.java +++ b/jsprit-core/src/main/java/algorithms/RouteLevelActivityInsertionCostsEstimator.java @@ -35,8 +35,6 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost private HardActivityLevelConstraint hardConstraint; - private VehicleRoutingTransportCosts routingCosts; - private VehicleRoutingActivityCosts activityCosts; private AuxilliaryCostCalculator auxilliaryPathCostCalculator; @@ -47,9 +45,9 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost public RouteLevelActivityInsertionCostsEstimator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint, StateManager stateManager) { super(); - this.routingCosts = routingCosts; this.activityCosts = actCosts; this.hardConstraint = hardActivityLevelConstraint; + this.stateManager = stateManager; auxilliaryPathCostCalculator = new AuxilliaryCostCalculator(routingCosts, activityCosts); } @@ -75,46 +73,6 @@ class RouteLevelActivityInsertionCostsEstimator implements ActivityInsertionCost return new ActivityInsertionCosts(additionalCosts, 0.0); - -// -// -// 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 act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); -// -// double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); -// 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; -// -// 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; -// -// double oldCosts; -// double oldTime; -// if(iFacts.getRoute().isEmpty()){ -// oldCosts = 0.0; -// oldTime = 0.0; -// } -// else{ -// double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle()); -// double arrTime_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle()); -// -// double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle()); -// oldCosts = tp_costs_prevAct_nextAct + actCost_nextAct; -// oldTime = (nextAct.getArrTime() - iFacts.getRoute().getDepartureTime()); -// } -// -// double additionalCosts = totalCosts - oldCosts; -// double additionalTime = (nextAct_arrTime - iFacts.getNewDepTime()) - oldTime; -// -// return new ActivityInsertionCosts(additionalCosts,additionalTime); } private double actCostsOld(VehicleRoute vehicleRoute, TourActivity act) { diff --git a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java index ae1ef0c9..3af69cb6 100644 --- a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java +++ b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertionOnRouteLevel.java @@ -147,14 +147,13 @@ public class TestCalculatesServiceInsertionOnRouteLevel { states = new StateManagerImpl(); ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction(); - serviceInsertion = new CalculatesServiceInsertionOnRouteLevel(costs,activityCosts, hardRouteLevelConstraint); + ActivityInsertionCostsCalculator actInsertionCostCalculator = new RouteLevelActivityInsertionCostsEstimator(costs, activityCosts, new HardConstraints.HardTimeWindowActivityLevelConstraint(states, costs), states); + serviceInsertion = new CalculatesServiceInsertionOnRouteLevel(costs,activityCosts, new HardConstraints.HardLoadConstraint(states), actInsertionCostCalculator); serviceInsertion.setNuOfActsForwardLooking(4); serviceInsertion.setStates(states); updateStates = new UpdateStates(states, costs, activityCosts); - - } public TourActivity getActivityMock(String id, double earliestOperationStart, double currCost){