File size: 5,101 Bytes
5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d 8a63926 5ac2f2d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | import json
import gradio as gr
import pandas as pd
from solver import (
generate_random_instance,
solve_vrp,
plot_solution,
parse_uploaded_csv,
make_template_dataframe,
)
TITLE = "Ride-Sharing Optimizer (Capacitated VRP) β Gradio Demo"
DESC = """
This demo assigns **stops (riders)** to **drivers (vehicles)** with a simple, fast heuristic:
**Sweep clustering** β **Greedy routing** β **2-opt improvement**.
You can **generate a sample** dataset or **upload a CSV** with columns:
`id,x,y,demand,tw_start,tw_end,service`.
- **Capacity** = max riders per vehicle (sum of `demand` per route).
- **Time windows** are *soft* (violations are reported in metrics).
- Distances are Euclidean on the X-Y plane for clarity.
π‘ Tip: Start with the generator, then switch to your CSV.
"""
FOOTER = "Made with β€οΈ using Gradio. No native dependencies; runs quickly on Spaces."
# -----------------------------
# Functions
# -----------------------------
def run_generator(n_clients, n_vehicles, capacity, spread, demand_min, demand_max, seed):
df = generate_random_instance(
n_clients=n_clients,
n_vehicles=n_vehicles,
capacity=capacity,
spread=spread,
demand_min=demand_min,
demand_max=demand_max,
seed=seed,
)
depot = (0.0, 0.0)
sol = solve_vrp(df, depot=depot, n_vehicles=n_vehicles, capacity=capacity, speed=1.0)
# β
plot_solution now returns a PIL image
img = plot_solution(df, sol, depot=depot)
route_table = sol["assignments_table"]
metrics = json.dumps(sol["metrics"], indent=2)
return img, route_table, metrics, df
def run_csv(file, n_vehicles, capacity):
if file is None:
raise gr.Error("Please upload a CSV first.")
try:
df = parse_uploaded_csv(file)
except Exception as e:
raise gr.Error(f"CSV parsing error: {e}")
depot = (0.0, 0.0)
sol = solve_vrp(df, depot=depot, n_vehicles=n_vehicles, capacity=capacity, speed=1.0)
img = plot_solution(df, sol, depot=depot)
route_table = sol["assignments_table"]
metrics = json.dumps(sol["metrics"], indent=2)
return img, route_table, metrics
def download_template():
return make_template_dataframe()
# -----------------------------
# UI Layout
# -----------------------------
with gr.Blocks(title=TITLE) as demo:
gr.Markdown(f"# {TITLE}")
gr.Markdown(DESC)
with gr.Tab("π Generate sample"):
with gr.Row():
with gr.Column():
n_clients = gr.Slider(5, 200, value=30, step=1, label="Number of riders (clients)")
n_vehicles = gr.Slider(1, 20, value=4, step=1, label="Number of drivers (vehicles)")
capacity = gr.Slider(1, 50, value=10, step=1, label="Vehicle capacity (sum of demand)")
spread = gr.Slider(10, 200, value=50, step=1, label="Spatial spread (larger = wider map)")
demand_min = gr.Slider(1, 5, value=1, step=1, label="Min demand per stop")
demand_max = gr.Slider(1, 10, value=3, step=1, label="Max demand per stop")
seed = gr.Slider(0, 9999, value=42, step=1, label="Random seed")
run_btn = gr.Button("π Generate & Optimize", variant="primary")
with gr.Column():
img = gr.Image(type="pil", label="Route Visualization", interactive=False)
with gr.Row():
route_df = gr.Dataframe(label="Route assignments (per stop)", wrap=True)
metrics = gr.Code(label="Metrics (JSON)")
with gr.Accordion("Show generated dataset", open=False):
data_out = gr.Dataframe(label="Generated input data")
run_btn.click(
fn=run_generator,
inputs=[n_clients, n_vehicles, capacity, spread, demand_min, demand_max, seed],
outputs=[img, route_df, metrics, data_out],
)
with gr.Tab("π Upload CSV"):
with gr.Row():
with gr.Column():
file = gr.File(label="Upload CSV (id,x,y,demand,tw_start,tw_end,service)")
dl_tmp = gr.Button("Get CSV Template")
n_vehicles2 = gr.Slider(1, 50, value=5, step=1, label="Number of drivers (vehicles)")
capacity2 = gr.Slider(1, 200, value=15, step=1, label="Vehicle capacity (sum of demand)")
run_btn2 = gr.Button("π Optimize uploaded data", variant="primary")
with gr.Column():
img2 = gr.Image(type="pil", label="Route Visualization", interactive=False)
with gr.Row():
route_df2 = gr.Dataframe(label="Route assignments (per stop)")
metrics2 = gr.Code(label="Metrics (JSON)")
run_btn2.click(
fn=run_csv,
inputs=[file, n_vehicles2, capacity2],
outputs=[img2, route_df2, metrics2],
)
def _tmpl():
return gr.File.update(value=None), download_template()
dl_tmp.click(fn=_tmpl, outputs=[file, route_df2], inputs=None)
gr.Markdown(f"---\n{FOOTER}")
if __name__ == "__main__":
demo.launch()
|