mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
add Figliozzi utilities to benchmark VRP with time dependent costs
This commit is contained in:
parent
427bca13cc
commit
8df550e0e6
3 changed files with 244 additions and 139 deletions
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
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<Double> timeBins = createTimeBins(depotClosingTime);
|
||||||
|
List<Double> speedValues = createSpeedValues(speedDistribution);
|
||||||
|
return new TDCosts(locations,timeBins,speedValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Double> createSpeedValues(SpeedDistribution speedDistribution) {
|
||||||
|
List<Double> 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<Double> createTimeBins(double depotClosingTime) {
|
||||||
|
List<Double> timeBins = new ArrayList<Double>();
|
||||||
|
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<Double> timeBins;
|
||||||
|
|
||||||
|
private List<Double> speed;
|
||||||
|
|
||||||
|
private Locations locations;
|
||||||
|
|
||||||
|
private double transportDistanceParameter = 1.;
|
||||||
|
|
||||||
|
private double transportTimeParameter = 1.;
|
||||||
|
|
||||||
|
public TDCosts(Locations locations, List<Double> timeBins, List<Double> 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<timeBins.size();i++){
|
||||||
|
double timeThreshold = timeBins.get(i);
|
||||||
|
if(currentTime < timeThreshold){
|
||||||
|
double maxReachableDistance = (timeThreshold-currentTime)*speed.get(i);
|
||||||
|
if(distanceToTravel > 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
******************************************************************************/
|
|
||||||
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<Double> timeBins;
|
|
||||||
|
|
||||||
private List<Double> speed;
|
|
||||||
|
|
||||||
private CrowFlyCosts crowFly;
|
|
||||||
|
|
||||||
public TDCosts(Locations locations, List<Double> timeBins, List<Double> 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<timeBins.size();i++){
|
|
||||||
double timeThreshold = timeBins.get(i);
|
|
||||||
if(currentTime < timeThreshold){
|
|
||||||
double maxReachableDistance = (timeThreshold-currentTime)*speed.get(i);
|
|
||||||
if(distanceToTravel > 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){
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
package jsprit.instance.reader;
|
||||||
|
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FigliozziReaderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void factoryShouldReturnCorrectSpeedDistribution(){
|
||||||
|
List<Double> 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<Double> 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<Double> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue