]> Skullheadx's Git Forge - The-Traveling-Salesman-Problem.git/commitdiff
Nearest Neighbor Heuristic added
authorSkullheadx <704277@pdsb.net>
Wed, 28 Dec 2022 02:07:30 +0000 (21:07 -0500)
committerSkullheadx <704277@pdsb.net>
Wed, 28 Dec 2022 02:07:30 +0000 (21:07 -0500)
README.md
main.py
nearest_neighbor.py [new file with mode: 0644]

index b1161992549eec5daa252fd1121c729d36176432..97d518fdb75411cc526c36b662580b306648f227 100644 (file)
--- a/README.md
+++ b/README.md
@@ -17,3 +17,8 @@ Assuming that:
 **Method 1: Brute Force**
 
 By checking every single possibility and calculating the distance of each route, the shortest path can be determined. As **n**, the number of towns, increases, on the first turn, (starting at any town) there are n-1 towns to choose from, then on the second turn there are n-2 choices and so on until there is only one option left which is to return to the starting town. This means that there are `(n - 1)! / 2` total possibilities accounting for duplicates. This strategy while easy to implement, is not suited to calculating more than 20 nodes as the number possibilities that would be considered at _n=20_ is `(20-1)!/2 = 60,822,550,204,416,000`. 
+
+--------------------------------------------------------------------------------------------------------------
+**Method 2: Nearest Neighbor (NN) Heuristic**
+
+If we start at any town and find the closest town that we haven't been to yet and continue this until all the cities have been visited, this creates a complete tour.
diff --git a/main.py b/main.py
index a8c1ebecfeb36f6306ad1094794bef09b60a0cf2..6959aa6d9961634208bfeb5e41d3303ecf1f3b62 100644 (file)
--- a/main.py
+++ b/main.py
@@ -1,6 +1,8 @@
-from graph import create
+from graph import create, print_info
 from display import Display
 from brute_force import brute_force
+from nearest_neighbor import nearest_neighbor
+from time import perf_counter
 import os
 
 GRAPH_PATH = "graphs/"
@@ -18,12 +20,17 @@ def main():
                 else:
                     print("The file does not exist")
 
-    graph, filename = create(GRAPH_PATH, 640, 640, 5)
-    display = Display(os.path.join(GRAPH_PATH, filename))
+    graph, filename = create(GRAPH_PATH, 720, 720, 100)
 
-    route = brute_force(graph)
+    time_start = perf_counter()
+    # route = brute_force(graph)  # 10 nodes in 85.042 seconds. Optimal = 2,262.29
+    route = nearest_neighbor(graph)  # 100 nodes in 0.5762094999663532 seconds. Distance = 6,270.568142156188
+    time_end = perf_counter()
 
-    display.show(route)
+    print_info(route, time_end - time_start, "NN Heuristic", r=100)
+
+    display = Display(os.path.join(GRAPH_PATH, filename), route)
+    display.show()
 
 
 if __name__ == "__main__":
diff --git a/nearest_neighbor.py b/nearest_neighbor.py
new file mode 100644 (file)
index 0000000..582a009
--- /dev/null
@@ -0,0 +1,33 @@
+from graph import distance, find_shortest_route
+
+
+def nearest_neighbor(graph: list) -> list:
+    routes = []
+    for start_index in range(len(graph)):
+        routes.append(NN(graph, start_index))
+
+    return find_shortest_route(routes)
+
+
+def NN(graph: list, start_index):
+    route = []
+    seen = set()
+    start = graph[start_index]
+    route.append(start)
+    seen.add(start)
+
+    for i in range(len(graph) - 1):
+        shortest_distance = None
+        next_town = None
+        for town in graph:
+            if town in seen:
+                continue
+            d = distance(route[-1], town)
+            if shortest_distance is None or d < shortest_distance:
+                shortest_distance = d
+                next_town = town
+        route.append(next_town)
+        seen.add(next_town)
+
+    route.append(start)
+    return route