Skip to content

Aditya8102/Grow_Simplee_backend

Repository files navigation

Grow Simplee — VRP Routing Backend

A Django REST API that solves the Capacitated Vehicle Routing Problem with Time Windows (CVRPTW) for last-mile logistics — unified delivery and pickup stops on the same route, no paid API keys required.


Architecture

POST /address/optimize/
          │
          │  stops_csv (address, AWB, demand, lat, lon, stop_type)
          ▼
┌─────────────────────────────────────────────────┐
│             VRP Solver  (scripts/solver/)        │
│                                                  │
│  1. Build N×N time matrix (Haversine + speed)   │
│  2. Construct initial routes (PATH_CHEAPEST_ARC) │
│  3. Improve with GUIDED_LOCAL_SEARCH             │
│     (penalises overused arcs → escapes optima)  │
└──────────────────────┬──────────────────────────┘
                       │  dict[vehicle_id → list[RoutedStop]]
                       ▼
          Django REST API writes Orders to DB
                       │
                       ▼
          GET /address/csvDetails/    ← DP mobile app
          GET /address/analytics/     ← Admin dashboard

Key Features

  • Unified CVRPTW — pickups and deliveries in a single solve; pickups interleave naturally mid-route
  • GUIDED_LOCAL_SEARCH — measurably better than AUTOMATIC on 20–60 stop problems; escapes local optima by penalising overused arcs
  • Configurable per-request — every solver parameter (speed, shift length, fleet size, time limit) is an optional API param; nothing is hardcoded
  • Time-of-day speed — pass departure_hour to engage Bangalore rush-hour profiles; response includes speed_profile for immediate feedback
  • Role-based access — DP sees own orders; AD sees all; PA runs optimization
  • Free geocoding — Nominatim / OpenStreetMap for CLI mode; no API key needed
  • Analytics endpoint — completion rates, per-driver breakdown, capacity utilization

Tech Stack

Layer Technology
API framework Django 4.x + Django REST Framework
VRP solver Google OR-Tools (CVRPTW)
Distance model Haversine formula → integer time matrix
Geocoding (CLI) geopy + OpenStreetMap Nominatim
Auth DRF Token Authentication
Database SQLite (dev) / PostgreSQL via DATABASE_URL
Deployment Gunicorn + WhiteNoise

Quick Start

# 1. Clone and create virtualenv
git clone <repo-url>
cd Grow_Simplee_backend
python -m venv venv && source venv/bin/activate

# 2. Install dependencies
pip install -r requirements-dev.txt

# 3. Configure environment
cp .env.example .env          # Edit SECRET_KEY at minimum

# 4. Migrate and seed demo accounts
python manage.py migrate
python manage.py seed_demo    # creates driver50/51/52, admin, parent (password: demo1234)

# 5. Run
python manage.py runserver    # http://localhost:8000

Seed + run sample optimization in one command:

python manage.py seed_demo --reset --run-sample

API Reference

Method Endpoint Role Description
POST /login/register/ Open Register account
POST /login/token/ Open Get auth token
GET /login/me/ Any Current user info
POST /address/csvDetails/ DP / AD Orders by date with optional filters
POST /address/optimize/ PA Run VRP, persist routes, return summary
GET /address/analytics/ AD / PA Aggregated metrics for a date
POST /address/feeder/ PA Import CLI-generated CSVs from output_files/

All protected endpoints require Authorization: Token <token>.


POST /address/optimize/ — params

Param Type Default Description
stops_csv file sample_stops.csv Unified CSV: address, AWB, demand, latitude, longitude, stop_type
num_vehicles int auto Override fleet size
vehicle_capacity int 640 000 cm³ per vehicle
speed_kmh float 22.0 Fixed rider speed (ignored if departure_hour set)
departure_hour int 0–23 Enables Bangalore rush-hour speed profile
shift_hours float 6.0 Working shift length
solver_time_limit_secs int 300 OR-Tools hard stop
driver_emails str all DPs Comma-separated emails for assignment order
clear_today str "true" Replace existing orders for today

Sample response:

{
  "status": "completed",
  "date": "2026-03-22",
  "total_orders": 37,
  "vehicles": 3,
  "speed_profile": {
    "speed_kmh": 10.0,
    "mode": "time_of_day",
    "profile": "morning_rush (07:00–10:00)",
    "departure_hour": 8
  },
  "routes": [
    {
      "vehicle": 0, "driver": "driver50",
      "stops": 13, "deliveries": 10, "pickups": 3,
      "total_time_secs": 4320
    }
  ]
}

GET /address/analytics/?date=YYYY-MM-DD

{
  "date": "2026-03-22",
  "total_orders": 37,
  "deliveries": 29,
  "pickups": 8,
  "completed": 14,
  "pending": 23,
  "completion_rate": 0.378,
  "vehicles_active": 3,
  "avg_stops_per_vehicle": 12.3,
  "per_driver": [
    { "driver": "driver50", "stops": 13, "deliveries": 10,
      "pickups": 3, "completed": 5, "pending": 8 }
  ]
}

Algorithm Deep-Dive

Q: Why CVRPTW instead of a simpler greedy approach?

Greedy nearest-neighbour assigns each stop to the closest vehicle as stops arrive, producing routes 30–50% longer than optimal on typical Bangalore cluster distributions. CVRPTW models vehicle capacity and time windows simultaneously, allowing OR-Tools to explore thousands of candidate routes and enforce constraints globally.

Q: What does PATH_CHEAPEST_ARC do?

It's a greedy construction heuristic: starting from the depot, always extend the current route by the cheapest available arc (shortest travel time to an unvisited stop). This produces a feasible initial solution in milliseconds — fast, but often locally trapped because it never "looks ahead" past the next stop.

Q: Why GUIDED_LOCAL_SEARCH instead of AUTOMATIC?

AUTOMATIC uses the solver's default local search strategy, which for this problem class tends to run simulated annealing and get stuck in the same neighbourhood. GUIDED_LOCAL_SEARCH (GLS) adds a penalty to arcs that appear frequently in local optima, forcing the solver to explore qualitatively different route structures. On 20–60 stop inputs, GLS typically reduces total route time by 12–18% compared to AUTOMATIC within the same time budget.

Q: Why are pickups and deliveries solved together?

The original 3-pass design (delivery → pickup → second_pickup) solved each wave independently. Stops assigned to wave 1 were invisible to wave 2, so a driver might drive past a pickup location twice. The unified solve gives OR-Tools visibility of all stops simultaneously — pickups are interleaved naturally between deliveries on the least-cost route.

Q: Why Haversine instead of a real road-distance matrix?

A road distance matrix requires a mapping API (Google Maps, OSRM) — either paid or self-hosted. Haversine (crow-flies distance) divided by speed gives a lower-bound travel time; the solver's time limit compensates for inaccuracy by finding good solutions within the Haversine metric. For a production system, swapping matrix.py to call OSRM would improve accuracy with no changes to the solver or API.


Bangalore Speed Profiles

When departure_hour is set, the solver uses observed urban delivery speeds:

Time window Profile Speed
07:00–10:00 morning_rush 10 km/h
10:00–16:00 off_peak 25 km/h
16:00–20:00 evening_rush 12 km/h
20:00–07:00 night / early_morning 22 km/h

The selected profile and effective speed are returned in speed_profile for immediate feedback. Omit departure_hour (or set speed_kmh) to use a fixed speed throughout.


CLI Mode

# Run optimizer on input_files/sample_stops.csv, write to output_files/
cd scripts && python3 route.py

# Custom fleet and timing
python3 route.py --num-vehicles 3 --speed-kmh 25 --shift-hours 8

# Import CLI output into DB
python3 reader.py --all

Project Structure

delivery/           Django project settings
login/              Account model, DRF token auth, 3 user roles
address/            Location + Order models, views, serializers
scripts/
  solver/
    constants.py    Named constants + Bangalore speed profiles
    types.py        VRPNode, VRPConfig, RoutedStop dataclasses
    matrix.py       Haversine time_calculator + create_time_matrix
    optimizer.py    Unified solve_vrp() — single OR-Tools CVRPTW solve
    geocoding.py    Nominatim geocoding for CLI mode
    output.py       CLI CSV writer
  route.py          optimize_from_dataframe() API entry point + CLI
  reader.py         Imports output_files/Final_Driver*.csv into DB
input_files/        sample_stops.csv (38 rows, 3 Bangalore clusters)
.env.example        Environment variable template

Environment Variables

Variable Default Description
SECRET_KEY Django secret key (required)
DEBUG False Enable debug mode
ALLOWED_HOSTS localhost,127.0.0.1 Comma-separated
DATABASE_URL SQLite PostgreSQL URL in production
CORS_ALLOWED_ORIGINS http://localhost:3000 Comma-separated

Tests

python manage.py test --verbosity=2   # 37 tests

Covers: auth flows, role-based filtering, optimizer mocking, rush-hour speed profiles, analytics aggregation, solver error handling.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors