Permalink
Browse files

Preparing to paralelize

  • Loading branch information...
1 parent 9da9816 commit afd1e35ea913f487b95ee2305e10b68adb8028cf @Delawen Delawen committed Apr 30, 2012
@@ -30,9 +30,9 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
-import java.util.Stack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -46,44 +46,100 @@
public class BackTrackingTSP implements TSPAlgorithm {
private static Log LOG = LogFactory.getLog(BackTrackingTSP.class);
+ private Boolean partialSolution = false;
+ private Integer seconds = 15;
+
+ 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) {
+
DistanceMatrix distances = new DistanceMatrix();
- if (!(_bag instanceof BacktrackStopBag)) {
- List<TSPStop> all = new LinkedList<TSPStop>();
- all.addAll(_bag.getAll());
- _bag = new BacktrackStopBag(all, _bag.getFirst(), _bag.getLast());
- }
+ initializeMatrix(distances, _bag);
- BacktrackStopBag bag = (BacktrackStopBag) _bag;
- BackTrackSolution res = new BackTrackSolution(new Stack<TSPStop>());
+ Runtime runtime = Runtime.getRuntime();
+ int numthreads = runtime.availableProcessors() * 3;
- initializeMatrix(distances, bag);
+ ExecutorService executor = Executors.newFixedThreadPool(numthreads);
- if (bag.hasFirst()) {
- res.push(bag.getFirst());
- }
+ List<BackTrackSolution> solutions = Collections
+ .synchronizedList(new LinkedList<BackTrackSolution>());
- BackTrackSolution best = backtrack(res, bag, distances,
- new BackTrackSolution(new Stack<TSPStop>()));
+ executor.execute(new Backtracking(_bag, distances, solutions));
- if (best != null && best.getStack().size() == bag.size())
- return best.getStack();
+ executor.shutdown();
+ try {
+ executor.awaitTermination(this.seconds, TimeUnit.SECONDS);
+ } 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);
+ }
+ }
+
+ if (solutions.size() > 0)
+ return getBest(solutions, distances, _bag.size());
throw new RuntimeException(
- "I'm embarrased, I was unable to find a solution.");
+ "Something went wrong. I couldn't find a solution."
+ + "Have you tried giving me more time and "
+ + "allowing me to produce partial solutions?");
+ }
+
+ private List<TSPStop> getBest(List<BackTrackSolution> solutions,
+ DistanceMatrix distances, Integer size) {
+
+ List<TSPStop> res = null;
+ Double cost = Double.MAX_VALUE;
+
+ for (BackTrackSolution sol : solutions) {
+ if (sol.getDistance(distances) <= cost) {
+ if (size == sol.getStack().size()) {
+ cost = sol.getDistance(distances);
+ res = sol.getStack();
+ }
+ }
+ }
+ if (res == 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;
+
}
+ /**
+ * Initialices the distance matrix on background while tsp is running.
+ *
+ * @param distances
+ * @param bag
+ */
@SuppressWarnings("unchecked")
- private void initializeMatrix(DistanceMatrix distances, BacktrackStopBag bag) {
+ private void initializeMatrix(DistanceMatrix distances, TSPStopBag bag) {
+
+ Runtime runtime = Runtime.getRuntime();
+ int numthreads = runtime.availableProcessors() * 3;
- Runtime runtime = Runtime.getRuntime();
- int numthreads = runtime.availableProcessors() * 10;
-
ExecutorService executor = Executors.newFixedThreadPool(numthreads);
- List<BacktrackStop> candidates = new ArrayList<BacktrackStop>(
- bag.size());
+ List<BacktrackStop> candidates = new ArrayList<BacktrackStop>();
candidates.addAll((Collection<? extends BacktrackStop>) bag.getAll());
for (BacktrackStop from : candidates) {
@@ -92,58 +148,9 @@ private void initializeMatrix(DistanceMatrix distances, BacktrackStopBag bag) {
}
executor.shutdown();
try {
- executor.awaitTermination(10, TimeUnit.SECONDS);
+ executor.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
LOG.error(e, e);
}
-
}
-
- private BackTrackSolution backtrack(BackTrackSolution current,
- BacktrackStopBag bag, DistanceMatrix distances,
- BackTrackSolution best) {
-
- Collection<TSPStop> all = bag.getAll();
-
- final int size = all.size();
- if (size > 0) {
- List<TSPStop> candidates = new ArrayList<TSPStop>(size);
- candidates.addAll(all);
-
- for (TSPStop stop : candidates) {
- bag.removeStop(stop);
- current.push(stop);
-
- if (!(best != null && current.getDistance(distances) > best
- .getDistance(distances))) {
- backtrack(current, bag, distances, best);
- }
- if (LOG.isTraceEnabled())
- LOG.trace("Current: " + current);
-
- current.pop();
- bag.addStop(stop);
- }
- } else {
- if (bag.hasLast()) {
- current.push(bag.getLast());
-
- if (current.getDistance(distances) < best
- .getDistance(distances)) {
- best.setStack(current.getStack());
- }
-
- current.pop();
- } else {
- if (current.getDistance(distances) < best
- .getDistance(distances)) {
- best.setStack(current.getStack());
- }
- }
- }
-
- best.getDistance(distances);
- return best;
- }
-
}
@@ -41,7 +41,8 @@
private TSPStop first = null;
private TSPStop last = null;
- private List<TSPStop> bag = new ArrayList<TSPStop>();
+ private List<TSPStop> bag = Collections
+ .synchronizedList(new ArrayList<TSPStop>());
public TSPStop getFirst() {
return this.first;
@@ -74,32 +75,32 @@ public BacktrackStopBag(List<TSPStop> stops, TSPStop first, TSPStop last) {
this.last = last;
}
- public void removeStop(TSPStop stop){
+ public void removeStop(TSPStop stop) {
this.bag.remove(stop);
}
- public void addStop(TSPStop stop){
+ public void addStop(TSPStop stop) {
this.bag.add(stop);
}
- public int size() {
- int size = 0;
- if(this.hasFirst())
+ public Integer size() {
+ Integer size = 0;
+ if (this.hasFirst())
size++;
- if(this.hasLast())
+ if (this.hasLast())
size++;
return size + this.bag.size();
}
-
+
@Override
public String toString() {
String s = "{";
-
- for(TSPStop stop : this.bag)
+
+ for (TSPStop stop : this.bag)
s += stop.getPosition().toText() + " ";
-
+
s += "}";
-
+
return s;
}
}
@@ -0,0 +1,97 @@
+package org.emergya.backtrackTSP;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+
+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 Backtracking extends Thread {
+ private static Log LOG = LogFactory.getLog(Backtracking.class);
+
+ private BackTrackSolution current;
+ private BacktrackStopBag bag;
+ private DistanceMatrix distances;
+ private List<BackTrackSolution> best;
+
+ public Backtracking(TSPStopBag _bag, DistanceMatrix distances,
+ List<BackTrackSolution> best) {
+ this.current = initializeResBag(_bag);
+ this.bag = getBacktrackingBag(_bag);
+ this.distances = distances;
+ this.best = best;
+ }
+
+ @Override
+ public void run() {
+ BackTrackSolution solution = backtrack(this.current, this.bag,
+ this.distances, new BackTrackSolution(new Stack<TSPStop>()));
+ best.add(solution);
+ }
+
+ private BackTrackSolution backtrack(BackTrackSolution current,
+ BacktrackStopBag bag, DistanceMatrix distances,
+ BackTrackSolution best) {
+
+ Collection<TSPStop> all = bag.getAll();
+ if (all.size() > 0) {
+ List<TSPStop> candidates = null;
+ candidates = new ArrayList<TSPStop>();
+ candidates.addAll(all);
+ for (TSPStop stop : candidates) {
+ bag.removeStop(stop);
+ current.push(stop);
+
+ if (!(best != null && current.getDistance(distances) > best
+ .getDistance(distances))) {
+ backtrack(current, bag, distances, best);
+ }
+ if (LOG.isTraceEnabled())
+ LOG.trace("Current: " + current);
+
+ current.pop();
+ bag.addStop(stop);
+ }
+ } else {
+ if (bag.hasLast()) {
+ current.push(bag.getLast());
+
+ if (current.getDistance(distances) < best
+ .getDistance(distances)) {
+ best.setStack(current.getStack());
+ }
+
+ current.pop();
+ } else {
+ if (current.getDistance(distances) < best
+ .getDistance(distances)) {
+ best.setStack(current.getStack());
+ }
+ }
+ }
+
+ best.getDistance(distances);
+ return best;
+ }
+
+ private BackTrackSolution initializeResBag(TSPStopBag bag) {
+ BackTrackSolution res = new BackTrackSolution(new Stack<TSPStop>());
+
+ if (bag.hasFirst()) {
+ res.push(bag.getFirst());
+ }
+ return res;
+ }
+
+ private BacktrackStopBag getBacktrackingBag(TSPStopBag _bag) {
+ List<TSPStop> all = new LinkedList<TSPStop>();
+ all.addAll(_bag.getAll());
+ return new BacktrackStopBag(all, _bag.getFirst(), _bag.getLast());
+ }
+
+}
@@ -1,5 +1,4 @@
-
/**
* Copyright (C) 2012, Emergya (http://www.emergya.es)
*
@@ -73,4 +72,12 @@
*/
Boolean hasLast();
+ /**
+ * Returns the number of stops the solution has to have (which means, the
+ * total number of stops of this bag).
+ *
+ * @return
+ */
+ Integer size();
+
}

0 comments on commit afd1e35

Please sign in to comment.