From 8df550e0e66dea49d813e1346fcc56ca7c1f3e60 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Wed, 17 Sep 2014 12:54:24 +0200 Subject: [PATCH] add Figliozzi utilities to benchmark VRP with time dependent costs --- .../jsprit/instance/reader/Figliozzi.java | 190 ++++++++++++++++++ .../instance/reader/FigliozziReader.java | 139 ------------- .../instance/reader/FigliozziReaderTest.java | 54 +++++ 3 files changed, 244 insertions(+), 139 deletions(-) create mode 100644 jsprit-instances/src/main/java/jsprit/instance/reader/Figliozzi.java delete mode 100644 jsprit-instances/src/main/java/jsprit/instance/reader/FigliozziReader.java create mode 100644 jsprit-instances/src/test/java/jsprit/instance/reader/FigliozziReaderTest.java diff --git a/jsprit-instances/src/main/java/jsprit/instance/reader/Figliozzi.java b/jsprit-instances/src/main/java/jsprit/instance/reader/Figliozzi.java new file mode 100644 index 00000000..7382637a --- /dev/null +++ b/jsprit-instances/src/main/java/jsprit/instance/reader/Figliozzi.java @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (C) 2014 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 jsprit.instance.reader; + +import jsprit.core.problem.cost.VehicleRoutingTransportCosts; +import jsprit.core.problem.driver.Driver; +import jsprit.core.problem.vehicle.Vehicle; +import jsprit.core.util.EuclideanDistanceCalculator; +import jsprit.core.util.Locations; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +public class Figliozzi { + + public static class TimeDependentTransportCostsFactory { + + public static enum SpeedDistribution { + + TD1a, TD1b, TD1c, TD2a, TD2b, TD2c, TD3a, TD3b, TD3c, TD1d, TD2d, TD3d, TD4, TD5, TD6 + + } + + + public static TDCosts createCosts(Locations locations, SpeedDistribution speedDistribution, double depotClosingTime){ + List timeBins = createTimeBins(depotClosingTime); + List speedValues = createSpeedValues(speedDistribution); + return new TDCosts(locations,timeBins,speedValues); + } + + static List createSpeedValues(SpeedDistribution speedDistribution) { + List speedValues = Collections.emptyList(); + switch(speedDistribution){ + case TD1a: speedValues = Arrays.asList(1.,1.6,1.05,1.6,1.); break; + case TD2a: speedValues = Arrays.asList(1.,2.,1.5,2.,1.); break; + case TD3a: speedValues = Arrays.asList(1.,2.5,1.75,2.5,1.); break; + + case TD1b: speedValues = Arrays.asList(1.6,1.,1.05,1.,1.6); break; + case TD2b: speedValues = Arrays.asList(2.,1.,1.5,1.,2.); break; + case TD3b: speedValues = Arrays.asList(2.5,1.,1.75,1.,2.5); break; + + case TD1c: speedValues = Arrays.asList(1.6,1.6,1.05,1.,1.); break; + case TD2c: speedValues = Arrays.asList(2.,2.,1.5,1.,1.); break; + case TD3c: speedValues = Arrays.asList(2.5,2.5,1.75,1.,1.); break; + + case TD1d: speedValues = Arrays.asList(1.,1.,1.05,1.6,1.6); break; + case TD2d: speedValues = Arrays.asList(1.,1.,1.5,2.,2.); break; + case TD3d: speedValues = Arrays.asList(1.,1.,1.75,2.5,2.5); break; + + case TD4: speedValues = Arrays.asList(1.1,0.85,1.1,0.85,1.1); break; + case TD5: speedValues = Arrays.asList(1.2,0.8,1.,0.8,1.2); break; + case TD6: speedValues = Arrays.asList(1.2,0.7,1.2,0.7,1.2); break; + } + return speedValues; + } + + private static List createTimeBins(double depotClosingTime) { + List timeBins = new ArrayList(); + timeBins.add(.2 * depotClosingTime); + timeBins.add(.4 * depotClosingTime); + timeBins.add(.6 * depotClosingTime); + timeBins.add(.8 * depotClosingTime); + timeBins.add(depotClosingTime); + return timeBins; + } + + } + + + public static class TDCosts implements VehicleRoutingTransportCosts { + + private List timeBins; + + private List speed; + + private Locations locations; + + private double transportDistanceParameter = 1.; + + private double transportTimeParameter = 1.; + + public TDCosts(Locations locations, List timeBins, List speedValues) { + super(); + speed = speedValues; + this.timeBins = timeBins; + this.locations = locations; + } + + public void setTransportDistanceParameter(double transportDistanceParameter) { + this.transportDistanceParameter = transportDistanceParameter; + } + + public void setTransportTimeParameter(double transportTimeParameter) { + this.transportTimeParameter = transportTimeParameter; + } + + @Override + public double getTransportCost(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) { + return transportDistanceParameter * EuclideanDistanceCalculator.calculateDistance(locations.getCoord(fromId),locations.getCoord(toId)) + + transportTimeParameter * getTransportTime(fromId,toId,departureTime, driver, vehicle); + } + + @Override + public double getBackwardTransportCost(String fromId, String toId,double arrivalTime, Driver driver, Vehicle vehicle) { + return transportDistanceParameter * EuclideanDistanceCalculator.calculateDistance(locations.getCoord(fromId),locations.getCoord(toId)) + + transportTimeParameter * getBackwardTransportTime(fromId, toId, arrivalTime, driver, vehicle); + } + + + @Override + public double getTransportTime(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) { + if(fromId.equals(toId)){ + return 0.0; + } + double totalTravelTime = 0.0; + double distanceToTravel = EuclideanDistanceCalculator.calculateDistance(locations.getCoord(fromId), locations.getCoord(toId)); + double currentTime = departureTime; + for(int i=0;i maxReachableDistance){ + distanceToTravel = distanceToTravel - maxReachableDistance; + totalTravelTime += (timeThreshold-currentTime); + currentTime = timeThreshold; + } + else{ //<= maxReachableDistance + totalTravelTime += distanceToTravel/speed.get(i); + return totalTravelTime; + } + } + } + return Double.MAX_VALUE; + } + + + @Override + public double getBackwardTransportTime(String fromId, String toId,double arrivalTime, Driver driver, Vehicle vehicle) { + if(fromId.equals(toId)){ + return 0.0; + } + double totalTravelTime = 0.0; + double distanceToTravel = EuclideanDistanceCalculator.calculateDistance(locations.getCoord(fromId), locations.getCoord(toId)); + double currentTime = arrivalTime; + for(int i=timeBins.size()-1;i>=0;i--){ + double nextLowerTimeThreshold; + if(i>0){ + nextLowerTimeThreshold = timeBins.get(i-1); + } + else{ + nextLowerTimeThreshold = 0; + } + if(currentTime > nextLowerTimeThreshold){ + double maxReachableDistance = (currentTime - nextLowerTimeThreshold)*speed.get(i); + if(distanceToTravel > maxReachableDistance){ + distanceToTravel = distanceToTravel - maxReachableDistance; + totalTravelTime += (currentTime-nextLowerTimeThreshold); + currentTime = nextLowerTimeThreshold; + } + else{ //<= maxReachableDistance + totalTravelTime += distanceToTravel/speed.get(i); + return totalTravelTime; + } + } + } + return Double.MAX_VALUE; + } + + + + } + +} diff --git a/jsprit-instances/src/main/java/jsprit/instance/reader/FigliozziReader.java b/jsprit-instances/src/main/java/jsprit/instance/reader/FigliozziReader.java deleted file mode 100644 index d41c0712..00000000 --- a/jsprit-instances/src/main/java/jsprit/instance/reader/FigliozziReader.java +++ /dev/null @@ -1,139 +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 jsprit.instance.reader; - -import java.util.List; - -import jsprit.core.problem.cost.VehicleRoutingTransportCosts; -import jsprit.core.problem.driver.Driver; -import jsprit.core.problem.vehicle.Vehicle; -import jsprit.core.util.CrowFlyCosts; -import jsprit.core.util.Locations; - - -public class FigliozziReader { - - public static class TDCosts implements VehicleRoutingTransportCosts { - - private List timeBins; - - private List speed; - - private CrowFlyCosts crowFly; - - public TDCosts(Locations locations, List timeBins, List speedValues) { - super(); - speed = speedValues; - this.timeBins = timeBins; - crowFly = new CrowFlyCosts(locations); - } - - @Override - public double getTransportCost(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) { - return 1.0*crowFly.getTransportCost(fromId, toId, departureTime, null, null) + - 1.0*getTransportTime(fromId,toId,departureTime, null, null); -// return getTransportTime(fromId, toId, departureTime, driver, vehicle); -// return crowFly.getTransportCost(fromId, toId, departureTime, null, null); - } - - @Override - public double getBackwardTransportCost(String fromId, String toId,double arrivalTime, Driver driver, Vehicle vehicle) { -// return crowFly.getTransportCost(fromId, toId, arrivalTime, null,null) + getBackwardTransportTime(fromId, toId, arrivalTime,null,null); - return getBackwardTransportTime(fromId, toId, arrivalTime, driver, vehicle); -// return crowFly.getTransportCost(fromId, toId, arrivalTime, null, null); - } - - - @Override - public double getTransportTime(String fromId, String toId, double departureTime, Driver driver, Vehicle vehicle) { - if(fromId.equals(toId)){ - return 0.0; - } - double totalTravelTime = 0.0; - double distanceToTravel = crowFly.getTransportCost(fromId, toId, departureTime, null, null); - double currentTime = departureTime; - for(int i=0;i maxReachableDistance){ - distanceToTravel = distanceToTravel - maxReachableDistance; - totalTravelTime += (timeThreshold-currentTime); - currentTime = timeThreshold; - continue; - } - else{ //<= maxReachableDistance - totalTravelTime += distanceToTravel/speed.get(i); - return totalTravelTime; - } - } - } - return Double.MAX_VALUE; - } - - - @Override - public double getBackwardTransportTime(String fromId, String toId,double arrivalTime, Driver driver, Vehicle vehicle) { - if(fromId.equals(toId)){ - return 0.0; - } - double totalTravelTime = 0.0; - double distanceToTravel = crowFly.getTransportCost(fromId, toId, arrivalTime, null, null); - double currentTime = arrivalTime; - for(int i=timeBins.size()-1;i>=0;i--){ - double nextLowerTimeThreshold; - if(i>0){ - nextLowerTimeThreshold = timeBins.get(i-1); - } - else{ - nextLowerTimeThreshold = 0; - } - if(currentTime > nextLowerTimeThreshold){ - double maxReachableDistance = (currentTime - nextLowerTimeThreshold)*speed.get(i); - if(distanceToTravel > maxReachableDistance){ - distanceToTravel = distanceToTravel - maxReachableDistance; - totalTravelTime += (currentTime-nextLowerTimeThreshold); - currentTime = nextLowerTimeThreshold; - continue; - } - else{ //<= maxReachableDistance - totalTravelTime += distanceToTravel/speed.get(i); - return totalTravelTime; - } - } - } - return Double.MAX_VALUE; - } - - - - } - -// private VehicleRoutingProblem.Builder builder; -// -// public FigliozziReader(Builder builder) { -// super(); -// this.builder = builder; -// } -// -// public void read(String instanceFile, String speedScenarioFile, String speedScenario){ -// -// -// } -// - -} diff --git a/jsprit-instances/src/test/java/jsprit/instance/reader/FigliozziReaderTest.java b/jsprit-instances/src/test/java/jsprit/instance/reader/FigliozziReaderTest.java new file mode 100644 index 00000000..c5d18b00 --- /dev/null +++ b/jsprit-instances/src/test/java/jsprit/instance/reader/FigliozziReaderTest.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (C) 2014 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 jsprit.instance.reader; + + +import junit.framework.Assert; +import org.junit.Test; + +import java.util.List; + +public class FigliozziReaderTest { + + @Test + public void factoryShouldReturnCorrectSpeedDistribution(){ + List speedValues = Figliozzi.TimeDependentTransportCostsFactory.createSpeedValues(Figliozzi.TimeDependentTransportCostsFactory.SpeedDistribution.TD1a); + Assert.assertEquals(speedValues.get(0),1.,0.01); + Assert.assertEquals(speedValues.get(1),1.6,0.01); + Assert.assertEquals(speedValues.get(2),1.05,0.01); + Assert.assertEquals(5,speedValues.size()); + } + + @Test + public void whenAskingForTD1b_factoryShouldReturnCorrectSpeedDistribution(){ + List speedValues = Figliozzi.TimeDependentTransportCostsFactory.createSpeedValues(Figliozzi.TimeDependentTransportCostsFactory.SpeedDistribution.TD1b); + Assert.assertEquals(speedValues.get(0),1.,0.01); + Assert.assertEquals(speedValues.get(1),2.,0.01); + Assert.assertEquals(speedValues.get(2),1.5,0.01); + Assert.assertEquals(5,speedValues.size()); + } + + @Test + public void whenAskingForTD1c_factoryShouldReturnCorrectSpeedDistribution(){ + List speedValues = Figliozzi.TimeDependentTransportCostsFactory.createSpeedValues(Figliozzi.TimeDependentTransportCostsFactory.SpeedDistribution.TD1c); + Assert.assertEquals(speedValues.get(0),1.,0.01); + Assert.assertEquals(speedValues.get(1),2.5,0.01); + Assert.assertEquals(speedValues.get(2),1.75,0.01); + Assert.assertEquals(5,speedValues.size()); + } +}