package vroom.common.modeling.dataModel;
import vroom.common.modeling.util.CostCalculationDelegate;
/**
* <code>DistanceMatrix</code> is a {@link CostCalculationDelegate} that is based on an double matrix representing the
* distances between two vertexes.
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a> - <a
* href="http://copa.uniandes.edu.co">Copa</a>, <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0 #created 15-Feb-2010 11:29:50 a.m.
*/
public class DistanceMatrix extends CostCalculationDelegate {
/** The distance matrix between all nodes of the graph. */
private final double mDistances[][];
private String mType;
/**
* Creates a new empty <code>DistanceMatrix</code> based on the given matrix.
*
* @param distances
* the matrix of distances that will be used by this cost helper
*/
public DistanceMatrix(double[][] distances) {
mDistances = distances;
mType = "EXPLICIT";
}
/**
* Creates a new <code>DistanceMatrix</code> based on the given instance.
*/
public DistanceMatrix(IVRPInstance instance) {
int size = 0;
for (Depot d : instance.getDepots())
if (d.getID() > size)
size = d.getID();
for (IVRPRequest r : instance.getRequests())
if (r.getNode().getID() > size)
size = r.getNode().getID();
size++;
mDistances = new double[size][size];
mType = "EXPLICIT";
double[] x = new double[mDistances.length];
double[] y = new double[mDistances.length];
for (int d = 0; d < instance.getDepotCount(); d++) {
Depot depot = instance.getDepot(d);
x[depot.getID()] = depot.getLocation().getX();
y[depot.getID()] = depot.getLocation().getY();
}
for (IVRPRequest r : instance.getRequests()) {
x[r.getNode().getID()] = r.getNode().getLocation().getX();
y[r.getNode().getID()] = r.getNode().getLocation().getY();
}
for (int i = 0; i < mDistances.length; i++) {
for (int j = 0; j < mDistances.length; j++) {
mDistances[i][j] = Math.sqrt(Math.pow(x[i] - x[j], 2) + Math.pow(y[i] - y[j], 2));
}
}
mType = "EUC_2D";
}
/**
* Creates a new empty <code>DistanceMatrix</code> based on a matrix of dimension <code>size x size</code> .
*
* @param size
* the number of vertexes in the graph
*/
public DistanceMatrix(int size) {
this(new double[size][size]);
}
/**
* Gets the distance between two nodes.
*
* @param origin
* the index of the origin node
* @param destination
* the index of the destination node
* @return the distance between the specified nodes
*/
public double getDistance(int origin, int destination) {
return mDistances[origin][destination];
}
@Override
public double getDistance(Node origin, Node destination) {
return getDistance(origin.getID(), destination.getID());
}
@Override
protected double getDistanceInternal(Node origin, Node destination) {
return getDistance(origin.getID(), destination.getID());
}
/**
* Gets the cost of traveling between two nodes with a given vehicle.
*
* @param origin
* the index of the origin node
* @param destination
* the index of the destination node
* @param vehicle
* the considered vehicle
* @return the cost of arc <code>(origin,destination)</code> for <code>vehicle</code>
*/
public double getCost(int origin, int destination, Vehicle vehicle) {
return getDistance(origin, destination) * vehicle.getVariableCost();
}
@Override
public String getDistanceType() {
return mType;
}
@Override
protected void precisionChanged() {
mType = String.format("%s[%s]", mType, getPrecision());
for (int i = 0; i < mDistances.length; i++) {
for (int j = 0; j < mDistances[i].length; j++) {
mDistances[i][j] = vroom.common.utilities.Utilities.Math.round(mDistances[i][j],
getPrecision(), getRoundingMethod());
}
}
}
/**
* Sets the distance between two nodes
*
* @param i
* @param j
* @param distance
* @author vpillac
*/
public void setDistance(int i, int j, double distance) {
mDistances[i][j] = distance;
}
@Override
public String toString() {
return String.format("%s[%s]", getClass().getSimpleName(), getDistanceType());
}
}// end DistanceMatrix