1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

add and test FastTransportCostMatrix based array

This commit is contained in:
oblonski 2014-12-17 21:29:22 +01:00
parent 7ea5c5d650
commit 0a196f0abd
2 changed files with 249 additions and 0 deletions

View file

@ -0,0 +1,150 @@
/*******************************************************************************
* 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.core.util;
import jsprit.core.problem.Location;
import jsprit.core.problem.cost.AbstractForwardVehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleTypeImpl.VehicleCostParams;
/**
* CostMatrix that allows pre-compiled time and distance-matrices to be considered as {@link jsprit.core.problem.cost.VehicleRoutingTransportCosts}
* in the {@link jsprit.core.problem.VehicleRoutingProblem}.
* <p>Note that you can also use it with distance matrix only (or time matrix).
* @author schroeder
*
*/
public class FastVehicleRoutingTransportCostsMatrix extends AbstractForwardVehicleRoutingTransportCosts {
/**
* Builder that builds the matrix.
*
* @author schroeder
*
*/
public static class Builder {
private boolean isSymmetric;
private double[][][] matrix;
/**
* Creates a new builder returning the matrix-builder.
* <p>If you want to consider symmetric matrices, set isSymmetric to true.
* @param isSymmetric true if matrix is symmetric, false otherwise
* @return builder
*/
public static Builder newInstance(int noLocations, boolean isSymmetric){
return new Builder(noLocations, isSymmetric);
}
private Builder(int noLocations, boolean isSymmetric){
this.isSymmetric = isSymmetric;
matrix = new double[noLocations][noLocations][2];
}
/**
* Adds a transport-distance for a particular relation.
* @param fromIndex from location index
* @param toIndex to location index
* @param distance the distance to be added
* @return builder
*/
public Builder addTransportDistance(int fromIndex, int toIndex, double distance){
add(fromIndex,toIndex,0,distance);
return this;
}
private void add(int fromIndex, int toIndex, int indicatorIndex, double distance){
if(isSymmetric){
if(fromIndex < toIndex) matrix[fromIndex][toIndex][indicatorIndex] = distance;
else matrix[toIndex][fromIndex][indicatorIndex] = distance;
}
else matrix[fromIndex][toIndex][indicatorIndex] = distance;
}
/**
* Adds transport-time for a particular relation.
* @param fromIndex from location index
* @param toIndex to location index
* @param time the time to be added
* @return builder
*/
public Builder addTransportTime(int fromIndex, int toIndex, double time){
add(fromIndex,toIndex,1,time);
return this;
}
/**
* Builds the matrix.
* @return matrix
*/
public FastVehicleRoutingTransportCostsMatrix build(){
return new FastVehicleRoutingTransportCostsMatrix(this);
}
}
private final boolean isSymmetric;
private final double[][][] matrix;
private FastVehicleRoutingTransportCostsMatrix(Builder builder){
this.isSymmetric = builder.isSymmetric;
matrix = builder.matrix;
}
@Override
public double getTransportTime(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) {
return get(from.getIndex(),to.getIndex(),1);
}
private double get(int from, int to, int indicatorIndex){
double value;
if(isSymmetric){
if(from < to) value = matrix[from][to][indicatorIndex];
else value = matrix[to][from][indicatorIndex];
}
else{
value = matrix[from][to][indicatorIndex];
}
return value;
}
/**
* Returns the distance from to to.
*
* @param fromIndex from location index
* @param toIndex to location index
* @return the distance
*/
public double getDistance(int fromIndex, int toIndex) {
return get(fromIndex,toIndex,0);
}
@Override
public double getTransportCost(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) {
if(vehicle == null) return getDistance(from.getIndex(), to.getIndex());
VehicleCostParams costParams = vehicle.getType().getVehicleCostParams();
return costParams.perDistanceUnit * getDistance(from.getIndex(), to.getIndex()) + costParams.perTimeUnit * getTransportTime(from, to, departureTime, driver, vehicle);
}
}

View file

@ -0,0 +1,99 @@
/*******************************************************************************
* 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.core.util;
import jsprit.core.problem.Location;
import jsprit.core.problem.vehicle.Vehicle;
import jsprit.core.problem.vehicle.VehicleType;
import jsprit.core.problem.vehicle.VehicleTypeImpl;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class FastVehicleRoutingTransportCostsMatrixTest {
@Test
public void whenAddingDistanceToSymmetricMatrix_itShouldReturnCorrectValues(){
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3,true);
matrixBuilder.addTransportDistance(1, 2, 2.);
FastVehicleRoutingTransportCostsMatrix matrix = matrixBuilder.build();
assertEquals(2.,matrix.getTransportCost(loc(1), loc(2), 0.0, null, null),0.1);
assertEquals(2.,matrix.getDistance(1, 2),0.1);
assertEquals(2.,matrix.getTransportCost(loc(2), loc(1), 0.0, null, null),0.1);
assertEquals(2.,matrix.getDistance(2, 1),0.1);
}
@Test
public void whenAddingDistanceToAsymmetricMatrix_itShouldReturnCorrectValues(){
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3,false);
matrixBuilder.addTransportDistance(1, 2, 2.);
FastVehicleRoutingTransportCostsMatrix matrix = matrixBuilder.build();
assertEquals(2.,matrix.getTransportCost(loc(1), loc(2), 0.0, null, null),0.1);
}
private Location loc(int index) {
return Location.Builder.newInstance().setIndex(index).build();
}
@Test
public void whenAddingTimeToSymmetricMatrix_itShouldReturnCorrectValues(){
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3,true);
matrixBuilder.addTransportTime(1, 2, 2.);
FastVehicleRoutingTransportCostsMatrix matrix = matrixBuilder.build();
assertEquals(2.,matrix.getTransportTime(loc(1), loc(2), 0.0, null, null),0.1);
assertEquals(2.,matrix.getTransportTime(loc(2), loc(1), 0.0, null, null),0.1);
}
@Test
public void whenAddingTimeToAsymmetricMatrix_itShouldReturnCorrectValues(){
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3,false);
matrixBuilder.addTransportTime(1, 2, 2.);
FastVehicleRoutingTransportCostsMatrix matrix = matrixBuilder.build();
assertEquals(2.,matrix.getTransportTime(loc(1), loc(2), 0.0, null, null),0.1);
}
@Test
public void whenAddingTimeAndDistanceToSymmetricMatrix_itShouldReturnCorrectValues(){
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3,true);
matrixBuilder.addTransportDistance(1, 2, 20.);
matrixBuilder.addTransportTime(1, 2, 2.);
FastVehicleRoutingTransportCostsMatrix matrix = matrixBuilder.build();
Vehicle vehicle = mock(Vehicle.class);
VehicleType type = VehicleTypeImpl.Builder.newInstance("t").setCostPerDistance(1.).setCostPerTime(2.).build();
when(vehicle.getType()).thenReturn(type);
assertEquals(24.,matrix.getTransportCost(loc(1), loc(2), 0.0, null, vehicle),0.1);
assertEquals(24.,matrix.getTransportCost(loc(2), loc(1), 0.0, null, vehicle),0.1);
}
@Test
public void whenAddingTimeAndDistanceToAsymmetricMatrix_itShouldReturnCorrectValues(){
FastVehicleRoutingTransportCostsMatrix.Builder matrixBuilder = FastVehicleRoutingTransportCostsMatrix.Builder.newInstance(3,false);
matrixBuilder.addTransportTime(1, 2, 2.);
matrixBuilder.addTransportTime(2, 1, 8.);
FastVehicleRoutingTransportCostsMatrix matrix = matrixBuilder.build();
Vehicle vehicle = mock(Vehicle.class);
VehicleType type = VehicleTypeImpl.Builder.newInstance("t").setCostPerDistance(1.).setCostPerTime(2.).build();
when(vehicle.getType()).thenReturn(type);
assertEquals(4.,matrix.getTransportCost(loc(1), loc(2), 0.0, null, vehicle),0.1);
assertEquals(16.,matrix.getTransportCost(loc(2), loc(1), 0.0, null, vehicle),0.1);
}
}