diff --git a/ExampleGraph10x10.txt b/ExampleGraph10x10.txt new file mode 100644 index 0000000..2e89b51 --- /dev/null +++ b/ExampleGraph10x10.txt @@ -0,0 +1,14 @@ +example graph10x10 +Shortest path distance: 6586 +Shortest path: 1->10->7->6->5->3->9->8->4->2->1 +10 +-1 0 648 2625 549 2185 1898 1458 1752 1963 427 +-2 648 0 2363 481 2129 2030 1641 1594 1638 557 +-3 2625 2362 0 1965 669 1274 1541 920 744 2172 +-4 549 481 1965 0 1667 1605 1194 1132 1242 431 +-5 2185 2129 669 1667 0 621 906 541 643 1733 +-6 1898 2030 1274 1605 621 0 443 662 978 1482 +-7 1458 1641 1541 1194 906 443 0 754 1106 1074 +-8 1752 1594 920 1132 541 662 754 0 347 1293 +-9 1963 1638 744 1242 643 978 1106 347 0 1511 +-10 427 557 2172 431 1733 1482 1074 1293 1511 0 \ No newline at end of file diff --git a/ExampleGraph15x15.txt b/ExampleGraph15x15.txt new file mode 100644 index 0000000..eb154fc --- /dev/null +++ b/ExampleGraph15x15.txt @@ -0,0 +1,19 @@ +example graph15x15 +Shortest path distance: 9010 +Shortest path: 1->15->2->4->11->12->8->13->9->3->5->6->7->14->10->1 +15 +-1 0 648 2625 549 2185 1898 1458 1752 1963 427 1743 1817 1899 1060 1148 +-2 648 0 2363 481 2129 2030 1641 1594 1638 557 1214 1492 1710 1126 825 +-3 2625 2362 0 1965 669 1274 1541 920 744 2172 1623 875 720 1595 3085 +-4 549 481 1965 0 1667 1605 1194 1132 1242 431 963 1096 1280 664 1249 +-5 2185 2129 669 1667 0 621 906 541 643 1733 1504 733 459 1187 2880 +-6 1898 2030 1274 1605 621 0 443 662 978 1482 1669 925 839 1007 2855 +-7 1458 1641 1541 1194 906 443 0 754 1106 1074 1447 976 968 638 2477 +-8 1752 1594 920 1132 541 662 754 0 347 1293 1015 261 209 724 2319 +-9 1963 1638 744 1242 643 978 1106 347 0 1511 961 170 183 970 2361 +-10 427 557 2172 431 1733 1482 1074 1293 1511 0 1318 1363 1447 585 1378 +-11 1743 1214 1623 963 1504 1669 1447 1015 961 1318 0 813 1078 918 1571 +-12 1817 1492 875 1096 733 925 976 261 170 1363 813 0 271 826 2215 +-13 1899 1710 720 1280 459 839 968 209 183 1447 1078 271 0 882 2453 +-14 1060 1126 1595 664 1187 1007 638 724 970 585 918 826 882 0 1891 +-15 1148 825 3085 1249 2880 2855 2477 2319 2361 1378 1571 2215 2453 1891 0 diff --git a/ExampleGraph20x20.txt b/ExampleGraph20x20.txt new file mode 100644 index 0000000..234d2d4 --- /dev/null +++ b/ExampleGraph20x20.txt @@ -0,0 +1,24 @@ +example graph20x20 +Shortest path distance: 10162 +Shortest path: 9->19>8->13->16->20->3->5->6->7->18->14->10->1->4->2->17->15->11->12->9 +20 +-1 0 648 2625 549 2185 1898 1458 1752 1963 427 1743 1817 1899 1060 1148 2084 732 1095 1725 2524 +-2 648 0 2363 481 2129 2030 1641 1594 1638 557 1214 1492 1710 1126 825 1861 811 1195 1375 2262 +-3 2625 2362 0 1965 669 1274 1541 920 744 2172 1623 875 720 1595 3085 543 3113 1734 1111 103 +-4 549 481 1965 0 1667 1605 1194 1132 1242 431 963 1096 1280 664 1249 1464 1276 799 979 1866 +-5 2185 2129 669 1667 0 621 906 541 643 1733 1504 733 459 1187 2880 479 2791 1169 932 566 +-6 1898 2030 1274 1605 621 0 443 662 978 1482 1669 925 839 1007 2855 929 2541 843 1107 1172 +-7 1458 1641 1541 1194 906 443 0 754 1106 1074 1447 976 968 638 2477 1148 2132 435 1027 1442 +-8 1752 1594 920 1132 541 662 754 0 347 1293 1015 261 209 724 2319 389 2346 841 443 818 +-9 1963 1638 744 1242 643 978 1106 347 0 1511 961 170 183 970 2361 287 2389 1124 388 688 +-10 427 557 2172 431 1733 1482 1074 1293 1511 0 1318 1363 1447 585 1378 1631 1063 641 1275 2071 +-11 1743 1214 1623 963 1504 1669 1447 1015 961 1318 0 813 1078 918 1571 1182 1882 1147 582 1583 +-12 1817 1492 875 1096 733 925 976 261 170 1363 813 0 271 826 2215 373 2242 979 241 774 +-13 1899 1710 720 1280 459 839 968 209 183 1447 1078 271 0 882 2453 192 2408 1049 504 621 +-14 1060 1126 1595 664 1187 1007 638 724 970 585 918 826 882 0 1891 1066 1667 251 798 1495 +-15 1148 825 3085 1249 2880 2855 2477 2319 2361 1378 1571 2215 2453 1891 0 2583 559 2042 2108 2984 +-16 2084 1861 543 1464 479 929 1148 389 287 1631 1182 373 192 1066 2583 0 2612 1220 611 442 +-17 732 811 3113 1276 2791 2541 2132 2346 2389 1063 1882 2242 2408 1667 559 2612 0 1701 2125 3012 +-18 1095 1195 1734 799 1169 843 435 841 1124 641 1147 979 1049 251 2042 1220 1701 0 977 1634 +-19 1725 1375 1111 979 932 1107 1027 443 388 1275 582 241 504 798 2108 611 2125 977 0 1011 +-20 2524 2262 103 1866 566 1172 1442 818 688 2071 1583 774 621 1495 2984 442 3012 1634 1011 0 \ No newline at end of file diff --git a/ExampleGraph3x3.txt b/ExampleGraph3x3.txt new file mode 100644 index 0000000..43885ff --- /dev/null +++ b/ExampleGraph3x3.txt @@ -0,0 +1,7 @@ +example graph3x3 +Shortest path distance: 9 +Shortest path: 1->2->3->1 +3 +-1 0 1 2 +-2 6 0 3 +-3 5 4 0 diff --git a/ExampleGraph4x4.txt b/ExampleGraph4x4.txt new file mode 100644 index 0000000..69cbbe1 --- /dev/null +++ b/ExampleGraph4x4.txt @@ -0,0 +1,8 @@ +example graph4x4 +Shortest path distance: 21 +Shortest path: 1->3->4->2->1 +4 +-1 0 2 9 10 +-2 1 0 6 4 +-3 15 7 0 8 +-4 6 3 12 0 \ No newline at end of file diff --git a/ExampleGraph5x5-2.txt b/ExampleGraph5x5-2.txt new file mode 100644 index 0000000..e737bfb --- /dev/null +++ b/ExampleGraph5x5-2.txt @@ -0,0 +1,9 @@ +example graph5x5-2 +Shortest path distance: 29 +Shortest path: 1->3->5->4->2->1 +5 +-1 0 8 4 9 9 +-2 8 0 6 7 10 +-3 4 6 0 5 6 +-4 9 7 5 0 4 +-5 9 10 6 4 0 \ No newline at end of file diff --git a/ExampleGraph5x5.txt b/ExampleGraph5x5.txt new file mode 100644 index 0000000..d87a702 --- /dev/null +++ b/ExampleGraph5x5.txt @@ -0,0 +1,9 @@ +example graph5x5 +Shortest path distance: 9 +Shortest path: 1->3->4->5->2->1 +5 +-1 0 2 0 6 1 +-2 1 0 4 4 2 +-3 5 3 0 1 5 +-4 4 7 2 0 1 +-5 2 6 3 6 0 diff --git a/ExampleGraph6x6.txt b/ExampleGraph6x6.txt new file mode 100644 index 0000000..ab3efd0 --- /dev/null +++ b/ExampleGraph6x6.txt @@ -0,0 +1,10 @@ +example graph6x6 +Shortest path distance: 229 +Shortest path: 1->6->5->4->3->2->1 +6 +-1 0 36 32 54 20 40 +-2 36 0 22 58 54 67 +-3 32 22 0 36 42 71 +-4 54 58 36 0 50 92 +-5 20 54 42 50 0 45 +-6 40 67 71 92 45 0 \ No newline at end of file diff --git a/GraphSolutions.txt b/GraphSolutions.txt new file mode 100644 index 0000000..2a761e2 --- /dev/null +++ b/GraphSolutions.txt @@ -0,0 +1,26 @@ +3x3 + Shortest path distance: 9 + Shortest path: 1->2->3->1 + or + Shortest path distance: 9 + Shortest path: 1->3->2->1 +4x4 + Shortest path distance: 21 + Shortest path: 1->3->4->2->1 +5x5 + Shortest path distance: 9 + Shortest path: 1->3->4->5->2->1 +5x5-2 + Shortest path distance: 29 + Shortest path: 1->3->5->4->2->1 +6x6 + Shortest path distance: 229 + Shortest path: 1->6->5->4->3->2->1 +10x10 + Shortest path distance: 6586 + Shortest path: 1->10->7->6->5->3->9->8->4->2->1 + +15x15 + Shortest path distance: 9010 + Shortest path: 1->15->2->4->11->12->8->13->9->3->5->6->7->14->10->1 + diff --git a/HashTable.java b/HashTable.java new file mode 100644 index 0000000..fc39ffd --- /dev/null +++ b/HashTable.java @@ -0,0 +1,79 @@ +import java.util.Set; +public class HashTable{ + private class Node { + public Set data; + public int vertex; + public int minCost; + public Node next; + public Node(Set data, int vertex, int minCost) { + this.data = data; + this.vertex = vertex; + this.minCost = minCost; + this.next = null; + } + } + public HashTable(int size){ + list = new Node[size]; + for(int i = 0; i < list.length;i++){ + list[i] = null; + } + totalSize = 0; + } + private Node[] list; + public int totalSize; + private int hash(int vertex, Set data){ + if(data != null){ + return ((23 * vertex + (data.hashCode())) % list.length); + } + else{ + return vertex % list.length; + } + } + public void insert(Set input, int vertex, int minCost) { + Node temp = new Node(input,vertex,minCost); + int key = hash(vertex,input); + if(list[key] == null){ + list[key] = temp; + } + else{ + Node curr = list[key]; + while(curr.next != null){ + curr = curr.next; + } + curr.next = temp; + } + totalSize++; + } + public int get(Set set, int vertex){ + int key = hash(vertex,set); + Node curr = list[key]; + if(!set.containsAll(curr.data) || curr.vertex != vertex){ + while(curr.next != null){ + if(vertex == curr.vertex){ + if(set.containsAll(curr.data)){ + return curr.minCost; + } + } + curr = curr.next; + } + } + return curr.minCost; + } + public void print(){ + for(int i = 0; i < list.length;i++){ + Node curr = list[i]; + System.out.println("List[" + i + "]"); + while(curr != null){ + System.out.print("\tVertex: " + curr.vertex + " Data:"); + if(curr.data.isEmpty()){ + System.out.print("[0]"); + } + else{ + System.out.print(curr.data); + } + System.out.println("\t\tMin cost: " + curr.minCost); + curr = curr.next; + } + } + } +} \ No newline at end of file diff --git a/Held_Karp_Algorithm.java b/Held_Karp_Algorithm.java new file mode 100644 index 0000000..e42e50d --- /dev/null +++ b/Held_Karp_Algorithm.java @@ -0,0 +1,125 @@ +import java.util.HashSet; +import java.util.Set; + +public class Held_Karp_Algorithm { + private int[][] D; + private int numVertices = -1; + private HashTable minCostDP; + private HashTable parent; + private LinkedList sets; + public long run(int[][] data, int verticies) { + D = data; + numVertices = verticies; + sets = new LinkedList(); + createSets(); + int size = numVertices*numVertices; + minCostDP = new HashTable(size); + parent = new HashTable(size); + + long startTime = System.currentTimeMillis(); + int result = TSP(); + long time = System.currentTimeMillis()-startTime; + + printTour(); + System.out.println(", Distance: " + result); + return time; + } + private int TSP(){ + Node curr = sets.top; + while(curr != null){ + for(int i = 1; i < numVertices; i++) { + if(curr.set.contains(i)) { + continue; + } + int[] temp = loop(curr.set, Integer.MAX_VALUE, 0, i); + if(curr.set.isEmpty()) { + temp[0] = D[0][i]; + } + minCostDP.insert(curr.set, i, temp[0]); + parent.insert(curr.set, i, temp[1]); + } + curr = curr.next; + } + Set set = new HashSet<>(); + for(int i = 1; i < numVertices; i++) { + set.add(i); + } + int[] temp = loop(set, Integer.MAX_VALUE, -1, 0); + parent.insert(set, 0, temp[1]); + return temp[0]; + } + private int[] loop(Set set, int min, int minPos, int val){ + int[] results = new int[2]; + results[0] = min; + results[1] = minPos; + Set setCopy = deepCopy(set); //you get an error if you use the normal set + for(int k : set) { + int cost = D[k][val] + Cost(setCopy, k); + if(cost < results[0]) { + results[0] = cost; + results[1] = k; + } + } + return results; + } + private int Cost(Set set, int j) { + set.remove(j); + int cost = minCostDP.get(set, j); + set.add(j); + return cost; + } + private Set deepCopy(Set set){ + Set result = new HashSet<>(); + for(int i: set){ + result.add(i); + } + return result; + } + private void printTour() { + String order = ""; + Set set = new HashSet<>(); + for(int i = 0; i < numVertices; i++) { + set.add(i); + } + int start = 0; + while(!set.isEmpty()) { + order = (start + 1) + " -> " + order;// fix for 0 indexing + set.remove(start); + start = parent.get(set,start); + } + order = (0 + 1) + " -> " + order;// we start from vertex 0 + System.out.print("Shortest path: " + order.substring(0,order.length()-4)); + // -4 to remove the last " -> " + } + private void printSets(){ + Node top = sets.top; + while(top != null){ + if(top.set.isEmpty()){ + System.out.println("[0]"); + } + else{ + System.out.println(top.set); + } + top = top.next; + } + } + private void createSets() { + int result[] = new int[numVertices-1]; + generateCombination(0, 0, result); + } + private void generateCombination(int start, int end, int result[]) { + if(end != result.length) { + Set set = new HashSet<>(); + if(end > 0){ + for(int i = 0; i < end; i++) { + set.add(result[i]); + } + } + sets.addOrdered(set); + for(int i = start; i < result.length; i++) { + result[end] = i+1; + generateCombination(i+1, end+1, result); + } + } + } +} diff --git a/LinkedList.java b/LinkedList.java new file mode 100644 index 0000000..0609486 --- /dev/null +++ b/LinkedList.java @@ -0,0 +1,76 @@ +import java.util.Set; +public class LinkedList { + public Node top; + public int size = 0; + public LinkedList() { + top = null; + } + public LinkedList(Set set) { + top = new Node(set); + top.next = null; + } + public void addOrdered(Set set) { + Node newNode = new Node(set); + if(top == null){ + top = newNode; + top.next = null; + } + else{ + Node curr = top; + Node prev = curr; + boolean end = false; + + while(curr != null && !end){ + if(prev.set.size() == set.size() && curr.set.size() > set.size()){ + end = true; + } + else{ + prev = curr; + curr = curr.next; + } + } + if(end){ + prev.next = newNode; + newNode.next = curr; + } + else{ + if(curr != null){ + curr.next = newNode; + } + else{ + prev.next = newNode; + } + } + } + size++; + } + public boolean contains(Set set){ + boolean result = false; + if(!isEmpty()){ + Node start = top; + while(start.next != null){ + if(start.set.containsAll(set)){ + return true; + } + start = start.next; + } + } + return result; + } + + public boolean isEmpty(){ + return top == null; + } + public void remove(Set set){ + Node curr = top; + Node prev = curr; + while(curr != null & curr.set != set){ + prev = curr; + curr = curr.next; + } + if(curr.set == set){ + prev.next = curr.next; + } + size--; + } +} diff --git a/Main.java b/Main.java new file mode 100644 index 0000000..eab7fa2 --- /dev/null +++ b/Main.java @@ -0,0 +1,107 @@ + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Scanner; +import javax.swing.JFileChooser; +import java.nio.file.Paths; + +public class Main { + private static int[][] D; + private static int numVertices = -1; + public static void main(String[] args) { + processInput(); + printGraph(D); + long startTime1 = System.currentTimeMillis(); + System.out.println("Held_Karp_Algorithm:"); + Held_Karp_Algorithm HK = new Held_Karp_Algorithm(); + long t1 = HK.run(D, numVertices); + long time1 = System.currentTimeMillis()-startTime1; + time(time1, String.format("%35s", "Held_Karp_Algorithm Total ")); + time(t1, String.format("%35s", "Held_Karp_Algorithm Only Algorithm ")); + } + private static void time(long time, String msg){ + int secs = 0; + if(time >= 1000){ + secs = (int)(time/1000); + } + time = time-(secs*1000); + System.out.println(msg + "Time: " + secs + " Seconds, " + time + " Miliseconds"); + } + public static File getFile() { + String directory = Paths.get(".").toAbsolutePath().toString(); + JFileChooser chooser = new JFileChooser(directory); + File file = null; + int returnValue; + returnValue = chooser.showOpenDialog(null); + if (returnValue == JFileChooser.APPROVE_OPTION) { + file = chooser.getSelectedFile(); + } + return file; + } + public static void processInput(){ + File aFile = getFile(); + try { + Scanner fileReader = new Scanner(aFile); + String name = fileReader.nextLine(); + String shortestDist = fileReader.nextLine(); + String shorestPath = fileReader.nextLine(); + numVertices = Integer.parseInt(fileReader.nextLine()); + D = new int[numVertices][numVertices]; + System.out.println(name); + System.out.println(shortestDist); + System.out.println(shorestPath); + System.out.println("File contains " + numVertices + " vertices."); + String input = fileReader.nextLine(); + do{ + input = input.trim(); + String[] line = input.split("\\s+"); + int position = -Integer.parseInt(line[0])-1; + for(int i = 1; i < line.length;i++){ + int val = Integer.parseInt(line[i]); + D[position][i-1] = val; + } + input = fileReader.nextLine(); + }while(fileReader.hasNextLine()); + fileReader.close(); + input = input.trim(); + String[] line = input.split("\\s+"); + int position = -Integer.parseInt(line[0])-1; + for(int i = 1; i < line.length;i++){ + int val = Integer.parseInt(line[i]); + D[position][i-1] = val; + } + } + catch (FileNotFoundException e) { + System.out.println("Error: " + e); + } + } + private static void printGraph(int[][] graph){ + String[] lines = new String[numVertices]; + String startLine = String.format("%3s", "|"); + for(int i = 0; i < numVertices;i++){ + lines[i] = ""; + for(int j = 0; j < numVertices;j++){ + if(j > 0){ + lines[i] += " "; + } + lines[i] += String.format("%4d", (graph[i][j])); + } + startLine += String.format(" %4d", (i+1)); + } + String temp = ""; + for(int i = 0; i < startLine.length();i++){ + if(i == 2){ + temp += "|"; + } + else{ + temp += "-"; + } + } + System.out.println(startLine); + System.out.println(temp); + for(int i = 0; i < numVertices;i++){ + System.out.println(String.format("%2d| %s",(i+1), lines[i])); + } + System.out.println(); + } +} diff --git a/Node.java b/Node.java new file mode 100644 index 0000000..55cf733 --- /dev/null +++ b/Node.java @@ -0,0 +1,9 @@ +import java.util.Set; +public class Node { + public Node next; + public Set set; + public Node(Set set){ + this.set = set; + this.next = null; + } +}