org.emergya.backtrackTSP.BackTrackingTSP.java Source code

Java tutorial

Introduction

Here is the source code for org.emergya.backtrackTSP.BackTrackingTSP.java

Source

/**
 * Copyright (C) 2012, Emergya (http://www.emergya.es)
 * 
 * @author <a href="mailto:marias@emergya.com">Mara Arias de Reyna</a>
 * 
 *         This file is part of GoFleet
 * 
 *         This software is free software; you can redistribute it and/or modify
 *         it under the terms of the GNU General Public License as published by
 *         the Free Software Foundation; either version 2 of the License, or (at
 *         your option) any later version.
 * 
 *         This software 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
 *         General Public License for more details.
 * 
 *         You should have received a copy of the GNU General Public License
 *         along with this library; if not, write to the Free Software
 *         Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 *         02110-1301 USA
 * 
 *         As a special exception, if you link this library with other files to
 *         produce an executable, this library does not by itself cause the
 *         resulting executable to be covered by the GNU General Public License.
 *         This exception does not however invalidate any other reasons why the
 *         executable file might be covered by the GNU General Public License.
 */
package org.emergya.backtrackTSP;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.gofleet.openLS.tsp.TSPAlgorithm;
import org.gofleet.openLS.tsp.TSPStop;
import org.gofleet.openLS.tsp.TSPStopBag;

public class BackTrackingTSP implements TSPAlgorithm {
    private static Log LOG = LogFactory.getLog(BackTrackingTSP.class);

    private Boolean partialSolution = false;
    private Integer seconds = 18;

    private ExecutorService executor;
    private ExecutorService executor2;

    public BackTrackingTSP() {
    }

    /**
     * If we cannot find a solution, do you like to get the best partial
     * solution reached?
     * 
     * @param partialSolution
     */
    public BackTrackingTSP(Boolean partialSolution, Integer seconds) {
        this();
        if (partialSolution != null)
            this.partialSolution = partialSolution;
        this.seconds = seconds;
    }

    public List<TSPStop> order(TSPStopBag _bag) {
        long time = System.currentTimeMillis();

        Runtime runtime = Runtime.getRuntime();
        int numthreads = runtime.availableProcessors() * 10;

        executor = Executors.newFixedThreadPool(numthreads);

        DistanceMatrix distances = new DistanceMatrix();

        initializeMatrix(distances, _bag);

        SolutionContainer solutions = new SolutionContainer(distances);

        if (_bag.size() > 7) {
            if (_bag.hasLast()) {
                // run(executor, new AStar(_bag, distances, solutions));
                run(executor, new HeuristicBacktracking(_bag, distances, solutions));
            } else {
                for (TSPStop stop : _bag.getAll()) {
                    List<TSPStop> stops = new ArrayList<TSPStop>();
                    stops.addAll(_bag.getAll());
                    stops.remove(stop);

                    BacktrackStopBag bag = new BacktrackStopBag(stops, _bag.getFirst(), stop);
                    // run(executor, new AStar(bag, distances, solutions));
                    run(executor, new HeuristicBacktracking(bag, distances, solutions));
                }
            }
        }
        run(executor, new Backtracking(_bag, distances, solutions));

        executor.shutdown();

        try {
            if (!executor.awaitTermination(this.seconds - (System.currentTimeMillis() - time) / 1000,
                    TimeUnit.SECONDS)) {
                stop();
            }
        } catch (InterruptedException e) {
            if (!this.partialSolution) {
                throw new RuntimeException("Timeout reached. I couldn't find a solution on a proper time. "
                        + "Please, give me another chance with more time or"
                        + " accept a partial solution. I won't fail you, I promise.", e);
            }
        }

        return getBest(solutions, distances, _bag.size());
    }

    private void run(final ExecutorService executor, final Runnable aStar) {
        executor.execute(aStar);
    }

    private List<TSPStop> getBest(SolutionContainer solutions, DistanceMatrix distances, Integer size) {

        BackTrackSolution solution = solutions.getSolution();

        if (solution == null)
            throw new RuntimeException("I'm embarrased, I was unable to find a solution for you. "
                    + "Please, forgive me. I am just a machine.");

        return solution.getStack();

    }

    /**
     * Initialices the distance matrix on background while tsp is running.
     * 
     * @param distances
     * @param bag
     */
    private void initializeMatrix(DistanceMatrix distances, TSPStopBag bag) {

        Runtime runtime = Runtime.getRuntime();
        int numthreads = runtime.availableProcessors() * 3;

        executor2 = Executors.newFixedThreadPool(numthreads);

        List<BacktrackStop> candidates = null;
        candidates = new ArrayList<BacktrackStop>();
        for (TSPStop stop : bag.getAll())
            candidates.add((BacktrackStop) stop);

        for (BacktrackStop from : candidates) {
            executor2.execute(new InitializeDistances(from, candidates, distances));
        }
        executor2.shutdown();
        Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    executor2.awaitTermination(6, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    LOG.error(e, e);
                }
            }
        };
        t.start();
    }

    @Override
    public boolean stop() {
        LOG.info("Shutting down backtracking");

        if (executor2 != null)
            executor2.shutdownNow();
        if (executor != null)
            executor.shutdownNow();
        else
            return false;

        LOG.info("Backtracking shut down");

        return true;
    }
}

class SolutionContainer {
    private BackTrackSolution solution = null;
    private DistanceMatrix distances = null;

    public SolutionContainer(DistanceMatrix distances) {
        this.distances = distances;
    }

    public BackTrackSolution getSolution() {
        synchronized (this) {
            return this.solution;
        }
    }

    public void add(BackTrackSolution solution) {
        synchronized (this) {
            if (this.solution == null)
                this.solution = solution;
            else {
                if (this.solution.getDistance(distances) > solution.getDistance(distances))
                    this.solution = solution;
            }
        }
    }
}