MBG0903 commited on
Commit
b96bdaa
·
verified ·
1 Parent(s): c877f03

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -37
app.py CHANGED
@@ -1,62 +1,162 @@
1
  import gradio as gr
2
  import pandas as pd
3
  import numpy as np
 
 
 
4
  from ortools.constraint_solver import pywrapcp, routing_enums_pb2
 
 
5
 
6
- def optimize_route(address_text):
 
 
7
 
8
- # Parse addresses
9
- addresses = [a.strip() for a in address_text.split("\n") if a.strip()]
10
- if len(addresses) < 2:
11
- return "❌ Please enter at least two locations.", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- # Generate fake symmetric distance matrix (Phase 1 demo)
14
- n = len(addresses)
15
- np.random.seed(42)
16
- distance_matrix = np.random.randint(5, 50, size=(n, n))
17
- np.fill_diagonal(distance_matrix, 0)
18
 
19
- # OR-Tools Manager
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  manager = pywrapcp.RoutingIndexManager(n, 1, 0)
21
  routing = pywrapcp.RoutingModel(manager)
22
 
23
- def distance_callback(from_idx, to_idx):
24
- return distance_matrix[manager.IndexToNode(from_idx)][manager.IndexToNode(to_idx)]
25
 
26
- callback_idx = routing.RegisterTransitCallback(distance_callback)
27
- routing.SetArcCostEvaluatorOfAllVehicles(callback_idx)
28
 
29
- search_params = pywrapcp.DefaultRoutingSearchParameters()
30
- search_params.first_solution_strategy = (
31
- routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
32
- )
33
 
34
- solution = routing.SolveWithParameters(search_params)
35
- if not solution:
36
- return "❌ Route optimization failed.", None
37
 
38
- # Extract route
39
  index = routing.Start(0)
40
- ordered_stops = []
41
  while not routing.IsEnd(index):
42
- ordered_stops.append(manager.IndexToNode(index))
43
- index = solution.Value(routing.NextVar(index))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- ordered_addresses = [addresses[i] for i in ordered_stops]
 
46
 
47
- # Build readable text
48
- route_text = "🚚 **Optimized Route:**\n\n"
49
- for i, loc in enumerate(ordered_addresses):
50
- route_text += f"**{i+1}. {loc}**\n"
51
 
52
- df = pd.DataFrame(distance_matrix, columns=addresses, index=addresses)
53
 
54
- return route_text, df
55
 
 
 
 
56
 
57
- # Gradio interface
58
  interface = gr.Interface(
59
- fn=optimize_route,
60
  inputs=gr.Textbox(
61
  lines=8,
62
  label="Enter addresses (one per line):",
@@ -64,10 +164,12 @@ interface = gr.Interface(
64
  ),
65
  outputs=[
66
  gr.Markdown(label="Optimized Route"),
67
- gr.Dataframe(label="Distance Matrix (Demo Mode)")
 
 
68
  ],
69
  title="Procelevate AI Route Planner",
70
- description="AI-powered optimization for logistics & 3PL route planning.",
71
  )
72
 
73
  interface.launch()
 
1
  import gradio as gr
2
  import pandas as pd
3
  import numpy as np
4
+ import requests
5
+ from geopy.geocoders import Nominatim
6
+ from geopy.extra.rate_limiter import RateLimiter
7
  from ortools.constraint_solver import pywrapcp, routing_enums_pb2
8
+ import folium
9
+ from folium.plugins import AntPath
10
 
11
+ # -------------------------------------------
12
+ # 1. Geocoding Function (Address -> Lat/Lon)
13
+ # -------------------------------------------
14
 
15
+ geolocator = Nominatim(user_agent="procelevate_route_planner")
16
+ geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
17
+
18
+ def get_coordinates(address):
19
+ loc = geocode(address)
20
+ if loc:
21
+ return (loc.latitude, loc.longitude)
22
+ return None
23
+
24
+
25
+ # -------------------------------------------
26
+ # 2. OSRM Distance API
27
+ # -------------------------------------------
28
+
29
+ def osrm_distance(coord1, coord2):
30
+ url = f"http://router.project-osrm.org/route/v1/driving/{coord1[1]},{coord1[0]};{coord2[1]},{coord2[0]}?overview=false"
31
+ res = requests.get(url).json()
32
+ if "routes" in res:
33
+ d = res["routes"][0]["distance"] # meters
34
+ t = res["routes"][0]["duration"] # seconds
35
+ return d, t
36
+ return None, None
37
+
38
+
39
+ # -------------------------------------------
40
+ # 3. Build Distance & Time Matrix
41
+ # -------------------------------------------
42
 
43
+ def build_matrices(coords):
44
+ n = len(coords)
45
+ dist_mat = np.zeros((n, n))
46
+ time_mat = np.zeros((n, n))
 
47
 
48
+ for i in range(n):
49
+ for j in range(n):
50
+ if i == j:
51
+ continue
52
+ d, t = osrm_distance(coords[i], coords[j])
53
+ if d is None:
54
+ return None, None
55
+ dist_mat[i][j] = int(d)
56
+ time_mat[i][j] = int(t)
57
+
58
+ return dist_mat, time_mat
59
+
60
+
61
+ # -------------------------------------------
62
+ # 4. OR-Tools Route Optimization
63
+ # -------------------------------------------
64
+
65
+ def optimize_route(dist_matrix):
66
+ n = len(dist_matrix)
67
  manager = pywrapcp.RoutingIndexManager(n, 1, 0)
68
  routing = pywrapcp.RoutingModel(manager)
69
 
70
+ def callback(from_index, to_index):
71
+ return int(dist_matrix[manager.IndexToNode(from_index)][manager.IndexToNode(to_index)])
72
 
73
+ transit_idx = routing.RegisterTransitCallback(callback)
74
+ routing.SetArcCostEvaluatorOfAllVehicles(transit_idx)
75
 
76
+ search = pywrapcp.DefaultRoutingSearchParameters()
77
+ search.first_solution_strategy = routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC
 
 
78
 
79
+ sol = routing.SolveWithParameters(search)
80
+ if not sol:
81
+ return None
82
 
 
83
  index = routing.Start(0)
84
+ route = []
85
  while not routing.IsEnd(index):
86
+ route.append(manager.IndexToNode(index))
87
+ index = sol.Value(routing.NextVar(index))
88
+
89
+ return route
90
+
91
+
92
+ # -------------------------------------------
93
+ # 5. Build Folium Map
94
+ # -------------------------------------------
95
+
96
+ def build_map(coords, addresses, route_order):
97
+ start = coords[route_order[0]]
98
+ m = folium.Map(location=start, zoom_start=12)
99
+
100
+ # Add markers
101
+ for i, idx in enumerate(route_order):
102
+ folium.Marker(coords[idx], tooltip=f"{i+1}. {addresses[idx]}").add_to(m)
103
+
104
+ # Draw lines between points
105
+ path = [coords[idx] for idx in route_order]
106
+ AntPath(path, color="blue", weight=4).add_to(m)
107
+
108
+ return m._repr_html_()
109
+
110
+
111
+ # -------------------------------------------
112
+ # MAIN FUNCTION
113
+ # -------------------------------------------
114
+
115
+ def run_planner(address_text):
116
+
117
+ addresses = [a.strip() for a in address_text.split("\n") if a.strip()]
118
+ if len(addresses) < 2:
119
+ return "❌ Enter at least two locations.", None, None, None
120
+
121
+ # 1. Geocode
122
+ coords = []
123
+ for a in addresses:
124
+ c = get_coordinates(a)
125
+ if not c:
126
+ return f"❌ Unable to geocode: {a}", None, None, None
127
+ coords.append(c)
128
+
129
+ # 2. Build matrices
130
+ dist_mat, time_mat = build_matrices(coords)
131
+ if dist_mat is None:
132
+ return "❌ Failed to fetch OSRM distances.", None, None, None
133
+
134
+ # 3. Optimize route
135
+ route_order = optimize_route(dist_mat)
136
+ if route_order is None:
137
+ return "❌ Route optimization failed.", None, None, None
138
+
139
+ # 4. Format output text
140
+ route_text = "🚚 **Optimized Real Route (OSRM):**\n\n"
141
+ for i, idx in enumerate(route_order):
142
+ route_text += f"**{i+1}. {addresses[idx]}**\n"
143
 
144
+ # 5. Build map
145
+ map_html = build_map(coords, addresses, route_order)
146
 
147
+ # 6. Convert matrices to DataFrames
148
+ df_dist = pd.DataFrame(dist_mat, columns=addresses, index=addresses)
149
+ df_time = pd.DataFrame(time_mat, columns=addresses, index=addresses)
 
150
 
151
+ return route_text, df_dist, df_time, map_html
152
 
 
153
 
154
+ # -------------------------------------------
155
+ # GRADIO UI
156
+ # -------------------------------------------
157
 
 
158
  interface = gr.Interface(
159
+ fn=run_planner,
160
  inputs=gr.Textbox(
161
  lines=8,
162
  label="Enter addresses (one per line):",
 
164
  ),
165
  outputs=[
166
  gr.Markdown(label="Optimized Route"),
167
+ gr.Dataframe(label="Distance (meters)"),
168
+ gr.Dataframe(label="Time (seconds)"),
169
+ gr.HTML(label="Route Map"),
170
  ],
171
  title="Procelevate AI Route Planner",
172
+ description="Real logistics routing using OSRM, OR-Tools, and AI-driven insights.",
173
  )
174
 
175
  interface.launch()