Kshitij2604 commited on
Commit
cdb1307
·
verified ·
1 Parent(s): f81256a

Update app_improved.py

Browse files
Files changed (1) hide show
  1. app_improved.py +125 -126
app_improved.py CHANGED
@@ -1,4 +1,4 @@
1
- # app_improved.py — Compatible with Gradio 5.0.0
2
 
3
  import io
4
  import os
@@ -6,9 +6,7 @@ import json
6
  import tempfile
7
  import pandas as pd
8
 
9
- # --------------------
10
- # Compatibility shim for mismatched huggingface_hub versions
11
- # --------------------
12
  try:
13
  import huggingface_hub as _hf
14
  except Exception:
@@ -35,50 +33,69 @@ from solver import (
35
  make_template_dataframe,
36
  )
37
 
38
- TITLE = "Ride-Sharing Optimizer — Clean UI"
39
- FOOTER = "Made with ❤️ using Gradio — improved layout and UX"
 
 
 
 
 
 
40
 
41
  CUSTOM_CSS = r"""
42
- :root{--bg:#0f1724;--card:#0b1220;--muted:#94a3b8;--accent:#4f46e5;--accent-2:#06b6d4}
43
- body{background:linear-gradient(180deg,#071024 0%, var(--bg) 100%); color:#dbeafe}
44
- .gradio-container {padding:20px 14px}
45
- .header {display:flex;align-items:center;gap:16px}
46
- .brand {font-size:20px;font-weight:700;color:var(--accent)}
47
- .subtitle{color:var(--muted);margin-top:4px}
48
- .card{background:var(--card);padding:14px;border-radius:12px;box-shadow:0 6px 18px rgba(2,6,23,0.6)}
49
- .small{font-size:13px;color:var(--muted)}
50
- .note{font-size:12px;color:var(--muted)}
51
- .footer{margin-top:16px;color:var(--muted);font-size:13px}
52
  """
53
 
54
- def format_metrics(metrics_dict):
55
- rows = []
56
- for i, d in enumerate(metrics_dict.get("per_route_distance", []), 1):
57
- load = metrics_dict.get("per_route_load", [])[i-1] if metrics_dict.get("per_route_load") else "-"
58
- rows.append(f"| {i} | {d:.2f} | {load} |")
59
- route_table = "\n".join(rows)
60
-
61
- md = f"""
62
- ### 🚗 Summary
63
- **Vehicles used:** {metrics_dict.get('vehicles_used',0)}
64
- **Capacity:** {metrics_dict.get('capacity',0)}
65
- **Total distance:** {metrics_dict.get('total_distance',0):.2f}
66
-
67
- **Per-route**
68
- | Route | Distance | Load |
69
- |:-----|--------:|:----:|
70
- {route_table}
71
-
72
- **Time windows**
73
- - total lateness count: {metrics_dict.get('time_window_report',{}).get('total_lateness_count',0)}
74
- - total lateness: {metrics_dict.get('time_window_report',{}).get('total_lateness',0):.2f}
75
- - status: {metrics_dict.get('time_window_report',{}).get('status','-')}
76
-
77
- **Note:** {metrics_dict.get('note','')}
78
- """
79
- return md
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
- def run_generator(n_clients, n_vehicles, capacity, spread, demand_min, demand_max, seed, speed):
82
  df = generate_random_instance(
83
  n_clients=int(n_clients),
84
  n_vehicles=int(n_vehicles),
@@ -88,106 +105,88 @@ def run_generator(n_clients, n_vehicles, capacity, spread, demand_min, demand_ma
88
  demand_max=int(demand_max),
89
  seed=int(seed),
90
  )
91
- depot = (0.0, 0.0)
92
- sol = solve_vrp_tw(df, depot=depot, n_vehicles=int(n_vehicles), capacity=int(capacity), speed=float(speed))
93
- img = plot_solution(df, sol, depot=depot)
94
-
95
- tf = tempfile.NamedTemporaryFile(delete=False, suffix=".csv")
96
- sol['assignments_table'].to_csv(tf.name, index=False)
97
- tf.flush(); tf.close()
98
-
99
  metrics_md = format_metrics(sol.get('metrics', {}))
100
- return img, sol['assignments_table'], metrics_md, tf.name
 
101
 
102
- def run_csv(file, n_vehicles, capacity, speed):
103
  if file is None:
104
- raise gr.Error("Upload a CSV first")
 
105
  df = parse_uploaded_csv(file.name if hasattr(file, 'name') else file)
106
- depot = (0.0, 0.0)
107
- sol = solve_vrp_tw(df, depot=depot, n_vehicles=int(n_vehicles), capacity=int(capacity), speed=float(speed))
108
- img = plot_solution(df, sol, depot=depot)
109
-
110
- tf = tempfile.NamedTemporaryFile(delete=False, suffix=".csv")
111
- sol['assignments_table'].to_csv(tf.name, index=False)
112
- tf.flush(); tf.close()
113
-
114
  metrics_md = format_metrics(sol.get('metrics', {}))
115
- return img, sol['assignments_table'], metrics_md, tf.name
 
116
 
117
  def download_template():
118
  df = make_template_dataframe()
119
- tf = tempfile.NamedTemporaryFile(delete=False, suffix=".csv")
120
- df.to_csv(tf.name, index=False)
121
- tf.flush(); tf.close()
122
- return tf.name
123
 
 
124
  with gr.Blocks(title=TITLE, css=CUSTOM_CSS) as demo:
125
- with gr.Row(elem_id="header"):
126
  with gr.Column(scale=1):
127
- gr.Markdown(f"<div class='header'><div class='brand'>{TITLE}</div></div>")
128
- gr.Markdown("<div class='subtitle'>Generate sample scenarios or upload your own CSV. Capacity-based VRP with soft time windows.</div>")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
- with gr.Row():
131
  with gr.Column(scale=2):
132
- with gr.Tabs() as main_tabs:
133
- with gr.TabItem("Generate sample"):
134
- with gr.Row():
135
- with gr.Column(scale=1, min_width=300):
136
- n_clients = gr.Slider(5, 200, value=30, step=1, label="Number of riders")
137
- n_vehicles = gr.Slider(1, 20, value=4, step=1, label="Number of drivers")
138
- capacity = gr.Slider(1, 50, value=10, step=1, label="Vehicle capacity")
139
- spread = gr.Slider(10, 400, value=50, step=1, label="Spatial spread")
140
- demand_min = gr.Slider(1, 5, value=1, step=1, label="Min demand")
141
- demand_max = gr.Slider(1, 10, value=3, step=1, label="Max demand")
142
- seed = gr.Number(value=42, label="Random seed")
143
- speed = gr.Number(value=10.0, label="Vehicle speed (units/min)")
144
- run_btn = gr.Button("Generate & Optimize", variant="primary")
145
-
146
- with gr.Column(scale=1):
147
- img = gr.Image(type="pil", label="Route visualization")
148
- with gr.Row():
149
- dl_assign = gr.File(label="Download assignments (CSV)")
150
- export_btn = gr.Button("Export latest assignments")
151
-
152
- with gr.Row():
153
- route_df = gr.Dataframe(label="Route assignments", wrap=True)
154
- metrics = gr.Markdown(label="Metrics summary")
155
-
156
- with gr.TabItem("Upload CSV"):
157
- with gr.Row():
158
- with gr.Column(min_width=300):
159
- file = gr.File(label="Upload CSV (id,x,y,demand,tw_start,tw_end,service)")
160
- dl_tmp = gr.Button("Download template CSV")
161
- n_vehicles2 = gr.Slider(1, 50, value=5, step=1, label="Number of drivers")
162
- capacity2 = gr.Slider(1, 200, value=15, step=1, label="Vehicle capacity")
163
- speed2 = gr.Number(value=10.0, label="Vehicle speed (units/min)")
164
- run_btn2 = gr.Button("Optimize uploaded data", variant="primary")
165
- with gr.Column():
166
- img2 = gr.Image(type="pil", label="Route visualization")
167
-
168
- with gr.Row():
169
- route_df2 = gr.Dataframe(label="Route assignments", wrap=True)
170
- metrics2 = gr.Markdown(label="Metrics summary")
171
- dl_assign2 = gr.File(label="Download assignments (CSV)")
172
-
173
- gr.Markdown(f"---\n{FOOTER}")
174
-
175
- run_btn.click(
176
- fn=run_generator,
177
- inputs=[n_clients, n_vehicles, capacity, spread, demand_min, demand_max, seed, speed],
178
- outputs=[img, route_df, metrics, dl_assign],
179
  )
180
 
181
- run_btn2.click(
182
- fn=run_csv,
183
- inputs=[file, n_vehicles2, capacity2, speed2],
184
- outputs=[img2, route_df2, metrics2, dl_assign2],
185
  )
186
 
187
- def _tmpl():
188
- return download_template()
189
-
190
- dl_tmp.click(fn=_tmpl, outputs=[gr.File()])
191
 
192
  if __name__ == '__main__':
193
  demo.launch()
 
1
+ # app_improved.py — Redesigned UI
2
 
3
  import io
4
  import os
 
6
  import tempfile
7
  import pandas as pd
8
 
9
+ # Compatibility shim for huggingface_hub
 
 
10
  try:
11
  import huggingface_hub as _hf
12
  except Exception:
 
33
  make_template_dataframe,
34
  )
35
 
36
+ # ---------- Design notes
37
+ # Goals:
38
+ # - Sidebar controls (compact) and large visualization area
39
+ # - Clear download buttons and readable metrics
40
+ # - Presets + small help text
41
+
42
+ TITLE = "Ride-Sharing Optimizer"
43
+ FOOTER = "Gradio UI — improved layout"
44
 
45
  CUSTOM_CSS = r"""
46
+ :root{--bg:#0b1220;--panel:#0f1724;--muted:#94a3b8;--accent:#7c3aed}
47
+ body{background:linear-gradient(180deg,#061022 0%, var(--bg) 100%);color:#e6eef8}
48
+ .gradio-container{padding:18px}
49
+ .sidebar{background:var(--panel);padding:14px;border-radius:10px}
50
+ .brand{font-weight:700;font-size:18px;color:var(--accent)}
51
+ .small{color:var(--muted);font-size:13px}
52
+ .controls .gr-button{width:100%}
53
+ .metrics{background:rgba(255,255,255,0.02);padding:10px;border-radius:8px}
54
+ .table-wrap{max-height:280px;overflow:auto}
 
55
  """
56
 
57
+ # ---------- helpers
58
+
59
+ def format_metrics(metrics):
60
+ if not metrics:
61
+ return "No metrics available"
62
+ lines = [f"**Vehicles used:** {metrics.get('vehicles_used',0)} ",
63
+ f"**Capacity:** {metrics.get('capacity',0)} ",
64
+ f"**Total distance:** {metrics.get('total_distance',0):.2f}
65
+ "]
66
+ per = metrics.get('per_route_distance', [])
67
+ if per:
68
+ lines.append("**Per-route distances:**
69
+ ")
70
+ for i, d in enumerate(per, 1):
71
+ load = metrics.get('per_route_load', [])[i-1] if metrics.get('per_route_load') else "-"
72
+ lines.append(f"- Route {i}: {d:.2f} (load {load}) ")
73
+ tw = metrics.get('time_window_report', {})
74
+ if tw:
75
+ lines.append('
76
+ **Time windows** ')
77
+ lines.append(f"- lateness count: {tw.get('total_lateness_count',0)} ")
78
+ lines.append(f"- total lateness: {tw.get('total_lateness',0):.2f} ")
79
+ lines.append(f"- status: {tw.get('status','-')} ")
80
+ return "
81
+ ".join(lines)
82
+
83
+ # Safe file writer
84
+ def _write_df_to_temp(df):
85
+ tf = tempfile.NamedTemporaryFile(delete=False, suffix='.csv')
86
+ df.to_csv(tf.name, index=False)
87
+ tf.flush(); tf.close()
88
+ return tf.name
89
+
90
+ # ---------- core app functions (return types compatible with Gradio)
91
+
92
+ def run_generate(n_clients, n_vehicles, capacity, spread, demand_min, demand_max, seed, speed, preset):
93
+ # presets tweak spread / capacities
94
+ if preset == 'City (dense)':
95
+ spread = max(20, spread/2)
96
+ elif preset == 'Suburban':
97
+ spread = max(80, spread*1.5)
98
 
 
99
  df = generate_random_instance(
100
  n_clients=int(n_clients),
101
  n_vehicles=int(n_vehicles),
 
105
  demand_max=int(demand_max),
106
  seed=int(seed),
107
  )
108
+ sol = solve_vrp_tw(df, depot=(0,0), n_vehicles=int(n_vehicles), capacity=int(capacity), speed=float(speed))
109
+ img = plot_solution(df, sol, depot=(0,0))
110
+ csv_path = _write_df_to_temp(sol['assignments_table'])
 
 
 
 
 
111
  metrics_md = format_metrics(sol.get('metrics', {}))
112
+ return img, sol['assignments_table'], metrics_md, csv_path
113
+
114
 
115
+ def run_upload(file, n_vehicles, capacity, speed):
116
  if file is None:
117
+ raise gr.Error('Please upload a CSV')
118
+ # Gradio's File returns a tempfile-like object with .name
119
  df = parse_uploaded_csv(file.name if hasattr(file, 'name') else file)
120
+ sol = solve_vrp_tw(df, depot=(0,0), n_vehicles=int(n_vehicles), capacity=int(capacity), speed=float(speed))
121
+ img = plot_solution(df, sol, depot=(0,0))
122
+ csv_path = _write_df_to_temp(sol['assignments_table'])
 
 
 
 
 
123
  metrics_md = format_metrics(sol.get('metrics', {}))
124
+ return img, sol['assignments_table'], metrics_md, csv_path
125
+
126
 
127
  def download_template():
128
  df = make_template_dataframe()
129
+ return _write_df_to_temp(df)
 
 
 
130
 
131
+ # ---------- UI
132
  with gr.Blocks(title=TITLE, css=CUSTOM_CSS) as demo:
133
+ with gr.Row():
134
  with gr.Column(scale=1):
135
+ with gr.Box(elem_classes='sidebar'):
136
+ gr.Markdown(f"<div class='brand'>{TITLE}</div>")
137
+ gr.Markdown("<div class='small'>Quickly generate scenarios or upload your data. Use presets for common patterns.</div>")
138
+ with gr.TabbedInterface():
139
+ with gr.Tab('Generate'):
140
+ preset = gr.Dropdown(['Default','City (dense)','Suburban'], value='Default', label='Preset')
141
+ n_clients = gr.Slider(5, 200, value=30, step=1, label='Clients')
142
+ n_vehicles = gr.Slider(1, 50, value=5, step=1, label='Vehicles')
143
+ capacity = gr.Slider(1, 100, value=10, step=1, label='Capacity')
144
+ spread = gr.Slider(10, 500, value=60, step=5, label='Spread')
145
+ demand_min = gr.Slider(1, 5, value=1, step=1, label='Demand min')
146
+ demand_max = gr.Slider(1, 10, value=3, step=1, label='Demand max')
147
+ seed = gr.Number(value=42, label='Seed')
148
+ speed = gr.Number(value=10.0, label='Vehicle speed')
149
+ gen_btn = gr.Button('Generate & Solve')
150
+ gen_dl = gr.File(label='Download last assignments')
151
+
152
+ with gr.Tab('Upload'):
153
+ upload_file = gr.File(label='Upload CSV (id,x,y,demand,tw_start,tw_end,service)')
154
+ up_vehicles = gr.Slider(1, 100, value=5, step=1, label='Vehicles')
155
+ up_capacity = gr.Slider(1, 200, value=15, step=1, label='Capacity')
156
+ up_speed = gr.Number(value=10.0, label='Vehicle speed')
157
+ up_btn = gr.Button('Optimize uploaded CSV')
158
+ tmpl_btn = gr.Button('Download template CSV')
159
+ up_dl = gr.File(label='Download assignments')
160
+
161
+ gr.Markdown('---')
162
+ gr.Markdown('*Tip: click a run button, then download CSV from the right panel.*', elem_classes='small')
163
 
 
164
  with gr.Column(scale=2):
165
+ with gr.Box():
166
+ out_img = gr.Image(type='pil', label='Route map')
167
+ with gr.Row():
168
+ with gr.Column():
169
+ out_table = gr.Dataframe(headers=None, label='Assignments (table)', interactive=False)
170
+ with gr.Column(min_width=300):
171
+ out_metrics = gr.Markdown('No results yet', label='Metrics', elem_classes='metrics')
172
+ out_csv = gr.File(label='Download CSV')
173
+
174
+ gr.Markdown(f"---
175
+ {FOOTER}")
176
+
177
+ gen_btn.click(
178
+ fn=run_generate,
179
+ inputs=[n_clients, n_vehicles, capacity, spread, demand_min, demand_max, seed, speed, preset],
180
+ outputs=[out_img, out_table, out_metrics, gen_dl],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  )
182
 
183
+ up_btn.click(
184
+ fn=run_upload,
185
+ inputs=[upload_file, up_vehicles, up_capacity, up_speed],
186
+ outputs=[out_img, out_table, out_metrics, up_dl],
187
  )
188
 
189
+ tmpl_btn.click(fn=download_template, inputs=[], outputs=[up_dl])
 
 
 
190
 
191
  if __name__ == '__main__':
192
  demo.launch()