com.graphhopper.jsprit.analysis.toolbox.ConcurrentBenchmarker.java Source code

Java tutorial

Introduction

Here is the source code for com.graphhopper.jsprit.analysis.toolbox.ConcurrentBenchmarker.java

Source

/*******************************************************************************
 * Copyright (C) 2013  Stefan Schroeder
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package com.graphhopper.jsprit.analysis.toolbox;

import com.graphhopper.jsprit.analysis.util.BenchmarkWriter;
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithmFactory;
import com.graphhopper.jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import com.graphhopper.jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import com.graphhopper.jsprit.core.util.BenchmarkInstance;
import com.graphhopper.jsprit.core.util.BenchmarkResult;
import com.graphhopper.jsprit.core.util.Solutions;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;

public class ConcurrentBenchmarker {

    public static interface Cost {
        public double getCost(VehicleRoutingProblemSolution sol);
    }

    private String algorithmConfig = null;

    private List<BenchmarkInstance> benchmarkInstances = new ArrayList<BenchmarkInstance>();

    private int runs = 1;

    private Collection<BenchmarkWriter> writers = new ArrayList<BenchmarkWriter>();

    private Collection<BenchmarkResult> results = new ArrayList<BenchmarkResult>();

    private Cost cost = new Cost() {

        @Override
        public double getCost(VehicleRoutingProblemSolution sol) {
            return sol.getCost();
        }

    };

    private VehicleRoutingAlgorithmFactory algorithmFactory;

    public void setCost(Cost cost) {
        this.cost = cost;
    }

    public ConcurrentBenchmarker(String algorithmConfig) {
        super();
        this.algorithmConfig = algorithmConfig;
        //      LogManager.getRootLogger().setLevel(Level.ERROR);
    }

    public ConcurrentBenchmarker(VehicleRoutingAlgorithmFactory algorithmFactory) {
        this.algorithmFactory = algorithmFactory;
    }

    public void addBenchmarkWriter(BenchmarkWriter writer) {
        writers.add(writer);
    }

    public void addInstance(String name, VehicleRoutingProblem problem) {
        benchmarkInstances.add(new BenchmarkInstance(name, problem, null, null));
    }

    public void addInstane(BenchmarkInstance instance) {
        benchmarkInstances.add(instance);
    }

    public void addAllInstances(Collection<BenchmarkInstance> instances) {
        benchmarkInstances.addAll(instances);
    }

    public void addInstance(String name, VehicleRoutingProblem problem, Double bestKnownResult,
            Double bestKnownVehicles) {
        benchmarkInstances.add(new BenchmarkInstance(name, problem, bestKnownResult, bestKnownVehicles));
    }

    /**
     * Sets nuOfRuns with same algorithm on same instance.
     * <p>Default is 1
     *
     * @param runs
     */
    public void setNuOfRuns(int runs) {
        this.runs = runs;
    }

    public void run() {
        System.out.println("start benchmarking [nuOfInstances=" + benchmarkInstances.size() + "][runsPerInstance="
                + runs + "]");
        double startTime = System.currentTimeMillis();
        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
        List<Future<BenchmarkResult>> futures = new ArrayList<Future<BenchmarkResult>>();
        for (final BenchmarkInstance p : benchmarkInstances) {

            Future<BenchmarkResult> futureResult = executor.submit(new Callable<BenchmarkResult>() {

                @Override
                public BenchmarkResult call() throws Exception {
                    return runAlgoAndGetResult(p);
                }

            });
            futures.add(futureResult);

        }
        try {
            int count = 1;
            for (Future<BenchmarkResult> f : futures) {
                BenchmarkResult r = f.get();
                print(r, count);
                results.add(f.get());
                count++;
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        executor.shutdown();
        print(results);
        System.out.println("done [time=" + (System.currentTimeMillis() - startTime) / 1000 + "sec]");
    }

    private BenchmarkResult runAlgoAndGetResult(BenchmarkInstance p) {
        double[] vehicles = new double[runs];
        double[] results = new double[runs];
        double[] times = new double[runs];

        for (int run = 0; run < runs; run++) {
            VehicleRoutingAlgorithm vra = createAlgorithm(p);
            StopWatch stopwatch = new StopWatch();
            vra.getAlgorithmListeners().addListener(stopwatch, Priority.HIGH);
            Collection<VehicleRoutingProblemSolution> solutions = vra.searchSolutions();
            VehicleRoutingProblemSolution best = Solutions.bestOf(solutions);
            vehicles[run] = best.getRoutes().size();
            results[run] = cost.getCost(best);
            times[run] = stopwatch.getCompTimeInSeconds();
        }

        return new BenchmarkResult(p, runs, results, times, vehicles);
    }

    private VehicleRoutingAlgorithm createAlgorithm(BenchmarkInstance p) {
        if (algorithmConfig != null) {
            return VehicleRoutingAlgorithms.readAndCreateAlgorithm(p.vrp, algorithmConfig);
        } else {
            return algorithmFactory.createAlgorithm(p.vrp);
        }

    }

    private void print(Collection<BenchmarkResult> results) {
        double sumTime = 0.0;
        double sumResult = 0.0;
        for (BenchmarkResult r : results) {
            sumTime += r.getTimesStats().getMean();
            sumResult += r.getResultStats().getMean();
            //         print(r);
        }
        System.out.println("[avgTime=" + round(sumTime / (double) results.size(), 2) + "][avgResult="
                + round(sumResult / (double) results.size(), 2) + "]");
        for (BenchmarkWriter writer : writers) {
            writer.write(results);
        }
    }

    private void print(BenchmarkResult r, int count) {
        Double avgDelta = null;
        Double bestDelta = null;
        Double worstDelta = null;
        if (r.instance.bestKnownResult != null) {
            avgDelta = (r.getResultStats().getMean() / r.instance.bestKnownResult - 1) * 100;
            bestDelta = (r.getResultStats().getMin() / r.instance.bestKnownResult - 1) * 100;
            worstDelta = (r.getResultStats().getMax() / r.instance.bestKnownResult - 1) * 100;
        }
        System.out.println("(" + count + "/" + benchmarkInstances.size() + ")" + "\t[instance=" + r.instance.name
                + "][avgTime=" + round(r.getTimesStats().getMean(), 2) + "]" + "[Result="
                + getString(r.getResultStats()) + "]" + "[Vehicles=" + getString(r.getVehicleStats()) + "]"
                + "[Delta[%]=" + getString(bestDelta, avgDelta, worstDelta) + "]");
    }

    private String getString(Double bestDelta, Double avgDelta, Double worstDelta) {
        return "[best=" + round(bestDelta, 2) + "][avg=" + round(avgDelta, 2) + "][worst=" + round(worstDelta, 2)
                + "]";
    }

    private String getString(DescriptiveStatistics stats) {
        return "[best=" + round(stats.getMin(), 2) + "][avg=" + round(stats.getMean(), 2) + "][worst="
                + round(stats.getMax(), 2) + "][stdDev=" + round(stats.getStandardDeviation(), 2) + "]";
    }

    private Double round(Double value, int i) {
        if (value == null)
            return null;
        long roundedVal = Math.round(value * Math.pow(10, i));
        return (double) roundedVal / (double) (Math.pow(10, i));
    }

}