package vroom.trsp.datamodel.costDelegates;
import vroom.trsp.datamodel.ITRSPTour;
import vroom.trsp.datamodel.ITourIterator;
import vroom.trsp.datamodel.TRSPDistanceMatrix;
import vroom.trsp.datamodel.TRSPTour;
import vroom.trsp.datamodel.TRSPTour.TRSPTourIterator;
import vroom.trsp.optimization.InsertionMove;
import vroom.trsp.optimization.RemoveMove;
import vroom.trsp.optimization.localSearch.TRSPShift.TRSPShiftMove;
import vroom.trsp.optimization.localSearch.TRSPTwoOpt.TRSPTwoOptMove;
/**
* <code>TRSPDistance</code> is an implementation of {@link TRSPCostDelegate} based on the traveled distance. It ignores
* service times.
* <p>
* Creation date: Jun 6, 2011 - 4:46:03 PM
*
* @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
*/
public class TRSPDistance extends TRSPCostDelegate {
// FIXME implement specific update methods to improve performance
@Override
protected double evaluateTRSPTour(TRSPTour tour, int node, boolean updateTour) {
if (tour.length() < 2) {
if (updateTour) {
for (int i : tour) {
tour.setCumulativeCost(i, 0);
}
tour.setTotalCost(0);
}
return 0;
}
// Cumulated distance
double d = node != ITRSPTour.UNDEFINED ? tour.getCumulativeCost(node) : 0;
// Iterator over the tour
TRSPTourIterator it = node != ITRSPTour.UNDEFINED ? tour.iterator(node) : tour.iterator();
if (!it.hasNext()) {
if (updateTour)
tour.setTotalCost(d);
return d;
}
int pred = it.next();
while (it.hasNext()) {
if (updateTour)
tour.setCumulativeCost(pred, d);
int succ = it.next();
d += tour.getInstance().getCostDelegate().getDistance(pred, succ);
pred = succ;
}
if (updateTour)
tour.setCumulativeCost(pred, d);
if (updateTour)
tour.setTotalCost(d);
return d;
}
@Override
protected double evaluateGenericTour(ITRSPTour tour) {
if (tour.length() == 0)
return 0;
// Cumulated distance
double dist = 0;
// Iterator over the tour
ITourIterator it = tour.iterator();
int pred = it.next();
while (it.hasNext()) {
int succ = it.next();
dist += tour.getInstance().getCostDelegate().getDistance(pred, succ);
pred = succ;
}
return dist;
}
@Override
public double evaluateDetour(ITRSPTour tour, int i, int n, int j,
boolean isRemoval) {
TRSPDistanceMatrix c = tour.getInstance().getCostDelegate();
return c.getDistance(i, n) + c.getDistance(n, j)
- c.getDistance(i, j);
}
@Override
protected double evaluateRemMove(RemoveMove move) {
TRSPTour tour = (TRSPTour) move.getTour();
int node = move.getNodeId();
int pred = tour.getPred(node);
int succ = tour.getSucc(node);
TRSPDistanceMatrix c = tour.getInstance().getCostDelegate();
int imp = 0;
// Node removal
if (pred != ITRSPTour.UNDEFINED)
imp += c.getDistance(pred, node);
if (succ != ITRSPTour.UNDEFINED)
imp += c.getDistance(node, succ);
if (pred != ITRSPTour.UNDEFINED && succ != ITRSPTour.UNDEFINED)
imp -= c.getDistance(pred, succ);
return imp;
}
@Override
protected double evaluateTwoOptMove(TRSPTwoOptMove move) {
TRSPTour tour = (TRSPTour) move.getTour();
TRSPDistanceMatrix c = tour.getInstance().getCostDelegate();
int i = move.getFirst();
int j = tour.getSucc(i);
int m = move.getSecond();
int n = tour.getSucc(m);
// We assume that the instance is symmetric
return c.getDistance(i, j) + c.getDistance(m, n) - c.getDistance(i, m)
- c.getDistance(j, n);
}
@Override
protected double evaluateShiftMove(TRSPShiftMove move) {
TRSPTour tour = (TRSPTour) move.getTour();
if (move.getNewSucc() == tour.getSucc(move.getNode()))
return 0;
TRSPDistanceMatrix c = tour.getInstance().getCostDelegate();
int node = move.getNode();
int insSucc = move.getNewSucc();
int insPred = insSucc != ITRSPTour.UNDEFINED ? tour.getPred(insSucc) : move.getTour()
.getLastNode();
int nodePred = tour.getPred(node);
int nodeSucc = tour.getSucc(node);
double imp = 0;
// Node removal
if (nodePred != ITRSPTour.UNDEFINED)
imp += c.getDistance(nodePred, node);
if (nodeSucc != ITRSPTour.UNDEFINED)
imp += c.getDistance(node, nodeSucc);
if (nodePred != ITRSPTour.UNDEFINED && nodeSucc != ITRSPTour.UNDEFINED)
imp -= c.getDistance(nodePred, nodeSucc);
// Node insertion
if (insSucc != ITRSPTour.UNDEFINED && insPred != ITRSPTour.UNDEFINED)
imp += c.getDistance(insPred, insSucc);
if (insPred != ITRSPTour.UNDEFINED)
imp -= c.getDistance(insPred, node);
if (insSucc != ITRSPTour.UNDEFINED)
imp -= c.getDistance(node, insSucc);
return imp;
}
@Override
protected double evaluateInsMove(InsertionMove move) {
TRSPTour tour = (TRSPTour) move.getTour();
if (move.getTour().length() == 0)
return 0;
int succ = move.getInsertionSucc();
int node = move.getNodeId();
int pred;
TRSPDistanceMatrix c = move.getTour().getInstance().getCostDelegate();
double imp = 0;
if (succ == ITRSPTour.UNDEFINED)
pred = move.getTour().getLastNode();
else
pred = tour.getPred(succ);
if (pred != ITRSPTour.UNDEFINED)
imp -= c.getDistance(pred, node);
if (succ != ITRSPTour.UNDEFINED)
imp -= c.getDistance(node, succ);
if (pred != ITRSPTour.UNDEFINED && succ != ITRSPTour.UNDEFINED)
imp += c.getDistance(pred, succ);
if (move.isDepotTrip()) {
int depSucc = move.getDepotSucc();
int depPred = depSucc != node ? tour.getPred(depSucc) : pred;
if (depPred != ITRSPTour.UNDEFINED)
imp -= c.getDistance(depPred, tour.getMainDepotId());
imp -= c.getDistance(tour.getMainDepotId(), depSucc);
imp += c.getDistance(depPred, depSucc);
}
return imp;
}
@Override
public boolean isInsertionSeqDependent() {
return false;
}
}