From 922f360fe42ffe49c1d631340f19ebe6a6b1b1e0 Mon Sep 17 00:00:00 2001 From: Stefan Schroeder <4sschroeder@gmail.com> Date: Thu, 22 Aug 2013 16:25:20 +0200 Subject: [PATCH] internal experiments with serviceInsertion --- .../CalculatesServiceInsertion.java | 142 +++++------- ...erviceInsertionWithTriangleInequality.java | 208 ------------------ .../java/algorithms/CalculatorBuilder.java | 13 +- .../main/java/algorithms/HardConstraint.java | 7 - .../main/java/algorithms/HardConstraints.java | 33 ++- .../src/main/java/algorithms/Marginals.java | 27 +++ .../java/algorithms/MarginalsCalculus.java | 9 + .../algorithms/MarginalsCalculusDefault.java | 70 ++++++ .../java/algorithms/GendreauPostOptTest.java | 4 +- .../TestCalculatesServiceInsertion.java | 3 +- .../input/algorithmConfig_solomon.xml | 1 + .../main/java/examples/SolomonExample.java | 11 +- 12 files changed, 200 insertions(+), 328 deletions(-) delete mode 100644 jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTriangleInequality.java delete mode 100644 jsprit-core/src/main/java/algorithms/HardConstraint.java create mode 100644 jsprit-core/src/main/java/algorithms/Marginals.java create mode 100644 jsprit-core/src/main/java/algorithms/MarginalsCalculus.java create mode 100644 jsprit-core/src/main/java/algorithms/MarginalsCalculusDefault.java diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java index 65c2d6b4..20f2f69c 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java +++ b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertion.java @@ -15,11 +15,9 @@ package algorithms; import org.apache.log4j.Logger; import util.Neighborhood; -import algorithms.StateManager.State; +import algorithms.HardConstraints.HardRouteLevelConstraint; import basics.Job; import basics.Service; -import basics.costs.VehicleRoutingActivityCosts; -import basics.costs.VehicleRoutingTransportCosts; import basics.route.Driver; import basics.route.End; import basics.route.ServiceActivity; @@ -34,25 +32,36 @@ import basics.route.VehicleRoute; final class CalculatesServiceInsertion implements JobInsertionCalculator{ + static class Break { + private Marginals marginals; + private boolean breakLoop; + public Break(Marginals marginals, boolean breakLoop) { + super(); + this.marginals = marginals; + this.breakLoop = breakLoop; + } + /** + * @return the marginals + */ + public Marginals getMarginals() { + return marginals; + } + /** + * @return the breakLoop + */ + public boolean isBreakLoop() { + return breakLoop; + } + + } + private static final Logger logger = Logger.getLogger(CalculatesServiceInsertion.class); - private StateManager states; - - private VehicleRoutingTransportCosts routingCosts; - - private VehicleRoutingActivityCosts activityCosts; - private Start start; private End end; - private HardConstraint hardConstraint = new HardConstraint() { - - @Override - public boolean fulfilled(InsertionScenario iScenario) { - return true; - } - }; + private HardRouteLevelConstraint hardRouteLevelConstraint; private Neighborhood neighborhood = new Neighborhood() { @@ -62,24 +71,17 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{ } }; - void setHardConstraint(HardConstraint hardConstraint){ - this.hardConstraint = hardConstraint; - } + private MarginalsCalculus marginalCalculus; public void setNeighborhood(Neighborhood neighborhood) { this.neighborhood = neighborhood; logger.info("initialise neighborhood " + neighborhood); } - - - public void setStates(StateManager activityStates2){ - this.states = activityStates2; - } - public CalculatesServiceInsertion(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) { + public CalculatesServiceInsertion(MarginalsCalculus marginalsCalculus, HardRouteLevelConstraint hardRouteLevelConstraint) { super(); - this.routingCosts = vehicleRoutingTransportCosts; - this.activityCosts = vehicleRoutingActivityCosts; + this.marginalCalculus = marginalsCalculus; + this.hardRouteLevelConstraint = hardRouteLevelConstraint; logger.info("initialise " + this); } @@ -99,50 +101,48 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{ if(newVehicle == null || newVehicle instanceof NoVehicle) throw new IllegalStateException("newVehicle is missing."); InsertionFacts iFacts = new InsertionFacts(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime); - if(!hardConstraint.fulfilled(new InsertionScenario(iFacts, null))){ + if(!hardRouteLevelConstraint.fulfilled(new InsertionScenario(iFacts, null))){ return InsertionData.noInsertionFound(); } TourActivities tour = currentRoute.getTourActivities(); double bestCost = bestKnownCosts; + Marginals bestMarginals = null; Service service = (Service)jobToInsert; - int insertionIndex = InsertionData.NO_INDEX; - TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service); initialiseStartAndEnd(newVehicle, newVehicleDepartureTime); TourActivity prevAct = start; - double prevCostInOriginalTour = 0.0; int actIndex = 0; -// logger.debug(prevAct.toString()); + for(TourActivity nextAct : tour.getActivities()){ -// logger.debug(prevAct.toString() + " arrTime=" + prevAct.getArrTime() + " endTime=" + prevAct.getEndTime()); -// logger.debug(deliveryAct2Insert.toString() + " arrTime=" + deliveryAct2Insert.getArrTime() + " endTime=" + deliveryAct2Insert.getEndTime()); -// logger.debug(nextAct.toString() + " arrTime=" + nextAct.getArrTime() + " endTime=" + nextAct.getEndTime()); - double nextCostInOriginalTour = states.getActivityState(nextAct,StateTypes.COSTS).toDouble(); + if(deliveryAct2Insert.getTheoreticalLatestOperationStartTime() < prevAct.getTheoreticalEarliestOperationStartTime()){ + break; + } if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ - double mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, nextCostInOriginalTour - prevCostInOriginalTour); - if(mc < bestCost){ - bestCost = mc; - insertionIndex = actIndex; + Marginals mc = calculate(iFacts, prevAct, nextAct, deliveryAct2Insert); + if(mc != null){ + if(mc.getAdditionalCosts() < bestCost){ + bestCost = mc.getAdditionalCosts(); + bestMarginals = mc; + insertionIndex = actIndex; + } } } - prevCostInOriginalTour = nextCostInOriginalTour; prevAct = nextAct; actIndex++; } End nextAct = end; -// logger.debug(prevAct.toString() + " arrTime=" + prevAct.getArrTime() + " endTime=" + prevAct.getEndTime()); -// logger.debug(deliveryAct2Insert.toString() + " arrTime=" + deliveryAct2Insert.getArrTime() + " endTime=" + deliveryAct2Insert.getEndTime()); -// logger.debug(nextAct.toString() + " arrTime=" + nextAct.getArrTime() + " endTime=" + nextAct.getEndTime()); if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ - double oldRouteCosts = states.getRouteState(currentRoute, StateTypes.COSTS).toDouble(); - double mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle, bestCost, oldRouteCosts - prevCostInOriginalTour); - if(mc < bestCost){ - bestCost = mc; - insertionIndex = actIndex; + Marginals mc = calculate(iFacts, prevAct, nextAct, deliveryAct2Insert); + if(mc != null) { + if(mc.getAdditionalCosts() < bestCost){ + bestCost = mc.getAdditionalCosts(); + bestMarginals = mc; + insertionIndex = actIndex; + } } } @@ -151,6 +151,7 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{ } InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver); insertionData.setVehicleDepartureTime(newVehicleDepartureTime); + insertionData.setAdditionalTime(bestMarginals.getAdditionalTime()); return insertionData; } @@ -177,47 +178,8 @@ final class CalculatesServiceInsertion implements JobInsertionCalculator{ } } - public double calculate(TourActivity prevAct, TourActivity nextAct, TourActivity newAct, Driver driver, Vehicle vehicle, double bestKnownCosts, double costWithoutNewJob) { + public Marginals calculate(InsertionFacts iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct) { + return marginalCalculus.calculate(iFacts, prevAct, nextAct, newAct); - double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle); - double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle); - - double newAct_arrTime = prevAct.getEndTime() + tp_time_prevAct_newAct; - double newAct_operationStartTime = Math.max(newAct_arrTime, newAct.getTheoreticalEarliestOperationStartTime()); - - double newAct_endTime = newAct_operationStartTime + newAct.getOperationTime(); - - double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, driver, vehicle); - -// if((tp_costs_prevAct_newAct + act_costs_newAct - costWithoutNewJob) > bestKnownCosts){ -// return Double.MAX_VALUE; -// } - - double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle); - double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), newAct_endTime, driver, vehicle); - - double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct; - double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, driver, vehicle); - -// logger.debug("nextActArrTime="+nextAct_arrTime); - - double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + act_costs_newAct + act_costs_nextAct; - - if(totalCosts - costWithoutNewJob > bestKnownCosts){ - return Double.MAX_VALUE; - } - if(nextAct_arrTime > getLatestOperationStart(nextAct)){ - return Double.MAX_VALUE; - } - return totalCosts - costWithoutNewJob; - - } - - private double getLatestOperationStart(TourActivity act) { - if(act instanceof End) { - return end.getTheoreticalLatestOperationStartTime(); - } - return states.getActivityState(act, StateTypes.LATEST_OPERATION_START_TIME).toDouble(); - } } diff --git a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTriangleInequality.java b/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTriangleInequality.java deleted file mode 100644 index 9bd152ff..00000000 --- a/jsprit-core/src/main/java/algorithms/CalculatesServiceInsertionWithTriangleInequality.java +++ /dev/null @@ -1,208 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Stefan Schroeder. - * eMail: stefan.schroeder@kit.edu - * - * 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 - * - * Contributors: - * Stefan Schroeder - initial API and implementation - ******************************************************************************/ -package algorithms; - -import org.apache.log4j.Logger; - -import util.Neighborhood; - -import algorithms.RouteStates.ActivityState; -import algorithms.StateManager.State; -import algorithms.StateManager.States; -import basics.Job; -import basics.Service; -import basics.costs.VehicleRoutingActivityCosts; -import basics.costs.VehicleRoutingTransportCosts; -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.Vehicle; -import basics.route.VehicleRoute; -import basics.route.VehicleImpl.NoVehicle; - - - -final class CalculatesServiceInsertionWithTriangleInequality implements JobInsertionCalculator{ - - class Marginals { - private double marginalCosts; - private double marginalTime; - public Marginals(double marginalCosts, double marginalTime) { - super(); - this.marginalCosts = marginalCosts; - this.marginalTime = marginalTime; - } - /** - * @return the marginalCosts - */ - public double getMarginalCosts() { - return marginalCosts; - } - /** - * @return the marginalTime - */ - public double getMarginalTime() { - return marginalTime; - } - - } - - private static final Logger logger = Logger.getLogger(CalculatesServiceInsertionWithTriangleInequality.class); - - private StateManager routeStates; - - private VehicleRoutingTransportCosts routingCosts; - - private Start start; - - private End end; - - private HardConstraint hardConstraint = new HardConstraint() { - - @Override - public boolean fulfilled(InsertionScenario iScenario) { - return true; - } - }; - - public void setHardConstraint(HardConstraint hardConstraint){ - this.hardConstraint = hardConstraint; - } - - private Neighborhood neighborhood = new Neighborhood() { - - @Override - public boolean areNeighbors(String location1, String location2) { - return true; - } - }; - - - - public void setNeighborhood(Neighborhood neighborhood) { - this.neighborhood = neighborhood; - logger.info("initialise neighborhood " + neighborhood); - } - - public void setActivityStates(StateManager activityStates2){ - this.routeStates = activityStates2; - } - - public CalculatesServiceInsertionWithTriangleInequality(VehicleRoutingTransportCosts vehicleRoutingTransportCosts, VehicleRoutingActivityCosts vehicleRoutingActivityCosts) { - super(); - this.routingCosts = vehicleRoutingTransportCosts; - logger.info("initialise " + this); - } - - @Override - public String toString() { - return "[name=calculatesServiceInsertion]"; - } - - /** - * Calculates the marginal cost of inserting job i locally. This is based on the - * assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1. - * - */ - @Override - public InsertionData calculate(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."); - - TourActivities tour = currentRoute.getTourActivities(); - Marginals bestMarginals = new Marginals(bestKnownCosts,Double.MAX_VALUE); - Service service = (Service)jobToInsert; - - if(getCurrentLoad(currentRoute) + service.getCapacityDemand() > newVehicle.getCapacity()){ - return InsertionData.noInsertionFound(); - } - int insertionIndex = InsertionData.NO_INDEX; - - TourActivity deliveryAct2Insert = ServiceActivity.newInstance(service); - - initialiseStartAndEnd(newVehicle, newVehicleDepartureTime); - - TourActivity prevAct = start; - int actIndex = 0; - for(TourActivity nextAct : tour.getActivities()){ - if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ - Marginals mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle); - if(mc.getMarginalCosts() < bestMarginals.getMarginalCosts()){ - bestMarginals = mc; - insertionIndex = actIndex; - } - } - prevAct = nextAct; - actIndex++; - } - End nextAct = end; - if(neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), prevAct.getLocationId()) && neighborhood.areNeighbors(deliveryAct2Insert.getLocationId(), nextAct.getLocationId())){ - Marginals mc = calculate(prevAct, nextAct, deliveryAct2Insert, newDriver, newVehicle); - if(mc.getMarginalCosts() < bestMarginals.getMarginalCosts()){ - bestMarginals = mc; - insertionIndex = actIndex; - } - } - - if(insertionIndex == InsertionData.NO_INDEX) { - return InsertionData.noInsertionFound(); - } - InsertionData insertionData = new InsertionData(bestMarginals.getMarginalCosts(), InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver); - insertionData.setVehicleDepartureTime(newVehicleDepartureTime); - insertionData.setAdditionalTime(bestMarginals.getMarginalTime()); - return insertionData; - } - - private int getCurrentLoad(VehicleRoute currentRoute) { - return (int) routeStates.getRouteState(currentRoute, StateTypes.LOAD).toDouble(); - } - - private void initialiseStartAndEnd(final Vehicle newVehicle, double newVehicleDepartureTime) { - if(start == null){ - start = Start.newInstance(newVehicle.getLocationId(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival()); - start.setEndTime(newVehicleDepartureTime); - } - else{ - start.setLocationId(newVehicle.getLocationId()); - start.setTheoreticalEarliestOperationStartTime(newVehicle.getEarliestDeparture()); - start.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival()); - start.setEndTime(newVehicleDepartureTime); - } - - if(end == null){ - end = End.newInstance(newVehicle.getLocationId(), 0.0, newVehicle.getLatestArrival()); - } - else{ - end.setLocationId(newVehicle.getLocationId()); - end.setTheoreticalEarliestOperationStartTime(newVehicleDepartureTime); - end.setTheoreticalLatestOperationStartTime(newVehicle.getLatestArrival()); - } - } - - public Marginals calculate(TourActivity prevAct, TourActivity nextAct, TourActivity newAct, Driver driver, Vehicle vehicle) { - - double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle); - double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), driver, vehicle); - - double tp_costs_newAct_nextAct = routingCosts.getTransportCost(newAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle); - double tp_time_newAct_nextAct = routingCosts.getTransportTime(newAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle); - - double tp_costs_prevAct_nextAct = routingCosts.getTransportCost(prevAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle); - double tp_time_prevAct_nextAct = routingCosts.getTransportTime(prevAct.getLocationId(), nextAct.getLocationId(), 0.0, driver, vehicle); - - return new Marginals(tp_costs_prevAct_newAct + tp_costs_newAct_nextAct - tp_costs_prevAct_nextAct, tp_time_prevAct_newAct + tp_time_newAct_nextAct - tp_time_prevAct_nextAct); - } -} diff --git a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java index c2793ea0..c8c745cb 100644 --- a/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java +++ b/jsprit-core/src/main/java/algorithms/CalculatorBuilder.java @@ -22,18 +22,10 @@ package algorithms; import java.util.ArrayList; import java.util.List; -import java.util.Set; - -import org.apache.commons.configuration.XMLConfiguration; - -import util.NeighborhoodImpl; import basics.VehicleRoutingProblem; -import basics.VehicleRoutingProblem.FleetComposition; import basics.algo.InsertionListener; import basics.algo.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener; -import basics.algo.VehicleRoutingAlgorithmListeners.Priority; -import basics.costs.VehicleRoutingActivityCosts; @@ -222,11 +214,10 @@ class CalculatorBuilder { } private CalculatorPlusListeners createStandardLocal(VehicleRoutingProblem vrp, StateManager activityStates2){ - JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(vrp.getTransportCosts(), vrp.getActivityCosts()); + MarginalsCalculus defaultCalc = new MarginalsCalculusDefault(vrp.getTransportCosts(), vrp.getActivityCosts(), new HardConstraints.HardTimeWindowConstraint(activityStates2) ); + JobInsertionCalculator standardServiceInsertion = new CalculatesServiceInsertion(defaultCalc, new HardConstraints.HardLoadConstraint(activityStates2)); - ((CalculatesServiceInsertion) standardServiceInsertion).setStates(activityStates2); ((CalculatesServiceInsertion) standardServiceInsertion).setNeighborhood(vrp.getNeighborhood()); - ((CalculatesServiceInsertion) standardServiceInsertion).setHardConstraint(new HardConstraints.HardLoadConstraint(activityStates2)); CalculatorPlusListeners calcPlusListeners = new CalculatorPlusListeners(standardServiceInsertion); return calcPlusListeners; diff --git a/jsprit-core/src/main/java/algorithms/HardConstraint.java b/jsprit-core/src/main/java/algorithms/HardConstraint.java deleted file mode 100644 index 8fbbad8c..00000000 --- a/jsprit-core/src/main/java/algorithms/HardConstraint.java +++ /dev/null @@ -1,7 +0,0 @@ -package algorithms; - -interface HardConstraint { - - public boolean fulfilled(InsertionScenario iScenario); - -} diff --git a/jsprit-core/src/main/java/algorithms/HardConstraints.java b/jsprit-core/src/main/java/algorithms/HardConstraints.java index 5eaac689..566ae5d7 100644 --- a/jsprit-core/src/main/java/algorithms/HardConstraints.java +++ b/jsprit-core/src/main/java/algorithms/HardConstraints.java @@ -1,10 +1,23 @@ package algorithms; import basics.Service; +import basics.route.TourActivity; class HardConstraints { - static class HardLoadConstraint implements HardConstraint{ + interface HardRouteLevelConstraint { + + public boolean fulfilled(InsertionScenario iScenario); + + } + + interface HardActivityLevelConstraint { + + public boolean fulfilled(InsertionFacts iFacts, TourActivity act, double arrTime); + + } + + static class HardLoadConstraint implements HardRouteLevelConstraint{ private StateManager states; @@ -22,7 +35,25 @@ class HardConstraints { } return true; } + } + + static class HardTimeWindowConstraint implements HardActivityLevelConstraint { + + private StateManager states; + public HardTimeWindowConstraint(StateManager states) { + super(); + this.states = states; + } + + @Override + public boolean fulfilled(InsertionFacts iFacts, TourActivity act, double arrTime) { + if(arrTime > states.getActivityState(act, StateTypes.LATEST_OPERATION_START_TIME).toDouble()){ + return false; + } + return true; + } + } } diff --git a/jsprit-core/src/main/java/algorithms/Marginals.java b/jsprit-core/src/main/java/algorithms/Marginals.java new file mode 100644 index 00000000..48cffd4b --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/Marginals.java @@ -0,0 +1,27 @@ +package algorithms; + +class Marginals { + + private double additionalCosts; + private double additionalTime; + public Marginals(double additionalCosts, double additionalTime) { + super(); + this.additionalCosts = additionalCosts; + this.additionalTime = additionalTime; + } + /** + * @return the additionalCosts + */ + public double getAdditionalCosts() { + return additionalCosts; + } + /** + * @return the additionalTime + */ + public double getAdditionalTime() { + return additionalTime; + } + + + +} diff --git a/jsprit-core/src/main/java/algorithms/MarginalsCalculus.java b/jsprit-core/src/main/java/algorithms/MarginalsCalculus.java new file mode 100644 index 00000000..b5728fb7 --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/MarginalsCalculus.java @@ -0,0 +1,9 @@ +package algorithms; + +import basics.route.TourActivity; + +interface MarginalsCalculus { + + Marginals calculate(InsertionFacts iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct); + +} diff --git a/jsprit-core/src/main/java/algorithms/MarginalsCalculusDefault.java b/jsprit-core/src/main/java/algorithms/MarginalsCalculusDefault.java new file mode 100644 index 00000000..699779ed --- /dev/null +++ b/jsprit-core/src/main/java/algorithms/MarginalsCalculusDefault.java @@ -0,0 +1,70 @@ +package algorithms; + +import algorithms.HardConstraints.HardActivityLevelConstraint; +import basics.costs.VehicleRoutingActivityCosts; +import basics.costs.VehicleRoutingTransportCosts; +import basics.route.TourActivity; + +class MarginalsCalculusDefault implements MarginalsCalculus{ + + private HardActivityLevelConstraint hardConstraint; + + private VehicleRoutingTransportCosts routingCosts; + private VehicleRoutingActivityCosts activityCosts; + + public MarginalsCalculusDefault(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts actCosts, HardActivityLevelConstraint hardActivityLevelConstraint) { + super(); + this.routingCosts = routingCosts; + this.activityCosts = actCosts; + this.hardConstraint = hardActivityLevelConstraint; + } + + @Override + public Marginals calculate(InsertionFacts iFacts, TourActivity prevAct, TourActivity nextAct, TourActivity newAct) { + double tp_costs_prevAct_newAct = routingCosts.getTransportCost(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle()); + double tp_time_prevAct_newAct = routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevAct.getEndTime(), iFacts.getNewDriver(), iFacts.getNewVehicle()); + + double newAct_arrTime = prevAct.getEndTime() + tp_time_prevAct_newAct; + + if(!hardConstraint.fulfilled(iFacts, newAct, newAct_arrTime)){ + return null; + } + + double newAct_operationStartTime = Math.max(newAct_arrTime, newAct.getTheoreticalEarliestOperationStartTime()); + + double newAct_endTime = newAct_operationStartTime + newAct.getOperationTime(); + + 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; + + 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; + + double oldCosts; + if(iFacts.getRoute().isEmpty()){ + oldCosts = 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; + } + + double additionalCosts = totalCosts - oldCosts; + double additionalTime = nextAct_arrTime - nextAct.getArrTime(); + + return new Marginals(additionalCosts,additionalTime); + } + +} diff --git a/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java b/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java index e092b53e..ee80235e 100644 --- a/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java +++ b/jsprit-core/src/test/java/algorithms/GendreauPostOptTest.java @@ -151,8 +151,8 @@ public class GendreauPostOptTest { activityCosts = new ExampleActivityCostFunction(); - CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(cost, activityCosts); - standardServiceInsertion.setStates(states); + CalculatesServiceInsertion standardServiceInsertion = new CalculatesServiceInsertion(new MarginalsCalculusDefault(cost, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states)); + CalculatesServiceInsertionConsideringFixCost withFixCost = new CalculatesServiceInsertionConsideringFixCost(standardServiceInsertion, states); withFixCost.setWeightOfFixCost(1.2); diff --git a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java index 9948e816..de649284 100644 --- a/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java +++ b/jsprit-core/src/test/java/algorithms/TestCalculatesServiceInsertion.java @@ -156,8 +156,7 @@ public class TestCalculatesServiceInsertion { ExampleActivityCostFunction activityCosts = new ExampleActivityCostFunction(); - serviceInsertion = new CalculatesServiceInsertion(costs, activityCosts); - serviceInsertion.setStates(states); + serviceInsertion = new CalculatesServiceInsertion(new MarginalsCalculusDefault(costs, activityCosts, new HardConstraints.HardTimeWindowConstraint(states)), new HardConstraints.HardLoadConstraint(states)); stateUpdater = new UpdateStates(states, costs, activityCosts); diff --git a/jsprit-examples/input/algorithmConfig_solomon.xml b/jsprit-examples/input/algorithmConfig_solomon.xml index e3817e95..12b98942 100755 --- a/jsprit-examples/input/algorithmConfig_solomon.xml +++ b/jsprit-examples/input/algorithmConfig_solomon.xml @@ -7,6 +7,7 @@ + diff --git a/jsprit-examples/src/main/java/examples/SolomonExample.java b/jsprit-examples/src/main/java/examples/SolomonExample.java index c72ebd1b..1b13d865 100644 --- a/jsprit-examples/src/main/java/examples/SolomonExample.java +++ b/jsprit-examples/src/main/java/examples/SolomonExample.java @@ -24,19 +24,15 @@ import java.io.File; import java.util.Collection; import readers.SolomonReader; -import algorithms.GreedySchrimpfFactory; -import algorithms.SchrimpfFactory; import algorithms.VehicleRoutingAlgorithms; import algorithms.selectors.SelectBest; import analysis.AlgorithmSearchProgressChartListener; import analysis.SolutionPlotter; import analysis.SolutionPrinter; import analysis.SolutionPrinter.Print; -import analysis.StopWatch; import basics.VehicleRoutingAlgorithm; import basics.VehicleRoutingProblem; import basics.VehicleRoutingProblemSolution; -import basics.algo.VehicleRoutingAlgorithmListeners.Priority; public class SolomonExample { @@ -76,9 +72,10 @@ public class SolomonExample { * * The algorithm can be defined and configured in an xml-file. */ - VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp); -// VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_solomon.xml"); - vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png")); +// VehicleRoutingAlgorithm vra = new SchrimpfFactory().createAlgorithm(vrp); + VehicleRoutingAlgorithm vra = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "input/algorithmConfig_solomon.xml"); + vra.setPrematureBreak(100); +// vra.getAlgorithmListeners().addListener(new AlgorithmSearchProgressChartListener("output/sol_progress.png")); /* * Solve the problem. *