Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
import io
|
| 2 |
import json
|
| 3 |
import gradio as gr
|
| 4 |
import pandas as pd
|
|
@@ -21,14 +20,16 @@ You can **generate a sample** dataset or **upload a CSV** with columns:
|
|
| 21 |
- **Time windows** are *soft* (violations are reported in metrics).
|
| 22 |
- Distances are Euclidean on the X-Y plane for clarity.
|
| 23 |
|
| 24 |
-
Tip: Start with the generator, then switch to your CSV.
|
| 25 |
"""
|
| 26 |
|
| 27 |
FOOTER = "Made with β€οΈ using Gradio. No native dependencies; runs quickly on Spaces."
|
| 28 |
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
|
|
|
|
|
|
| 32 |
df = generate_random_instance(
|
| 33 |
n_clients=n_clients,
|
| 34 |
n_vehicles=n_vehicles,
|
|
@@ -39,23 +40,18 @@ def run_generator(
|
|
| 39 |
seed=seed,
|
| 40 |
)
|
| 41 |
depot = (0.0, 0.0)
|
| 42 |
-
sol = solve_vrp(
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
buf = io.BytesIO()
|
| 47 |
-
fig.savefig(buf, format="png", bbox_inches="tight", dpi=160)
|
| 48 |
-
buf.seek(0)
|
| 49 |
|
| 50 |
-
# Route table
|
| 51 |
route_table = sol["assignments_table"]
|
| 52 |
metrics = json.dumps(sol["metrics"], indent=2)
|
| 53 |
|
| 54 |
-
return
|
| 55 |
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
):
|
| 59 |
if file is None:
|
| 60 |
raise gr.Error("Please upload a CSV first.")
|
| 61 |
try:
|
|
@@ -64,22 +60,22 @@ def run_csv(
|
|
| 64 |
raise gr.Error(f"CSV parsing error: {e}")
|
| 65 |
|
| 66 |
depot = (0.0, 0.0)
|
| 67 |
-
sol = solve_vrp(
|
| 68 |
-
|
| 69 |
-
)
|
| 70 |
-
fig = plot_solution(df, sol, depot=depot)
|
| 71 |
-
buf = io.BytesIO()
|
| 72 |
-
fig.savefig(buf, format="png", bbox_inches="tight", dpi=160)
|
| 73 |
-
buf.seek(0)
|
| 74 |
|
| 75 |
route_table = sol["assignments_table"]
|
| 76 |
metrics = json.dumps(sol["metrics"], indent=2)
|
| 77 |
-
return
|
|
|
|
| 78 |
|
| 79 |
def download_template():
|
| 80 |
-
|
| 81 |
-
return df
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
with gr.Blocks(title=TITLE) as demo:
|
| 84 |
gr.Markdown(f"# {TITLE}")
|
| 85 |
gr.Markdown(DESC)
|
|
@@ -96,7 +92,8 @@ with gr.Blocks(title=TITLE) as demo:
|
|
| 96 |
seed = gr.Slider(0, 9999, value=42, step=1, label="Random seed")
|
| 97 |
run_btn = gr.Button("π Generate & Optimize", variant="primary")
|
| 98 |
with gr.Column():
|
| 99 |
-
img = gr.Image(label="Route Visualization", interactive=False)
|
|
|
|
| 100 |
with gr.Row():
|
| 101 |
route_df = gr.Dataframe(label="Route assignments (per stop)", wrap=True)
|
| 102 |
metrics = gr.Code(label="Metrics (JSON)")
|
|
@@ -118,7 +115,7 @@ with gr.Blocks(title=TITLE) as demo:
|
|
| 118 |
capacity2 = gr.Slider(1, 200, value=15, step=1, label="Vehicle capacity (sum of demand)")
|
| 119 |
run_btn2 = gr.Button("π Optimize uploaded data", variant="primary")
|
| 120 |
with gr.Column():
|
| 121 |
-
img2 = gr.Image(label="Route Visualization", interactive=False)
|
| 122 |
|
| 123 |
with gr.Row():
|
| 124 |
route_df2 = gr.Dataframe(label="Route assignments (per stop)")
|
|
|
|
|
|
|
| 1 |
import json
|
| 2 |
import gradio as gr
|
| 3 |
import pandas as pd
|
|
|
|
| 20 |
- **Time windows** are *soft* (violations are reported in metrics).
|
| 21 |
- Distances are Euclidean on the X-Y plane for clarity.
|
| 22 |
|
| 23 |
+
π‘ Tip: Start with the generator, then switch to your CSV.
|
| 24 |
"""
|
| 25 |
|
| 26 |
FOOTER = "Made with β€οΈ using Gradio. No native dependencies; runs quickly on Spaces."
|
| 27 |
|
| 28 |
+
|
| 29 |
+
# -----------------------------
|
| 30 |
+
# Functions
|
| 31 |
+
# -----------------------------
|
| 32 |
+
def run_generator(n_clients, n_vehicles, capacity, spread, demand_min, demand_max, seed):
|
| 33 |
df = generate_random_instance(
|
| 34 |
n_clients=n_clients,
|
| 35 |
n_vehicles=n_vehicles,
|
|
|
|
| 40 |
seed=seed,
|
| 41 |
)
|
| 42 |
depot = (0.0, 0.0)
|
| 43 |
+
sol = solve_vrp(df, depot=depot, n_vehicles=n_vehicles, capacity=capacity, speed=1.0)
|
| 44 |
+
|
| 45 |
+
# β
plot_solution now returns a PIL image
|
| 46 |
+
img = plot_solution(df, sol, depot=depot)
|
|
|
|
|
|
|
|
|
|
| 47 |
|
|
|
|
| 48 |
route_table = sol["assignments_table"]
|
| 49 |
metrics = json.dumps(sol["metrics"], indent=2)
|
| 50 |
|
| 51 |
+
return img, route_table, metrics, df
|
| 52 |
|
| 53 |
+
|
| 54 |
+
def run_csv(file, n_vehicles, capacity):
|
|
|
|
| 55 |
if file is None:
|
| 56 |
raise gr.Error("Please upload a CSV first.")
|
| 57 |
try:
|
|
|
|
| 60 |
raise gr.Error(f"CSV parsing error: {e}")
|
| 61 |
|
| 62 |
depot = (0.0, 0.0)
|
| 63 |
+
sol = solve_vrp(df, depot=depot, n_vehicles=n_vehicles, capacity=capacity, speed=1.0)
|
| 64 |
+
|
| 65 |
+
img = plot_solution(df, sol, depot=depot)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
route_table = sol["assignments_table"]
|
| 68 |
metrics = json.dumps(sol["metrics"], indent=2)
|
| 69 |
+
return img, route_table, metrics
|
| 70 |
+
|
| 71 |
|
| 72 |
def download_template():
|
| 73 |
+
return make_template_dataframe()
|
|
|
|
| 74 |
|
| 75 |
+
|
| 76 |
+
# -----------------------------
|
| 77 |
+
# UI Layout
|
| 78 |
+
# -----------------------------
|
| 79 |
with gr.Blocks(title=TITLE) as demo:
|
| 80 |
gr.Markdown(f"# {TITLE}")
|
| 81 |
gr.Markdown(DESC)
|
|
|
|
| 92 |
seed = gr.Slider(0, 9999, value=42, step=1, label="Random seed")
|
| 93 |
run_btn = gr.Button("π Generate & Optimize", variant="primary")
|
| 94 |
with gr.Column():
|
| 95 |
+
img = gr.Image(type="pil", label="Route Visualization", interactive=False)
|
| 96 |
+
|
| 97 |
with gr.Row():
|
| 98 |
route_df = gr.Dataframe(label="Route assignments (per stop)", wrap=True)
|
| 99 |
metrics = gr.Code(label="Metrics (JSON)")
|
|
|
|
| 115 |
capacity2 = gr.Slider(1, 200, value=15, step=1, label="Vehicle capacity (sum of demand)")
|
| 116 |
run_btn2 = gr.Button("π Optimize uploaded data", variant="primary")
|
| 117 |
with gr.Column():
|
| 118 |
+
img2 = gr.Image(type="pil", label="Route Visualization", interactive=False)
|
| 119 |
|
| 120 |
with gr.Row():
|
| 121 |
route_df2 = gr.Dataframe(label="Route assignments (per stop)")
|