mamut_routing_tools.generation.select¶
Depot and customer selection on a road graph (port of the workbench selection methods: parametric attach, POI categories, hybrid).
vertex_latlon
¶
Per-vertex (lat, lon), indexed by 0-based graph vertex.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/generation/select.py
pick_depot_vertex
¶
pick_depot_vertex(mode: str, vertex_ll: list[tuple[float, float]], rng: Random, exclude: set[int] | frozenset[int] = frozenset()) -> int
The depot vertex for mode, never one of exclude.
exclude is meant for the graph's synthetic crop nodes: corner
takes the vertex nearest the south-west corner of the extract, which is
exactly where a road leaving the bounds gets its invented boundary node,
so 16 of the 100 Mamut2026 depots landed on a point that exists in no
other extract of their city. center is guarded the same way; random
redraws only when it hits an excluded vertex, so seeded draws that never
touched one are unchanged. When every vertex is excluded the guard is
dropped rather than failing the generation.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/generation/select.py
attach_pois
¶
attach_pois(graph: RoadGraph, pois: list[Poi], mode: str = POI_ATTACH_NEAREST_NODE, radius_m: float = DEFAULT_POI_ATTACH_RADIUS_M) -> list[tuple[int, float] | None]
Per POI, the (vertex, snap_distance_m) it attaches to, or None.
nearest_node is the Julia findnode + md.v membership semantic:
the nearest ROAD NODE must itself be a graph vertex, so a POI whose closest
node sits mid-segment is dropped even when an intersection stands a metre
further. It keeps generated instances identical to the published pipeline,
at the cost of discarding most of a city's amenities.
nearest_vertex instead snaps each POI to the closest routable vertex
within radius_m, which is what manual picking has always done. Far more
of the pool becomes usable; the distance is returned so every customer can
record how far its amenity was moved.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/generation/select.py
catalog_attachment
¶
catalog_attachment(graph: RoadGraph, osm_path: str | Path, mode: str = POI_ATTACH_NEAREST_NODE, radius_m: float = DEFAULT_POI_ATTACH_RADIUS_M) -> list[tuple[int, float] | None]
attach_pois over the whole cached catalog, computed at most once.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/generation/select.py
select_customers_poi
¶
select_customers_poi(graph: RoadGraph, osm_path: str | Path, n_customers: int, categories: list[str], rng: Random, stats: dict[str, Any] | None = None, attach_mode: str = POI_ATTACH_NEAREST_NODE, attach_radius_m: float = DEFAULT_POI_ATTACH_RADIUS_M, exclude: Iterable[int] | None = None) -> tuple[list[int], list[float], list[float], list[str], list[Poi | None]]
Chosen vertices plus, per vertex, the POI it came from.
The trailing list[Poi | None] carries the amenity value, OSM node id and
display name so callers can persist them; None marks a non-POI customer.
exclude names vertices that must not become customers -- in practice the
depot. Without it the caller has to drop a POI that landed on the depot
after the fact, which silently costs one customer: the selection returns
the n it was asked for, one is discarded, and the shortfall is made up
with a sampled road point. A POI-only instance then quietly stops being one,
even in a city with four times the amenities it needs.
stats, when given, is filled with how big the pool actually was:
pool_matching (POIs of these categories in the extract), attached
(the number of distinct graph vertices the whole pool can reach, which is
the hard ceiling on POI customers) and co_located (per chosen vertex,
the other POIs that snap to it and are therefore not customers of their
own). Callers need the first two to explain a shortfall and the last to say
which amenities a single customer stands for.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/generation/select.py
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | |