diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..18d70f0
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..c9b5e0a
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ Dynamic_ACO_Example
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8000cd6
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/Testberlin52.tsp b/Testberlin52.tsp
new file mode 100644
index 0000000..7abb307
--- /dev/null
+++ b/Testberlin52.tsp
@@ -0,0 +1,20 @@
+NAME: berlin52
+TYPE: TSP
+COMMENT: 52 locations in Berlin (Groetschel)
+DIMENSION: 52
+EDGE_WEIGHT_TYPE: EUC_2D
+NODE_COORD_SECTION
+1 565.0 575.0
+2 25.0 185.0
+3 345.0 750.0
+4 945.0 685.0
+5 845.0 655.0
+6 880.0 660.0
+7 25.0 230.0
+8 525.0 1000.0
+9 580.0 1175.0
+10 650.0 1130.0
+11 1605.0 620.0
+12 1220.0 580.0
+EOF
+
diff --git a/berlin52.tsp b/berlin52.tsp
new file mode 100644
index 0000000..6f35791
--- /dev/null
+++ b/berlin52.tsp
@@ -0,0 +1,60 @@
+NAME: berlin52
+TYPE: TSP
+COMMENT: 52 locations in Berlin (Groetschel)
+DIMENSION: 52
+EDGE_WEIGHT_TYPE: EUC_2D
+NODE_COORD_SECTION
+1 565.0 575.0
+2 25.0 185.0
+3 345.0 750.0
+4 945.0 685.0
+5 845.0 655.0
+6 880.0 660.0
+7 25.0 230.0
+8 525.0 1000.0
+9 580.0 1175.0
+10 650.0 1130.0
+11 1605.0 620.0
+12 1220.0 580.0
+13 1465.0 200.0
+14 1530.0 5.0
+15 845.0 680.0
+16 725.0 370.0
+17 145.0 665.0
+18 415.0 635.0
+19 510.0 875.0
+20 560.0 365.0
+21 300.0 465.0
+22 520.0 585.0
+23 480.0 415.0
+24 835.0 625.0
+25 975.0 580.0
+26 1215.0 245.0
+27 1320.0 315.0
+28 1250.0 400.0
+29 660.0 180.0
+30 410.0 250.0
+31 420.0 555.0
+32 575.0 665.0
+33 1150.0 1160.0
+34 700.0 580.0
+35 685.0 595.0
+36 685.0 610.0
+37 770.0 610.0
+38 795.0 645.0
+39 720.0 635.0
+40 760.0 650.0
+41 475.0 960.0
+42 95.0 260.0
+43 875.0 920.0
+44 700.0 500.0
+45 555.0 815.0
+46 830.0 485.0
+47 1170.0 65.0
+48 830.0 610.0
+49 605.0 625.0
+50 595.0 360.0
+51 1340.0 725.0
+52 1740.0 245.0
+EOF
+
diff --git a/src/ACO.java b/src/ACO.java
new file mode 100644
index 0000000..be58cb4
--- /dev/null
+++ b/src/ACO.java
@@ -0,0 +1,261 @@
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class ACO {
+
+ private static final int MAX_ANTS = 2048 * 20;
+ private final String TSP_FILE;
+ private double[][] problem;
+ private double[][] pheromones;
+ private Random random;
+ private ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+
+ private LinkedBlockingQueue results;
+
+ public static final double PHEROMONE_PERSISTENCE = 0.3d; // between 0 and 1
+
+ // greedy
+ public static final double ALPHA = -0.2d;
+ // rapid selection
+ public static final double BETA = 9.6d;
+
+ public static final double Q = 0.0001d; // somewhere between 0 and 1
+
+ public ACO(String file) {
+ this.TSP_FILE = file;
+ this.random = new Random(System.currentTimeMillis());
+ this.results = new LinkedBlockingQueue();
+ }
+
+ private final double[][] readMatrixFromFile() throws IOException {
+
+ final BufferedReader br = new BufferedReader(new FileReader(new File(TSP_FILE)));
+
+ final ArrayList records = new ArrayList();
+
+ boolean readAhead = false;
+ String line;
+
+ // Read the TSP file containind coordinates and populate a List of Record object.
+ while ((line = br.readLine()) != null) {
+
+ if (line.equals("EOF")) {
+ break;
+ }
+
+ if (readAhead) {
+ String[] split = sweepNumbers(line.trim());
+ records.add(new Record(Double.parseDouble(split[1].trim()), Double.parseDouble(split[2].trim())));
+ }
+
+ if (line.equals("NODE_COORD_SECTION")) {
+ readAhead = true;
+ }
+ }
+
+ br.close();
+
+ // Create a matrix N x N; N is the size of the list that was populated.
+ final double[][] localMatrix = new double[records.size()][records.size()];
+ System.out.println(records.size());
+
+ int rIndex = 0;
+ // For each record populated in the matrix,
+ for (Record r : records) {
+ int hIndex = 0;
+ for (Record h : records) {
+ // Calculate the euclidian distance between them.
+ localMatrix[rIndex][hIndex] = calculateEuclidianDistance(r.x, r.y, h.x, h.y);
+ hIndex++;
+ }
+ rIndex++;
+ }
+ // The matrix with all the distances within it's vertices.
+ return localMatrix;
+ }
+
+ private final String[] sweepNumbers(String trim) {
+ String[] arr = new String[3];
+ int currentIndex = 0;
+ for (int i = 0; i < trim.length(); i++) {
+ final char c = trim.charAt(i);
+ if ((c) != 32) {
+ for (int f = i + 1; f < trim.length(); f++) {
+ final char x = trim.charAt(f);
+ if ((x) == 32) {
+ arr[currentIndex] = trim.substring(i, f);
+ currentIndex++;
+ break;
+ } else if (f == trim.length() - 1) {
+ arr[currentIndex] = trim.substring(i, trim.length());
+ break;
+ }
+ }
+ i = i + arr[currentIndex - 1].length();
+ }
+ }
+ return arr;
+ }
+
+ private final double calculateEuclidianDistance(double x1, double y1, double x2, double y2) {
+ // In mathematics, the Euclidean distance or Euclidean metric is the "ordinary" distance between two points in Euclidean space. With this distance, Euclidean space becomes a metric space. The
+ // associated norm is called the Euclidean norm. Older literature refers to the metric as Pythagorean metric.
+ // http://en.wikipedia.org/wiki/Euclidean_distance
+ final double xDiff = x2 - x1;
+ final double yDiff = y2 - y1;
+ return Math.abs((Math.sqrt((xDiff * xDiff) + (yDiff * yDiff))));
+ }
+
+ private final double[][] initializePheromones() {
+ double randValue = this.random.nextDouble();
+ final double[][] localMatrix = new double[problem.length][problem.length];
+
+ for (int i = 0; i < localMatrix.length; i++) {
+ for (int j = 0; j < localMatrix[i].length; j++) {
+ localMatrix[i][j] = randValue;
+ }
+ }
+
+ return localMatrix;
+ }
+
+ private AntResult bestResult(ArrayList list) {
+ AntResult ar, bestResult;
+ double bestDistance = Double.MAX_VALUE;
+ bestResult = null;
+
+ for (int i = 0; i < list.size(); i++) {
+ ar = list.get(i);
+ if (ar.getDistance() < bestDistance) {
+ bestResult = ar;
+ bestDistance = ar.getDistance();
+ }
+ }
+
+ return bestResult;
+ }
+
+ private void printBest(ArrayList list) {
+ AntResult best;
+
+ best = this.bestResult(list);
+
+ if (best != null)
+ System.out.printf("%s\n", best);
+ }
+
+ private void findBestWay() {
+
+ ArrayList partialResult = new ArrayList(ACO.MAX_ANTS);
+ for (int i = 0; i < ACO.MAX_ANTS; i++)
+ this.service.execute(new Ant(this, this.random.nextInt(this.problem.length)));
+
+ for (int i = 0, j = 0; i < ACO.MAX_ANTS; i++, j++) {
+ try {
+ AntResult ar = this.results.take();
+ partialResult.add(ar);
+
+ // Pretty cool
+ if (j % 10000 == 0){
+ this.printBest(partialResult);
+ }
+
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ System.out.printf("----Final Result----\n");
+ this.printBest(partialResult);
+ this.service.shutdown();
+ }
+
+ private final double calculatePheromones(double current, double newPheromone) {
+ final double result = (1 - ACO.PHEROMONE_PERSISTENCE) * current + newPheromone;
+ return result;
+ }
+
+ public synchronized void adjustPheromone(int x, int y, double newPheromone) {
+ final double result = calculatePheromones(this.pheromones[x][y], newPheromone);
+ if (result >= 0.0) {
+ this.pheromones[x][y] = result;
+ } else {
+ this.pheromones[x][y] = 0;
+ }
+ }
+
+ public synchronized double readPheromone(int x, int y) {
+ return pheromones[x][y];
+ }
+
+ public void start() throws IOException {
+ this.problem = this.readMatrixFromFile();
+ this.pheromones = this.initializePheromones();
+ this.findBestWay();
+
+ // Print the matrix with all the distance values.
+ for (int i = 0; i < problem.length; i++) {
+ for (int j = 0; j < problem[i].length; j++) {
+ System.out.printf("%g\t", problem[i][j]);
+ }
+ System.out.printf("\n");
+ }
+
+ }
+
+ public double[][] getProblem() {
+ return problem;
+ }
+
+ public LinkedBlockingQueue getResults() {
+ return results;
+ }
+
+}
+
+class AntResult {
+
+ private int[] way;
+ private double distance;
+
+ public AntResult(int[] w, double d) {
+ this.way = w;
+ this.distance = d;
+ }
+
+ public int[] getWay() {
+ return way;
+ }
+
+ public void setWay(int[] way) {
+ this.way = way;
+ }
+
+ public double getDistance() {
+ return distance;
+ }
+
+ public void setDistance(double distance) {
+ this.distance = distance;
+ }
+
+ public String toString() {
+ StringBuffer r = new StringBuffer("");
+
+ r.append("Distance:" + String.valueOf(distance) + "\nNodes:");
+
+ for (int i = 0; i < way.length; i++)
+ r.append(String.valueOf(way[i]) + "\t");
+
+ return r.toString();
+
+ }
+
+}
diff --git a/src/Ant.java b/src/Ant.java
new file mode 100644
index 0000000..c368d6f
--- /dev/null
+++ b/src/Ant.java
@@ -0,0 +1,113 @@
+import java.util.Random;
+
+public class Ant implements Runnable {
+
+ private ACO instance;
+ private boolean[] visited;
+ private int[] way;
+ private double distance;
+ private int start;
+ private int toVisit;
+
+ public Ant(ACO in, int start) {
+ this.instance = in;
+ this.visited = new boolean[in.getProblem().length];
+ this.way = new int[in.getProblem().length];
+ this.visited[start] = true;
+ this.distance = 0.0;
+ this.start = start;
+ this.toVisit = this.visited.length - 1;
+ }
+
+ private double invertDouble(double distance) {
+ if (distance == 0.0)
+ return 0.0;
+ else
+ return 1.0 / distance;
+ }
+
+ private int getNextNode(int lastNode) {
+
+ double columnSum = 0.0;
+ int danglingUnvisited = -1;
+ final double[] weights = new double[this.visited.length];
+
+ if (this.toVisit <= 0)
+ return -1;
+
+ for (int i = 0; i < this.visited.length; i++) {
+ columnSum += Math.pow(this.instance.readPheromone(lastNode, i),
+ ACO.ALPHA)
+ * Math.pow(this.invertDouble(this.instance.getProblem()[lastNode][i]),
+ ACO.BETA);
+ }
+
+ double sum = 0.0;
+
+ for (int x = 0; x < this.visited.length; x++) {
+ if (!this.visited[x]) {
+ weights[x] = calculateProbability(x, lastNode, columnSum);
+ sum += weights[x];
+ danglingUnvisited = x;
+ }
+ }
+
+ if (sum == 0.0d)
+ return danglingUnvisited;
+
+ // weighted indexing stuff
+ double pSum = 0.0;
+ for (int i = 0; i < this.visited.length; i++) {
+ pSum += weights[i] / sum;
+ weights[i] = pSum;
+ }
+
+ final double r = new Random(System.currentTimeMillis()).nextDouble();
+
+ for (int i = 0; i < this.visited.length; i++) {
+ if (!this.visited[i]) {
+ if (r <= weights[i]) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ private double calculateProbability(int row, int column, double sum) {
+ final double p = Math.pow(instance.readPheromone(column, row),
+ ACO.ALPHA)
+ * Math.pow(this.invertDouble(this.instance.getProblem()[column][row]),
+ ACO.BETA);
+ return p / sum;
+ }
+
+ @Override
+ public void run() {
+ int i, next, lastNode;
+
+ i = 0;
+ next = lastNode = start;
+
+ while((next = this.getNextNode(lastNode)) != -1) {
+ this.way[i++] = lastNode;
+ this.distance += this.instance.getProblem()[lastNode][next];
+ final double phero = (ACO.Q / (this.distance));
+ this.instance.adjustPheromone(lastNode, next, phero);
+ this.visited[next] = true;
+ lastNode = next;
+ this.toVisit--;
+ }
+
+ this.distance += this.instance.getProblem()[lastNode][this.start];
+ this.way[i] = lastNode;
+
+ try {
+ this.instance.getResults().put(new AntResult(this.way, this.distance));
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/Main.java b/src/Main.java
new file mode 100644
index 0000000..d5e65ee
--- /dev/null
+++ b/src/Main.java
@@ -0,0 +1,20 @@
+import java.io.IOException;
+
+
+public class Main {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+ ACO aco = new ACO("berlin52.tsp");
+ try {
+ aco.start();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/Record.java b/src/Record.java
new file mode 100644
index 0000000..e67c709
--- /dev/null
+++ b/src/Record.java
@@ -0,0 +1,10 @@
+class Record {
+ double x;
+ double y;
+
+ public Record(double x, double y) {
+ super();
+ this.x = x;
+ this.y = y;
+ }
+ }
\ No newline at end of file