vincentiusyoshuac commited on
Commit
4e34654
·
verified ·
1 Parent(s): 4687ad4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -86
app.py CHANGED
@@ -60,39 +60,23 @@ def calculate_real_distances(places):
60
  return distances, routing_info
61
 
62
  def optimize_route(distances):
63
- """Optimize route using Hungarian algorithm"""
 
 
 
 
 
 
64
  row_ind, col_ind = linear_sum_assignment(distances)
65
- return col_ind
66
-
67
- def get_place_coordinates(place_name):
68
- """Get coordinates using Nominatim geocoding"""
69
- try:
70
- geolocator = Nominatim(user_agent="my_travel_app")
71
- location = geolocator.geocode(place_name)
72
- return (location.latitude, location.longitude) if location else None
73
- except:
74
- return None
75
-
76
- def create_numbered_marker(number):
77
- """Create a custom marker with a number"""
78
- return plugins.BeautifyIcon(
79
- number=number,
80
- border_color='#b4b4b4',
81
- border_width=1,
82
- text_color='black',
83
- background_color='white',
84
- inner_icon_style='margin-top:0;'
85
- )
86
-
87
- def format_instructions(steps):
88
- """Format routing instructions from OSRM steps"""
89
- instructions = []
90
- for step in steps:
91
- if 'maneuver' in step:
92
- instruction = step.get('maneuver', {}).get('instruction', '')
93
- if instruction:
94
- instructions.append(instruction)
95
- return instructions
96
 
97
  def main():
98
  st.title("AI Travel Route Optimizer (with OSRM)")
@@ -115,42 +99,42 @@ def main():
115
 
116
  # Only proceed if we have all places
117
  if len(places) == num_places and num_places >= 2:
118
-
119
  with st.spinner("Calculating optimal route..."):
120
  # Calculate real distances
121
  distances, routing_info = calculate_real_distances(places)
122
 
123
- # Optimize route
124
- optimized_indices = optimize_route(distances)
125
 
126
  # Create map
127
  center_lat = sum(coord[0] for _, coord in places) / len(places)
128
  center_lon = sum(coord[1] for _, coord in places) / len(places)
129
-
130
  m = folium.Map(location=[center_lat, center_lon], zoom_start=4)
131
 
132
- # Create optimized itinerary list
133
- optimized_places = [(i+1, places[idx][0]) for i, idx in enumerate(optimized_indices)]
 
134
 
135
- # Add markers and route lines
136
- for i in range(len(optimized_indices)):
137
- current_idx = optimized_indices[i]
138
- next_idx = optimized_indices[(i + 1) % len(optimized_indices)]
139
 
140
- # Add numbered marker
141
- place_name, (lat, lon) = places[current_idx]
142
- next_place = places[next_idx]
143
 
144
  # Get routing info for this segment
145
  segment_info = routing_info.get((current_idx, next_idx), {})
146
 
147
- # Create detailed popup content
148
  popup_content = f"""
149
- <b>Stop {i+1}: {place_name}</b><br>
150
- To next stop:<br>
151
- Distance: {segment_info.get('distance_km', 'N/A')}<br>
152
- Duration: {segment_info.get('duration_mins', 'N/A')}
153
  """
 
 
 
 
 
 
154
 
155
  folium.Marker(
156
  [lat, lon],
@@ -158,60 +142,58 @@ def main():
158
  icon=create_numbered_marker(i+1)
159
  ).add_to(m)
160
 
161
- # Draw route line using polyline from OSRM
162
- if 'geometry' in segment_info:
163
- try:
164
- import polyline
165
- route_coords = polyline.decode(segment_info['geometry'])
166
- folium.PolyLine(
167
- route_coords,
168
- weight=2,
169
- color='blue',
170
- opacity=0.8
171
- ).add_to(m)
172
- except:
173
- # Fallback to straight line if polyline decoding fails
174
- folium.PolyLine(
175
- [[lat, lon], [next_place[1][0], next_place[1][1]]],
176
- weight=2,
177
- color='red',
178
- opacity=0.8
179
- ).add_to(m)
 
 
 
 
 
 
 
180
 
181
  # Display map
182
  st.components.v1.html(m._repr_html_(), height=600)
183
 
184
- # Display optimized itinerary with route information
185
  st.header("Optimized Itinerary")
186
 
187
- total_distance = 0
188
- total_duration = 0
189
-
190
- for i in range(len(optimized_indices)):
191
- current_idx = optimized_indices[i]
192
- next_idx = optimized_indices[(i + 1) % len(optimized_indices)]
193
 
194
- place_name = places[current_idx][0]
195
  segment_info = routing_info.get((current_idx, next_idx), {})
196
 
197
- st.write(f"{i+1}. {place_name}")
198
 
199
- if i < len(optimized_indices) - 1:
200
  st.write(f" ↓ ({segment_info.get('distance_km', 'N/A')}, "
201
  f"Duration: {segment_info.get('duration_mins', 'N/A')})")
202
 
203
- # Display turn-by-turn instructions
204
  if 'steps' in segment_info:
205
  with st.expander(f"Route instructions to next stop"):
206
  instructions = format_instructions(segment_info['steps'])
207
  for idx, instruction in enumerate(instructions, 1):
208
  st.write(f"{idx}. {instruction}")
209
-
210
- # Add to totals
211
- if 'distance_km' in segment_info:
212
- total_distance += float(segment_info['distance_km'].split()[0])
213
- if 'duration_mins' in segment_info:
214
- total_duration += float(segment_info['duration_mins'].split()[0])
215
 
216
  # Display totals
217
  st.write("\nSummary:")
 
60
  return distances, routing_info
61
 
62
  def optimize_route(distances):
63
+ """
64
+ Optimize route using modified Hungarian algorithm for TSP.
65
+ Returns the optimal order of visits.
66
+ """
67
+ n = len(distances)
68
+
69
+ # Solve assignment problem
70
  row_ind, col_ind = linear_sum_assignment(distances)
71
+
72
+ # Convert assignment to tour
73
+ tour = []
74
+ current = 0 # Start from first city
75
+ for _ in range(n):
76
+ tour.append(current)
77
+ current = col_ind[current]
78
+
79
+ return tour
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
  def main():
82
  st.title("AI Travel Route Optimizer (with OSRM)")
 
99
 
100
  # Only proceed if we have all places
101
  if len(places) == num_places and num_places >= 2:
 
102
  with st.spinner("Calculating optimal route..."):
103
  # Calculate real distances
104
  distances, routing_info = calculate_real_distances(places)
105
 
106
+ # Get optimized route order
107
+ optimal_order = optimize_route(distances)
108
 
109
  # Create map
110
  center_lat = sum(coord[0] for _, coord in places) / len(places)
111
  center_lon = sum(coord[1] for _, coord in places) / len(places)
 
112
  m = folium.Map(location=[center_lat, center_lon], zoom_start=4)
113
 
114
+ # Add markers and route lines following optimal order
115
+ total_distance = 0
116
+ total_duration = 0
117
 
118
+ for i in range(len(optimal_order)):
119
+ current_idx = optimal_order[i]
120
+ next_idx = optimal_order[(i + 1) % len(optimal_order)]
 
121
 
122
+ # Get current and next place info
123
+ current_place, (lat, lon) = places[current_idx]
 
124
 
125
  # Get routing info for this segment
126
  segment_info = routing_info.get((current_idx, next_idx), {})
127
 
128
+ # Add marker with proper numbering
129
  popup_content = f"""
130
+ <b>Stop {i+1}: {current_place}</b><br>
 
 
 
131
  """
132
+ if i < len(optimal_order) - 1:
133
+ popup_content += f"""
134
+ To next stop:<br>
135
+ Distance: {segment_info.get('distance_km', 'N/A')}<br>
136
+ Duration: {segment_info.get('duration_mins', 'N/A')}
137
+ """
138
 
139
  folium.Marker(
140
  [lat, lon],
 
142
  icon=create_numbered_marker(i+1)
143
  ).add_to(m)
144
 
145
+ # Draw route line to next point
146
+ if i < len(optimal_order) - 1:
147
+ if 'geometry' in segment_info:
148
+ try:
149
+ route_coords = polyline.decode(segment_info['geometry'])
150
+ folium.PolyLine(
151
+ route_coords,
152
+ weight=2,
153
+ color='blue',
154
+ opacity=0.8
155
+ ).add_to(m)
156
+ except:
157
+ next_place = places[next_idx][1]
158
+ folium.PolyLine(
159
+ [[lat, lon], [next_place[0], next_place[1]]],
160
+ weight=2,
161
+ color='red',
162
+ opacity=0.8
163
+ ).add_to(m)
164
+
165
+ # Add to totals if not last point
166
+ if i < len(optimal_order) - 1:
167
+ if 'distance_km' in segment_info:
168
+ total_distance += float(segment_info['distance_km'].split()[0])
169
+ if 'duration_mins' in segment_info:
170
+ total_duration += float(segment_info['duration_mins'].split()[0])
171
 
172
  # Display map
173
  st.components.v1.html(m._repr_html_(), height=600)
174
 
175
+ # Display optimized itinerary
176
  st.header("Optimized Itinerary")
177
 
178
+ for i in range(len(optimal_order)):
179
+ current_idx = optimal_order[i]
180
+ next_idx = optimal_order[(i + 1) % len(optimal_order)]
 
 
 
181
 
182
+ current_place = places[current_idx][0]
183
  segment_info = routing_info.get((current_idx, next_idx), {})
184
 
185
+ st.write(f"{i+1}. {current_place}")
186
 
187
+ if i < len(optimal_order) - 1:
188
  st.write(f" ↓ ({segment_info.get('distance_km', 'N/A')}, "
189
  f"Duration: {segment_info.get('duration_mins', 'N/A')})")
190
 
191
+ # Show turn-by-turn directions
192
  if 'steps' in segment_info:
193
  with st.expander(f"Route instructions to next stop"):
194
  instructions = format_instructions(segment_info['steps'])
195
  for idx, instruction in enumerate(instructions, 1):
196
  st.write(f"{idx}. {instruction}")
 
 
 
 
 
 
197
 
198
  # Display totals
199
  st.write("\nSummary:")