package vrp2013.sol.algorithms;
import java.util.ArrayList;
import java.util.List;
import vroom.common.heuristics.ConstraintHandler;
import vroom.common.heuristics.vrp.OrOptNeighborhood;
import vroom.common.heuristics.vrp.StringExchangeNeighborhood;
import vroom.common.heuristics.vrp.SwapNeighborhood;
import vroom.common.heuristics.vrp.TwoOptNeighborhood;
import vroom.common.modeling.dataModel.INodeVisit;
import vroom.common.modeling.dataModel.IVRPInstance;
import vroom.common.modeling.util.IRoutePool;
import vroom.common.modeling.util.ISolutionFactory;
import vroom.common.utilities.Stopwatch;
import vroom.common.utilities.optimization.INeighborhood;
import vroom.common.utilities.optimization.SimpleParameters;
import vrp2013.algorithms.IVRPOptimizationAlgorithm;
import vrp2013.util.VRPLogging;
import vrp2013.util.VRPSolution;
/**
* The class <code>VND</code> is a simple implementation of a Variable Neighborhood Descent algorithm with a fixed set
* of neighborhoods (Swap, 2-Opt, Or-Opt, String-Exchange).
* <p>
* Creation date: May 4, 2013 - 10:18:18 AM
*
* @author Victor Pillac, <a href="http://www.nicta.com.au">National ICT Australia</a>, <a
* href="http://www.victorpillac.com">www.victorpillac.com</a>
* @version 1.0
*/
public class VND implements IVRPOptimizationAlgorithm {
private final IVRPInstance mInstance;
private final List<INeighborhood<VRPSolution, ?>> mNeighborhoods;
private final IRoutePool<INodeVisit> mRoutePool;
private final Stopwatch mNeighStopwatch;
/** the current solution **/
private VRPSolution mCurrentSolution;
/**
* Getter for the current solution
*
* @return the current solution
*/
public VRPSolution getCurrentSolution() {
return this.mCurrentSolution;
}
/**
* Setter for the current solution
*
* @param solution
* the current solution
*/
public void setInitialSolution(VRPSolution solution) {
this.mCurrentSolution = solution;
}
/**
* Creates a new <code>VND</code>
*
* @param instance
* the instance on which optimization will be performed
* @param constraintHandler
* a constraint handler that contains the constraints from the VRP
* @param routePool
* a pool that will store the routes found in the local search
*/
public VND(IVRPInstance instance, ConstraintHandler<VRPSolution> constraintHandler,
IRoutePool<INodeVisit> routePool) {
mInstance = instance;
mNeighborhoods = new ArrayList<>(4);
mNeighborhoods.add(new SwapNeighborhood<>(constraintHandler));
mNeighborhoods.add(new TwoOptNeighborhood<>(constraintHandler));
mNeighborhoods.add(new OrOptNeighborhood<>(constraintHandler));
mNeighborhoods.add(new StringExchangeNeighborhood<>(constraintHandler));
mNeighStopwatch = new Stopwatch();
mRoutePool = routePool;
}
@Override
public void dispose() {
mNeighborhoods.clear();
}
/**
* Execute the VND algorithm on the given {@code solution}
*
* @param solution
* the solution on which the local search will be applied
* @return {@code true} if the solution was changed, {@code false} otherwise
*/
public boolean localSearch(VRPSolution solution) {
boolean changed = true;
while (changed) {
for (INeighborhood<VRPSolution, ?> neighborhood : mNeighborhoods) {
mNeighStopwatch.restart();
// Explore the neighborhood
changed = neighborhood.localSearch(solution, SimpleParameters.BEST_IMPROVEMENT);
mNeighStopwatch.pause();
// Log the solution
VRPLogging.logOptResults(neighborhood.getShortName(), changed, mNeighStopwatch,
solution);
// Add the routes from the solution to the pool
if (mRoutePool != null)
mRoutePool.add(solution);
// An improvement was found, restart from the first neighborhood
if (changed)
break;
}
}
return changed;
}
@Override
public VRPSolution call() {
localSearch(getCurrentSolution());
return getCurrentSolution();
}
/**
* Return the list of neighborhoods defined in this VND
*
* @return the list of neighborhoods defined in this VND
* @author vpillac
*/
protected List<INeighborhood<VRPSolution, ?>> getNeighborhoods() {
return mNeighborhoods;
}
@Override
public IRoutePool<INodeVisit> getRoutePool() {
return mRoutePool;
}
@Override
public VRPSolution getBestSolution() {
return getCurrentSolution();
}
@Override
public IVRPInstance getInstance() {
return mInstance;
}
@Override
public int getIterations() {
return 0;
}
@Override
public ISolutionFactory getSolutionFactory() {
return null;
}
}