vincentiusyoshuac commited on
Commit
cc02ee9
·
verified ·
1 Parent(s): e4ae25f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -19
app.py CHANGED
@@ -8,9 +8,9 @@ import time
8
  from functools import lru_cache
9
  from concurrent.futures import ThreadPoolExecutor
10
 
11
- def held_karp_tsp(dist_matrix: np.ndarray, return_to_start: bool = True) -> tuple:
12
  """
13
- Modified Held-Karp algorithm for solving TSP
14
  Returns: (minimum cost, optimal route)
15
  """
16
  if len(dist_matrix) < 2:
@@ -19,19 +19,24 @@ def held_karp_tsp(dist_matrix: np.ndarray, return_to_start: bool = True) -> tupl
19
  n = len(dist_matrix)
20
  inf = float('inf')
21
 
 
22
  dp = np.full((1 << n, n), inf)
23
  parent = np.full((1 << n, n), -1, dtype=int)
24
 
 
25
  for i in range(1, n):
26
- dp[1 << i][i] = dist_matrix[0][i]
27
 
 
28
  for mask in range(1, 1 << n):
29
- if bin(mask).count('1') <= 1:
30
  continue
31
  for curr in range(n):
32
  if not (mask & (1 << curr)):
33
  continue
34
  prev_mask = mask ^ (1 << curr)
 
 
35
  for prev in range(n):
36
  if not (prev_mask & (1 << prev)):
37
  continue
@@ -40,14 +45,18 @@ def held_karp_tsp(dist_matrix: np.ndarray, return_to_start: bool = True) -> tupl
40
  dp[mask][curr] = candidate
41
  parent[mask][curr] = prev
42
 
 
43
  mask = (1 << n) - 1
44
  if return_to_start:
45
- curr = min(range(n), key=lambda x: dp[mask][x] + dist_matrix[x][0])
 
46
  final_cost = dp[mask][curr] + dist_matrix[curr][0]
47
  else:
48
- curr = min(range(n), key=lambda x: dp[mask][x])
 
49
  final_cost = dp[mask][curr]
50
 
 
51
  path = []
52
  while curr != -1:
53
  path.append(curr)
@@ -55,18 +64,17 @@ def held_karp_tsp(dist_matrix: np.ndarray, return_to_start: bool = True) -> tupl
55
  curr = parent[mask][curr]
56
  mask = new_mask
57
 
 
58
  if return_to_start:
59
- path.append(0)
60
  path.reverse()
61
 
62
  return final_cost, path
63
 
 
64
  @st.cache_data
65
  def get_route_osrm(start_coords: tuple, end_coords: tuple) -> tuple:
66
- """
67
- Get route using OSRM public API
68
- Returns: (distance in km, encoded polyline of the route)
69
- """
70
  try:
71
  coords = f"{start_coords[1]},{start_coords[0]};{end_coords[1]},{end_coords[0]}"
72
  url = f"http://router.project-osrm.org/route/v1/driving/{coords}"
@@ -110,9 +118,7 @@ def cached_geocoding(city_name: str) -> tuple:
110
  return None
111
 
112
  def create_distance_matrix_with_routes(coordinates: list) -> tuple:
113
- """
114
- Create distance matrix and store routes between all points using OSRM
115
- """
116
  valid_coordinates = [c for c in coordinates if c is not None]
117
  n = len(valid_coordinates)
118
 
@@ -149,9 +155,7 @@ def create_distance_matrix_with_routes(coordinates: list) -> tuple:
149
 
150
  def plot_route_with_roads(map_obj: folium.Map, coordinates: list, route: list,
151
  city_names: list, routes_dict: dict, return_to_start: bool) -> folium.Map:
152
- """
153
- Plot route using actual road paths from OSRM
154
- """
155
  route_group = folium.FeatureGroup(name="Route")
156
 
157
  for i in range(len(route)-1):
@@ -204,6 +208,7 @@ def main():
204
  st.markdown("""
205
  Temukan rute optimal berkendara antar lokasi.
206
  Masukkan nama lokasi dibawah dan klik 'Optimize Route' untuk melihat hasilnya.
 
207
  """)
208
 
209
  col1, col2 = st.columns([1, 2])
@@ -231,8 +236,9 @@ def main():
231
  city_coords = []
232
 
233
  for i in range(city_count):
 
234
  city_name = st.text_input(
235
- f"Kota {i+1}",
236
  value=st.session_state.city_inputs[i],
237
  key=f"city_{i}"
238
  )
@@ -264,7 +270,7 @@ def main():
264
  start_time = time.time()
265
 
266
  dist_matrix, valid_coordinates, routes_dict = create_distance_matrix_with_routes(city_coords)
267
- min_cost, optimal_route = held_karp_tsp(dist_matrix, return_to_start)
268
 
269
  end_time = time.time()
270
 
 
8
  from functools import lru_cache
9
  from concurrent.futures import ThreadPoolExecutor
10
 
11
+ def held_karp_tsp_fixed_start(dist_matrix: np.ndarray, return_to_start: bool = True) -> tuple:
12
  """
13
+ Modified Held-Karp algorithm for solving TSP with fixed starting point (index 0)
14
  Returns: (minimum cost, optimal route)
15
  """
16
  if len(dist_matrix) < 2:
 
19
  n = len(dist_matrix)
20
  inf = float('inf')
21
 
22
+ # Only consider paths that start from index 0
23
  dp = np.full((1 << n, n), inf)
24
  parent = np.full((1 << n, n), -1, dtype=int)
25
 
26
+ # Initialize paths from start (index 0) to other cities
27
  for i in range(1, n):
28
+ dp[1 << i | 1][i] = dist_matrix[0][i]
29
 
30
+ # Process all possible subsets of cities
31
  for mask in range(1, 1 << n):
32
+ if not (mask & 1): # Skip if start city (0) is not in the subset
33
  continue
34
  for curr in range(n):
35
  if not (mask & (1 << curr)):
36
  continue
37
  prev_mask = mask ^ (1 << curr)
38
+ if not prev_mask: # Skip if no previous cities
39
+ continue
40
  for prev in range(n):
41
  if not (prev_mask & (1 << prev)):
42
  continue
 
45
  dp[mask][curr] = candidate
46
  parent[mask][curr] = prev
47
 
48
+ # Find the optimal end point
49
  mask = (1 << n) - 1
50
  if return_to_start:
51
+ # For closed loop, find best path back to start
52
+ curr = min(range(1, n), key=lambda x: dp[mask][x] + dist_matrix[x][0])
53
  final_cost = dp[mask][curr] + dist_matrix[curr][0]
54
  else:
55
+ # For single trip, find best ending point
56
+ curr = min(range(1, n), key=lambda x: dp[mask][x])
57
  final_cost = dp[mask][curr]
58
 
59
+ # Reconstruct the path
60
  path = []
61
  while curr != -1:
62
  path.append(curr)
 
64
  curr = parent[mask][curr]
65
  mask = new_mask
66
 
67
+ path.append(0) # Add start city
68
  if return_to_start:
69
+ path.append(0) # Add start city again for closed loop
70
  path.reverse()
71
 
72
  return final_cost, path
73
 
74
+ # Keep other helper functions unchanged
75
  @st.cache_data
76
  def get_route_osrm(start_coords: tuple, end_coords: tuple) -> tuple:
77
+ """Get route using OSRM public API"""
 
 
 
78
  try:
79
  coords = f"{start_coords[1]},{start_coords[0]};{end_coords[1]},{end_coords[0]}"
80
  url = f"http://router.project-osrm.org/route/v1/driving/{coords}"
 
118
  return None
119
 
120
  def create_distance_matrix_with_routes(coordinates: list) -> tuple:
121
+ """Create distance matrix and store routes between all points"""
 
 
122
  valid_coordinates = [c for c in coordinates if c is not None]
123
  n = len(valid_coordinates)
124
 
 
155
 
156
  def plot_route_with_roads(map_obj: folium.Map, coordinates: list, route: list,
157
  city_names: list, routes_dict: dict, return_to_start: bool) -> folium.Map:
158
+ """Plot route using actual road paths from OSRM"""
 
 
159
  route_group = folium.FeatureGroup(name="Route")
160
 
161
  for i in range(len(route)-1):
 
208
  st.markdown("""
209
  Temukan rute optimal berkendara antar lokasi.
210
  Masukkan nama lokasi dibawah dan klik 'Optimize Route' untuk melihat hasilnya.
211
+ Kota 1 akan menjadi titik awal perjalanan.
212
  """)
213
 
214
  col1, col2 = st.columns([1, 2])
 
236
  city_coords = []
237
 
238
  for i in range(city_count):
239
+ label = "Kota 1 (Titik Awal)" if i == 0 else f"Kota {i+1}"
240
  city_name = st.text_input(
241
+ label,
242
  value=st.session_state.city_inputs[i],
243
  key=f"city_{i}"
244
  )
 
270
  start_time = time.time()
271
 
272
  dist_matrix, valid_coordinates, routes_dict = create_distance_matrix_with_routes(city_coords)
273
+ min_cost, optimal_route = held_karp_tsp_fixed_start(dist_matrix, return_to_start)
274
 
275
  end_time = time.time()
276