]> Skullheadx's Git Forge - The-Traveling-Salesman-Problem.git/commitdiff
MST + One Tree bounds added
authorSkullheadx <94652084+Skullheadx@users.noreply.github.com>
Wed, 28 Dec 2022 06:34:36 +0000 (01:34 -0500)
committerSkullheadx <94652084+Skullheadx@users.noreply.github.com>
Wed, 28 Dec 2022 06:34:36 +0000 (01:34 -0500)
display.py
graph.py
main.py

index dbb42346c01b96f5838fb9b12ccde9f09f943c6b..afeeae0b147565638e848e6f871968d37be7f109 100644 (file)
@@ -1,6 +1,7 @@
 import pygame
 import math
 from graph import distance
+from queue import PriorityQueue
 
 pygame.init()
 
@@ -14,20 +15,24 @@ GREEN = (0, 255, 0)
 
 
 def find_MST(route: list) -> list:
-    visited = [route[0]]
-    unvisited = route[1:]
-    for i in range(len(route) - 1):
-        v1 = visited[i]
-        minimum = None
-        min_town = None
-        for v2 in unvisited:
-            d = distance(v1, v2)
-            if minimum is None or d <= minimum:
-                minimum = d
-                min_town = v2
-        visited.append(min_town)
-        unvisited.remove(min_town)
-    return visited
+    q = PriorityQueue()
+    head = route[0]
+    seen = set()
+    mst = []
+    for town in route:
+        q.put((distance(town, head), head, town))
+    while not q.empty():
+        d, start, end = q.get()
+        if end in seen:
+            continue
+        seen.add(end)
+
+        mst.append((start, end))
+
+        for town in route:
+            q.put((distance(town, end), end, town))
+
+    return mst
 
 
 def find_one_tree(route: list) -> list:
@@ -37,13 +42,10 @@ def find_one_tree(route: list) -> list:
     for town in route[1:-1]:
         distances.append((distance(removed_vertex, town), town))
     distances.sort()
-    mst.insert(0, removed_vertex)
-    mst.insert(0, distances[0][1])
-    mst.insert(0, removed_vertex)
-    mst.insert(0, distances[1][1])
-    mst.insert(0, removed_vertex)
+    mst.append((distances[0][1], removed_vertex))
+    mst.append((distances[1][1], removed_vertex))
 
-    return mst
+    return mst, removed_vertex
 
 
 class Node:
@@ -51,10 +53,10 @@ class Node:
     outline_colour = BLACK
     text_colour = WHITE
 
-    radius = 5
+    radius = 6
     thickness = 1
 
-    # font = pygame.font.SysFont("arial", 12)
+    # font = pygame.font.SysFont("arial", 20)
 
     def __init__(self, position: tuple, number: int) -> None:
         self.position = pygame.Vector2(position)
@@ -115,14 +117,14 @@ class Display:
                 contents = contents[:-1]
 
         self.WIDTH, self.HEIGHT, self.N = tuple(map(int, contents[0].split(" ")))
-        self.nodes = [Node(node, num) for num, node in enumerate(route)]
+        self.nodes = [Node(tuple(map(int, node.split(" "))), num) for num, node in enumerate(contents[1:])]
         self.screen = pygame.display.set_mode((self.WIDTH, self.HEIGHT))
 
         self.route = route
         self.salesman = Salesman(self.route)
 
-        self.mst = find_MST(route[:-1])
-        # self.ot = find_one_tree(route)
+        self.mst = find_MST(route[:-1])
+        self.ot,self.ot_removed_point = find_one_tree(route)
 
     def update(self, delta: float) -> None:
         self.salesman.update(delta)
@@ -141,14 +143,18 @@ class Display:
 
             self.screen.fill(WHITE)
 
+            pygame.draw.circle(self.screen,BLUE,self.ot_removed_point,15)
+
             if len(self.route) > 1:
-                # pygame.draw.lines(self.screen, GREEN, False, self.ot, 15)  # One Tree
-                # pygame.draw.lines(self.screen, RED, False, self.mst, 10)  # Minimum Spanning Tree
-                pygame.draw.lines(self.screen, BLUE, True, self.route, 3)  # Route
+                for line in self.ot:  # One Tree
+                    start, end = line
+                    pygame.draw.line(self.screen, GREEN, start, end, 12)
+                for line in self.mst:  # Minimum Spanning Tree
+                    start, end = line
+                    pygame.draw.line(self.screen, RED, start, end, 7)
+                pygame.draw.aalines(self.screen, BLUE, True, self.route)  # Route
             for node in self.nodes:
                 node.draw(self.screen)
-
             self.salesman.draw(self.screen)
-
             pygame.display.update()
             delta = clock.tick(60) / 1000  # Seconds
index 52423ccc80fe346f8bf8e957e03c6003c44cfdfa..b3cad99a8c8fb20f8fffe6efb6ec61c512501462 100644 (file)
--- a/graph.py
+++ b/graph.py
@@ -1,5 +1,6 @@
 import os
 import random
+from queue import PriorityQueue
 
 
 def prune_filename(filename: str) -> int:
@@ -50,7 +51,8 @@ def get_distances(graph: list) -> dict:
     for town1 in graph:
         distances[town1] = dict()
         for town2 in graph:
-            distances[town1][town2] = distance(town1, town2)
+            if town1 != town2:
+                distances[town1][town2] = distance(town1, town2)
     return distances
 
 
@@ -79,14 +81,14 @@ def find_shortest_route(routes: list) -> list:
 def print_info(route: list, time: float, method_name: str, mst: float, ot: float, r=0) -> None:
     print(
         f"""
-        Traveling Salesman Problem
-        Method Used: {method_name}
-        Time Used: {round(time, r):,} seconds
-        Number of Nodes: {(len(route) - 1):,}
-        Distance: {round(calculate_route(route), r):,}
-        Minimum Spanning Tree: {round(mst, r):,}
-        One Tree: {round(ot, r):,}
-        """)
+Traveling Salesman Problem
+Method Used: {method_name}
+Time Used: {round(time, r):,} seconds
+Number of Nodes: {(len(route) - 1):,}
+Distance: {round(calculate_route(route), r):,}
+Minimum Spanning Tree: {round(mst, r):,}
+One Tree: {round(ot, r):,}
+""")
 
 
 """
@@ -110,22 +112,19 @@ MST cost <= cost(T)
 
 def find_MST(graph: list) -> float:
     mst = 0.0
-    visited = [graph[0]]
-    unvisited = graph[1:]
-    for i in range(len(graph) - 1):
-        minimum = None
-        min_town1 = None
-        min_town2 = None
-        for v1 in visited:
-            for v2 in unvisited:
-                d = distance(v1, v2)
-                if minimum is None or d <= minimum:
-                    minimum = d
-                    min_town1 = v1
-                    min_town2 = v2
-        visited.append(min_town2)
-        unvisited.remove(min_town2)
-        mst += distance(min_town1, min_town2)
+    q = PriorityQueue()
+    head = graph[0]
+    seen = set()
+    for town in graph:
+        q.put((distance(town, head), head, town))
+    while not q.empty():
+        d, start, end = q.get()
+        if end in seen:
+            continue
+        seen.add(end)
+        mst += d
+        for town in graph:
+            q.put((distance(town, end), end, town))
     return mst
 
 
@@ -136,5 +135,4 @@ def find_one_tree(graph: list) -> float:
     for town in graph[1:]:
         distances.append(distance(removed_vertex, town))
     distances.sort()
-
     return mst + distances[1]
diff --git a/main.py b/main.py
index d20e379bf145ae3d82bd5d5d6a2b30e775468b40..eedd9ff8580c9f191c88b42ce9045b12569cad95 100644 (file)
--- a/main.py
+++ b/main.py
@@ -22,7 +22,7 @@ def main():
                     print("The file does not exist")
 
     if CREATE_NEW_GRAPHS:
-        graph, filename = create(GRAPH_PATH, 640, 640, 500)
+        graph, filename = create(GRAPH_PATH, 640, 640, 100)
     else:
         filename = "graph1.txt"
         graph = read(GRAPH_PATH, filename)
@@ -32,10 +32,10 @@ def main():
     route = nearest_neighbor(graph)  # 100 nodes in 0.5762094999663532 seconds. Distance = 6,270.568142156188
     time_end = perf_counter()
 
-    MST = find_MST(graph)
+    MST = find_MST(graph)
     ONE_TREE = find_one_tree(graph)
 
-    print_info(route, time_end - time_start, "NN Heuristic", 0.0, ONE_TREE, r=100)
+    print_info(route, time_end - time_start, "NN Heuristic", MST, ONE_TREE, r=100)
 
     display = Display(os.path.join(GRAPH_PATH, filename), route)
     display.show()