Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Aditya8102/Grow_Simplee_backend

Open more actions menu

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

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.