package vrp2013.datamodel; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /** * JAVADOC <code>DoublyLinkedIdRoute</code> * <p> * Creation date: 09/04/2013 - 8:14:03 PM * * @author Victor Pillac, <a href="http://www.nicta.com.au">National ICT Australia</a>, <a * href="http://www.victorpillac.com">www.victorpillac.com</a> * @version 1.0 */ public class DoublyLinkedRoute extends Route { private final static int UNDEFINED = -2; private final int[] mPred; private final int[] mSucc; private final double[] mCumulatedCost; private int mFirst; private int mLast; private int mLength = 0; /** * Instantiates a new doubly linked tsp route. * * @param parentSolution * the parent solution * @param vehicle * the vehicle * @param depot * the depot */ public DoublyLinkedRoute(int vehicle, int maxId) { super(vehicle); mPred = new int[maxId]; mSucc = new int[maxId]; mCumulatedCost = new double[maxId]; Arrays.fill(mPred, UNDEFINED); Arrays.fill(mSucc, UNDEFINED); Arrays.fill(mCumulatedCost, 0); mFirst = UNDEFINED; mLast = UNDEFINED; mLength = 0; } @Override public int getNodePosition(int node) { // Complexity : O(n) int cursor = 0; int pred = node; while (this.mPred[pred] != UNDEFINED) { pred = this.mPred[pred]; cursor++; } return cursor; } @Override public int getFirstNode() { return mFirst; } @Override public int getLastNode() { return mLast; } @Override public int length() { return mLength; } @Override public ListIterator<Integer> iterator() { return new DoublyLinkedIdRouteIterator(); } /** * Gets the Id of the node at the given position * * @param index * @return the id of the node at index * @see #getNodeAt(int) */ @Override public int getNodeAt(int index) { if (index < length() / 2) { int cursor = 0; int node = mFirst; while (cursor < index) { cursor++; node = this.mSucc[node]; } return node; } else { int cursor = length() - 1; int node = mLast; while (cursor > index) { cursor--; node = this.mPred[node]; } return node; } } @Override public List<Integer> getSubroute(int start, int end) { List<Integer> subroute = new ArrayList<Integer>(end - start + 1); int node = getNodeAt(start); int cursor = start; while (cursor < end) { subroute.add(node); node = this.mSucc[node]; cursor++; } return subroute; } @Override public void append(int node) { this.mSucc[mLast] = node; this.mPred[node] = mLast; this.mLast = node; mLength++; } @Override public void append(List<Integer> nodes) { for (int n : nodes) { append(n); } } @Override public int setNodeAt(int index, int node) { int current = getNodeAt(index); if (this.mPred[current] != UNDEFINED) this.mSucc[this.mPred[current]] = node; if (this.mSucc[current] != UNDEFINED) this.mPred[this.mSucc[current]] = node; this.mPred[node] = this.mPred[current]; this.mSucc[node] = this.mSucc[current]; this.mPred[current] = UNDEFINED; this.mSucc[current] = UNDEFINED; return current; } @Override public int extractNodeAt(int index) { int node = getNodeAt(index); this.mSucc[this.mPred[node]] = this.mSucc[node]; this.mPred[this.mSucc[node]] = this.mPred[node]; this.mPred[node] = UNDEFINED; this.mSucc[node] = UNDEFINED; return node; } @Override public List<Integer> extractSubroute(int start, int end) { List<Integer> nodes = new ArrayList<Integer>(end - start + 1); int current = getNodeAt(start); int pred = this.mPred[current]; int succ = this.mSucc[current]; int cursor = start; while (cursor <= end && current != UNDEFINED) { succ = this.mSucc[current]; this.mPred[current] = UNDEFINED; this.mSucc[current] = UNDEFINED; current = succ; cursor++; } this.mSucc[pred] = succ; this.mPred[succ] = pred; return nodes; } @Override public void remove(int node) { if (this.mPred[node] != UNDEFINED) this.mSucc[this.mPred[node]] = this.mSucc[node]; if (this.mSucc[node] != UNDEFINED) this.mPred[this.mSucc[node]] = this.mPred[node]; this.mPred[node] = UNDEFINED; this.mSucc[node] = UNDEFINED; } @Override public void insertNodeAt(int node, int index) { int current = getNodeAt(index); this.mSucc[this.mPred[current]] = node; this.mPred[node] = this.mPred[current]; this.mPred[current] = node; this.mSucc[node] = current; } @Override public void insertNodesAt(List<Integer> subroute, int index) { int current = getNodeAt(index); Iterator<Integer> it = subroute.iterator(); int first = UNDEFINED, last = UNDEFINED; int pred = it.next(); int succ = pred; first = pred; while (it.hasNext()) { succ = it.next(); this.mPred[succ] = pred; this.mSucc[pred] = succ; pred = succ; } last = succ; this.mSucc[this.mPred[current]] = first; this.mPred[first] = this.mPred[current]; this.mPred[current] = last; this.mSucc[last] = current; } @Override public List<Integer> getNodeSequence() { List<Integer> seq = new ArrayList<Integer>(length()); int node = mFirst; while (node != UNDEFINED) { seq.add(node); node = this.mSucc[node]; } return seq; } @Override public boolean contains(int node) { return mPred[node] != UNDEFINED || mSucc[node] != UNDEFINED; } @Override public Route clone() { DoublyLinkedRoute clone = new DoublyLinkedRoute(getVehicle(), mPred.length); clone.mFirst = this.mFirst; clone.mLast = this.mLast; clone.mLength = this.mLength; for (int i = 0; i < this.mPred.length; i++) { clone.mPred[i] = this.mPred[i]; clone.mSucc[i] = this.mSucc[i]; } return clone; } protected class DoublyLinkedIdRouteIterator implements ListIterator<Integer> { private int current; private int cursor; protected DoublyLinkedIdRouteIterator() { current = mFirst; cursor = 0; } @Override public boolean hasNext() { return cursor < DoublyLinkedRoute.this.length(); } @Override public boolean hasPrevious() { return cursor > 0; } @Override public Integer next() { if (hasNext()) { cursor++; int c = current; current = DoublyLinkedRoute.this.mSucc[current]; return c; } else throw new IllegalStateException("Iterator has no next element"); } @Override public Integer previous() { if (hasPrevious()) { cursor--; int c = current; current = DoublyLinkedRoute.this.mPred[current]; return c; } else throw new IllegalStateException("Iterator has no previous element"); } @Override public int nextIndex() { return cursor + 1; } @Override public int previousIndex() { return cursor - 1; } @Override public void remove() { // DoublyLinkedRoute.this.remove(getLastReturnedNextNode()); throw new UnsupportedOperationException( "set operation is not supported by this iterator"); } @Override public void set(Integer e) { // int l = getLastReturnedNextNode(); // TODO Auto-generated method stub throw new UnsupportedOperationException( "set operation is not supported by this iterator"); } @Override public void add(Integer e) { // DoublyLinkedRoute.this.in // TODO Auto-generated method stub throw new UnsupportedOperationException( "add operation is not supported by this iterator"); } private int getLastReturnedNextNode() { return DoublyLinkedRoute.this.mPred[current]; } } }