Skip to main content

mesoLTM

PyPI Version Package Build Python Types Python Tests License: AGPL-3.0

A mesoscopic (individual-vehicle) Link Transmission Model for traffic flow on general road networks, distributed as the pip package mesoltm.

mesoltm implements the discrete LTM of de Souza, Verbas, Auld & Tampère — a computationally efficient macroscopic-style model that nonetheless tracks every vehicle individually, so each vehicle carries its own (re-routable) path. It runs on arbitrary graphs and grids, supports parallel links (fast/slow lanes and detours), and exposes clean interfaces for external routing and per-step simulation plugins.

Full documentation: https://sjschlapbach.github.io/mesoLTM
Python Package: https://pypi.org/project/mesoltm

Requirements

  • Python 3.11+

Install

pip install mesoltm

For plotting support, install the plot extra:

pip install "mesoltm[plot]"

From source (editable, for development)

python3.11 -m venv venv && source venv/bin/activate
pip install -e ".[dev,plot]"     # core + dev tooling + plotting

Extras: plot (matplotlib visualisations), ui (network editor, optional), calib (scipy, for calibration examples), dev (pytest, pylint, black, mypy, build).

Quick Start

from mesoltm import Vehicle, grid_network, ShortestPathPolicy

# A 4x4 grid where every node can be an origin or a destination.
net = grid_network(4, 4, link_length=200.0, all_nodes_od=True)
net.set_origin((0, 0), vehicles=[
    Vehicle(vehicle_id=k, start=float(k), origin=(0, 0), destination=(3, 3))
    for k in range(50)
])

sim = net.compile(time_step=1.0, total_time=400.0,
                  routing_policy=ShortestPathPolicy(dynamic=True))
sim.run()
print(sum(len(n.get_arrived_trips()) for n in sim.nodes), "vehicles arrived")

Or run a JSON scenario from the command line:

python -m mesoltm examples/scenario.json     # writes link/trip CSVs

Examples

Executable scripts under examples/ (run with python examples/<name>.py). Each writes its figures (and any CSVs) to its own subdirectory examples/output/<script_name>/, so results are easy to tell apart.

  • freeway_onramp.py — a freeway on-ramp merge on a calibrated topology with a synthetic demand profile.
  • grid_demo.py — a partial grid with shortest-path routing.
  • rerouting_demo.py — manual per-vehicle rerouting: dynamic routing is off (static route-following), and a plugin hand-picks specific vehicles and rewrites their routes onto a detour mid-run (no closed links, no shortest-path search).
  • adaptive_rerouting_intersection.py — the most basic 2-in/2-out uncontrolled ("no-way-stop") intersection (a general node); agents are re-checked every step against the live shortest path from their current link onward (no U-turns), reroutes are versioned, and a few agents' initial-vs-final plans are plotted.
  • parallel_links_demo.py — fast lane, slow lane and an inflated-length detour, run twice: free-flow routing (everyone piles on the fast lane until it closes) vs congestion-aware routing (a cost that grows with each link's load spreads traffic onto the slow lane and detour).
  • vehicle_metrics_demo.py — collect per-vehicle travel times (overall and per link) with mesoltm.metrics and plot the travel-time distribution, per-link means, and a per-link travel-time time series showing congestion building up.
  • bottleneck_access_policy.py — a random bottleneck access policy driven with Simulation.start/step/inject: vehicles are released toward a goal via a fast bottleneck, and a ReroutingPlugin tosses a coin as each one approaches to admit it or divert it onto a slower parallel path (one toss per access). Plots each of four vehicles' route before the toss, after it, and as actually driven, and records the run as a video (plus per-step frames) of the vehicles moving link-to-link — blue while planning the bottleneck, then green (admitted) or orange (diverted).
  • congestion_aware_routing.py — a ReroutingPlugin that balances a burst of traffic across a short and a long route using a shortest-path cost that combines link length (free-flow time) with current load (state.occupancy).
  • grid_visualization.py — grids under congestion-aware route-based rerouting: a DensityRerouter plugin re-plans each vehicle (shortest path on free-flow time + a linear density penalty) at every node and writes the plan onto vehicle.route, so the recorded log is exactly the route that ran. Two scenarios: a tiny 2x2 grid (few vehicles, short horizon) whose per-step PNGs + JSON log can be checked by hand, and a dense 7x7 grid (with holes) carrying many vehicles between random OD pairs. Each records a video of the agents moving, coloured by the link each takes next — showing the animation stays readable on a dense scenario (sizes scale to the network, per-agent detail auto-drops but is available on request). One still is coloured by a custom function of each vehicle's props metadata (a vehicle class) to show color_by is fully overridable.

Key Concepts

  • Network builder (mesoltm.Network, grid_network, corridor_network): add nodes/links, mark any node an origin/destination, compile() to a simulation.
  • Routing (RoutingPolicy): per-vehicle, mutable mid-run; StaticRoutePolicy (follow vehicle.route) or ShortestPathPolicy, or your own.
  • Plugins (Plugin): per-step loop hooks that run first each step to inspect NetworkState and change the simulation — reroute vehicles (each vehicle carries its own route, which the network merely propagates), gate/close links, run dispatchers or local auctions. ReroutingPlugin is the minimal rerouting form.
  • Visualisations (mesoltm.visualizations, needs [plot]): cumulative curves, flow over time (plot_link_flow sums links into a cut; plot_link_flows draws one labelled line per link), per-link travel time over time (plot_link_time_series, to see congestion build up), and network maps (plot_network, colour links by flow/occupancy/…, optionally label each link and fan out parallel links).
  • Movement video (mesoltm.visualizations + record_history=True): capture a per-step history (Network.compile(record_history=True[, history_path=…]), off by default; exposed as Simulation.history, JSON-serialisable) and render it to an MP4/GIF (save_animation, default 25 fps, subsample sets playback speed) and/or per-step PNGs (save_frames) of agents moving link-to-link — with next-link cues and a count badge on each node for agents waiting to enter. color_by chooses what a dot's colour means: "category", "next_link", None (uniform), or a custom callable fn(snapshot) -> str colouring by anything on the snapshot — most usefully each vehicle's free-form Vehicle(props=…) metadata, which travels with the vehicle and round-trips through the log. The log records each agent's remaining route straight from vehicle.route (never recomputed), so it always matches the simulation. The saved JSON log is self-describing (each agent/waiting entry is a keyed object). Scales from a small bottleneck to a dense grid.

Development

pytest                        # tests (includes a numeric regression vs. the reference)
pylint src/mesoltm examples   # lint
black --check src examples    # format check
mypy src                      # types
python -m build               # sdist + wheel

venv/ and build artefacts are git-ignored.

Release

Releases are automated. Pushing a v*.*.* tag triggers the release workflow, which validates versions, generates the changelog with git-cliff (config in cliff.toml), builds the distribution, publishes to PyPI, and creates a GitHub Release. The changelog is derived from conventional commit messages, so nothing in CHANGELOG.md needs to be edited by hand. Make sure all tests and builds are passing, then follow these steps.

0. Prerequisites (important!)

Switch to master and make sure it has all the changes that should be in the release:

git checkout master
git pull origin master

You also need permission to push tags, and a PYPI_TOKEN repository secret must be configured (a PyPI API token) for the publish step.

1. Update the version in pyproject.toml

Set the version in pyproject.toml to the next release version according to the conventional-commit history. To see what git-cliff computes as the next version, run:

git-cliff --bump --unreleased

⚠️ Do not commit any CHANGELOG.md changes — the release workflow regenerates and commits the changelog automatically. Commit only the version bump in pyproject.toml. If the pyproject.toml version and the git-cliff-computed version disagree, the release workflow fails.

2. Commit the version change

git checkout master                     # safeguard: ensure you are on master
git commit -m "chore(release): v0.1.0"  # replace v0.1.0 with the release version
git push origin master

3. Create and push the tag (this triggers the workflow)

git checkout master                                   # safeguard: ensure you are on master
git tag -a v0.1.0 -m "chore(release): version 0.1.0"  # replace v0.1.0 with the release version
git push origin v0.1.0                                # push the tag to trigger the release workflow

4. GitHub Actions then automatically

  • Validates that the tag, pyproject.toml, changelog, and built wheel all agree on the version
  • Generates CHANGELOG.md with git-cliff and commits it back to master
  • Builds the sdist and wheel
  • Publishes to PyPI
  • Creates a GitHub Release with the changelog notes

Attribution and Citation

If you use mesoltm in academic or other work, please cite this repository. A machine-readable entry is provided in CITATION.cff:

J. Schlapbach, mesoLTM: a mesoscopic (individual-vehicle) Link Transmission Model. Software, https://github.com/sjschlapbach/mesoLTM

As a secondary reference, please also cite the paper whose model mesoltm implements, and whose abmmeso package (by Felipe de Souza, AGPL-3.0) it adapts (see NOTICE):

F. de Souza, O. Verbas, J. Auld, C. M. J. Tampère, "A mesoscopic link-transmission-model able to track individual vehicles", Simulation Modelling Practice and Theory 140 (2025) 103088. DOI: 10.1016/j.simpat.2025.103088

Deviations from the paper's formulation are documented on the Deviations from the paper page of the documentation.

License

mesoltm is distributed under the GNU Affero General Public License v3.0 or later — see LICENSE and NOTICE.

Download files

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

Source Distribution

mesoltm-0.3.1.tar.gz (234.9 kB view details)

Uploaded Source

Built Distribution

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

mesoltm-0.3.1-py3-none-any.whl (164.0 kB view details)

Uploaded Python 3

File details

Details for the file mesoltm-0.3.1.tar.gz.

File metadata

  • Download URL: mesoltm-0.3.1.tar.gz
  • Upload date:
  • Size: 234.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for mesoltm-0.3.1.tar.gz
Algorithm Hash digest
SHA256 f2d368153453e52abc8146611e6b340e6c7b9e2ac40f26ecb040483bd114f5e1
MD5 715747ad5a6d0b70cfb950adecc0f281
BLAKE2b-256 e3c5d0652b0d88738270ec3923fa2ec052f8a4778603114d106202d644ed6dad

See more details on using hashes here.

File details

Details for the file mesoltm-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: mesoltm-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 164.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for mesoltm-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e163a2c0a7ee733deeb49651c51372254bb1a4ea05ea1b92a87b9544adb9ccac
MD5 4abb859dc04d241b9173b7b56c5dc0f9
BLAKE2b-256 b0fd95f52f735007444435557bc36b8cd525d00a0c9aa275e97747effb7ccbde

See more details on using hashes here.

Release history Release notifications | RSS feed

1.0.0

2 files

This release

0.3.1 This release

2 files

0.3.0

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 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