Skip to main content

A Clean and Fast Vehicle Routing Problem Solver Powered by Genetic Algorithms.

Project description

pyRouteForge

A clean and fast Vehicle Routing Problem solver — powered by Genetic Algorithms.

pyRouteForge solves a wide family of routing problems with a single function call:

  • Capacitated VRP — ( Colab Demo ) — Assign customers to a vehicle fleet with capacity limits
  • Multi-Depot VRP — ( Colab Demo ) — Multiple starting depots, depot auto-assignment per route
  • VRP with Time Windows — ( Colab Demo ) — Earliest/latest arrival, service times, waiting costs
  • Heterogeneous Fleet — ( Colab Demo ) — Mix vehicle types with different capacities, costs, speeds
  • Finite or Infinite Fleet — ( Colab Demo ) — Set hard limits on vehicle counts or leave them open
  • TSP — ( Colab Demo ) — Classical Travelling Salesman
  • mTSP — ( Colab Demo ) — Multi-Depot Travelling Salesman
  • Open or Closed Routes — ( Colab Demo ) — Return to depot or finish at the last customer

Features

  • One function: solve() — that accepts a pandas DataFrame, a numpy array, or just a distance matrix
  • One result object: Solution — with .report, .routes, .total_distance, and .plot()
  • Plotly: that render natively in Google Colab, Jupyter, and as standalone HTML

Installation

pip install pyrouteforge

Quick start

import pandas as pd
from pyrouteforge import solve

# Row 0 is the depot, the rest are customers.
df = pd.DataFrame({
					"x":      [40, 25, 22, 22, 20, 20, 18, 15, 15],
					"y":      [50, 85, 75, 85, 80, 85, 75, 75, 80],
					"demand": [ 0, 20, 30, 10, 40, 20, 20, 20, 10],
				  })

result = solve(
					locations     = df,
					n_depots      = 1,
					capacity      = 150,
					fixed_cost    = 30,
					variable_cost = 2,
					velocity      = 70,
					generations   = 300,
					seed          = 42,
			   )

print(f"Total Distance: {result.total_distance:.2f}")
result.plot().show()         
result.plot_convergence().show()

Output:

Total distance: 263.41

Route #1: depot = 0, vehicle = 0, load = 130, distance = 152.66, stops = [5, 3, 1, 8, 7, 6, 2, 4]

Input formats

solve() is deliberately flexible. Whatever you have on hand, it'll work.

a. A pandas DataFrame (recommended)

The most natural format. pyRouteForge auto-detects column names:

What you mean Recognised column aliases
X coordinate x, lon, lng, longitude
Y coordinate y, lat, latitude
Demand demand, weight, load, qty, quantity
Time window start tw_early, ready_time, earliest, open_time
Time window end tw_late, due_time, latest, close_time
Service time tw_service_time, service_time, service
Waiting cost tw_wait_cost, wait_cost, waiting_cost
Display label name, label, id

b. A numpy array of coordinates

import numpy as np
arr    = np.array([
                    [40, 50], 
					[25, 85], 
					[22, 75], 
					[22, 85]
			      ])
result = solve(locations = arr, demand = [0, 20, 30, 10], capacity = 100)

c. A precomputed distance matrix

When your network isn't Euclidean (real-world driving distances, sea routes, etc.):

result = solve(
				distance_matrix = dm,            
				demand          = [0, 20, 30, 10],
				capacity        = 100,
			  )

Vehicle specification

Homogeneous fleet — simple kwargs

result = solve(
				locations     = df,
				capacity      = 150,
				fixed_cost    = 30,
				variable_cost = 2,
				velocity      = 70,
				fleet_size    = 5,  # omit for infinite
			)

Heterogeneous fleet — list of dicts

result = solve(
					locations = df,
					vehicles  = [
									{"capacity": 50,  "fixed_cost": 10, "variable_cost": 0.5,
									 "velocity": 60,  "count": 3},     
									{"capacity": 100, "fixed_cost": 30, "variable_cost": 1.2,
									 "velocity": 80,  "count": 2},    
								],
				)

Working with the result

solve() returns a Solution with everything you need:

result.total_distance      # float
result.total_cost          # float
result.n_routes            # int
result.routes              # list of dicts: route_id, vehicle_type, depot, stops, load, distance
result.report              # pandas DataFrame: per-stop schedule (load, arrival/leave times, etc.)
result.history             # list[float] — best distance per generation
result.coordinates         # np.ndarray — the (n, 2) layout used for plotting
result.raw                 # internal [depots, routes, vehicles] structure (advanced use)

# Plotting
result.plot()              # main route map
result.plot_convergence()  # GA fitness curve
result.plot_loads(         # bar chart of load vs capacity per route
					capacity   = [150],
					parameters = problem.parameters,
				 )

# Export
result.to_csv("routes.csv")

Plotting

All figures are plotly.graph_objects.Figure instances:

fig = result.plot(title = "Solution", width = 1100, height = 750)
fig.show()                                 # Jupyter / Colab inline
fig.write_html("solution.html")            # standalone HTML
fig.write_image("solution.png", scale = 2) # requires kaleido

The default styling is a dark theme with:

  • Glow underlay + crisp main line for each route, distinct colors per route
  • Arrowheads on every leg so direction is obvious
  • Square depot markers in amber, circular client markers in slate
  • Rich hover tooltips with stop number, vehicle type, coordinates
  • Equal-aspect axes so geometry isn't distorted

Customize anything by accessing fig.layout / fig.data directly — it's just Plotly underneath.


GA hyper-parameters

All optional with sensible defaults. Larger instances generally want bigger populations and more generations.

Parameter Default Meaning
population_size 50 Number of candidate solutions per generation
generations 200 Total iterations
mutation_rate 0.10 Probability of mutation per individual
elite 1 Best individuals carried over unchanged each generation
penalty_value 10000 Penalty for violating capacity / time-window constraints
selection 'rw' 'rw' (roulette wheel) or 'rank'
seed None Reproducibility
verbose False Print per-generation progress

You can also pass an on_generation callback for live monitoring:

def progress(gen, distance, cost):
    print(f"Gen {gen}: distance = {distance:.2f}")

solve(locations = df, capacity = 100, on_generation = progress)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyrouteforge-1.4.0.tar.gz (32.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyrouteforge-1.4.0-py3-none-any.whl (30.5 kB view details)

Uploaded Python 3

File details

Details for the file pyrouteforge-1.4.0.tar.gz.

File metadata

  • Download URL: pyrouteforge-1.4.0.tar.gz
  • Upload date:
  • Size: 32.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.9

File hashes

Hashes for pyrouteforge-1.4.0.tar.gz
Algorithm Hash digest
SHA256 dc7e00a4513b0248862cc03064ce0cf88ed7d64af230170c2ebb9c741100b744
MD5 70ef6cd501835262f5daca8c66ad7d5d
BLAKE2b-256 62ab459c687cde4bf47a3af024d70fcd00634e0ee36cdf75b800a8471ce16739

See more details on using hashes here.

File details

Details for the file pyrouteforge-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: pyrouteforge-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 30.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.9

File hashes

Hashes for pyrouteforge-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 516d0ca4ce160d1479e05d9d165c1c8109c496ee962c63ea4abb4e0774ae3729
MD5 fc40e36026eb7f5d8957625374ed3d0e
BLAKE2b-256 59e207a1f94b1a9d4238f8763168aa408b1b9a2f5016e6be7b013fa3c5acef12

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page