Skip to main content

Solver-agnostic VRP modeling library

Project description

vrp-model

Solver-agnostic vehicle routing: a canonical Model, layered validation, automatic feature detection, and pluggable backends. Entities reference each other via view objects (Depot, Vehicle, Job) on the same model. Optional label is for display/export only.

Python: 3.11+ · Core dependency: vrplib (instance I/O).

Installation

As a dependency

The distribution name on PyPI is vrp-model; import the package as vrp_model.

pip

pip install vrp-model
pip install "vrp-model[pyvrp]"  # one optional extra
pip install "vrp-model[pyvrp,ortools,vroom,nextroute]"  # multiple extras

uv

uv add vrp-model
uv add "vrp-model[pyvrp]"
uv add "vrp-model[pyvrp,ortools,vroom,nextroute]"

Optional dependency groups use the same names as in Available solvers: pyvrp, ortools, vroom, nextroute.

From this repository

uv sync                                    # core only (no solver backends)
uv sync --extra pyvrp                      # PyVRP
uv sync --extra ortools                    # Google OR-Tools
uv sync --extra vroom                      # VROOM (pyvroom + NumPy + pandas)
uv sync --extra nextroute                  # Nextmv Nextroute
uv sync --extra pyvrp --extra ortools --extra vroom --extra nextroute --group dev

Each extra installs the matching third-party package; solver classes raise SolverNotInstalledError if the extra was not installed.

Available solvers

Solvers register under short names (import the submodule once so registration runs, or construct the class directly):

Registry name Class Extra Notes
pyvrp PyVRPSolver pyvrp In-process PyVRP; strong default for “classic” VRP with sparse matrices or Euclidean legs.
ortools ORToolsSolver ortools Google OR-Tools routing; broadest feature coverage in this repo.
vroom VroomSolver vroom pyvroom; matrix-based. On some platforms, matrix setup can fail unless NumPy and pyvroom versions match (see solver docstring).
nextroute NextrouteSolver nextroute Nextmv Nextroute; time windows use an anchor datetime in solver options.
from vrp_model.solvers.pyvrp import PyVRPSolver  # registers "pyvrp"
from vrp_model.solvers import get

solver_cls = get("pyvrp")
result = solver_cls({"time_limit": 2.0, "msg": False}).solve(model)

Placeholder packages under vrp_model/solvers/ (e.g. jsprit, vrpy) are not implemented; they are reserved for future work.

What is modeled (VRP in this package)

Vehicle routing here means assigning jobs to vehicles (routes), respecting travel between unified node ids (depots and jobs), optional capacity dimensions, time logic (service durations, windows, and caps), pickup–delivery pairs, job groups (mutually exclusive alternatives via add_job_group), depot topology, and fleet diversity. The canonical Model holds jobs, vehicles, optional pickup–delivery links, and sparse travel overrides; Feature summarizes which constraint families appear so solvers can declare compatibility.

Detection vs. adapters. Model.detect_features() sets Feature from stored fields (e.g. any positive demand or non-empty vehicle capacity → CAPACITY; job or vehicle time windows → TIME_WINDOWS; soft penalties in TimeWindowFlexFLEXIBLE_TIME_WINDOWS). Other behavior—service times, Euclidean vs matrix travel, primary optimization emphasis (distance vs duration)—is not a Feature flag but is still passed through each solver adapter where the backend supports it.

Solver capability matrix

Before solving, Solver.solve runs Model.validate() and Model.check_solver_compatibility(solver), which raises SolverCapabilityError if a declared Feature is missing from the solver’s supported_features. One row per modeled capability:

Feature pyvrp ortools nextroute vroom
Capacity (one or more resource dimensions; demands on jobs, caps on vehicles)
Hard time windows at jobs
Hard time windows at vehicles (shift / availability)
Pickup–delivery pairs (precedence and same vehicle)
Multi-depot (vehicles may start/end at different depots)
Heterogeneous fleet (distinct vehicle definitions)
Service time at jobs (added into time accounting)
Vehicle fixed use cost (activation / fixed cost per route)
Maximum route distance per vehicle
Maximum route duration / shift length per vehicle
Optional jobs / prize-collecting (mandatory vs skip penalty via prize)
Job groups (mutually exclusive job alternatives)
Flexible time windows (linear soft penalties via TimeWindowFlex)
Route overtime (extra duration allowed + unit penalty on overage)
Skills (jobs require a subset of vehicle skills)
Maximum wait / time slack at nodes (max_slack_time on vehicles)

What each backend minimizes (not a Feature flag): ORToolsSolver minimizes total travel distance (arc cost from the distance matrix; time is a separate dimension). PyVRPSolver minimizes PyVRP’s objective on the edge costs it receives as distance, with duration driving time feasibility. VroomSolver passes duration and distance matrices; VROOM’s default behavior is duration-oriented for optimization. NextrouteSolver uses the Nextroute engine’s objective on the constructed instance.

Model assumptions and travel

Unified nodes: The model stores one append-only list of nodes. Each row has a NodeKind (DEPOT or JOB). node_id is the row index—shared across depots and jobs in creation order. Use Depot.node_id and Job.node_id as keys in (from_id, to_id) travel maps.

Locations: Depot and job location are optional for construction, but feasibility validation requires every job to have coordinates unless you supply a non-empty sparse travel map (see below). Solvers may still synthesize coordinates internally when a location is missing (e.g. PyVRP).

Sparse travel: Travel is stored as (from_id, to_id) → TravelEdgeAttrs with optional distance and duration (int or None). At least one of distance or duration must be set on each stored edge. Model-level routing helpers treat a missing field on a stored edge as infinite cost; TRAVEL_COST_INF is the large sentinel (aligned with PyVRP’s MAX_VALUE scale).

  • If travel_edges is empty, leg distance and duration fall back to integer Euclidean distances between planar coordinates for all pairs (depots and jobs). Validation then requires every job to have a location.
  • If travel_edges is non-empty, the model uses matrix-only semantics: any directed pair not present in the map has infinite distance and duration (no Euclidean fallback for missing arcs).

Use set_travel_edges, update_travel_edge, and clear_travel_edges on the model; validate() checks node ids, forbids self-loops, and rejects negative costs.

Solving and solutions

Solver.solve validates the model, checks capabilities, runs the backend, and attaches a Solution to model.solution. The return value is SolutionStatus (mapped status, timing, stop reason, solver cost, etc.).

Use model.solution_cost(), model.is_solution_feasible(), and model.unassigned_jobs() for metrics; these raise SolutionUnavailableError if no solution is attached.

VRPLIB (vrplib)

read_model and vrplib_dict_to_model build a Model without calling validate(). Call model.validate() before relying on consistency, or use Solver.solve, which validates first. write_vrplib_instance / write_vrplib_solution export instances and routes.

Example

from vrp_model import Model
from vrp_model.solvers.pyvrp import PyVRPSolver

model = Model()
depot = model.add_depot(location=(0.0, 0.0), label="hub")
vehicle = model.add_vehicle(10, depot, label="truck1")
job = model.add_job(3, location=(1.0, 2.0))

result = PyVRPSolver({"time_limit": 2.0, "msg": False}).solve(model)
solution = model.solution
assert result.mapped_status.name == "FEASIBLE"

With OR-Tools installed: from vrp_model.solvers.ortools import ORToolsSolver and ORToolsSolver({"time_limit": 5.0}).solve(model).

Development

uv sync --group dev --extra pyvrp    # CI uses this set
uv run python -m unittest discover -s tests
uv run ruff check vrp_model tests && uv run ruff format vrp_model tests --check
uv run ty check vrp_model

Full solver coverage in tests requires installing the extras you care about (see .github/workflows/ci.yml; default CI only adds pyvrp). Some tests skip backends that are not installed.

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

vrp_model-0.2.0.tar.gz (133.5 kB view details)

Uploaded Source

Built Distribution

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

vrp_model-0.2.0-py3-none-any.whl (65.2 kB view details)

Uploaded Python 3

File details

Details for the file vrp_model-0.2.0.tar.gz.

File metadata

  • Download URL: vrp_model-0.2.0.tar.gz
  • Upload date:
  • Size: 133.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vrp_model-0.2.0.tar.gz
Algorithm Hash digest
SHA256 50cfecea29c869ca7bfed9e8d47c91f9fbd0f117635fd269ef23a08b6909628a
MD5 14ac4fe1a0f686c34828c0a3ed7e0f00
BLAKE2b-256 f1ef34cded2c744c5826a89e35c4e34da444d4d5cffe2c0706035efe72083a9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for vrp_model-0.2.0.tar.gz:

Publisher: publish.yml on pchtsp/vrp-model

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vrp_model-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: vrp_model-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 65.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vrp_model-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7c7887142279ca785a372e7dd0317930bac7aa9a0b047c5d813aaa52e4ad5eba
MD5 230ec54af59eb524bb8717618394c0e4
BLAKE2b-256 ba194cb70de52a08c400e48e99850cf0bbbadf6b41ec01ed4bbc474df4db6364

See more details on using hashes here.

Provenance

The following attestation bundles were made for vrp_model-0.2.0-py3-none-any.whl:

Publisher: publish.yml on pchtsp/vrp-model

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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