cleaned up

This commit is contained in:
Helldragon67 2024-07-08 02:13:13 +02:00
parent 30ed2bb9ed
commit 4896e95617
2 changed files with 15 additions and 202 deletions

View File

@ -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,42 +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):
# 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):
@ -125,105 +93,6 @@ def is_connected(resx):
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) :
# 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()
# 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 :

View File

@ -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]:
@ -117,4 +76,3 @@ 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')