**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.
-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/"
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__":
--- /dev/null
+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