/** * */ package vroom.common.heuristics.vrp; import java.util.LinkedList; import vroom.common.heuristics.Move; import vroom.common.modeling.dataModel.INodeVisit; import vroom.common.modeling.dataModel.IRoute; import vroom.common.modeling.dataModel.IVRPSolution; import vroom.common.modeling.dataModel.NodeInsertion; /** * <code>RelocateMove</code> * <p> * Creation date: Sep 29, 2010 - 2:49:21 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 RelocateMove extends Move { private final LinkedList<RelocateAtomicMove> mAtomicMoves; /** The parent solution for this move **/ private final IVRPSolution<?> mSolution; /** * Getter for The parent solution for this move * * @return the value of solution */ public IVRPSolution<?> getSolution() { return mSolution; } /** * List of atomic relocate moves * * @return the list of relocate moves */ public LinkedList<RelocateAtomicMove> getAtomicMoves() { return mAtomicMoves; } public RelocateMove(IVRPSolution<?> sol) { super(0); mSolution = sol; mAtomicMoves = new LinkedList<RelocateMove.RelocateAtomicMove>(); } /** * Creates a new <code>RelocateAtomicMove</code> * * @param node * the node to be relocated * @param route * its current route * @param nodeIndex * its index within the route */ public RelocateAtomicMove newAtomicMove(INodeVisit node, int route, int nodeIndex) { RelocateAtomicMove move = new RelocateAtomicMove(node, route, nodeIndex); return move; } /** * Add an atomic move to this move * * @param reloc */ public void addAtomicMove(RelocateAtomicMove reloc) { mAtomicMoves.add(reloc); } @Override public double getImprovement() { double cost = 0; for (RelocateAtomicMove r : mAtomicMoves) { cost += r.getInsertion() != null ? r.getInsertion().getCost() : 0; } setImprovement(-cost); return -cost; } /* * (non-Javadoc) * @see vroom.common.heuristics.Move#getMoveName() */ @Override public String getMoveName() { return "reloc"; } @Override public String toString() { return String.format("%s(%s,%.3f)", getMoveName(), getAtomicMoves(), getImprovement()); } public class RelocateAtomicMove extends Move { private final INodeVisit mNode; private final int mRoute; private NodeInsertion mInsertion; /** * Creates a new <code>RelocateAtomicMove</code> * * @param node * the node to be relocated * @param route * its current route * @param nodeIndex * its index within the route */ private RelocateAtomicMove(INodeVisit node, int route, int nodeIndex) { super(0); mNode = node; mRoute = route; } /** * Getter for <code>insertion</code> * * @return the insertion */ public NodeInsertion getInsertion() { return mInsertion; } /** * Setter for <code>insertion</code> * * @param insertion * the insertion to set */ public void setInsertion(NodeInsertion insertion) { mInsertion = insertion; IRoute<?> rte = getSolution().getRoute(getRoute()); int pos = rte.getNodePosition(getNode()); double extractCost = 0; if (pos >= 0) { INodeVisit pred = pos > 0 ? rte.getNodeAt(pos - 1) : null; INodeVisit suc = pos < rte.length() - 1 ? rte.getNodeAt(pos + 1) : null; extractCost = -rte.getParentSolution() .getParentInstance() .getInsertionCost(getNode(), pred, suc, rte.getVehicle()); } if (mInsertion != null) { setImprovement(-mInsertion.getCost() + extractCost); } else { setImprovement(0); } } /** * Getter for <code>node</code> * * @return the node */ public INodeVisit getNode() { return mNode; } /** * Getter for <code>route</code> * * @return the route */ public int getRoute() { return mRoute; } /** * The parent solution for this move * * @return The parent solution for this move */ public IVRPSolution<?> getSolution() { return RelocateMove.this.getSolution(); } @Override public String getMoveName() { return "relocAt"; } @Override public String toString() { return String.format("(%s[%s]->[%s])", getNode().getID(), getRoute(), getInsertion()); } } }