/*
* jCW : a java library for the development of saving based heuristics
*/
package vroom.common.heuristics.cw.kernel;
import vroom.common.heuristics.ConstraintHandler;
import vroom.common.heuristics.IInitialization;
import vroom.common.heuristics.cw.CWParameters;
import vroom.common.heuristics.vls.IVLSState;
import vroom.common.modeling.dataModel.IVRPInstance;
import vroom.common.modeling.dataModel.IVRPSolution;
import vroom.common.modeling.util.ISolutionFactory;
import vroom.common.utilities.Utilities;
import vroom.common.utilities.optimization.IConstraint;
import vroom.common.utilities.optimization.IInstance;
import vroom.common.utilities.optimization.IParameters;
import vroom.common.utilities.params.ClassParameterKey;
import vroom.common.utilities.ssj.RandomSourceBase;
/**
* <code>ClarkeAndWrightHeuristic</code> is the entry point to the jCW framework.
* <p>
* It contains {@link CWParameters} definition, as well as a {@link ConstraintHandler} and a reference to the
* {@link ISavingsAlgorithm} used.
* <p>
* It implements {@link Runnable} so that a CW heuristic can directly be run in a {@linkplain Thread thread}
* <p>
* Creation date: Apr 16, 2010 - 11:11:48 AM
*
* @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 ClarkeAndWrightHeuristic<S extends IVRPSolution<?>> extends RandomSourceBase implements
Runnable, IInitialization<S> {
/** The Constant VERSION_TAG. */
public static final String VERSION_TAG = "v2 (2010-04-17)";
public static final String MAIN_RANDOM_STREAM = "CWRndStream";
/**
* The {@linkplain ISavingsAlgorithm saving algorithm} used in this instance.
*/
private final ISavingsAlgorithm<S> mSavingsAlgo;
/**
* Getter for the savings algorithm.
*
* @return The {@linkplain ISavingsAlgorithm saving algorithm} used in this instance
*/
public ISavingsAlgorithm<S> getSavingsAlgo() {
return mSavingsAlgo;
}
/** The {@linkplain CWParameters global parameters} used in this instance. */
private final CWParameters mParameters;
/**
* Getter for the global parameters.
*
* @return The {@linkplain CWParameters global parameters} used in this instance
*/
public CWParameters getParameters() {
return mParameters;
}
/**
* The {@linkplain ConstraintHandler constraint handler} used in this instance.
*/
private final ConstraintHandler<S> mConstraintHandler;
/**
* Getter for the constraint handler.
*
* @return The {@linkplain ConstraintHandler constraint handler} used in this instance
*/
public ConstraintHandler<S> getConstraintHandler() {
return mConstraintHandler;
}
/** the solution factory used in this instance **/
private ISolutionFactory mSolutionFactory;
/**
* Getter for the solution factory used in this instance
*
* @return the value of solutionFactory
*/
public ISolutionFactory getSolutionFactory() {
return this.mSolutionFactory;
}
/**
* Setter for the solution factory used in this instance
*
* @param solutionFactory
* the solution factory to be used
*/
public void setSolutionFactory(ISolutionFactory solutionFactory) {
mSolutionFactory = solutionFactory;
}
/**
* The {@linkplain IVRPInstance problem instance} that will be used in to run the heuristic.
*/
private IVRPInstance mInstance;
/** The mSolution that will be modified by the CW heuristic */
private S mSolution;
/**
* Getter for problem instance.
*
* @param <I>
* the implementation of {@link IVRPInstance} to which the problem instance should be casted
* @return The {@linkplain IVRPInstance problem instance} that will be used in to run the heuristic
*/
public IVRPInstance getInstance() {
return mInstance;
}
/**
* Sets the problem instance : The {@linkplain IVRPInstance problem instance} that will be used in to run the
* heuristic.
*
* @param instance
* the value to be set for problem instance {@linkplain #isRunning() running flag})
*/
public void initialize(IVRPInstance instance) {
if (isRunning()) {
throw new IllegalStateException("Heuristic is running");
}
mInstance = instance;
}
/**
* Sets the problem instance : The {@linkplain IVRPInstance problem instance} that will be used in to run the
* heuristic.
*
* @param instance
* the value to be set for problem instance {@linkplain #isRunning() running flag})
* @param mSolution
* the mSolution that will be modified by the cw heuristic
*/
public void initialize(IVRPInstance instance, S solution) {
if (isRunning()) {
throw new IllegalStateException("Heuristic is running");
}
mInstance = instance;
mSolution = solution;
}
/**
* A flag for the state of the procedure: <code>true</code> if the heuristic is currently running.
*/
private boolean mRunning;
/**
* Flag for the state of the procedure.
*
* @return if the heuristic is currently running
*/
public boolean isRunning() {
return mRunning;
}
/**
* Creates a new <code>ClarkeAndWrightHeuristic</code>.
* <p>
* The {@linkplain #getSavingsAlgo() savings algorithm} and the global parameters for this heuristic
* {@linkplain #getConstraintHandler() constraint handler} will be instantiated using the given
* <code>parameters</code>.
*
* @param parameters
*/
@SuppressWarnings("rawtypes")
public ClarkeAndWrightHeuristic(CWParameters parameters) {
mParameters = parameters;
// Setup random source
updateSeed(this.mParameters.get(CWParameters.RANDOM_SEED));
mSavingsAlgo = getParameters().newInstance(CWParameters.ALGORITHM_CLASS, this);
mConstraintHandler = getParameters().newInstance(CWParameters.CTR_HANDLER_CLASS);
// Instantiate the solution factory
mSolutionFactory = getParameters().newInstance(CWParameters.SOLUTION_FACTORY_CLASS);
// Load the constraints defined as parameters
for (ClassParameterKey<IConstraint> key : getParameters().getConstraintKeys()) {
mConstraintHandler.addConstraint(getParameters()
.<IConstraint<S>> newInstance(key, this));
}
}
/**
* Creates a new <code>ClarkeAndWrightHeuristic</code> with the given saving algorithm and constraint handler
*
* @param parameters
* the global parameters for this instance
* @param savingsAlgo
* the saving algorithm to be used
* @param constraintHandler
* a constraint handler containing all the considered constraints
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public ClarkeAndWrightHeuristic(CWParameters parameters,
Class<? extends ISavingsAlgorithm> savingsAlgo, ConstraintHandler<S> constraintHandler) {
mParameters = parameters;
mConstraintHandler = constraintHandler;
// Setup random source
updateSeed(this.mParameters.get(CWParameters.RANDOM_SEED));
// Instantiate the solution factory
mSolutionFactory = getParameters().newInstance(CWParameters.SOLUTION_FACTORY_CLASS);
mSavingsAlgo = Utilities.newInstance(savingsAlgo, this);
}
/**
* Update the random stream seed (and set {@link CWParameters#RANDOM_SEED}
*
* @author vpillac
*/
public void updateSeed(long seed) {
getParameters().set(CWParameters.RANDOM_SEED, seed);
setMRG32k3aRndStream(seed, MAIN_RANDOM_STREAM);
}
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (isRunning()) {
throw new IllegalStateException("The heuristic is already running");
}
if (getInstance() == null) {
throw new IllegalStateException("No instance has been defined");
}
mRunning = true;
newSolution(null, getInstance(), null);
mRunning = false;
}
/**
* Getter for the current mSolution
*
* @return the current mSolution found by the saving algorithm
*/
public S getSolution() {
return getSavingsAlgo().getSolution();
}
@Override
public String toString() {
return String.format("%s Algo:%s", this.getClass().getSimpleName(), mSavingsAlgo);
}
@Override
public S newSolution(IVLSState<S> state, IInstance instance, IParameters params) {
mInstance = (IVRPInstance) instance;
getSavingsAlgo().initialize(mSolution);
getSavingsAlgo().run();
return getSolution();
}
}