Skip to main content

MAMUT-routing-tools

Local generation tool suite for the MAMUT-routing benchmark project: OSM city acquisition, a road-graph engine, BKS route-geometry materialization, and interactive CVRP / VRPTW / time-dependent (TDVRP, TDVRPTW) instance generation. The public MAMUT-routing website is fully static; everything compute-heavy lives here and runs on your own machine.

Part of the ANR MAMUT project.

Status

Beta. All benchmark generation now lives here: the website's former Julia backend has been fully ported to Python and removed. Interfaces may still change between releases.

Components

  • mamut-tools roadgraph: build and inspect drivable road graphs from OSM XML extracts. The construction is a faithful Python port of the OpenStreetMapX.jl pipeline the project previously used (same road classes, oneway rules, intersection segmentation, ENU distances, and strongly-connected trim), so graphs and route geometry stay consistent with previously published data.
  • mamut-tools geometry: materialize road-following polylines for Best-Known Solutions (BKS), in the exact artifact format the MAMUT-routing website consumes.
  • mamut-tools osm fetch-city: download and structurally validate a purpose-filtered OSM extract for a city by name, using atomic tiled road and POI acquisition plus a persistent tile cache when a single Overpass query would be too large.
  • mamut-tools generate: per-instance generation on city road graphs — single (CVRP), preview, derive-vrptw (the fastest-metric VRPTW twin), and derive-td (the TDVRP + TDVRPTW twins: traffic overlay → arrival-time functions → time-window lift to time-dependent feasibility). Batch family generation (many cities × sizes) is delegated to per-campaign scripts that call the mamut_routing_tools.family and mamut_routing_tools.td library.
  • mamut-tools solve: PyVRP solving of generated and benchmark instances via mamut-routing-lib; with the kayros extra (pip install 'mamut-routing-tools[kayros]'), KAYROS solves the time-dependent instances (Duration objective, anytime with exact certification tooling).
  • mamut-tools convert: converters for external benchmark distributions (blauth2024). The inverse direction, exporting any .vrp.json to the classic CVRPLIB .vrp (or Solomon .txt) for solvers that do not read the lib contract, lives in mamut-routing-lib as mamut-routing export vrp; the workbench GUI exposes it as "Download .vrp".
  • mamut-tools gui: a CLI-owned local workbench GUI (loopback server with token security) for fetching cities, previewing, generating, solving, and rendering road-following routes on a map. Long operations run as persistent jobs with real state/logs; solver runs are checker-validated, retained across restarts, and comparable by objective, fleet, loads, route edges, and customer grouping.

Regenerating, deriving and saved runs (0.6.0)

  • No silent overwrite. An instance name encodes city, method, size and the minimum fleet k, so another seed, demand type or depot often gives the same name. generate single (and the GUI, and bulk generation) compare the new instance with the one on disk by content: identical content is left untouched ("action": "unchanged"), different content is written as <name>-2, -3... (renamed), or with --replace (the GUI's "Replace existing") replaces it after deleting everything derived from it: VRPTW and TD twins, BKS (replaced).
  • Saved runs follow their instance. A solver or imported run records the sha256 of the instance file it was validated on; after a replace the run is listed as stale, no longer counted, and refused by compare and render.
  • Feasible anchors. derive-vrptw centres route_centered windows on capacity-and-horizon-feasible routes and stores them (anchor_routes); derive-td certifies the windows along them (splitting a route that no longer returns by the horizon under traffic), so n = 200 and beyond derive. Failures raise TDDerivationError (derive-td exits 1) and nothing is written: the twins and sidecars are staged and verified first. The twins record the sha256 of their inputs; a re-run after the base changed re-derives them instead of keeping them.
  • Family builds are all or nothing. family.build_td stages the VRPTW file, overlays and twins, verifies them, then publishes; an existing atf_sha256 is reused only when it pins exactly the same road graph and overlay.

The traffic models (bpr commuter simulation, wave rush-hour dip) and the road-graph time-dependent travel model live in mamut_routing_tools.td; the family build engine (base publish, VRPTW derivation, TD-twin materialization) lives in mamut_routing_tools.family.

Install

Requires Python >= 3.11. Two variants:

Published on PyPI. With uv, no installation step is needed:

uvx --from mamut-routing-tools mamut-tools --help

Or install it into an environment:

pip install mamut-routing-tools
# or
uv add mamut-routing-tools

Clone the repository and use the project environment:

git clone --recurse-submodules https://github.com/ANR-MAMUT/MAMUT-routing-tools.git
cd MAMUT-routing-tools
uv sync
uv run mamut-tools --help
uv run pytest

The two variants differ in where the MAMUT-routing-lib contract library comes from. A PyPI install resolves it from PyPI. A source checkout builds it from the vendored submodule, at the exact commit this repository pins, because the tools regularly use library features that are not released yet. That is why the clone must be recursive, and why the submodule has to be up to date before uv sync.

Onboarding: discovering the CLI

Everything in this suite is reachable from the single mamut-tools entry point, and every level of the command tree answers --help. You do not need to hunt through this README for a flag: ask the CLI directly.

uv run mamut-tools --help              # top level: lists all command groups
uv run mamut-tools gui --help          # a command group: lists its sub-commands
uv run mamut-tools gui start --help    # a sub-command: its options and defaults

To find out which build you are actually running, use --version (or -V):

uv run mamut-tools --version
# mamut-tools 0.6.0 (/path/to/MAMUT-routing-tools/src/mamut_routing_tools)

It prints the version alongside the package location, which tells you whether you are on a PyPI install or an editable source checkout.

The top level lists the command groups (roadgraph, geometry, osm, generate, solve, gui); drilling down one level at a time is the intended way to explore. When in doubt, add --help to whatever you just typed.

Starting and stopping the workbench GUI

The GUI is the friendliest way to fetch a city, generate instances, solve them, and see routes drawn on a map. The CLI owns the server process: start launches it as a detached background process and returns immediately, so your shell stays free.

uv run mamut-tools gui start

This prints a URL carrying the access token for that server instance, and opens it in your browser:

Workbench GUI running (pid 391337), workspace /path/to/.cache/mamut-tools
http://127.0.0.1:39117/?token=<token>

The port is picked automatically and the server binds to loopback only, so it is never reachable from outside your machine. Useful options: --port <N> to pin a port, --no-open to skip opening the browser (handy over SSH), and --output-dir <DIR> to choose the workspace directory holding generated instances.

Check on it or shut it down with:

uv run mamut-tools gui status   # running? healthy? which URL and workspace?
uv run mamut-tools gui stop     # terminate the background server

The map offers the CARTO Positron and Dark Matter basemaps on top of OpenStreetMap tiles. CARTO basemaps need an API key, free within the CARTO fair-use tier (request one at https://carto.com/basemaps/apikey, and keep the CARTO and OpenStreetMap attribution visible, which the GUI does). Export it as MAMUT_BASEMAP_API_KEY before mamut-tools gui start (or gui run): the server inlines it into the page. Without it the map falls back to OpenStreetMap tiles only. Never commit the key.

gui status reprints the tokened URL, which is the quickest way to recover it if you lose the browser tab. If you would rather watch the server logs live, gui run runs it in the foreground instead (development mode, stop with Ctrl-C).

Generated instances remain under <workspace>/instances/. Generation controls include the historical POI amenity selection and random, centered, or excentered depot placement. Hybrid sampling exposes its target POI/parametric proportion; parametric sampling exposes the customer distribution, number of clusters, and clustering radius/decay distance. The GUI keeps its additional durable state separately:

  • validated solver runs under <workspace>/solutions/<instance-id>/;
  • job records under <workspace>/state/jobs/;
  • append-only job logs under <workspace>/state/logs/.

Besides the zip of every artifact of the selected instance, the Solve tab's "Download .vrp" button exports the metric variant chosen in the Metric selector as one classic CVRPLIB .vrp file (explicit full matrix, the published costs; rendered by mamut-routing-lib's mamut_routing_lib.cvrplib, so it matches mamut-routing export vrp and the website download byte for byte). For the euclidean variant an EUC_2D checkbox writes a coordinates-only file instead, whose TSPLIB nint costs differ from the published ones.

Both instances and solutions remain available after the GUI or machine restarts, until their workspace files are removed. Selecting an instance immediately displays its depot and customer positions without requiring a solve. Select any saved run to render it again—the customer markers then adopt their route colors—or compare two runs with the same objective and metric to inspect cost and route-count deltas, route loads, changed directed edges, and changes to customer grouping. Cancellation is cooperative: queued work stops immediately, while a running solver or matrix calculation stops at its next safe checkpoint.

The GUI fetches every POI category shown in its category picker when acquiring a city. Category checkboxes filter generation only, so changing them later does not require another OSM download. The lower-level mamut-tools osm fetch-city command remains configurable through repeated --poi-category options.

If the tool does not behave as documented

You are most likely running a different revision than you think. Start by asking the tool itself, then bring the checkout up to date:

uv run mamut-tools --version    # which version, and from which directory?
git pull --recurse-submodules   # update the repo AND the vendored submodule
uv sync                         # re-resolve dependencies afterwards

The MAMUT-routing-lib submodule is a frequent source of confusion: a conflict or a stale checkout there is easy to miss, and it leaves you on old behaviour with no obvious symptom. git status in the repository root reports a modified submodule; git submodule update --init --recursive puts it back on the pinned commit. Always run uv sync after pulling, since the dependency set moves between releases.

Quick examples

# Fetch Tokyo's urban area into ./osmdata (the administrative bbox includes
# distant islands, so explicitly clamp it around the geocoded city point)
uv run mamut-tools osm fetch-city Tokyo --country Japan --max-radius-km 15

# Road-cache builds skip POIs and download only road classes used by the engine
uv run mamut-tools osm fetch-city Tokyo --country Japan --max-radius-km 15 --profile road_cache

# Generation defaults to the seven built-in POI categories; override them by
# repeating --poi-category
uv run mamut-tools osm fetch-city Lyon --profile generation \
  --poi-category restaurant --poi-category cafe

# When running inside MAMUT-routing-tools, target the parent site's data folder
uv run mamut-tools osm fetch-city Tokyo --country Japan --max-radius-km 15 --osm-dir ../osmdata

# Verify that an extract has bounds, nodes and ways and contains no error remark
uv run mamut-tools osm validate ../osmdata/Tokyo.osm

# Road-graph statistics for a city extract
uv run mamut-tools roadgraph info path/to/City.osm

# Materialize a route-geometry group plan (website build contract)
uv run mamut-tools geometry materialize-plan plan.json --repo-root path/to/MAMUT-routing --result-dir out/

OSM download profiles

  • generation (default) downloads only the 16 road classes understood by the road engine, skeleton coordinates for their referenced nodes, and selected POI nodes. Roads and POIs use separate Overpass queries, so a POI failure cannot invalidate complete road data.
  • road_cache downloads the filtered road network without POIs. This is the profile used by the MAMUT-routing site build.
  • full retains the broad highway=* and amenity=* behavior for compatibility.

Successful tile responses are validated and cached under <osm-dir>/.mamut-osm-tile-cache. Repeating an interrupted request reuses those tiles; pass --no-tile-cache to disable reuse or --tile-cache-dir to choose another location.

Release files for mamut-routing-tools 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mamut-routing-tools 0.6.0
File Size Uploaded
mamut_routing_tools-0.6.0.tar.gz 663.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mamut-routing-tools 0.6.0
File Interpreter ABI Platform
mamut_routing_tools-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.4 MB

Release files / mamut_routing_tools-0.6.0.tar.gz

Download URL mamut_routing_tools-0.6.0.tar.gz
Size 663.2 kB
Tags Source
SHA-256 checksum
How to use checksums
8d81b6d962cf5deec435cdec95d8d20497d6b5b079ebb29164a70c1092691937
BLAKE2b-256 checksum
How to use checksums
9efd7b31b54dc04d5fe2b215f36cd7e1038d8dd64e0f436743c2940420b29172
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / mamut_routing_tools-0.6.0-py3-none-any.whl

Download URL mamut_routing_tools-0.6.0-py3-none-any.whl
Size 695.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9f0466878b95615b3b80a0991bdd5d70835991ad73aa6156229fbdfb0c9acf3c
BLAKE2b-256 checksum
How to use checksums
bf516e0a0ef64299bc8eac6385a6275375ef61dd1107c1cbb0190d0163118c80
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page