package vrp2013.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.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.util.VRPLogging; import vrp2013.util.VRPSolution; /** * The class <code>VND</code> is a simple implementation of a Variable Neighborhood Descent algorithm. * <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 start solution **/ private VRPSolution mStartSolution; /** the best solution **/ private VRPSolution mBestSolution; /** * Getter for the current solution * * @return the current solution */ public VRPSolution getCurrentSolution() { return this.mStartSolution; } /** * Setter for the current solution * * @param solution * the current solution */ public void setInitialSolution(VRPSolution solution) { this.mStartSolution = 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<>(); mNeighborhoods.add(new OrOptNeighborhood<>(constraintHandler)); mNeighborhoods.add(new SwapNeighborhood<>(constraintHandler)); mNeighborhoods.add(new TwoOptNeighborhood<>(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(final VRPSolution solution) { boolean changed = false; 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); } setBestSolution(solution); return changed; } @Override public VRPSolution call() { VRPSolution sol = getCurrentSolution().clone(); localSearch(sol); setBestSolution(sol); return sol; } /** * Return the list of neighborhoods defined in this VND * * @return the list of neighborhoods defined in this VND * @author vpillac */ List<INeighborhood<VRPSolution, ?>> getNeighborhoods() { return mNeighborhoods; } @Override public IRoutePool<INodeVisit> getRoutePool() { return mRoutePool; } @Override public VRPSolution getBestSolution() { return mBestSolution; } /** * Set the best solution found by this algorithm in the last call to {@link #call()} or * {@link #localSearch(VRPSolution)} JAVADOC * * @param bestSolution * @author vpillac */ protected void setBestSolution(VRPSolution bestSolution) { mBestSolution = bestSolution; } @Override public IVRPInstance getInstance() { return mInstance; } @Override public int getIterations() { return 0; } @Override public ISolutionFactory getSolutionFactory() { return null; } /** * Returns the stopwatch used in this instance * * @return the stopwatch used in this instance * @author vpillac */ protected Stopwatch getNeighStopwatch() { return mNeighStopwatch; } }