package vrp2013.sol.algorithms; import java.util.Map; import java.util.Map.Entry; import vroom.common.heuristics.ConstraintHandler; import vroom.common.modeling.dataModel.INodeVisit; import vroom.common.modeling.dataModel.IVRPInstance; import vroom.common.modeling.dataModel.RouteBase; import vroom.common.modeling.util.IRoutePool; import vroom.common.utilities.Stopwatch; import vroom.common.utilities.optimization.IAcceptanceCriterion; import vroom.common.utilities.optimization.OptimizationSense; import vroom.common.utilities.optimization.SAAcceptanceCriterion; import vrp2013.util.BatchExecutor.Result; import vrp2013.util.VRPLogging; import vrp2013.util.VRPSolution; import vrp2013.util.VRPUtilities; /** * The class <code>ParallelVND</code> is an implementation of VND that explores neighborhoods in parallel. * <p> * Creation date: 13/05/2013 - 9:36:40 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 ParallelVNSSA extends ParallelVNS { private IAcceptanceCriterion mAccept; public ParallelVNSSA(IVRPInstance instance, ConstraintHandler<VRPSolution> constraintHandler, IRoutePool<INodeVisit> routePool) { super(instance, constraintHandler, routePool); } @Override public boolean localSearch(final VRPSolution solution) { VRPLogging.logOptResults("ls-init", false, getNeighStopwatch(), solution); Stopwatch mainSW = new Stopwatch(); mainSW.start(); int it = 0; mAccept = new SAAcceptanceCriterion(OptimizationSense.MINIMIZATION, VRPUtilities .getInstance().getRandomStream(), solution.getCost(), 0.5, 0.5, 100, 0.001, false); setBestSolution(solution); // Start with the current solution VRPSolution bestNeighbor = solution; // The current solution is the best neighbor from the previous iteration VRPSolution currentSolution = solution; // A flag set to true if the solution was changed in the last iteration boolean changedLastIt = true; // A flag set to true if the solution was changed at least once boolean changedOverall = false; while (changedLastIt) { it++; // The explorer that found the best solution (for logging purposes) NeighborhoodExplorer bestExplorer = null; changedLastIt = false; getNeighStopwatch().restart(); for (NeighborhoodExplorer explorer : getExplorers()) { // Set the starting solution for this explorer explorer.setStartSolution(currentSolution); } Map<NeighborhoodExplorer, Result<VRPSolution>> results = null; // Explore the neighborhoods in parallel threads results = getExecutor().submitBatchAndWait(getExplorers()); // Find the best neighbor in the results bestNeighbor = null; for (Entry<NeighborhoodExplorer, Result<VRPSolution>> entry : results.entrySet()) { if (bestNeighbor == null || OptimizationSense.MINIMIZATION.isBetter(bestNeighbor, entry.getValue() .get())) { bestNeighbor = entry.getValue().get(); bestExplorer = entry.getKey(); } } if (mAccept.accept(currentSolution, bestNeighbor)) { changedLastIt = true; changedOverall = true; currentSolution = bestNeighbor; VRPLogging.logOptResults(bestExplorer.getShakeNeighborhood().getShortName() + "*", changedLastIt, getNeighStopwatch(), bestNeighbor); VRPLogging.getOptLogger().debug("[%9s] It: %5s Time:%s - obj=%.2f", "current", it, mainSW.readTimeString(3, true, false), currentSolution.getCost()); } getNeighStopwatch().stop(); if (currentSolution != null && OptimizationSense.MINIMIZATION.isBetter(getBestSolution(), currentSolution)) { setBestSolution(currentSolution); VRPLogging.getOptLogger().debug("[%9s] It: %5s Time:%s - obj=%.2f", "new best", it, mainSW.readTimeString(3, true, false), getBestSolution().getCost()); } } // Copy the best solution to the solution passed as argument if (changedOverall) { solution.clear(); for (RouteBase r : bestNeighbor) if (r.length() > 2) solution.addRoute(r); } mainSW.stop(); return changedOverall; } }