From 728b954643af33eee4842d551fba2d6d78a755f2 Mon Sep 17 00:00:00 2001 From: Helldragon67 Date: Wed, 28 Aug 2024 18:08:09 +0200 Subject: [PATCH 1/7] added image and website urls --- backend/src/structs/landmark.py | 3 +++ backend/src/utils/landmarks_manager.py | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/backend/src/structs/landmark.py b/backend/src/structs/landmark.py index 2f22d42..7e0cc97 100644 --- a/backend/src/structs/landmark.py +++ b/backend/src/structs/landmark.py @@ -15,8 +15,11 @@ class Landmark(BaseModel) : attractiveness : int n_tags : int image_url : Optional[str] = None # TODO future + website_url : Optional[str] = None + wikipedia_url : Optional[str] = None description : Optional[str] = None # TODO future duration : Optional[int] = 0 # TODO future + name_en : Optional[str] = None # Unique ID of a given landmark uuid: str = Field(default_factory=uuid4) # TODO implement this ASAP diff --git a/backend/src/utils/landmarks_manager.py b/backend/src/utils/landmarks_manager.py index 5f5e82e..db300f7 100644 --- a/backend/src/utils/landmarks_manager.py +++ b/backend/src/utils/landmarks_manager.py @@ -290,7 +290,10 @@ class LandmarkManager: elem_type = landmarktype # Add the landmark type as 'sightseeing, n_tags = len(elem.tags().keys()) # Add number of tags score = n_tags**self.tag_exponent # Add score - + website_url = None + wikpedia_url = None + image_url = None + name_en = None # remove specific tags skip = False @@ -304,7 +307,7 @@ class LandmarkManager: if "wiki" in tag: score += self.wikipedia_bonus # wikipedia entries count more - + # if tag == "wikidata": # Q = elem.tag('wikidata') # site = Site("wikidata", "wikidata") @@ -331,6 +334,18 @@ class LandmarkManager: if tag == "building" and elem.tag('building') in ['retail', 'supermarket', 'parking']: skip = True break + + + # Get additional information + # if tag == 'wikipedia' : + # wikpedia_url = elem.tag('wikipedia') + if tag in ['website', 'contact:website'] : + website_url = elem.tag(tag) + if tag == 'image' : + image_url = elem.tag('image') + if tag =='name:en' : + name_en = elem.tag('name:en') + if skip: continue @@ -356,7 +371,11 @@ class LandmarkManager: attractiveness=score, must_do=False, n_tags=int(n_tags), - duration = duration + duration = duration, + name_en=name_en, + image_url=image_url, + # wikipedia_url=wikpedia_url, + website_url=website_url ) return_list.append(landmark) From 20f20da9c5dd646370c1bef234ba3dfb87ae12dd Mon Sep 17 00:00:00 2001 From: Kilian PC Date: Tue, 10 Sep 2024 10:16:01 +0200 Subject: [PATCH 2/7] fixed int score --- backend/src/utils/landmarks_manager.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/utils/landmarks_manager.py b/backend/src/utils/landmarks_manager.py index db300f7..d914c74 100644 --- a/backend/src/utils/landmarks_manager.py +++ b/backend/src/utils/landmarks_manager.py @@ -81,19 +81,19 @@ class LandmarkManager: bbox = self.create_bbox(center_coordinates, reachable_bbox_side) # list for sightseeing if preferences.sightseeing.score != 0: - score_function = lambda score: int(score*10)*preferences.sightseeing.score/5 # self.count_elements_close_to(loc) + + score_function = lambda score: int(score*10*preferences.sightseeing.score/5) # self.count_elements_close_to(loc) + L1 = self.fetch_landmarks(bbox, self.amenity_selectors['sightseeing'], preferences.sightseeing.type, score_function) L += L1 # list for nature if preferences.nature.score != 0: - score_function = lambda score: int(score*10*self.nature_coeff)*preferences.nature.score/5 # self.count_elements_close_to(loc) + + score_function = lambda score: int(score*10*self.nature_coeff*preferences.nature.score/5) # self.count_elements_close_to(loc) + L2 = self.fetch_landmarks(bbox, self.amenity_selectors['nature'], preferences.nature.type, score_function) L += L2 # list for shopping if preferences.shopping.score != 0: - score_function = lambda score: int(score*10)*preferences.shopping.score/5 # self.count_elements_close_to(loc) + + score_function = lambda score: int(score*10*preferences.shopping.score/5) # self.count_elements_close_to(loc) + L3 = self.fetch_landmarks(bbox, self.amenity_selectors['shopping'], preferences.shopping.type, score_function) L += L3 From 3475990e5fc3db9317f676e0dbe510784b8b56c3 Mon Sep 17 00:00:00 2001 From: Helldragon67 Date: Tue, 10 Sep 2024 16:50:12 +0200 Subject: [PATCH 3/7] fixed timing and optimizer speed --- backend/src/parameters/landmark_parameters.yaml | 2 +- backend/src/parameters/optimizer_parameters.yaml | 2 +- backend/src/tester.py | 10 +++++----- backend/src/utils/landmarks_manager.py | 6 +++--- backend/src/utils/optimizer.py | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/src/parameters/landmark_parameters.yaml b/backend/src/parameters/landmark_parameters.yaml index 983b9c8..aa68e2f 100644 --- a/backend/src/parameters/landmark_parameters.yaml +++ b/backend/src/parameters/landmark_parameters.yaml @@ -7,5 +7,5 @@ tag_exponent: 1.15 image_bonus: 10 viewpoint_bonus: 15 wikipedia_bonus: 6 -N_important: 50 +N_important: 40 pay_bonus: -1 diff --git a/backend/src/parameters/optimizer_parameters.yaml b/backend/src/parameters/optimizer_parameters.yaml index 6dc49d2..77efa02 100644 --- a/backend/src/parameters/optimizer_parameters.yaml +++ b/backend/src/parameters/optimizer_parameters.yaml @@ -1,5 +1,5 @@ detour_factor: 1.4 -detour_corridor_width: 200 +detour_corridor_width: 300 average_walking_speed: 4.8 max_landmarks: 10 max_landmarks_refiner: 20 diff --git a/backend/src/tester.py b/backend/src/tester.py index acfec75..cc4118c 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -24,8 +24,8 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = nature=Preference(type='nature', score = 5), shopping=Preference(type='shopping', score = 5), - max_time_minute=1000, - detour_tolerance_minute=0 + max_time_minute=120, + detour_tolerance_minute=10 ) # Create start and finish @@ -70,9 +70,9 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = return linked_tour -test(tuple((48.8344400, 2.3220540))) # Café Chez César +# test(tuple((48.8344400, 2.3220540))) # Café Chez César # test(tuple((48.8375946, 2.2949904))) # Point random -# test(tuple((47.377859, 8.540585))) # Zurich HB -# test(tuple((45.7576485, 4.8330241))) # Lyon Bellecour +test(tuple((47.377859, 8.540585))) # Zurich HB +# test(tuple((45.758217, 4.831814))) # Lyon Bellecour # test(tuple((48.5848435, 7.7332974))) # Strasbourg Gare # test(tuple((48.2067858, 16.3692340))) # Vienne diff --git a/backend/src/utils/landmarks_manager.py b/backend/src/utils/landmarks_manager.py index d914c74..6e81237 100644 --- a/backend/src/utils/landmarks_manager.py +++ b/backend/src/utils/landmarks_manager.py @@ -318,6 +318,7 @@ class LandmarkManager: if "viewpoint" in tag: score += self.viewpoint_bonus + duration = 10 if "image" in tag: score += self.image_bonus @@ -334,7 +335,6 @@ class LandmarkManager: if tag == "building" and elem.tag('building') in ['retail', 'supermarket', 'parking']: skip = True break - # Get additional information # if tag == 'wikipedia' : @@ -352,14 +352,14 @@ class LandmarkManager: score = score_function(score) if "place_of_worship" in elem.tags().values() : score = int(score*self.church_coeff) - duration = 20 + duration = 15 elif "museum" in elem.tags().values() : score = int(score*self.church_coeff) duration = 60 else : - duration = 30 + duration = 5 # Generate the landmark and append it to the list landmark = Landmark( diff --git a/backend/src/utils/optimizer.py b/backend/src/utils/optimizer.py index b20412e..38fc375 100644 --- a/backend/src/utils/optimizer.py +++ b/backend/src/utils/optimizer.py @@ -193,7 +193,7 @@ class Optimizer: for j, spot2 in enumerate(landmarks) : t = get_time(spot1.location, spot2.location) + spot1.duration dist_table[j] = t - closest = sorted(dist_table)[:22] + closest = sorted(dist_table)[:20] for i, dist in enumerate(dist_table) : if dist not in closest : dist_table[i] = 32700 From 055089bf761fbc2db5d16099f3f5dcf5ec1ea22c Mon Sep 17 00:00:00 2001 From: Helldragon67 Date: Tue, 10 Sep 2024 17:07:26 +0200 Subject: [PATCH 4/7] better landmarks log --- backend/src/structs/landmark.py | 5 ++++- backend/src/tester.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/src/structs/landmark.py b/backend/src/structs/landmark.py index 7e0cc97..84b187b 100644 --- a/backend/src/structs/landmark.py +++ b/backend/src/structs/landmark.py @@ -37,5 +37,8 @@ class Landmark(BaseModel) : def __str__(self) -> str: time_to_next_str = f", time_to_next={self.time_to_reach_next}" if self.time_to_reach_next else "" - return f'Landmark({self.type}): [{self.name} @{self.location}, score={self.attractiveness}{time_to_next_str}]' + is_secondary_str = f", secondary" if self.is_secondary else "" + type_str = '(' + self.type + ')' + if self.type in ["start", "finish", "nature", "shopping"] : type_str += '\t ' + return f'Landmark{type_str}: [{self.name} @{self.location}, score={self.attractiveness}{time_to_next_str}{is_secondary_str}]' diff --git a/backend/src/tester.py b/backend/src/tester.py index cc4118c..8144101 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -72,7 +72,7 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = # test(tuple((48.8344400, 2.3220540))) # Café Chez César # test(tuple((48.8375946, 2.2949904))) # Point random -test(tuple((47.377859, 8.540585))) # Zurich HB +# test(tuple((47.377859, 8.540585))) # Zurich HB # test(tuple((45.758217, 4.831814))) # Lyon Bellecour -# test(tuple((48.5848435, 7.7332974))) # Strasbourg Gare +test(tuple((48.5848435, 7.7332974))) # Strasbourg Gare # test(tuple((48.2067858, 16.3692340))) # Vienne From 797db5c1da0e6f3cedf3aa511c6137c434d07944 Mon Sep 17 00:00:00 2001 From: Helldragon67 Date: Tue, 10 Sep 2024 17:11:36 +0200 Subject: [PATCH 5/7] set start and finish as primary --- backend/src/structs/linked_landmarks.py | 2 +- backend/src/tester.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/structs/linked_landmarks.py b/backend/src/structs/linked_landmarks.py index 6c74c74..a00a026 100644 --- a/backend/src/structs/linked_landmarks.py +++ b/backend/src/structs/linked_landmarks.py @@ -52,7 +52,7 @@ class LinkedLandmarks: # Update 'is_secondary' for landmarks with attractiveness below the threshold score for landmark in self._landmarks: - if landmark.attractiveness < threshold_score: + if landmark.attractiveness < threshold_score and landmark.type not in ["start", "finish"]: landmark.is_secondary = True diff --git a/backend/src/tester.py b/backend/src/tester.py index 8144101..ff81fb7 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -24,7 +24,7 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = nature=Preference(type='nature', score = 5), shopping=Preference(type='shopping', score = 5), - max_time_minute=120, + max_time_minute=180, detour_tolerance_minute=10 ) @@ -73,6 +73,6 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = # test(tuple((48.8344400, 2.3220540))) # Café Chez César # test(tuple((48.8375946, 2.2949904))) # Point random # test(tuple((47.377859, 8.540585))) # Zurich HB -# test(tuple((45.758217, 4.831814))) # Lyon Bellecour -test(tuple((48.5848435, 7.7332974))) # Strasbourg Gare +test(tuple((45.758217, 4.831814))) # Lyon Bellecour +# test(tuple((48.5848435, 7.7332974))) # Strasbourg Gare # test(tuple((48.2067858, 16.3692340))) # Vienne From d1c53e08bbab61bd07e8492395bf9d6bc54ed769 Mon Sep 17 00:00:00 2001 From: Helldragon67 Date: Tue, 10 Sep 2024 17:23:01 +0200 Subject: [PATCH 6/7] improved tour length --- .../src/parameters/optimizer_parameters.yaml | 1 + backend/src/tester.py | 1 + backend/src/utils/optimizer.py | 18 ++++++++++-------- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/backend/src/parameters/optimizer_parameters.yaml b/backend/src/parameters/optimizer_parameters.yaml index 77efa02..b9f7b58 100644 --- a/backend/src/parameters/optimizer_parameters.yaml +++ b/backend/src/parameters/optimizer_parameters.yaml @@ -3,3 +3,4 @@ detour_corridor_width: 300 average_walking_speed: 4.8 max_landmarks: 10 max_landmarks_refiner: 20 +overshoot: 1.4 diff --git a/backend/src/tester.py b/backend/src/tester.py index ff81fb7..dd25aa9 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -63,6 +63,7 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = logger.info("Optimized route : ") for l in linked_tour : logger.info(f"{l}") + logger.info(f"Estimated length of tour : {linked_tour.total_time}") # with open('linked_tour.yaml', 'w') as f: # yaml.dump(linked_tour.asdict(), f) diff --git a/backend/src/utils/optimizer.py b/backend/src/utils/optimizer.py index 38fc375..944bd49 100644 --- a/backend/src/utils/optimizer.py +++ b/backend/src/utils/optimizer.py @@ -17,10 +17,11 @@ class Optimizer: logger = logging.getLogger(__name__) - detour: int = None # accepted max detour time (in minutes) - detour_factor: float # detour factor of straight line vs real distance in cities - average_walking_speed: float # average walking speed of adult - max_landmarks: int # max number of landmarks to visit + detour: int = None # accepted max detour time (in minutes) + detour_factor: float # detour factor of straight line vs real distance in cities + average_walking_speed: float # average walking speed of adult + max_landmarks: int # max number of landmarks to visit + overshoot: float # overshoot to allow maxtime to overflow. Optimizer is a bit restrictive def __init__(self) : @@ -31,6 +32,7 @@ class Optimizer: self.detour_factor = parameters['detour_factor'] self.average_walking_speed = parameters['average_walking_speed'] self.max_landmarks = parameters['max_landmarks'] + self.overshoot = parameters['overshoot'] @@ -167,7 +169,7 @@ class Optimizer: - def init_ub_dist(self, landmarks: list[Landmark], max_steps: int): + def init_ub_dist(self, landmarks: list[Landmark], max_time: int): """ Initialize the objective function coefficients and inequality constraints for the optimization problem. @@ -176,7 +178,7 @@ class Optimizer: Args: landmarks (list[Landmark]): List of landmarks. - max_steps (int): Maximum number of steps allowed. + max_time (int): Maximum time of visit allowed. Returns: Tuple[list[float], list[float], list[int]]: Objective function coefficients, inequality constraint coefficients, and the right-hand side of the inequality constraint. @@ -200,7 +202,7 @@ class Optimizer: A_ub += dist_table c = c*len(landmarks) - return c, A_ub, [max_steps] + return c, A_ub, [max_time*self.overshoot] def respect_number(self, L, max_landmarks: int): @@ -474,7 +476,7 @@ class Optimizer: A, b = self.respect_start_finish(L) # Force start and finish positions A_eq = np.vstack((A_eq, A), dtype=np.int8) b_eq += b - A, b = self.respect_order(L) # Respect order of visit (only works when max_steps is limiting factor) + A, b = self.respect_order(L) # Respect order of visit (only works when max_time is limiting factor) A_eq = np.vstack((A_eq, A), dtype=np.int8) b_eq += b From 1ade92aed3b24f042ada0ad68e3a434585a20042 Mon Sep 17 00:00:00 2001 From: Kilian PC Date: Tue, 10 Sep 2024 18:12:17 +0200 Subject: [PATCH 7/7] better timing --- backend/src/parameters/optimizer_parameters.yaml | 4 ++-- backend/src/tester.py | 10 +++++----- backend/src/utils/optimizer.py | 2 +- backend/src/utils/refiner.py | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/src/parameters/optimizer_parameters.yaml b/backend/src/parameters/optimizer_parameters.yaml index b9f7b58..70ba2fa 100644 --- a/backend/src/parameters/optimizer_parameters.yaml +++ b/backend/src/parameters/optimizer_parameters.yaml @@ -2,5 +2,5 @@ detour_factor: 1.4 detour_corridor_width: 300 average_walking_speed: 4.8 max_landmarks: 10 -max_landmarks_refiner: 20 -overshoot: 1.4 +max_landmarks_refiner: 30 +overshoot: 1.8 diff --git a/backend/src/tester.py b/backend/src/tester.py index dd25aa9..6681396 100644 --- a/backend/src/tester.py +++ b/backend/src/tester.py @@ -24,8 +24,8 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = nature=Preference(type='nature', score = 5), shopping=Preference(type='shopping', score = 5), - max_time_minute=180, - detour_tolerance_minute=10 + max_time_minute=100, + detour_tolerance_minute=0 ) # Create start and finish @@ -63,7 +63,7 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = logger.info("Optimized route : ") for l in linked_tour : logger.info(f"{l}") - logger.info(f"Estimated length of tour : {linked_tour.total_time}") + logger.info(f"Estimated length of tour : {linked_tour.total_time} mintutes and visiting {len(linked_tour._landmarks)} landmarks.") # with open('linked_tour.yaml', 'w') as f: # yaml.dump(linked_tour.asdict(), f) @@ -74,6 +74,6 @@ def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = # test(tuple((48.8344400, 2.3220540))) # Café Chez César # test(tuple((48.8375946, 2.2949904))) # Point random # test(tuple((47.377859, 8.540585))) # Zurich HB -test(tuple((45.758217, 4.831814))) # Lyon Bellecour -# test(tuple((48.5848435, 7.7332974))) # Strasbourg Gare +# test(tuple((45.758217, 4.831814))) # Lyon Bellecour +test(tuple((48.5848435, 7.7332974))) # Strasbourg Gare # test(tuple((48.2067858, 16.3692340))) # Vienne diff --git a/backend/src/utils/optimizer.py b/backend/src/utils/optimizer.py index 944bd49..933bd28 100644 --- a/backend/src/utils/optimizer.py +++ b/backend/src/utils/optimizer.py @@ -195,7 +195,7 @@ class Optimizer: for j, spot2 in enumerate(landmarks) : t = get_time(spot1.location, spot2.location) + spot1.duration dist_table[j] = t - closest = sorted(dist_table)[:20] + closest = sorted(dist_table)[:25] for i, dist in enumerate(dist_table) : if dist not in closest : dist_table[i] = 32700 diff --git a/backend/src/utils/refiner.py b/backend/src/utils/refiner.py index 871e332..626bf4d 100644 --- a/backend/src/utils/refiner.py +++ b/backend/src/utils/refiner.py @@ -214,7 +214,7 @@ class Refiner : if self.is_in_area(area, landmark.location) and landmark.name not in visited_names: second_order_landmarks.append(landmark) - return take_most_important.take_most_important(second_order_landmarks, len(visited_landmarks)) + return take_most_important.take_most_important(second_order_landmarks, int(self.max_landmarks_refiner*0.75)) # Try fix the shortest path using shapely