diff --git a/TravellingSalesman.py b/TravellingSalesman.py index faf277b61b9c52aa387e249537813fd3fdd26a23..64bf2b852ef80def8237a1e0bb4b794409ff88e2 100644 --- a/TravellingSalesman.py +++ b/TravellingSalesman.py @@ -1,14 +1,21 @@ import matplotlib.pyplot as plt -from math import * +from math import sqrt from random import randint -from string import ascii_uppercase from itertools import permutations + # config: -brute_force = False -optimize = True +## use tsp01.data? +from_file = False +## number of nodes when false: num_nodes = 10 -do_plot = False -pause = 1 +## brute force or nearest neighbout? +brute_force = True +## apply 2-opt? +optimize = False +## plot better routes during calcutation +do_plot = True +## duration of pause between plots (for better visibility) +pause = 0 class Node: x: int @@ -21,39 +28,37 @@ class Node: def plot(this): plt.plot(this.x, this.y, 'ro', label=this.name) + + def __str__(self) -> str: + if self.name != "": + return "x: " + str(self.x) + "\ty: " + str(self.y) + "\tname: " + self.name + else: + return "x: " + str(self.x) + "\ty: " + str(self.y) def distance(A: Node, B: Node) -> float: return sqrt((A.x - B.x)**2 + (A.y - B.y)**2) -def total_distance(route: list) -> float: +def total_distance(route: list, circle: bool = False) -> float: total_distance = 0 for i in range(len(route)): if i == len(route)-1: - total_distance += distance(route[i], route[0]) + if circle: + total_distance += distance(route[i], route[0]) else: total_distance += distance(route[i], route[i+1]) return total_distance -class Path: - A: Node - B: Node - distance: float - def __init__(self, A: Node, B: Node): - self.A = A - self.B = B - #self.distance = distance(A, B) - - def plot(this): - plt.plot([this.A.x, this.B.x], [this.A.y, this.B.y], 'go-') - +def plot_path(A: Node, B: Node): + plt.plot([A.x, B.x], [A.y, B.y], 'go-') def plot_route(route: list, nodes: list = [], circle: bool = False) -> None: plt.close("all") for i in range(len(route)): - if i == len(route) - 1 and circle: - Path(A=route[i], B=route[0]).plot() + if i == len(route) - 1: + if circle: + plot_path(A=route[i], B=route[0]) else: - Path(A=route[i], B=route[i+1]).plot() + plot_path(A=route[i], B=route[i+1]) for node in nodes: node.plot() plt.show() @@ -64,18 +69,17 @@ def brute(nodes: list) -> list: if len(nodes) <= 1: return best_route = nodes - best_route_length = total_distance(nodes) + best_route_length = total_distance(nodes, circle=True) if do_plot: - plot_route(best_route) -#TODO Noch nicht rekursiv! + plot_route(best_route, circle=True) for i, route in enumerate(permutations(nodes, len(nodes))): - route_length = total_distance(route) + route_length = total_distance(route, circle=True) if route_length < best_route_length: best_route = route best_route_length = route_length print("Found shorter Route with length " + str(best_route_length) + " after " + str(i) + " iterations.") if do_plot: - plot_route(best_route) + plot_route(best_route, circle=True) print(str(i+1) + " iterations in total") return best_route @@ -110,29 +114,13 @@ def nearest_neighbour(_nodes: list) -> list: return route -def generate_paths(nodes: list) -> list: - _nodes = nodes.copy() - paths = [] - if _nodes.__len__() <= 1: - return [] - - this_node = _nodes[0] - _nodes.remove(_nodes[0]) - - for node in _nodes: - paths.append(Path(A=this_node, B=node)) - - if _nodes.__len__() >= 2: - paths = paths + generate_paths(_nodes) - - return paths - - #TODO Zuweisungen brechen die Kette! def optimize_2opt(_route: list) -> list: route = _route.copy() for i in range(len(route)-1): + print("My 2-opt is broken!") + print("TODO Zuweisungen brechen die Kette!") a = route[i] b = route[i+1] ab = distance(a, b) @@ -175,17 +163,24 @@ def optimize_2opt(_route: list) -> list: swapped = True if swapped: break - - return route - +def parse_data_file(path: str) -> list: + nodes = [] + with open(file=path, mode='r') as file: + for line in file: + coordinates = line.split('\t') + new_node = Node(x=float(coordinates[0]), y=float(coordinates[1])) + nodes.append(new_node) + return nodes if __name__ == "__main__": nodes = [] - for i in range(num_nodes): - nodes.append(Node(x=randint(0, 100), y=randint(0, 100), name=str(hex(i)))) - + if from_file: + nodes = parse_data_file("tsp01.data") + else: + for i in range(num_nodes): + nodes.append(Node(x=randint(0, 100), y=randint(0, 100), name=str(hex(i)))) plt.ion() diff --git a/tsp01.data b/tsp01.data new file mode 100644 index 0000000000000000000000000000000000000000..81262363c1d2c17acab5c4b09c2f732da834a09b --- /dev/null +++ b/tsp01.data @@ -0,0 +1,15 @@ +8.00 124.0 +125.0 80.0 +97.0 74.0 +69.0 96.0 +106.0 46.0 +49.0 57.0 +80.0 125.0 +42.0 93.0 +104.0 94.0 +35.0 17.0 +118.0 96.0 +151.0 22.0 +154.0 182.0 +57.0 165.0 +18.0 159.0 \ No newline at end of file