Skip to content

mamut_routing_tools.generation.demands

Demand distributions, route-size bands, and the capacity formula (port of the workbench generator's seven demand types).

generate_demands

generate_demands(
    rng: Random,
    customer_ll: list[tuple[float, float]],
    demand_type: int,
    avg_route_size: int,
) -> tuple[list[int], int, int, float]

Per-customer demands; returns (demands, total, max, target route size r).

Source code in MAMUT-routing-tools/src/mamut_routing_tools/generation/demands.py
def generate_demands(
    rng: random.Random,
    customer_ll: list[tuple[float, float]],
    demand_type: int,
    avg_route_size: int,
) -> tuple[list[int], int, int, float]:
    """Per-customer demands; returns (demands, total, max, target route size r)."""
    n = len(customer_ll)
    if n < 1:
        raise ValueError("At least one customer is required")

    rlo, rhi = avg_route_size_bounds(avg_route_size)
    r = rng.random() * (rhi - rlo) + rlo

    if demand_type == 1:
        demands = [1] * n
        return demands, n, 1, r

    lo, hi = demand_distribution_bounds(demand_type)
    lat_center = sum(p[0] for p in customer_ll) / n
    lon_center = sum(p[1] for p in customer_ll) / n

    demands = []
    for i in range(n):
        d = rng.randint(lo, hi)
        if demand_type == 6:
            lat, lon = customer_ll[i]
            same_diagonal = (lat < lat_center and lon < lon_center) or (lat >= lat_center and lon >= lon_center)
            d = rng.randint(51, 100) if same_diagonal else rng.randint(1, 50)
        elif demand_type == 7:
            # Julia iterates 1-based: the first ceil-ish 1.5*n/r customers in
            # POSITION get bulky demands, the rest small ones (then shuffled).
            if (i + 1) < (n / r) * 1.5:
                d = rng.randint(50, 100)
            else:
                d = rng.randint(1, 10)
        demands.append(d)

    if demand_type != 6:
        rng.shuffle(demands)

    return demands, sum(demands), max(demands), r