From 4896e95617c65764dc88ae9eb15e74657ce9d704 Mon Sep 17 00:00:00 2001
From: Helldragon67 <kilian.scheidecker@orange.fr>
Date: Mon, 8 Jul 2024 02:13:13 +0200
Subject: [PATCH] cleaned up

---
 backend/src/optimizer_v4.py | 173 +++---------------------------------
 backend/src/tester.py       |  44 +--------
 2 files changed, 15 insertions(+), 202 deletions(-)

diff --git a/backend/src/optimizer_v4.py b/backend/src/optimizer_v4.py
index 15b31fd..d8edea6 100644
--- a/backend/src/optimizer_v4.py
+++ b/backend/src/optimizer_v4.py
@@ -55,6 +55,7 @@ def prevent_config(resx):
     return h, [len(vertices_visited)-1]
 
 
+# Prevents the creation of the same circle (both directions)
 def prevent_circle(circle_vertices: list, L: int) :
 
     l1 = [0]*L*L
@@ -73,138 +74,9 @@ def prevent_circle(circle_vertices: list, L: int) :
 
     return np.vstack((l1, l2)), [0, 0]
 
-# Prevent the possibility of a given solution bit
-def break_circle(circle_vertices: list, L: int, A_ub: list, b_ub: list):
 
-    if L-1 in circle_vertices :
-        circle_vertices.remove(L-1)
-
-    h = [0]*L*L
-    for i in range(L) :
-        if i in circle_vertices :
-            h[i*L:i*L+L] = [1]*L
-
-    A_ub = np.vstack((A_ub, h))
-    b_ub.append(len(circle_vertices)-1)
-
-    return A_ub, b_ub
-
-"""
-def break_circles(circle_edges_list: list, L: int, A_ub: list, b_ub: list):
-
-    for circle_edges in circle_edges_list :
-        if L-1 in circle_vertices :
-            circle_vertices.remove(L-1)
-
-        h = [0]*L*L
-        for i in range(L) :
-            if i in circle_vertices :
-                h[i*L:i*L+L] = [1]*L
-
-        A_ub = np.vstack((A_ub, h))
-        b_ub.append(len(circle_vertices)-1)
-
-    return A_ub, b_ub
-"""
-
-# Checks if the path is connected, returns a circle if it finds one and the RESULT
-def is_connected(resx):
-    
-    # first round the results to have only 0-1 values
-    for i, elem in enumerate(resx):
-        resx[i] = round(elem)
-    
-    N = len(resx)               # length of res
-    L = int(np.sqrt(N))         # number of landmarks. CAST INTO INT but should not be a problem because N = L**2 by def.
-    n_edges = resx.sum()        # number of edges
-
-    nonzeroind = np.nonzero(resx)[0] # the return is a little funny so I use the [0]
-
-    nonzero_tup = np.unravel_index(nonzeroind, (L,L))
-
-    ind_a = nonzero_tup[0].tolist()
-    ind_b = nonzero_tup[1].tolist()
-
-    edges = []
-    edges_visited = []
-    vertices_visited = []
-
-    for i, a in enumerate(ind_a) :
-        edges.append((a, ind_b[i]))      # Create the list of edges
-
-    edge1 = (ind_a[0], ind_b[0])
-    del ind_a[0]
-
-    edges_visited.append(edge1)
-    vertices_visited.append(edge1[0])
-
-    remaining = edges
-    remaining.remove(edge1)
-
-    break_flag = False
-    while len(remaining) > 0 and not break_flag:
-        for edge2 in remaining :
-            if edge2[0] == edge1[1] :
-                """if edge1[1] in vertices_visited :
-                    ind_b.remove(edge2[1])
-                    #edges_visited.append(edge2)
-                    break_flag = True
-                    break
-                else :   """ 
-                vertices_visited.append(edge1[1])
-                ind_a.remove(edge2[0])
-                ind_b.remove(edge2[0])
-                #edges_visited.append(edge2)
-                remaining.remove(edge2)
-                edge1 = edge2
-
-            elif edge1[1] == L-1 or edge1[1] in vertices_visited:
-                ind_b.remove(edge1[1])
-                break_flag = True
-                break
-
-    vertices_visited.append(edge1[1])
-
-    # Return order of visit if all good
-    if len(vertices_visited) == n_edges +1 :
-        return vertices_visited, []
-
-    """edge1 = (ind_a[0], ind_b[0])
-
-    vertices_visited.clear()
-    edges_visited.clear()
-
-    edges_visited.append(edge1)
-    vertices_visited.append(edge1[0])
-
-    remaining = edges
-    remaining.remove(edge1)
-
-    break_flag = False
-    while len(remaining) > 0 and not break_flag:
-        for edge2 in remaining :
-            if edge2[0] == edge1[1] :
-                # if edge1[1] in vertices_visited :
-                #     edges_visited.append(edge2)
-                #     break_flag = True
-                #     break
-                # else :   
-                vertices_visited.append(edge1[1])
-                edges_visited.append(edge2)
-                remaining.remove(edge2)
-                edge1 = edge2
-
-            elif edge1[1] == L-1 or edge1[1] in vertices_visited:
-                break_flag = True
-                break
-
-    vertices_visited.append(edge1[1])
-    """
-
-    return vertices_visited, edges_visited
-
-
-def is_connected2(resx) :
+# Returns the order of visit as well as any circles if there are some
+def is_connected(resx) :
 
     # first round the results to have only 0-1 values
     for i, elem in enumerate(resx):
@@ -221,9 +93,6 @@ def is_connected2(resx) :
     ind_a = nonzero_tup[0].tolist()
     ind_b = nonzero_tup[1].tolist()
 
-    # print(f"ind_a = {ind_a}")
-    # print(f"ind_b = {ind_b}")
-
     # Step 1: Create a graph representation
     graph = defaultdict(list)
     for a, b in zip(ind_a, ind_b):
@@ -232,7 +101,6 @@ def is_connected2(resx) :
     # Step 2: Function to perform BFS/DFS to extract journeys
     def get_journey(start):
         journey_nodes = []
-        #journey_edges = []
         visited = set()
         stack = deque([start])
 
@@ -242,26 +110,21 @@ def is_connected2(resx) :
                 visited.add(node)
                 journey_nodes.append(node)
                 for neighbor in graph[node]:
-                    #journey_edges.append((node, neighbor))
                     if neighbor not in visited:
                         stack.append(neighbor)
 
-        return journey_nodes#, journey_edges
+        return journey_nodes
 
     # Step 3: Extract all journeys
     all_journeys_nodes = []
-    #all_journeys_edges = []
     visited_nodes = set()
 
     for node in ind_a:
         if node not in visited_nodes:
             journey_nodes = get_journey(node)
             all_journeys_nodes.append(journey_nodes)
-            #all_journeys_edges.append(journey_edges)
             visited_nodes.update(journey_nodes)
 
-
-
     for l in all_journeys_nodes :
         if 0 in l :
             order = l
@@ -274,16 +137,13 @@ def is_connected2(resx) :
     return order, all_journeys_nodes
 
 
-
-
-# Function that returns the distance in meters from one location to another
+# Function that returns the time in minutes from one location to another
 def get_time(p1: Tuple[float, float], p2: Tuple[float, float], detour: float, speed: float) :
     
     # Compute the straight-line distance in km
     if p1 == p2 :
         return 0
     else: 
-        #dist = 6371.01 * acos(sin(radians(p1[0]))*sin(radians(p2[0])) + cos(radians(p1[0]))*cos(radians(p2[0]))*cos(radians(p1[1]) - radians(p2[1])))
         dist = geodesic(p1, p2).kilometers
 
     # Consider the detour factor for average cityto deterline walking distance (in km)
@@ -292,12 +152,6 @@ def get_time(p1: Tuple[float, float], p2: Tuple[float, float], detour: float, sp
     # Time to walk this distance (in minutes)
     walk_time = walk_dist/speed*60
 
-    """if walk_time > 15 :
-        walk_time = 5*round(walk_time/5)
-    else :
-        walk_time = round(walk_time)"""
-  
-
     return round(walk_time)
 
 
@@ -394,8 +248,8 @@ def init_eq_not_stay(L: int):
     return [l], [0]
 
 
-# Go through the landmarks and force the optimizer to use landmarks where attractiveness is set to -1
-def respect_user_mustsee(landmarks: List[Landmark]) :
+# Go through the landmarks and force the optimizer to use landmarks marked as must_do
+def respect_user_must_do(landmarks: List[Landmark]) :
     L = len(landmarks)
 
     A = [0]*L*L
@@ -482,6 +336,7 @@ def link_list(order: List[int], landmarks: List[Landmark])->List[Landmark] :
     return L, total_dist
 
 
+# Same as link_list but does it on a already ordered list
 def link_list_simple(ordered_visit: List[Landmark])-> List[Landmark] :
     
     # Read the parameters from the file
@@ -528,7 +383,7 @@ def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_deta
 
     # SET CONSTRAINTS FOR EQUALITY
     A_eq, b_eq = init_eq_not_stay(L)                            # Force solution not to stay in same place
-    A, b = respect_user_mustsee(landmarks)                      # Check if there are user_defined must_see. Also takes care of start/goal
+    A, b = respect_user_must_do(landmarks)                      # Check if there are user_defined must_see. Also takes care of start/goal
     A_eq = np.vstack((A_eq, A))
     b_eq += b
     A, b = respect_start_finish(L)                  # Force start and finish positions
@@ -550,8 +405,8 @@ def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_deta
 
     # If there is a solution, we're good to go, just check for connectiveness
     else :
-        order, circles = is_connected2(res.x)
-        #nodes, edges = is_connected2(res.x)
+        order, circles = is_connected(res.x)
+        #nodes, edges = is_connected(res.x)
         i = 0
         timeout = 80
         while circles is not None and i < timeout:
@@ -564,8 +419,8 @@ def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_deta
                 A_eq = np.vstack((A_eq, A))
                 b_eq += b
             res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq = b_eq, bounds=x_bounds, method='highs', integrality=3)
-            order, circles = is_connected2(res.x)
-            #nodes, edges = is_connected2(res.x)
+            order, circles = is_connected(res.x)
+            #nodes, edges = is_connected(res.x)
             if circles is None :
                 break
             print(i)
@@ -575,7 +430,7 @@ def solve_optimization (landmarks :List[Landmark], max_steps: int, printing_deta
             raise TimeoutError(f"Optimization took too long. No solution found after {timeout} iterations.")
 
         # Add the times to reach and stop optimizing
-        L, total_dist = link_list(order, landmarks)
+        L, _ = link_list(order, landmarks)
             
         if printing_details is True :
             if i != 0 :
diff --git a/backend/src/tester.py b/backend/src/tester.py
index 0ad97c7..1b00985 100644
--- a/backend/src/tester.py
+++ b/backend/src/tester.py
@@ -1,6 +1,4 @@
 import pandas as pd
-import os
-import json
 
 from typing import List
 from landmarks_manager import generate_landmarks
@@ -25,45 +23,6 @@ def write_data(L: List[Landmark], file_name: str):
 
     data.to_json(file_name, indent = 2, force_ascii=False)
 
-def test3(city_country: str) -> List[Landmark]:
-
-
-    preferences = Preferences(
-                    sightseeing=Preference(
-                                  name='sightseeing', 
-                                  type=LandmarkType(landmark_type='sightseeing'),
-                                  score = 5),
-                    nature=Preference(
-                                  name='nature', 
-                                  type=LandmarkType(landmark_type='nature'),
-                                  score = 0),
-                    shopping=Preference(
-                                  name='shopping', 
-                                  type=LandmarkType(landmark_type='shopping'),
-                                  score = 5))
-
-    coordinates = None
-
-    landmarks, landmarks_short = generate_landmarks(preferences=preferences, city_country=city_country, coordinates=coordinates)
-
-    #write_data(landmarks)
-
-    start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.2044576, 16.3870242), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
-    finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.2044576, 16.3870242), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
-    
-
-    test = landmarks_short
-    
-    test.insert(0, start)
-    test.append(finish)
-
-    max_walking_time = 2 # hours
-
-    visiting_list = solve_optimization(test, max_walking_time*60, True)
-
-
-    
-
 
 def test4(coordinates: tuple[float, float]) -> List[Landmark]:
 
@@ -116,5 +75,4 @@ def test4(coordinates: tuple[float, float]) -> List[Landmark]:
 test4(tuple((48.8344400, 2.3220540)))       # Café Chez César 
 #test4(tuple((48.8375946, 2.2949904)))       # Point random
 #test4(tuple((47.377859, 8.540585)))         # Zurich HB
-#test4(tuple((45.7576485, 4.8330241)))      # Lyon Bellecour
-#test3('Vienna, Austria')
\ No newline at end of file
+#test4(tuple((45.7576485, 4.8330241)))      # Lyon Bellecour
\ No newline at end of file