From b847bf974aaacda4b718625a1055d7ccb42df917 Mon Sep 17 00:00:00 2001
From: tobiglaser <76131623+tobiglaser@users.noreply.github.com>
Date: Tue, 4 Apr 2023 22:54:52 +0200
Subject: [PATCH] travelling salesman finished, no 2-opt

---
 TravellingSalesman.py | 99 ++++++++++++++++++++-----------------------
 tsp01.data            | 15 +++++++
 2 files changed, 62 insertions(+), 52 deletions(-)
 create mode 100644 tsp01.data

diff --git a/TravellingSalesman.py b/TravellingSalesman.py
index faf277b..64bf2b8 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 0000000..8126236
--- /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
-- 
GitLab