package vroom.common.heuristics.vns.benchmarking; import java.io.File; import java.io.IOException; import java.util.LinkedList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import umontreal.iro.lecuyer.rng.MRG32k3a; import vroom.common.heuristics.ConstraintHandler; import vroom.common.heuristics.cw.CWParameters; import vroom.common.heuristics.cw.algorithms.RandomizedSavingsHeuristic; import vroom.common.heuristics.cw.kernel.ClarkeAndWrightHeuristic; import vroom.common.heuristics.vns.VNSParameters; import vroom.common.heuristics.vns.VariableNeighborhoodSearch; import vroom.common.heuristics.vns.VariableNeighborhoodSearch.VNSVariant; 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.heuristics.vrp.constraints.CapacityConstraint; import vroom.common.heuristics.vrp.constraints.FixedNodesConstraint; import vroom.common.modeling.dataModel.ListRoute.ArrayListRoute; import vroom.common.modeling.dataModel.DoublyLinkedRoute; import vroom.common.modeling.dataModel.Fleet; import vroom.common.modeling.dataModel.IRoute; import vroom.common.modeling.dataModel.IVRPInstance; import vroom.common.modeling.dataModel.IVRPSolution; import vroom.common.modeling.dataModel.Solution; import vroom.common.modeling.dataModel.Vehicle; import vroom.common.modeling.io.ChristofidesPersistenceHelper; import vroom.common.modeling.io.FlatFilePersistenceHelper; import vroom.common.modeling.io.NovoaPersistenceHelper; import vroom.common.modeling.io.TSPLibPersistenceHelper; import vroom.common.modeling.util.DefaultSolutionFactory; import vroom.common.modeling.util.ISolutionFactory; import vroom.common.modeling.util.SolutionChecker; import vroom.common.utilities.StatCollector; import vroom.common.utilities.StatCollector.Label; import vroom.common.utilities.Stopwatch; import vroom.common.utilities.logging.LoggerHelper; import vroom.common.utilities.optimization.INeighborhood; import vroom.common.utilities.optimization.OptimizationSense; /** * <code>RouteDataStructureBenchmarking</code> is used to test performance of different route data structures * <p> * Creation date: 9/09/2010 - 10:21:19 * * @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 */ @SuppressWarnings("unused") public class RouteDataStructureBenchmark implements Runnable { public final static String CHRISTOFIDES_INSTANCES_PATH = "../Instances/cvrp/christodifes-mingozzi-toth"; public final static String CHRISTOFIDES_SOLUTION_FILE = "../Instances/cvrp/christodifes-mingozzi-toth.sol"; private final static String INSTANCE_PATH = CHRISTOFIDES_INSTANCES_PATH; private final static String BKS_FILE = CHRISTOFIDES_SOLUTION_FILE; private final static String BENCH_NAME = "christofides"; private final static String INSTANCE_FILTER = "vrpnc"; private final static boolean RESET_ON_SIZE_CHANGE = false; protected final static FlatFilePersistenceHelper INSTANCE_READER = new ChristofidesPersistenceHelper(); private final static File INSTANCES_DIRECTORY = new File( INSTANCE_PATH); protected final static List<File> INSTANCES_FILES; static { String[] children = INSTANCES_DIRECTORY.list(); if (children == null) { // Either dir does not exist or is not a directory INSTANCES_FILES = null; System.err.println("Invalid directory :" + INSTANCES_DIRECTORY); System.exit(1); } else { INSTANCES_FILES = new LinkedList<File>(); for (String element : children) { if (element.startsWith(INSTANCE_FILTER)) { INSTANCES_FILES.add(new File(INSTANCES_DIRECTORY.getAbsolutePath() + File.separator + element)); } } } } private static String sStatFile = "benchmarks/route_banch.csv"; private static final Label<?>[] LABELS = new Label<?>[] { new Label<String>("comment", String.class), new Label<Integer>("run_id", Integer.class), new Label<String>("instance", String.class), new Label<Double>("obj", Double.class), new Label<Double>("cw_time", Double.class), new Label<Double>("vns_time", Double.class), new Label<Long>("total_time", Long.class) }; private static StatCollector sCollector = new StatCollector( new File( sStatFile), true, false, "RouteDataStructurBenchmarks", LABELS); private final ISolutionFactory mSolutionFactory; private final IVRPInstance mInstance; private final VariableNeighborhoodSearch<Solution<?>> mVNS; private final ClarkeAndWrightHeuristic<Solution<?>> mCW; private Solution<?> mSolution; private final int mRunId; private final String mRunComment; private final long mSeed; /** * Creates a new <code>RouteDataStructureBenchmarking</code> * * @param solutionFactories */ protected RouteDataStructureBenchmark(int runId, String comment, ISolutionFactory solutionFactory, IVRPInstance instance, long seed) { super(); mRunId = runId; mRunComment = comment; mSolutionFactory = solutionFactory; mInstance = instance; mSeed = seed; List<INeighborhood<Solution<?>, ?>> neighborhoods = new LinkedList<INeighborhood<Solution<?>, ?>>(); ConstraintHandler<Solution<?>> ctr = new ConstraintHandler<Solution<?>>(); ctr.addConstraint(new FixedNodesConstraint<Solution<?>>()); ctr.addConstraint(new CapacityConstraint<Solution<?>>()); neighborhoods.add(new SwapNeighborhood<Solution<?>>(ctr)); neighborhoods.add(new TwoOptNeighborhood<Solution<?>>(ctr)); neighborhoods.add(new OrOptNeighborhood<Solution<?>>(ctr)); neighborhoods.add(new StringExchangeNeighborhood<Solution<?>>(ctr)); mVNS = VariableNeighborhoodSearch.newVNS(VNSVariant.VND, OptimizationSense.MINIMIZATION, null, new MRG32k3a(), neighborhoods); CWParameters params = new CWParameters(); params.set(CWParameters.RANDOM_SEED, seed); mCW = new ClarkeAndWrightHeuristic<Solution<?>>(params, RandomizedSavingsHeuristic.class, ctr); mCW.setSolutionFactory(mSolutionFactory); } @Override public void run() { VNSParameters params = new VNSParameters(60000, 10000, false, 60000, 100, null, null); System.out .printf("%s\t %s (seed:%s) %s\n", mRunId, mInstance.getName(), mSeed, mRunComment); mCW.initialize(mInstance); Stopwatch t = new Stopwatch(); t.start(); mCW.run(); mSolution = mCW.getSolution(); t.stop(); double cwTime = t.readTimeMS(); t.restart(); mVNS.localSearch(mInstance, mSolution, params); t.stop(); double vnsTime = t.readTimeMS(); SolutionChecker.checkSolution(mSolution, true, true, true); sCollector.collect(mRunComment, mRunId, mInstance.getName(), mSolution.getCost(), cwTime, vnsTime, cwTime + vnsTime); } public static void main(String[] args) { int nRuns = 5; System.out.println("================================="); System.out.println("Running benchmarks for instances in folder"); System.out.println(INSTANCES_DIRECTORY); System.out.println("Stats saved in : " + sStatFile); System.out.println("Runs per instance: " + nRuns); System.out.println("================================="); LoggerHelper.setupRootLogger(LoggerHelper.LEVEL_WARN, LoggerHelper.LEVEL_WARN, true); LinkedBlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(); ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 1, TimeUnit.MINUTES, workQueue); List<IVRPInstance> instances = readInstances(); ISolutionFactory llFact = new DefaultSolutionFactory() { @Override public IRoute<?> newRoute(IVRPSolution<?> solution, Vehicle vehicle, Object... params) { return new DoublyLinkedRoute(solution, vehicle); }; }; ISolutionFactory alFact = new DefaultSolutionFactory() { @Override public IRoute<?> newRoute(IVRPSolution<?> solution, Vehicle vehicle, Object... params) { return new ArrayListRoute(solution, vehicle); }; }; System.out.println("================================="); int runId = 0; for (IVRPInstance instance : instances) { for (int seed = 0; seed < nRuns; seed++) { executor.execute(new RouteDataStructureBenchmark(runId, "LinkedList", llFact, instance, seed)); executor.execute(new RouteDataStructureBenchmark(runId, "ArrayList", alFact, instance, seed)); runId++; } } executor.shutdown(); try { executor.awaitTermination(60, TimeUnit.MINUTES); System.out.println("================================="); System.out.println("FINISHED"); System.out.println("================================="); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.exit(0); } } private static List<IVRPInstance> readInstances() { List<IVRPInstance> instances = new LinkedList<IVRPInstance>(); for (File f : INSTANCES_FILES) { if (!f.getName().equals("1_info.txt") && !f.getName().equals(".svn")) { try { IVRPInstance[] ins; if (INSTANCE_READER instanceof TSPLibPersistenceHelper) { ins = new IVRPInstance[] { INSTANCE_READER.readInstance(f, 100) }; int k = Integer.valueOf(ins[0].getName().substring( ins[0].getName().lastIndexOf('k') + 1)); ins[0].setFleet(Fleet.newHomogenousFleet(k, ins[0].getFleet().getVehicle())); } else if (INSTANCE_READER instanceof NovoaPersistenceHelper) { int s = Integer.valueOf(f.getName().substring(f.getName().indexOf('_') + 1, f.getName().indexOf('r'))); if (s <= 60) { ins = new IVRPInstance[] { INSTANCE_READER.readInstance(f, Double .valueOf(NovoaPersistenceHelper.getCapacity(s, 1, 0))), INSTANCE_READER.readInstance(f, Double .valueOf(NovoaPersistenceHelper.getCapacity(s, 1, 1))) }; } else { ins = new IVRPInstance[0]; } } else { ins = new IVRPInstance[] { INSTANCE_READER.readInstance(f) }; if (ins[0].getDepot(0).getTimeWindow() != null) { // Ignore distance constrained instances ins = new IVRPInstance[0]; } } for (IVRPInstance i : ins) { System.out.printf(" %s (%s clients) Fleet:%s\n", i.getName(), i.getRequestCount(), i.getFleet()); instances.add(i); } } catch (IOException e) { e.printStackTrace(); } } } return instances; } }