/** * */ package vroom.trsp.optimization.rch; import java.util.List; import java.util.ListIterator; import vroom.common.utilities.DoublyLinkedIntList; import vroom.trsp.datamodel.TRSPInstance; import vroom.trsp.datamodel.Technician; import vroom.trsp.datamodel.costDelegates.TRSPCostDelegate; import vroom.trsp.optimization.constraints.TRSPConstraintHandler; import vroom.trsp.util.TRSPGlobalParameters; /** * <code>TRSPRndNearestFarthestInsOld</code> is an implementation of both random nearest and farthest insertion. * <p> * It extends {@link TRSPRndNearestNeighbor} as it also uses a sorted list of neighbors * </p> * <p> * Creation date: Oct 4, 2011 - 1:44:48 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 * @deprecated use {@link TRSPRndNearestFarthestIns} instead */ public class TRSPRndNearestFarthestInsOld extends TRSPRndNearestNeighbor { /** * Creates a new <code>TRSPRndNearestFarthestInsOld</code> * * @param instance * @param parameters * @param constraintHandler * @param costDelegate * @param farthest * <code>true</code> if the farthest insertion should be selected, <code>false</code> if the nearest * insertion should be selected */ public TRSPRndNearestFarthestInsOld(TRSPInstance instance, TRSPGlobalParameters parameters, TRSPConstraintHandler constraintHandler, TRSPCostDelegate costDelegate, boolean farthest) { super(instance, parameters, constraintHandler, costDelegate, farthest); } @Override protected List<Integer> initTour(int tech) { DoublyLinkedIntList list = new DoublyLinkedIntList(getInstance().getMaxId()); // Add the technician home list.add(getInstance().getTechnician(tech).getHome().getID()); // Add a random node ObservableNode seed = getCompatibleRequests(tech)[getParameters().getRCHRndStream().nextInt(0, getCompatibleRequests(tech).length - 1)]; list.add(seed.getId()); seed.markAsServed(); // Return the list return list; } @Override protected ObservableNode selectNextNode(List<Integer> tour, int tech, int unserved) { // FIXME we must return a compatible node // Draw a random index k int targetK = nextIdx(unserved); // int bestNodeSeedIdx = -1; // int k = -1; // int[] currentNeighIndex = new int[tour.size()]; // if (mFarthest) { // ListIterator<Integer> it = tour.listIterator(); // while (it.hasNext()) { // int nodeIdx = it.nextIndex(); // int node = it.next(); // currentNeighIndex[nodeIdx] = getNeighbors(node).length - 1; // } // } // // while (k < targetK) { // ListIterator<Integer> it = tour.listIterator(); // double bestDist = mFarthest ? 0 : Double.POSITIVE_INFINITY; // while (it.hasNext()) { // int seedIdx = it.nextIndex(); // int seed = it.next(); // // Candidate neighbor // // Ignore already served nodes // if (mFarthest) { // while (currentNeighIndex[seedIdx] >= 0 // && !isUnserved[getNeighbors(seed)[currentNeighIndex[seedIdx]].getNode() // .getId()]) // currentNeighIndex[seedIdx]--; // } else { // while (currentNeighIndex[seedIdx] < getNeighbors(seed).length // && !isUnserved[getNeighbors(seed)[currentNeighIndex[seedIdx]].getNode() // .getId()]) // currentNeighIndex[seedIdx]++; // // } // if (currentNeighIndex[seedIdx] < 0 // || currentNeighIndex[seedIdx] >= getNeighbors(seed).length) // // This seed has no unserved neighbors // continue; // // Neighbor cand = getNeighbors(seed)[currentNeighIndex[seedIdx]]; // if (mFarthest ? cand.getDistance() > bestDist : cand.getDistance() < bestDist) { // // Find a new best candidate // bestNodeSeedIdx = seedIdx; // bestNode = getNeighbors(seed)[currentNeighIndex[seedIdx]]; // bestDist = bestNode.getDistance(); // } // } // // // We did not find any candidate node // if (bestNodeSeedIdx < 0) // return null; // // k++; // // We found the k-th farthest/closest node // // Update the offset of the corresponding seed // if (mFarthest) // currentNeighIndex[bestNodeSeedIdx]--; // else // currentNeighIndex[bestNodeSeedIdx]++; // } // // return bestNode != null ? bestNode.getNode() : null; NeighborListIterator[] neighbors = new NeighborListIterator[tour.size()]; int i = 0; for (Integer n : tour) { neighbors[i] = getNeighbors(n).iterator(); neighbors[i].next(); i++; } int k = -1; Neighbor kthBestNeigh = null; Neighbor selectedNeigh = null; while (k < targetK) { i = 0; NeighborListIterator bestIt = null; for (Integer n : tour) { Neighbor neigh = neighbors[i].peek(); if (neigh != null && (kthBestNeigh == null || kthBestNeigh.compareTo(neigh) < 0)) { kthBestNeigh = neigh; bestIt = neighbors[i]; } i++; } if (bestIt != null) { selectedNeigh = kthBestNeigh; if (bestIt.hasNext()) // Shift the iterator bestIt.next(); } k++; } if (selectedNeigh != null) return selectedNeigh.getNode(); else return null; } @Override protected void insertNextNode(List<Integer> ltour, ObservableNode node, int tech) { if (ltour.isEmpty()) ltour.add(node.getId()); double bestInsCost = Double.POSITIVE_INFINITY; Integer bestInsSucc = null; DoublyLinkedIntList tour = (DoublyLinkedIntList) ltour; Technician technician = getInstance().getTechnician(tech); // Check for all possible insertions ListIterator<Integer> it = tour.listIterator(); Integer pred = it.next(); while (it.hasNext()) { Integer succ = it.next(); double insCost = getInstance().getCostDelegate().getInsertionCost(node.getId(), pred, succ, technician); if (insCost < bestInsCost) { bestInsCost = insCost; bestInsSucc = succ; } } // Insertion in the last position before the return to the depot Integer succ = tour.getFirst(); double insCost = getInstance().getCostDelegate().getInsertionCost(node.getId(), pred, succ, technician); if (insCost < bestInsCost) { tour.add(node.getId()); } else { tour.insert(node.getId(), bestInsSucc); } } @Override public String toString() { return isInvertedSortOrder() ? "RFI" : "RNI"; } }