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