Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VRP Optimizer

Web application for the Capacitated Vehicle Routing Problem (CVRP) using the Column Elimination algorithm. Upload fleet and delivery data, compute travel times, run the solver, and view optimized routes on an interactive map.

Features

  • Upload locations via CSV (addresses and/or lat/lng)
  • Geocoding: Nominatim (free) or Google (with API key)
  • Distance matrix: haversine (free) or Google Distance Matrix (with API key)
  • Column Elimination solver with real-time progress over WebSocket
  • Interactive Leaflet map, route table, and solver log

Tech Stack

Layer Technology
Frontend React, TypeScript, Vite, Tailwind CSS, Leaflet, Recharts, Zustand, React Query
Backend Python 3.11+, FastAPI, SQLAlchemy (async), Celery, Redis
Database PostgreSQL
APIs Optional: Google Maps Geocoding + Distance Matrix; default: Nominatim + haversine

Prerequisites

  • Node.js 18+ and npm
  • Python 3.11+
  • PostgreSQL 16 (or use Docker)
  • Redis (or use Docker)
  • Docker and Docker Compose (optional, for full stack)

Quick Start (local)

If you see ECONNREFUSED or "http proxy error: /problems" in the Vite terminal: the frontend is running but the backend is not. Start the backend as below.

Option A: Run without Docker (no Postgres/Redis)

Works with no Docker, no PostgreSQL, no Redis. The app uses SQLite and runs the solver in-process.

  1. Backend (one terminal):

    cd backend
    pip install -r requirements.txt
    python -m uvicorn app.main:app --host 0.0.0.0 --port 8000

    Or on Windows: .\run_server.ps1 from the backend folder.

    Do not set DATABASE_URL or REDIS_URL (or leave REDIS_URL empty). Defaults: SQLite file ./vrp.db, solver runs in the same process.

  2. Frontend (another terminal):

    cd frontend
    npm install
    npm run dev
  3. Open http://localhost:5173. Upload a CSV, set K and Q, then Create and run. The run may take 30–60 seconds (solver runs in-process; no live progress in the UI).

Option B: Run with Docker (Postgres + Redis + Celery)

For live solver progress and production-like setup.

1. Database and Redis

docker compose up -d postgres redis

Wait ~10 seconds for Postgres to be ready.

2. Backend

cd backend
cp .env.example .env

Edit .env and set:

  • DATABASE_URL=postgresql+asyncpg://vrp_user:vrp_pass@localhost:5432/vrp_db
  • REDIS_URL=redis://localhost:6379/0

Then:

pip install -r requirements.txt
alembic upgrade head
uvicorn app.main:app --host 0.0.0.0 --port 8000

In a second terminal, start the Celery worker:

cd backend
celery -A app.celery_app worker -l info

3. Frontend

cd frontend
npm install
npm run dev

Open http://localhost:5173. The Vite dev server proxies /api and /ws to the backend.

Environment Variables

Backend (backend/.env)

Variable Description Default
DATABASE_URL PostgreSQL URL (use postgresql+asyncpg:// for async) postgresql+asyncpg://vrp_user:vrp_pass@localhost:5432/vrp_db
REDIS_URL Redis URL for Celery broker/backend redis://localhost:6379/0
GOOGLE_MAPS_API_KEY Google Geocoding + Distance Matrix key (empty)
GEOCODING_PROVIDER nominatim (free) or google nominatim
SECRET_KEY App secret (e.g. JWT) change-me-in-production
SOLVER_TIME_LIMIT_SECONDS Max solver runtime 60
SOLVER_MAX_NODES Max decision diagram nodes 50000
SOLVER_OPTIMALITY_GAP Stop when gap below this 0.005
MAPS_BATCH_SIZE Origins/destinations per Google Matrix request 10
UPLOAD_DIR Directory for uploaded files uploads

With no Google API key: geocoding uses Nominatim (1 req/sec), and the distance matrix uses haversine (straight-line). Suitable for testing.

Frontend

Variable Description
VITE_API_URL Backend base URL (e.g. http://localhost:8000). Omit to use dev proxy /api.
VITE_WS_URL WebSocket base URL. Omit to use same host as the app.

Running with Docker Compose

From the project root:

docker compose up -d postgres redis
docker compose up -d backend
docker compose up -d celery_worker
docker compose up -d frontend

Ensure backend/.env exists (or pass env in compose) with at least DATABASE_URL and REDIS_URL for the backend and worker.

Locations CSV Format

Required columns:

Column Description
location_id Unique string (e.g. STOP_001)
address Full address (optional if lat/lng provided)
latitude Decimal degrees (optional if address provided)
longitude Decimal degrees (optional if address provided)
demand Units to deliver; use 0 for depot
is_depot true or false; exactly one row must be true

Validation rules:

  • Exactly one row with is_depot = true
  • All demands ≥ 0
  • Total demand ≤ K × Q (number of vehicles × vehicle capacity)
  • Each row has either a non-empty address or both latitude and longitude

Fleet Configuration (form)

  • Number of vehicles (K) – integer, ≥ 1
  • Vehicle capacity (Q) – max demand per vehicle (homogeneous fleet)
  • Problem name – optional label

API Endpoints

Method Path Description
POST /problems Create problem (multipart: CSV + form)
GET /problems List problems
GET /problems/{id} Get problem status
DELETE /problems/{id} Delete problem
POST /problems/{id}/run Start solver (returns task_id)
GET /problems/{id}/solution Get latest solution
GET /problems/{id}/solver-log Solver iteration log
GET /solutions/{id} Get solution by ID
GET /tasks/{task_id} Celery task status
WS /ws/problems/{id}/progress Solver progress stream

Algorithm Constraints (UI disclaimer)

  • Homogeneous fleet – same capacity Q for all vehicles
  • Single depot – all routes start and end at the same depot
  • No time windows – objective is distance only
  • Scale – practical up to ~75 stops; beyond ~100 use heuristic/early-stop
  • Demands – integers or simple decimals recommended

Test Uploads (proof of concept)

Sample CSVs are in test-uploads/:

File Description Suggested K Q
small_5_stops.csv 5 locations (1 depot + 4), paper-style instance 2 3
medium_10_stops.csv 10 stops with lat/lng 2–3 15
addresses_only.csv Addresses only (tests Nominatim geocoding) 2 10
sample_with_labels.csv Same as small with clear labels 2 3

Use New problem in the app, upload one of these files, set K and Q, then Create and run. For the small instance, total demand is 5; use K=2, Q=3 so that 2×3 ≥ 5.

Project Structure

frontend/          # Vite + React app
backend/           # FastAPI app
  app/
    main.py        # FastAPI app, CORS, routes
    config.py      # Settings from env
    database.py    # Async SQLAlchemy engine/session
    models.py      # SQLAlchemy models
    schemas.py     # Pydantic schemas
    csv_parser.py  # CSV parse + validation
    celery_app.py  # Celery app
    tasks.py       # Celery pipeline (geocode → matrix → solver)
    services/maps.py  # Geocoding + distance matrix
    solver/column_elimination.py  # Column Elimination solver
    routers/       # problems, solutions, tasks
    websocket.py   # Progress WebSocket
  alembic/        # Migrations
  tests/          # Solver unit test
test-uploads/     # Sample CSV files for PoC
docker-compose.yml

Troubleshooting

Symptom Cause Fix
ECONNREFUSED or "http proxy error: /problems" in Vite Backend not running on port 8000 Start backend: cd backend then uvicorn app.main:app --host 0.0.0.0 --port 8000.
pip install fails with "Rust not found" / "pydantic-core" Old pydantic needs Rust to build on Python 3.13 Use the updated requirements.txt (pydantic>=2.10). If it still fails, run: pip install aiosqlite "pydantic>=2.10" "pydantic-settings>=2.0" then pip install -r requirements.txt. Or use Python 3.11/3.12.
ModuleNotFoundError: No module named 'aiosqlite' aiosqlite not installed (needed for SQLite) Run: pip install aiosqlite then start the backend again.
Backend fails on startup (password/auth) Wrong DATABASE_URL or local Postgres user For no-Docker, don't set DATABASE_URL (SQLite default). Or use Docker: docker compose up -d postgres redis.
Upload returns 500 Server error; check response details Backend returns the exception in the error details. Restart backend after code changes.

Running Tests

Backend solver test:

cd backend
pip install pytest
python -m pytest tests/test_column_elimination.py -v

License

Use as needed for the project.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages