mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
Merge 7a30aba0af into 74c3c6839b
This commit is contained in:
commit
584d8a39b8
2 changed files with 270 additions and 0 deletions
|
|
@ -0,0 +1,151 @@
|
||||||
|
package com.graphhopper.jsprit.core.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import com.graphhopper.jsprit.core.problem.Location;
|
||||||
|
import com.graphhopper.jsprit.core.problem.cost.AbstractForwardVehicleRoutingTransportCosts;
|
||||||
|
import com.graphhopper.jsprit.core.problem.driver.Driver;
|
||||||
|
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Shiv Krishna Jaiswal
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MultiVehicleCostMatrix extends AbstractForwardVehicleRoutingTransportCosts {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First index respresents index of from_location
|
||||||
|
* Second index represents index of to_location
|
||||||
|
* Third index represents distance and time: 0th entry is for Distance and 1st entry is for time.
|
||||||
|
* Fourth index represents vehicleType. Each vehicleTypeId is assigned an index.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private final double[][][][] costMatrix;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Map is used to map vehicleTypeID to an index.
|
||||||
|
* There is one to one relation between them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private final Map<String, Integer> vehicleTypeToIndex;
|
||||||
|
private final int defaultIndex;
|
||||||
|
|
||||||
|
private MultiVehicleCostMatrix(double[][][][] costMatrix, Map<String, Integer> vehicleTypeToIndex, int defaultIndex) {
|
||||||
|
this.costMatrix = costMatrix;
|
||||||
|
this.vehicleTypeToIndex = vehicleTypeToIndex;
|
||||||
|
this.defaultIndex = defaultIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method give transportation cost between two location for a vehicle.
|
||||||
|
* Transportation cost is defined as :
|
||||||
|
* perDistanceCost * distanceBetweenLocation + perTransportTime * timeBetweenLocation
|
||||||
|
* Parameters, perDistanceCost or perTransportTime, are controlled by VehicleType.
|
||||||
|
* Cases where Vehicle is null, then distance between the two locations are returned for default vehicleType.
|
||||||
|
* eg.(DefaultScorer.java:94)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public double getTransportCost(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) {
|
||||||
|
if (from.getIndex() < 0 || to.getIndex() < 0)
|
||||||
|
throw new IllegalArgumentException("Index of location must not be less than zero");
|
||||||
|
|
||||||
|
if (vehicle == null)
|
||||||
|
return costMatrix[from.getIndex()][to.getIndex()][0][defaultIndex];
|
||||||
|
|
||||||
|
VehicleTypeImpl.VehicleCostParams costParams = vehicle.getType().getVehicleCostParams();
|
||||||
|
|
||||||
|
return costParams.perDistanceUnit * costMatrix[from.getIndex()][to.getIndex()][0][vehicleTypeToIndex.get(vehicle.getType().getTypeId()).intValue()]
|
||||||
|
+ costParams.perTransportTimeUnit * getTransportTime(from, to, departureTime, driver, vehicle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method gives time to move between the two location by Vehicle.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTransportTime(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) {
|
||||||
|
if (from.getIndex() < 0 || to.getIndex() < 0)
|
||||||
|
throw new IllegalArgumentException("Index of location must not be less than zero");
|
||||||
|
|
||||||
|
return costMatrix[from.getIndex()][to.getIndex()][1][vehicle == null ? defaultIndex : vehicleTypeToIndex.get(vehicle.getType().getTypeId()).intValue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For convenience of retriving the distance and time taken between location,
|
||||||
|
* two methods are introduced below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public double getDistanceBetween(int from, int to, String vehicleType) {
|
||||||
|
|
||||||
|
return costMatrix[from][to][0][vehicleTypeToIndex.get(vehicleType).intValue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTransportTimeBetween(int from, int to, String vehicleType) {
|
||||||
|
|
||||||
|
return costMatrix[from][to][1][vehicleTypeToIndex.get(vehicleType).intValue()];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
private final double[][][][] costMatrix;
|
||||||
|
private final Map<String, Integer> vehicleTypeToIndex;
|
||||||
|
private final boolean isSymmetric;
|
||||||
|
private final int defaultIndex;
|
||||||
|
|
||||||
|
private Builder(int location, boolean isSymmetric, Map<String, Integer> vehicleTypeIDToIndex, int defaultIndex) {
|
||||||
|
this.costMatrix = new double[location][location][2][vehicleTypeIDToIndex.size()];
|
||||||
|
this.isSymmetric = isSymmetric;
|
||||||
|
this.defaultIndex = defaultIndex;
|
||||||
|
this.vehicleTypeToIndex = vehicleTypeIDToIndex;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* defaultVehicleTypeID is used to incorporate the case when Jsprit call
|
||||||
|
* method " public double getTransportCost(Location from, Location to, double departureTime, Driver driver,
|
||||||
|
* Vehicle vehicle)" with vehicle as null or any case similar. So in this case distance corresponding to default
|
||||||
|
* vehicleTypeId is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static Builder newInstance(int location, boolean isSymmetric, Collection<String> vehicleTypeIDs, String defaultVehicleID) {
|
||||||
|
|
||||||
|
List<String> vehicleTypeIDsList = new ArrayList<>(new TreeSet<>(vehicleTypeIDs));
|
||||||
|
Map<String, Integer> vehicleTypeIDToIndex = new HashMap<>(vehicleTypeIDsList.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < vehicleTypeIDsList.size(); i++)
|
||||||
|
vehicleTypeIDToIndex.put(vehicleTypeIDsList.get(i), Integer.valueOf(i));
|
||||||
|
|
||||||
|
return new Builder(location, isSymmetric, vehicleTypeIDToIndex, vehicleTypeIDToIndex.get(defaultVehicleID).intValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addTransportationDistance(int from, int to, String vehicleTypeID, double distance) {
|
||||||
|
costMatrix[from][to][0][vehicleTypeToIndex.get(vehicleTypeID).intValue()] = distance;
|
||||||
|
|
||||||
|
if (isSymmetric)
|
||||||
|
costMatrix[to][from][0][vehicleTypeToIndex.get(vehicleTypeID).intValue()] = distance;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addTransportationTime(int from, int to, String vehicleTypeID, double duration) {
|
||||||
|
costMatrix[from][to][1][vehicleTypeToIndex.get(vehicleTypeID).intValue()] = duration;
|
||||||
|
|
||||||
|
if (isSymmetric)
|
||||||
|
costMatrix[to][from][1][vehicleTypeToIndex.get(vehicleTypeID).intValue()] = duration;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiVehicleCostMatrix build() {
|
||||||
|
return new MultiVehicleCostMatrix(costMatrix, vehicleTypeToIndex, defaultIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
package com.graphhopper.jsprit.core.util;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.graphhopper.jsprit.core.problem.Location;
|
||||||
|
import com.graphhopper.jsprit.core.problem.driver.Driver;
|
||||||
|
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||||
|
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||||
|
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||||
|
|
||||||
|
public class MultiVehicleCostMatrixTest {
|
||||||
|
|
||||||
|
private MultiVehicleCostMatrix costMatrix;
|
||||||
|
private final double delta = 10e-8 , departureTime = 0;
|
||||||
|
private final Driver driver = null;
|
||||||
|
private final Location zerothLoc = Location.newInstance(0) , firstLoc = Location.newInstance(1);
|
||||||
|
private final Vehicle bike = VehicleImpl.Builder.newInstance("vehicle1")
|
||||||
|
.setType(VehicleTypeImpl.Builder.newInstance("bike")
|
||||||
|
.setCostPerTransportTime(1)
|
||||||
|
.build())
|
||||||
|
.setStartLocation(zerothLoc)
|
||||||
|
.build();
|
||||||
|
private final Vehicle van = VehicleImpl.Builder.newInstance("vehicle2")
|
||||||
|
.setType(VehicleTypeImpl.Builder.newInstance("van")
|
||||||
|
.setCostPerTransportTime(1)
|
||||||
|
.build())
|
||||||
|
.setStartLocation(zerothLoc)
|
||||||
|
.build();
|
||||||
|
private final Collection<String> vehicleTypes = asList("bike", "van");
|
||||||
|
private final String defaultVehicleType = "bike";
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
|
MultiVehicleCostMatrix.Builder costMatrixBuilder = MultiVehicleCostMatrix.Builder.newInstance(2, false, vehicleTypes, defaultVehicleType);
|
||||||
|
costMatrixBuilder.addTransportationDistance(0, 0, "bike", 0);
|
||||||
|
costMatrixBuilder.addTransportationDistance(0, 1, "bike", 4.2);
|
||||||
|
costMatrixBuilder.addTransportationDistance(1, 0, "bike", 3.6);
|
||||||
|
costMatrixBuilder.addTransportationDistance(1, 1, "bike", 0);
|
||||||
|
|
||||||
|
costMatrixBuilder.addTransportationDistance(0, 0, "van", 0);
|
||||||
|
costMatrixBuilder.addTransportationDistance(0, 1, "van", 5.2);
|
||||||
|
costMatrixBuilder.addTransportationDistance(1, 0, "van", 4.5);
|
||||||
|
costMatrixBuilder.addTransportationDistance(1, 1, "van", 0);
|
||||||
|
|
||||||
|
costMatrixBuilder.addTransportationTime(0, 0, "bike", 0);
|
||||||
|
costMatrixBuilder.addTransportationTime(0, 1, "bike", 12.);
|
||||||
|
costMatrixBuilder.addTransportationTime(1, 0, "bike", 22.6);
|
||||||
|
costMatrixBuilder.addTransportationTime(1, 1, "bike", 0);
|
||||||
|
|
||||||
|
costMatrixBuilder.addTransportationTime(0, 0, "van", 0);
|
||||||
|
costMatrixBuilder.addTransportationTime(0, 1, "van", 15.266);
|
||||||
|
costMatrixBuilder.addTransportationTime(1, 0, "van", 25.123);
|
||||||
|
costMatrixBuilder.addTransportationTime(1, 1, "van", 0);
|
||||||
|
|
||||||
|
this.costMatrix = costMatrixBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetTransportCost() {
|
||||||
|
assertEquals(costMatrix.getTransportCost(zerothLoc, zerothLoc, departureTime, driver, bike), 0, delta);
|
||||||
|
assertEquals(costMatrix.getTransportCost(zerothLoc, firstLoc, departureTime, driver, bike), 16.2, delta);// 16.2 = 4.2 + 12
|
||||||
|
assertEquals(costMatrix.getTransportCost(firstLoc, zerothLoc, departureTime, driver, bike), 26.2, delta);//26.2 = 3.6 + 22.6
|
||||||
|
assertEquals(costMatrix.getTransportCost(firstLoc, firstLoc, departureTime, driver, bike), 0, delta);
|
||||||
|
|
||||||
|
assertEquals(costMatrix.getTransportCost(zerothLoc, zerothLoc, departureTime, driver, van), 0, delta);
|
||||||
|
assertEquals(costMatrix.getTransportCost(zerothLoc, firstLoc, departureTime, driver, van), 20.466, delta);//20.466 = 5.2 + 15.266
|
||||||
|
assertEquals(costMatrix.getTransportCost(firstLoc, zerothLoc, departureTime, driver, van), 29.623, delta);//29.623 = 4.5 + 25.123
|
||||||
|
assertEquals(costMatrix.getTransportCost(firstLoc, firstLoc, departureTime, driver, van), 0, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetTransportTime() {
|
||||||
|
|
||||||
|
assertEquals(costMatrix.getTransportTime(zerothLoc, zerothLoc, departureTime, driver, bike), 0, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTime(zerothLoc, firstLoc, departureTime, driver, bike), 12, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTime(firstLoc, zerothLoc, departureTime, driver, bike), 22.6, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTime(firstLoc, firstLoc, departureTime, driver, bike), 0, delta);
|
||||||
|
|
||||||
|
assertEquals(costMatrix.getTransportTime(zerothLoc, zerothLoc, departureTime, driver, van), 0, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTime(zerothLoc, firstLoc, departureTime, driver, van), 15.266, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTime(firstLoc, zerothLoc, departureTime, driver, van), 25.123, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTime(firstLoc, firstLoc, departureTime, driver, van), 0, delta);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetDistanceBetween() {
|
||||||
|
assertEquals(costMatrix.getDistanceBetween(0, 0, "bike"), 0, delta);
|
||||||
|
assertEquals(costMatrix.getDistanceBetween(0, 1, "bike"), 4.2, delta);
|
||||||
|
assertEquals(costMatrix.getDistanceBetween(1, 0, "bike"), 3.6, delta);
|
||||||
|
assertEquals(costMatrix.getDistanceBetween(1, 1, "bike"), 0, delta);
|
||||||
|
|
||||||
|
assertEquals(costMatrix.getDistanceBetween(0, 0, "van"), 0, delta);
|
||||||
|
assertEquals(costMatrix.getDistanceBetween(0, 1, "van"), 5.2, delta);
|
||||||
|
assertEquals(costMatrix.getDistanceBetween(1, 0, "van"), 4.5, delta);
|
||||||
|
assertEquals(costMatrix.getDistanceBetween(1, 1, "van"), 0, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetTimeBetween() {
|
||||||
|
assertEquals(costMatrix.getTransportTimeBetween(0, 0, "bike"), 0, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTimeBetween(0, 1, "bike"), 12, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTimeBetween(1, 0, "bike"), 22.6, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTimeBetween(1, 1, "bike"), 0, delta);
|
||||||
|
|
||||||
|
assertEquals(costMatrix.getTransportTimeBetween(0, 0, "van"), 0, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTimeBetween(0, 1, "van"), 15.266, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTimeBetween(1, 0, "van"), 25.123, delta);
|
||||||
|
assertEquals(costMatrix.getTransportTimeBetween(1, 1, "van"), 0, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue