Skip to content

mamut_routing_tools.campaign.quotas

The coverage requirements of the Mamut2026 CVRP campaign.

Kept apart from the selector so the policy -- what this benchmark promises to cover -- is one readable block that a reader of the family README can check against the published coverage table, rather than something buried in a CLI.

ladder_tier_quotas

ladder_tier_quotas(rung_keys: Sequence[str]) -> list[Quota]

Coverage for a campaign whose sizes and sourcing are already assigned.

Four of the old quotas are gone because the ladder assignment decided them before selection began: method is fixed per rung, avg_route_size too, size_bucket is covered by construction (one instance per distinct n), and city is already one-per-instance. What replaces them is a single pinned quota -- exactly one instance per ladder position -- which is what turns "select 100 good instances" into "select the best instance for each of these 100 slots".

The axes that remain are the ones the assignment left free. They keep their floors so the set stays analysable on each of them, and demand_type gains a ceiling as well -- a floor alone does not stop a max-min selector from parking its spare budget on one level.

Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/quotas.py
def ladder_tier_quotas(rung_keys: Sequence[str]) -> list[Quota]:
    """Coverage for a campaign whose sizes and sourcing are already assigned.

    Four of the old quotas are gone because the ladder assignment decided them
    before selection began: ``method`` is fixed per rung, ``avg_route_size`` too,
    ``size_bucket`` is covered by construction (one instance per distinct ``n``),
    and ``city`` is already one-per-instance. What replaces them is a single pinned quota --
    exactly one instance per ladder position -- which is what turns "select 100
    good instances" into "select the best instance for each of these 100 slots".

    The axes that remain are the ones the assignment left free. They keep their
    floors so the set stays analysable on each of them, and ``demand_type`` gains
    a *ceiling* as well -- a floor alone does not stop a max-min selector from
    parking its spare budget on one level.
    """
    k = len(rung_keys)
    return [
        # min == max == 1: the selector must fill every rung and may not double
        # up. Quota.cap_for enforces the ceiling hard; _shortfall raises up
        # front if any rung has no usable candidate.
        Quota(
            name="rung",
            key=lambda c: c.spec.rung_key,
            minimum={key: 1 for key in rung_keys},
            maximum={key: 1 for key in rung_keys},
        ),
        Quota(name="city", key=lambda c: c.spec.city, per_level_maximum=1),
        Quota(
            name="distortion_stratum",
            key=lambda c: c.spec.distortion_stratum,
            minimum=_even_minimum(STRATA, k, 0.80),
        ),
        Quota(
            name="demand_type",
            key=lambda c: c.spec.demand_type,
            minimum=_even_minimum(DEMAND_TYPES, k, 0.70),
            maximum=_even_maximum(DEMAND_TYPES, k, 1.60),
        ),
        # No ``avg_route_size`` quota: the ladder assigns the band per rung, so
        # it is already exact rather than merely floored. See
        # ``ladder.assign_route_size_bands``.
        Quota(
            name="depot_mode",
            key=lambda c: c.spec.depot_mode,
            minimum=_even_minimum(DEPOT_MODES, k, 0.75),
        ),
        Quota(
            name="customer_mode",
            key=lambda c: c.spec.customer_mode,
            minimum=_even_minimum(CUSTOMER_MODES, k, 0.75),
        ),
    ]

main_tier_quotas

main_tier_quotas(k: int) -> list[Quota]

Coverage the ~100-instance main tier must satisfy.

One instance per city, all three road-distortion strata represented, and every level of every design axis present in analysable numbers. The fractions are deliberately below an even share: they are a floor that makes the set analysable, not a straitjacket that turns selection back into a grid.

Superseded by :func:ladder_tier_quotas for the ladder campaign; kept for the grid-drawn tiers, which still draw their sizes and methods at random.

Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/quotas.py
def main_tier_quotas(k: int) -> list[Quota]:
    """Coverage the ~100-instance main tier must satisfy.

    One instance per city, all three road-distortion strata represented, and
    every level of every design axis present in analysable numbers. The
    fractions are deliberately below an even share: they are a floor that makes
    the set analysable, not a straitjacket that turns selection back into a grid.

    Superseded by :func:`ladder_tier_quotas` for the ladder campaign; kept for
    the grid-drawn tiers, which still draw their sizes and methods at random.
    """
    return [
        Quota(name="city", key=lambda c: c.spec.city, per_level_maximum=1),
        Quota(
            name="distortion_stratum",
            key=lambda c: c.spec.distortion_stratum,
            minimum=_even_minimum(STRATA, k, 0.80),
        ),
        Quota(
            name="demand_type",
            key=lambda c: c.spec.demand_type,
            minimum=_even_minimum(DEMAND_TYPES, k, 0.70),
        ),
        Quota(
            name="avg_route_size",
            key=lambda c: c.spec.avg_route_size,
            minimum=_even_minimum(AVG_ROUTE_SIZES, k, 0.55),
        ),
        Quota(
            name="depot_mode",
            key=lambda c: c.spec.depot_mode,
            minimum=_even_minimum(DEPOT_MODES, k, 0.75),
        ),
        Quota(
            name="customer_mode",
            key=lambda c: c.spec.customer_mode,
            minimum=_even_minimum(CUSTOMER_MODES, k, 0.75),
        ),
        Quota(
            name="method",
            # The realized sourcing, not the requested one: see
            # EvaluatedCandidate.effective_method.
            key=lambda c: c.effective_method or c.spec.method,
            minimum=_even_minimum(METHODS, k, 0.60),
        ),
        Quota(
            name="size_bucket",
            key=lambda c: size_bucket(c.spec.n),
            minimum=_even_minimum([name for name, _, _ in SIZE_BUCKETS], k, 0.60),
        ),
    ]

large_tier_quotas

large_tier_quotas(k: int) -> list[Quota]

Coverage for the handful of large instances.

Far weaker, and deliberately so: at this size the budget is measured in hours per instance, so the only things worth insisting on are that no city appears twice and that the distortion strata are not all the same.

Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/quotas.py
def large_tier_quotas(k: int) -> list[Quota]:
    """Coverage for the handful of large instances.

    Far weaker, and deliberately so: at this size the budget is measured in
    hours per instance, so the only things worth insisting on are that no city
    appears twice and that the distortion strata are not all the same.
    """
    return [
        Quota(name="city", key=lambda c: c.spec.city, per_level_maximum=1),
        Quota(
            name="distortion_stratum",
            key=lambda c: c.spec.distortion_stratum,
            minimum={stratum: 1 for stratum in STRATA} if k >= len(STRATA) else {},
        ),
    ]

excluded_cities

excluded_cities(selected: Sequence[EvaluatedCandidate]) -> set[str]

Cities already used, so a later tier does not reuse one.

Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/quotas.py
def excluded_cities(selected: Sequence[EvaluatedCandidate]) -> set[str]:
    """Cities already used, so a later tier does not reuse one."""
    return {candidate.spec.city for candidate in selected}

poi_tier_quotas

poi_tier_quotas(k: int) -> list[Quota]

Coverage for the POI-only large tier.

Three axes only. The sourcing axis is gone -- every instance in this tier is poi_categories by construction, which is the tier's whole point -- and the demand and depot axes are left to the max-min pass, because the pool is already small: only a handful of cities on Earth hold enough attachable amenities to serve thousands of customers, and quota'ing every axis over ~10 slots would fix the selection rather than guide it.

What is worth insisting on is that the tier spans its size range. An instance set that is nominally "1000 to 5000" but is really nine instances at 1100 and one at 5000 does not measure what happens as n grows.

Route size gets a ceiling and no floor. A floor here would be one of the quotas that fixes rather than guides -- seven levels over ten slots -- but a ceiling costs the selector almost nothing and stops the thing that actually happened in v2, where five of these ten instances landed in the longest band and mamut-athens-n4000-poi came out at 154 customers per route. This is the tier where the longest band is legitimate, so it is capped rather than excluded.

Source code in MAMUT-routing-tools/src/mamut_routing_tools/campaign/quotas.py
def poi_tier_quotas(k: int) -> list[Quota]:
    """Coverage for the POI-only large tier.

    Three axes only. The sourcing axis is gone -- every instance in this tier is
    ``poi_categories`` by construction, which is the tier's whole point -- and
    the demand and depot axes are left to the max-min pass, because the pool is
    already small: only a handful of cities on Earth hold enough attachable
    amenities to serve thousands of customers, and quota'ing every axis over
    ~10 slots would fix the selection rather than guide it.

    What is worth insisting on is that the tier spans its *size* range. An
    instance set that is nominally "1000 to 5000" but is really nine instances
    at 1100 and one at 5000 does not measure what happens as n grows.

    Route size gets a *ceiling* and no floor. A floor here would be one of the
    quotas that fixes rather than guides -- seven levels over ten slots -- but a
    ceiling costs the selector almost nothing and stops the thing that actually
    happened in v2, where five of these ten instances landed in the longest band
    and ``mamut-athens-n4000-poi`` came out at 154 customers per route. This is
    the tier where the longest band is legitimate, so it is capped rather than
    excluded.
    """
    return [
        Quota(name="city", key=lambda c: c.spec.city, per_level_maximum=1),
        Quota(
            name="distortion_stratum",
            key=lambda c: c.spec.distortion_stratum,
            minimum={stratum: 1 for stratum in STRATA} if k >= len(STRATA) else {},
        ),
        Quota(
            name="poi_size_bucket",
            key=lambda c: poi_size_bucket(c.spec.n),
            minimum=_even_minimum([name for name, _, _ in POI_SIZE_BUCKETS], k, 0.60),
        ),
        Quota(
            name="avg_route_size",
            key=lambda c: c.spec.avg_route_size,
            per_level_maximum=max(2, int(k / len(AVG_ROUTE_SIZES) * 1.60)),
        ),
    ]