Permalink
Browse files

Performance: two new types of algorithms with different heuristics.

Timeout of 18 seconds by default
  • Loading branch information...
1 parent afd1e35 commit 2d3dd24511345ec1488ebfa58f1943bbd4722e67 @Delawen Delawen committed Apr 30, 2012
@@ -0,0 +1,100 @@
+package org.emergya.backtrackTSP;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Stack;
+import java.util.TreeMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.gofleet.openLS.tsp.TSPStop;
+import org.gofleet.openLS.tsp.TSPStopBag;
+
+class AStar implements Runnable {
+ private static Log LOG = LogFactory.getLog(AStar.class);
+
+ private DistanceMatrix distances;
+ private TSPStopBag bag;
+ private SolutionContainer best;
+ private TreeMap<Double, Stack<TSPStop>> openCandidates = new TreeMap<Double, Stack<TSPStop>>();
+ private List<TSPStop> stops = new ArrayList<TSPStop>();
+
+ public AStar(TSPStopBag _bag, DistanceMatrix distances,
+ SolutionContainer best) {
+ this.distances = distances;
+ this.bag = getBacktrackingBag(_bag);
+ this.best = best;
+ this.stops.addAll(_bag.getAll());
+ }
+
+ public void run() {
+ try {
+ Stack<TSPStop> stack = new Stack<TSPStop>();
+ stack.add(this.bag.getFirst());
+ openCandidates.put(-1d, stack);
+ BackTrackSolution solution = astar(this.distances,
+ new BackTrackSolution(new Stack<TSPStop>()));
+ best.add(solution);
+ } catch (Throwable t) {
+ LOG.error("Failure on astar procedure.", t);
+ }
+ }
+
+ private BackTrackSolution astar(DistanceMatrix distances,
+ BackTrackSolution partialSolution) {
+
+ Entry<Double, Stack<TSPStop>> candidate = openCandidates.firstEntry();
+
+ if (candidate == null)
+ return partialSolution;
+
+ openCandidates.remove(candidate.getKey());
+ BackTrackSolution current = new BackTrackSolution(candidate.getValue());
+
+ while (this.bag.size() != current.getStack().size()) {
+ Double distance = current.getDistance(distances);
+
+ List<TSPStop> candidates = new LinkedList<TSPStop>();
+ candidates.addAll(this.stops);
+ candidates.removeAll(current.getStack());
+
+ for (TSPStop stop : candidates) {
+ Stack<TSPStop> newstack = new Stack<TSPStop>();
+ newstack.addAll(current.getStack());
+
+ TSPStop end = this.bag.getLast();
+ TSPStop from = newstack.peek();
+
+ newstack.add(stop);
+ openCandidates.put(
+ (distance
+ + distances.distance((BacktrackStop) from,
+ (BacktrackStop) stop) + stop
+ .getPosition().distance(end.getPosition())),
+ newstack);
+
+ }
+ candidate = openCandidates.firstEntry();
+
+ if (candidate == null)
+ return partialSolution;
+
+ openCandidates.remove(candidate.getKey());
+ current = new BackTrackSolution(candidate.getValue());
+
+ }
+
+ return current;
+
+ }
+
+ private BacktrackStopBag getBacktrackingBag(TSPStopBag _bag) {
+ List<TSPStop> all = new LinkedList<TSPStop>();
+ all.addAll((Collection<? extends TSPStop>) _bag.getAll());
+ return new BacktrackStopBag(all, _bag.getFirst(), _bag.getLast());
+ }
+
+}
@@ -4,7 +4,7 @@
import org.gofleet.openLS.tsp.TSPStop;
-class BackTrackSolution {
+class BackTrackSolution implements Cloneable {
private Stack<TSPStop> res;
private Double cachedDistance;
@@ -44,14 +44,15 @@ public Double getDistance(DistanceMatrix distance) {
Double cost = 0d;
TSPStop last = null;
- for (TSPStop stop : this.res) {
- if (last != null) {
- cost += distance.distance((BacktrackStop) last,
- (BacktrackStop) stop);
+ synchronized (this.res) {
+ for (TSPStop stop : this.res) {
+ if (last != null) {
+ cost += distance.distance((BacktrackStop) last,
+ (BacktrackStop) stop);
+ }
+ last = stop;
}
- last = stop;
}
-
this.cachedDistance = cost;
return cost;
}
@@ -64,4 +65,9 @@ public String toString() {
s += "]";
return s;
}
+
+ @Override
+ protected Object clone() {
+ return new BackTrackSolution(this.res);
+ }
}
@@ -29,12 +29,10 @@
package org.emergya.backtrackTSP;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
@@ -47,7 +45,7 @@
private static Log LOG = LogFactory.getLog(BackTrackingTSP.class);
private Boolean partialSolution = false;
- private Integer seconds = 15;
+ private Integer seconds = 18;
public BackTrackingTSP() {
}
@@ -66,24 +64,48 @@ public BackTrackingTSP(Boolean partialSolution, Integer seconds) {
}
public List<TSPStop> order(TSPStopBag _bag) {
+ long time = System.currentTimeMillis();
DistanceMatrix distances = new DistanceMatrix();
initializeMatrix(distances, _bag);
Runtime runtime = Runtime.getRuntime();
- int numthreads = runtime.availableProcessors() * 3;
-
- ExecutorService executor = Executors.newFixedThreadPool(numthreads);
-
- List<BackTrackSolution> solutions = Collections
- .synchronizedList(new LinkedList<BackTrackSolution>());
-
- executor.execute(new Backtracking(_bag, distances, solutions));
+ int numthreads = runtime.availableProcessors() * 10;
+
+ final ExecutorService executor = Executors
+ .newFixedThreadPool(numthreads);
+
+ 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 {
- executor.awaitTermination(this.seconds, TimeUnit.SECONDS);
+ if (!executor.awaitTermination(
+ this.seconds - (System.currentTimeMillis() - time) / 1000,
+ TimeUnit.SECONDS))
+ executor.shutdownNow();
} catch (InterruptedException e) {
if (!this.partialSolution) {
throw new RuntimeException(
@@ -94,34 +116,36 @@ public BackTrackingTSP(Boolean partialSolution, Integer seconds) {
}
}
- if (solutions.size() > 0)
- return getBest(solutions, distances, _bag.size());
+ return getBest(solutions, distances, _bag.size());
+ }
- throw new RuntimeException(
- "Something went wrong. I couldn't find a solution."
- + "Have you tried giving me more time and "
- + "allowing me to produce partial solutions?");
+ private void run(final ExecutorService executor, final Runnable aStar) {
+ final FutureTask<Boolean> task = new FutureTask<Boolean>(aStar, true);
+ executor.execute(task);
+ Thread t = new Thread() {
+ @Override
+ public void run() {
+ try {
+ task.get(BackTrackingTSP.this.seconds, TimeUnit.SECONDS);
+ } catch (Throwable e) {
+ }
+ }
+
+ };
+ t.start();
}
- private List<TSPStop> getBest(List<BackTrackSolution> solutions,
+ private List<TSPStop> getBest(SolutionContainer solutions,
DistanceMatrix distances, Integer size) {
- List<TSPStop> res = null;
- Double cost = Double.MAX_VALUE;
+ BackTrackSolution solution = solutions.getSolution();
- for (BackTrackSolution sol : solutions) {
- if (sol.getDistance(distances) <= cost) {
- if (size == sol.getStack().size()) {
- cost = sol.getDistance(distances);
- res = sol.getStack();
- }
- }
- }
- if (res == null)
+ 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 res;
+
+ return solution.getStack();
}
@@ -131,26 +155,54 @@ public BackTrackingTSP(Boolean partialSolution, Integer seconds) {
* @param distances
* @param bag
*/
- @SuppressWarnings("unchecked")
private void initializeMatrix(DistanceMatrix distances, TSPStopBag bag) {
Runtime runtime = Runtime.getRuntime();
int numthreads = runtime.availableProcessors() * 3;
ExecutorService executor = Executors.newFixedThreadPool(numthreads);
- List<BacktrackStop> candidates = new ArrayList<BacktrackStop>();
- candidates.addAll((Collection<? extends BacktrackStop>) bag.getAll());
+ List<BacktrackStop> candidates = null;
+ candidates = new ArrayList<BacktrackStop>();
+ for (TSPStop stop : bag.getAll())
+ candidates.add((BacktrackStop) stop);
for (BacktrackStop from : candidates) {
executor.execute(new InitializeDistances(from, candidates,
distances));
}
executor.shutdown();
try {
- executor.awaitTermination(5, TimeUnit.SECONDS);
+ executor.awaitTermination(6, TimeUnit.SECONDS);
} catch (InterruptedException e) {
LOG.error(e, e);
}
}
}
+
+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;
+ }
+ }
+ }
+}
Oops, something went wrong.

0 comments on commit 2d3dd24

Please sign in to comment.