package vroom.common.heuristics.vls.vrp; import umontreal.iro.lecuyer.rng.RandomStream; import vroom.common.heuristics.vls.IVLSPertubation; import vroom.common.heuristics.vls.IVLSState; import vroom.common.heuristics.vls.VLSGlobalParameters; import vroom.common.heuristics.vls.VLSPhase; import vroom.common.heuristics.vrp.SwapMove; import vroom.common.modeling.dataModel.INodeVisit; import vroom.common.modeling.dataModel.IRoute; import vroom.common.modeling.dataModel.IVRPSolution; import vroom.common.utilities.optimization.IInstance; import vroom.common.utilities.optimization.IParameters; import vroom.common.utilities.optimization.ISolution; import vroom.common.utilities.params.GlobalParameters; import vroom.common.utilities.params.ParameterKey; /** * <code>PSwapPerturbation</code> is an implementation of {@link IVLSPertubation} that performs p swaps in a given tsp tour. * <p/> * The mSolution passe to {@link #pertub(IVLSState, IInstance, ISolution, IParameters)} should be a subtype of {@link VRPSolutionWrapper} * <p> * Creation date: Apr 26, 2010 - 3:57:36 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 PSwapPerturbation<S extends IVRPSolution<? extends IRoute<?>>> implements IVLSPertubation<S> { private final int mPMax; private static int sLoopBound = 100; /** The maximum number of swaps to be performed */ public static final ParameterKey<Integer> PSWAP_PMAX = new ParameterKey<Integer>("PSWAP_PMAX", Integer.class, 3); static { GlobalParameters.addRequiredParameter(VLSGlobalParameters.class, PSWAP_PMAX); } /** * Creates a new <code>PSwapPerturbation</code> * * @param params * the global parameters used */ public PSwapPerturbation(VLSGlobalParameters params) { this(params, params.get(PSWAP_PMAX)); } /** * Creates a new <code>PSwapPerturbation</code> with the given maximum number of swaps * * @param params * the global parameters used * @param pMax * the maximum number of swaps to be perfomed */ public PSwapPerturbation(VLSGlobalParameters params, int pMax) { mPMax = pMax; } @Override public void pertub(IVLSState<S> state, IInstance instance, S solution, IParameters params) { // Number of swaps RandomStream r = state.getParentVLS().getRandomStream(); int p = Math.max(state.getNonImprovingIterationCount(VLSPhase.ELS), mPMax); int k = 0, l = 0; while (k < p && l < sLoopBound) { int r1 = r.nextInt(0, solution.getRouteCount() - 1); int r2 = r.nextInt(0, solution.getRouteCount() - 1); if (solution.getRoute(r1).length() > 1 && solution.getRoute(r2).length() > 1) { int i = r.nextInt(0, solution.getRoute(r1).length() - 1); int j = r.nextInt(0, solution.getRoute(r2).length() - 1); SwapMove move = new SwapMove(0, solution, r1, r2, i, j); if (state.getParentVLS().getConstraintHandler().isFeasible(solution, move) && swap(solution.getRoute(r1), solution.getRoute(r2), i, j)) { k++; } } l++; } } @SuppressWarnings("unchecked") protected <V extends INodeVisit, W extends INodeVisit> boolean swap(IRoute<V> r1, IRoute<W> r2, int i, int j) { if (i != j && !r1.getNodeAt(i).isFixed() && !r2.getNodeAt(j).isFixed()) { r2.setNodeAt(j, (W) r1.setNodeAt(i, (V) r2.getNodeAt(j))); return true; } else { return false; } } }