package vroom.common.heuristics.cw.algorithms; import java.util.List; import java.util.Set; import umontreal.iro.lecuyer.rng.RandomPermutation; import vroom.common.heuristics.cw.CWLogging; import vroom.common.heuristics.cw.CWParameters; import vroom.common.heuristics.cw.IJCWArc; import vroom.common.heuristics.cw.kernel.ClarkeAndWrightHeuristic; import vroom.common.modeling.dataModel.IArc; import vroom.common.modeling.dataModel.IVRPSolution; import vroom.common.utilities.Utilities; /** * <code>RandomizedBasicSavingsHeuristic</code> is a specialization of the {@link BasicSavingsHeuristic} where the list * of savings is being shuffled before processing. * <p> * TODO another way of randomizing the heuristic would be to assign probabilities to arcs depending on their value. * * @author Jorge E. Mendoza <br/> * <a href="http://www.uco.fr">Universite Catholique de l'Ouest</a> * @author Victor Pillac <br/> * <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a href="http://copa.uniandes.edu.co">Copa</a> <br/> * <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 2.0 */ public class RandomizedSavingsHeuristic<S extends IVRPSolution<?>> extends BasicSavingsHeuristic<S> { public RandomizedSavingsHeuristic(ClarkeAndWrightHeuristic<S> parentHeuristic) { super(parentHeuristic); } @Override public List<IJCWArc> calculateSavings(Set<? extends IArc> arcs) { // Use an ArrayList for performance (set methods) List<IJCWArc> mergings = super.calculateSavings(arcs); randomizeSavings(mergings); return mergings; } /** * This method randomizes the savings list as proposed in: J.E. Mendoza, A.L. Medaglia and N. Velasco An * evolutionary-based decision support system for vehicle routing: the case of a public utility. Decision Support * Systems, 46(3):730-742,2009. * * @param savingsList * the savings list */ private void randomizeSavings(List<IJCWArc> savingsList) { // Calculate the proportion of savings that should be moved to a new // position int shuffledArcsCount = getParentHeuristic().getRandomStream().nextInt( (int) ((savingsList.size() - 1) * getParentHeuristic().getParameters().get( CWParameters.RND_MIN_FRACTION)), // (int) ((savingsList.size() - 1) * getParentHeuristic().getParameters().get( CWParameters.RND_MAX_FRACTION))); // IJCWArc temporarySaving = null; // int temporarySavingIndex = 0; // boolean exchangeWithNext = false; // Shuffled arcs IJCWArc[] shuffledArcs = new IJCWArc[shuffledArcsCount]; int[] shuffledArcsIndex = Utilities.Random.randomIndexes(savingsList.size(), shuffledArcsCount, getParentHeuristic().getRandomStream()); int i = 0; for (int idx : shuffledArcsIndex) { shuffledArcs[i++] = savingsList.get(idx); } RandomPermutation.shuffle(shuffledArcs, getParentHeuristic().getRandomStream()); i = 0; for (int idx : shuffledArcsIndex) { savingsList.set(idx, shuffledArcs[i++]); } // // We start from the top of the list cause exchanging arcs at the end of // // the list is not likely to impact the result of the C&W heuristic // for (int s = 0; s < savingsList.size(); s++) { // double randomizeProb = getParentHeuristic().getRandomStream().nextDouble(); // if (randomizeProb < randomizedSavingsProp) { // if (exchangeWithNext == true) { // savingsList.set(temporarySavingIndex, savingsList.get(s)); // savingsList.set(s, temporarySaving); // exchangeWithNext = false; // exchangedArcs = exchangedArcs + 2; // } else { // temporarySaving = savingsList.get(s); // temporarySavingIndex = s; // exchangeWithNext = true; // } // } // } CWLogging.getAlgoLogger().info( "RandomizedSavingsHeuristic.randomizeSavings: Shuffled saving arcs: %s (%.1f%%) ", shuffledArcsCount, (100d * shuffledArcsCount) / savingsList.size()); CWLogging.getAlgoLogger().debug( "RandomizedSavingsHeuristic.randomizeSavings: Savings list size: %s", savingsList.size()); CWLogging.getAlgoLogger().lowDebug( "RandomizedSavingsHeuristic.randomizeSavings: Savings list : %s", savingsList); } @Override public String toString() { return String.format("%s (%s)", super.toString(), getParentHeuristic().getRandomStream()); } }