import pygame
import math
from graph import distance
+from queue import PriorityQueue
pygame.init()
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:
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:
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)
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)
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
import os
import random
+from queue import PriorityQueue
def prune_filename(filename: str) -> int:
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
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):,}
+""")
"""
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
for town in graph[1:]:
distances.append(distance(removed_vertex, town))
distances.sort()
-
return mst + distances[1]
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)
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()