/** * */ package vroom.common.heuristics; import umontreal.iro.lecuyer.rng.RandomStream; import vroom.common.heuristics.utils.HeuristicsLogging; import vroom.common.utilities.IDisposable; import vroom.common.utilities.Stopwatch; import vroom.common.utilities.Stopwatch.ReadOnlyStopwatch; import vroom.common.utilities.dataModel.ISolutionChecker; import vroom.common.utilities.optimization.IAcceptanceCriterion; import vroom.common.utilities.optimization.ILocalSearch; import vroom.common.utilities.optimization.ISolution; import vroom.common.utilities.optimization.IStoppingCriterion; import vroom.common.utilities.optimization.ImprovingAcceptanceCriterion; import vroom.common.utilities.optimization.OptimizationSense; import vroom.common.utilities.ssj.RandomSourceBase; /** * <code>LocalSearchBase</code> is a base class for common local search based procedures. * <p> * Creation date: 11 juil. 2010 - 19:48:35 * * @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 abstract class LocalSearchBase<S extends ISolution> extends RandomSourceBase implements ILocalSearch<S>, IDisposable { public static final String MAIN_RANDOM_STREAM = "LSRndStream"; /** an acceptance criterion **/ private IAcceptanceCriterion mAcceptanceCriterion; /** * Getter for an acceptance criterion * * @return the acceptance criterion used in this local search */ public IAcceptanceCriterion getAcceptanceCriterion() { return this.mAcceptanceCriterion; } /** * Setter for an acceptance criterion * * @param acceptanceCriterion * the value to be set for acceptanceCriterion */ public void setAcceptanceCriterion(IAcceptanceCriterion acceptanceCriterion) { this.mAcceptanceCriterion = acceptanceCriterion; } /** a stopping criterion **/ private IStoppingCriterion mStoppingCriterion; /** * Getter for a stopping criterion * * @return the value of stoppingCriterion */ public IStoppingCriterion getStoppingCriterion() { return this.mStoppingCriterion; } /** * Setter for a stopping criterion * * @param stoppingCriterion * the value to be set for a stopping criterion */ protected void setStoppingCriterion(IStoppingCriterion stoppingCriterion) { this.mStoppingCriterion = stoppingCriterion; } /** the optimization sense for this local search **/ private final OptimizationSense mOptimizationSense; /** * Getter for the optimization sense for this local search * * @return the value of the optimization sense */ public OptimizationSense getOptimizationSense() { return this.mOptimizationSense; } /** <code>true</code> if the local search algorithm is currently running, <code>false</code> otherwise */ private boolean mRunning; /** * Sets the running flag to <code>true</code> * * @throws IllegalStateException * if the local search is already running */ protected void setRunning() { if (mRunning) { throw new IllegalStateException("The local search is already running"); } mRunning = true; getMainTimer().reset(); getMainTimer().start(); } /** * Sets the running flag to <code>false</code> */ protected void setStopped() { mRunning = false; if (getMainTimer().isStarted() && !getMainTimer().isStopped()) getMainTimer().stop(); } /** * Returns <code>true</code> if the local search algorithm is currently running, <code>false</code> otherwise * * @return <code>true</code> if the local search algorithm is currently running, <code>false</code> otherwise */ protected boolean isRunning() { return mRunning; } /** the main timer **/ private final Stopwatch mTimer; /** * Getter for the main timer * * @return the main timer */ public ReadOnlyStopwatch getTimer() { return this.mTimer.getReadOnlyStopwatch(); } /** * Getter for the main timer, for subclass use only * * @return the main timer */ protected Stopwatch getMainTimer() { return this.mTimer; } private static boolean sCheckSolutionAfterMove = false; /** * Setter for <code>checkSolutionAfterMove</code> * * @param checkSolutionAfterMove * the checkSolutionAfterMove to set */ public static void setCheckSolutionAfterMove(boolean checkSolutionAfterMove) { sCheckSolutionAfterMove = checkSolutionAfterMove; if (checkSolutionAfterMove) { HeuristicsLogging .getProcedureLogger() .warn("LocalSearchBase.CheckSolutionAfterMove is set to true, set to false to increase performance (set in %s)", Thread.currentThread().getStackTrace()[2]); } } /** * Getter for <code>checkSolutionAfterMove</code> * * @return the checkSolutionAfterMove */ public static boolean isCheckSolutionAfterMove() { return sCheckSolutionAfterMove; } private ISolutionChecker<S> mSolutionChecker = null; /** * Getter for the solution checker used in this local search * * @return the solution checker used in this local search */ public ISolutionChecker<S> getSolutionChecker() { return mSolutionChecker; } /** * Setter for the solution checker used in this local search * * @param solutionChecker * the solution checker used in this local search */ public void setSolutionChecker(ISolutionChecker<S> solutionChecker) { mSolutionChecker = solutionChecker; } /** * Check a solution against the defined solution checker if any, and only if the {@link #isCheckSolutionAfterMove() * checkSolutionAfterMove} flag is set to <code>true</code> * * @param solution * the solution to be checked * @return a string describing the infeasibility of <code>solution</code>, or an empty string if the solution is * feasible * @see ISolutionChecker#checkSolution(ISolution) */ protected String checkSolution(S solution) { if (isCheckSolutionAfterMove() && getSolutionChecker() != null) { return getSolutionChecker().checkSolution(solution); } else { return ""; } } /** * Creates a new <code>LocalSearchBase</code> * * @param optimizationSense * the sense of optimization * @see RandomSourceBase#RandomSourceBase() */ protected LocalSearchBase(OptimizationSense optimizationSense) { super(); mTimer = new Stopwatch(); mOptimizationSense = optimizationSense; setAcceptanceCriterion(new ImprovingAcceptanceCriterion(optimizationSense)); } /** * Creates a new <code>LocalSearchBase</code> * * @param optimizationSense * the sense of optimization * @param rndStream * the random stream that will be used in this local search * @see RandomSourceBase#RandomSourceBase(RandomStream) */ protected LocalSearchBase(OptimizationSense optimizationSense, RandomStream rndStream) { super(rndStream); mTimer = new Stopwatch(); mOptimizationSense = optimizationSense; setAcceptanceCriterion(new ImprovingAcceptanceCriterion(optimizationSense)); } }