mamut_routing_tools.campaign.poi_capacity¶
How many real amenities a city can actually serve as customers.
The large tier asks for POI-only instances: every customer is a real place on
the map, not a point sampled off the road network. That is the most defensible
kind of instance the platform can build -- the customer set is a fact about the
city rather than an artefact of a sampler -- but it is bounded by something the
size grid knows nothing about. A city can only serve as many POI customers as
it has distinct road vertices reachable from its amenities: two cafes on the
same corner collapse into one customer, and an amenity more than
attach_radius_m from any routable point is not a customer at all.
So the ceiling is neither the population nor the amenity count. It is
len({vertex for poi in catalog if poi attaches}), which
:func:~mamut_routing_tools.generation.select.select_customers_poi already
reports as stats["attached"]. This module measures it directly, per city,
so the tier is sized from what the extracts hold instead of from an assumption
about which cities are "big enough".
PoiCapacity
dataclass
¶
PoiCapacity(city: str, osm_file: str, num_vertices: int, catalog_size: int, attached_pois: int, capacity: int, collapse_ratio: float, attach_mode: str, attach_radius_m: float, categories_digest: str = '')
One city's ceiling on POI-only customers.
supports
¶
categories_digest
¶
A short fingerprint of a category list, order-independent.
A capacity is only meaningful for the categories it was measured over, and
curating the list changes every number in the file. Without a fingerprint a
stale poi-capacity.json is indistinguishable from a fresh one, and the
campaign would size instances against amenities it is no longer drawing
from.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/poi_capacity.py
measure_capacity
¶
measure_capacity(osm_path: str | Path, city: str, *, categories: Sequence[str] = POI_CATEGORIES, attach_mode: str = POI_ATTACH_NEAREST_VERTEX, attach_radius_m: float = DEFAULT_POI_ATTACH_RADIUS_M) -> PoiCapacity
Measure one city, reusing the same caches the generator uses.
Deliberately does not call select_customers_poi: that shuffles the pool
and builds customer lists to arrive at the same attached count. The
ceiling is a property of the attachment map alone, so the map is enough.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/poi_capacity.py
measure_cities
¶
measure_cities(cities: Iterable[tuple[str, Path]], *, categories: Sequence[str] = POI_CATEGORIES, attach_mode: str = POI_ATTACH_NEAREST_VERTEX, attach_radius_m: float = DEFAULT_POI_ATTACH_RADIUS_M, jobs: int = 1, on_progress: Callable[[str], None] | None = None) -> list[PoiCapacity]
Measure every city; one worker holds one extract at a time.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/poi_capacity.py
load_capacities
¶
load_capacities(path: str | Path, *, expect_categories: Sequence[str] | None = None) -> list[PoiCapacity]
Load a capacity file, refusing one measured over other categories.
expect_categories turns a silent mis-sizing into a loud failure: every
number in the file is relative to a category list, so reading it against a
different one would classify cities by amenities the campaign no longer
draws from.
Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/poi_capacity.py
cities_supporting
¶
cities_supporting(capacities: Iterable[PoiCapacity], n: int, *, headroom: float = 1.0) -> list[PoiCapacity]
Cities that can serve n POI customers, largest capacity first.
headroom above 1.0 demands slack: at exactly capacity == n + 1 the
"selection" is the whole amenity pool, so the seed stops mattering and the
instance is no longer a draw from anything.