mamut_routing_tools.td¶
Time-dependent traffic generation for the MAMUT road-graph model.
Ports the workbench's stage-3 traffic stage to Python on the tool's own road
graph. :func:build_bridge assembles the TD-bridge records in memory (the
streamlined path the family builder and the per-instance derivation consume);
:func:export_bridge serializes the same records to the git-ignored JSON
intermediate. The bridge record types and their JSON I/O live in
:mod:mamut_routing_tools.td.bridge.
BridgeFormatError
¶
Bases: ValueError
Raised when a TD bridge file violates the expected format.
BridgeBuild
dataclass
¶
BridgeBuild(graph: BridgeGraph, speeds: dict[tuple[str, str], BridgeSpeeds], nodes: dict[str, BridgeNodes])
The full TD bridge for one city, held in memory.
graph is shared by every combination; speeds is keyed by (model,
intensity); nodes is keyed by instance base name (one entry per
stage-1 meta). The consumer (mamut_routing_tools.family) takes these
records directly, so a per-instance derivation skips the JSON round-trip
entirely; :func:export_bridge serializes the same records to disk for the
cached / inspectable path.
BridgeEdge
dataclass
¶
One deduplicated directed edge of the bridge graph.
u / v are 0-based graph vertex indices; osm_u / osm_v are
the OSM node ids that key the bridge.
TrafficModelError
¶
Bases: ValueError
Raised on an unknown traffic model, intensity, or an empty edge set.
serialize_bridge_graph
¶
The graph.json payload for a :class:BridgeGraph.
Vertices ship as [osm_id, lon, lat] sorted by OSM id (the consumer
reads them into a dict, so order is cosmetic but kept stable); edges ship as
[osm_u, osm_v, length_m, class, free_speed_ms] in BridgeGraph.edges
order (the speed profiles align with it).
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/bridge.py
serialize_bridge_nodes
¶
The nodes-<instance_base>.json payload for a :class:BridgeNodes.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/bridge.py
serialize_bridge_speeds
¶
The speeds-<model>-<intensity>.json payload for a :class:BridgeSpeeds.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/bridge.py
bpr_speeds
¶
bpr_speeds(graph: RoadGraph, edges: list[BridgeEdge], osm_path: str | Path, intensity: str, seed: int) -> tuple[list[list[float]], int]
Per-edge 24-bin BPR speed profiles and the total number of trips routed.
Samples trips_per_vertex * |V| commuters (homes uniform on vertices,
workplaces from the POI pool with uniform fallback), routes every trip on
the free-flow fastest path, accumulates per-edge hourly flows at edge
entry time, then applies the BPR volume-delay function with class-based
capacities. Deterministic per seed within Python.
Routing is grouped by each trip's workplace endpoint (the small POI pool)
rather than by home, so Dijkstra runs ~2*|work pool| times instead of once
per home: work -> home trips keep a forward tree per workplace (bit-
identical to a per-origin forward routing) and home -> work trips use a
reverse tree per workplace over the transposed graph, which matches forward
routing except on equal-cost shortest-path ties.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
bpr_work_pool
¶
Workplace vertex pool: amenity-POI-snapped graph vertices when the OSM
file has enough of them (>= 50), otherwise all vertices (uniform
fallback). Mirrors td_work_pool: each POI snaps to its nearest road
node, which must itself be a graph vertex (the findnode + md.v
membership rule); first-seen dedup; sorted.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
bridge_seed
¶
Per-combination seed, matching the workbench's seed arithmetic so the
recorded seed field is stable across regenerations.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
build_bridge
¶
build_bridge(*, osm_path: str | Path, city_slug: str, models: list[str] | tuple[str, ...] = TD_MODELS, intensities: list[str] | tuple[str, ...] = TD_INTENSITIES, seed: int = 42, only_intersections: bool = True, trim_to_connected: bool = True, metas: list[dict] | tuple[dict, ...] = ()) -> BridgeBuild
Build the full TD bridge for one city in memory (no disk round-trip).
Loads the city road graph once, collects its deduplicated edges, then
assembles the shared :class:BridgeGraph, a :class:BridgeSpeeds for every
model x intensity combination, and a :class:BridgeNodes for every
stage-1 meta dict in metas (keyed by instance base name). This is the
streamlined path the per-instance TD derivation uses; it produces exactly the
records :func:export_bridge writes to and reads back from disk.
Each meta's graph_vertex_id values must index the same road graph the
bridge is built on, so the metas' map_options must match
only_intersections / trim_to_connected.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
build_bridge_graph
¶
build_bridge_graph(graph: RoadGraph, edges: list[BridgeEdge], city_slug: str, osm_path: str | Path, only_intersections: bool, trim_to_connected: bool) -> BridgeGraph
Assemble the shared :class:BridgeGraph for a road graph and its edges.
Edges carry the static free-flow limit (m/s, same rounding as the speed
profiles) so the consumer never needs the class table; every vertex
incident to an edge ships its WGS84 position for the consumer's geo cache.
Serializing this record (serialize_bridge_graph) then loading it back
(load_bridge_graph) returns an equal record, so the in-memory and disk
paths never diverge.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
build_bridge_nodes
¶
build_bridge_nodes(graph: RoadGraph, meta: dict, city_slug: str, *, only_intersections: bool, trim_to_connected: bool) -> BridgeNodes
Map one stage-1 meta's instance nodes (depot first) to a :class:BridgeNodes.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
build_bridge_speeds
¶
build_bridge_speeds(city_slug: str, model: str, intensity: str, seed: int, num_trips: int, speeds: list[list[float]]) -> BridgeSpeeds
Wrap one combination's per-edge speed profiles in a :class:BridgeSpeeds.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
build_static_bridge
¶
build_static_bridge(*, osm_path: str | Path, city_slug: str, metas: list[dict] | tuple[dict, ...] = (), only_intersections: bool = True, trim_to_connected: bool = True) -> BridgeBuild
The bridge a CVRP-only family needs: the graph and the nodes, no speeds.
:func:build_bridge simulates six traffic overlays per city, which is the
dominant cost and is pure waste for a static family. This builds the same
:class:BridgeGraph and :class:BridgeNodes records and leaves speeds
empty, so family.build_base works unchanged while family.build_td
stays unavailable (it would raise on the missing combinations, which is the
correct failure for a collection that has no time-dependent layer).
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
collect_edges
¶
Deduplicated directed edge list, one entry per (u, v) graph-vertex
pair, keeping the fastest free-flow representative (min free-flow time,
then min length). Self-loops and non-positive lengths are dropped.
RoadGraph already stores a single edge per (u, v), so the dedup is
a safety net; the filters mirror td_collect_edges exactly. Edges are
returned sorted by (u, v) so speed profiles align by position.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
export_bridge
¶
export_bridge(*, osm_path: str | Path, city_slug: str, out_root: str | Path, models: list[str] | tuple[str, ...] = TD_MODELS, intensities: list[str] | tuple[str, ...] = TD_INTENSITIES, seed: int = 42, force: bool = False, only_intersections: bool = True, trim_to_connected: bool = True, meta_paths: list[str | Path] | tuple[str | Path, ...] = ()) -> Path
Serialize the TD bridge for one city under <out_root>/<city_slug>/.
Writes graph.json (deduplicated directed edges keyed by OSM node ids),
speeds-<model>-<intensity>.json for every requested combination (speed
profiles aligned with the graph edge order, m/s), one
nodes-<instance_base>.json per stage-1 meta in meta_paths (instance
node -> OSM node ids, depot first), and a bridge-manifest.json. The bytes
written are exactly the serialized :func:build_bridge records, so
load_bridge_* reads them back unchanged. Existing per-combination speed
files are reused unless force=True (the disk path's only advantage over
building in memory: skipping an expensive recompute). Returns the city output
directory.
Each meta's graph_vertex_id values must index the same road graph the
bridge is built on, so the metas' map_options must match
only_intersections / trim_to_connected.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | |
node_osm_ids_from_meta
¶
node_osm_ids_from_meta(graph: RoadGraph, meta: dict, *, only_intersections: bool, trim_to_connected: bool) -> list[int]
Map a stage-1 meta's instance nodes (depot first) to OSM node ids on
graph.
The meta's graph_vertex_id values are indices into the road graph the
instance was sampled on, so the meta's map_options must match the graph
the bridge is built on for the numbering to align (this is the stage-1a /
stage-3 shared-numbering invariant).
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
vertex_latlon
¶
Per-vertex (lat, lon) indexed by 0-based graph vertex.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/td/traffic.py
wave_speeds
¶
wave_speeds(edges: list[BridgeEdge], vertex_ll: list[tuple[float, float]], center_latlon: tuple[float, float], intensity: str, seed: int) -> list[list[float]]
Per-edge 24-bin wave speed profiles (m/s), aligned with edges.
Each edge draws one uniform jitter in edge order, then applies a bimodal rush dip scaled by amplitude, road-centre proximity and jitter, clamped to a free-flow floor.