Functional Weave
Code in Python

manufacturing.batch-size@1.0.0

impl/python.py

2,345 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .math_integer_sqrt import integer_sqrt  ← from math.integer-sqrt ^1.0.0 · built alongside by fune
from .math_round_div import RoundingMode  ← from math.round-div ^1.0.0 · built alongside by fune
from .money_amount import Money, assert_same_currency  ← from money.amount ^1.0.0 · built alongside by fune

MAX_SAFE = 2**53 - 1
MAX_I64 = 2**63 - 1


def economic_batch_quantity(
    annual_demand: int,
    annual_production_rate: int,
    setup_cost: Money,
    holding_cost: Money,
    mode: RoundingMode,
) -> int:
    """Economic batch quantity, sqrt(2DSP / (H(P - D))), in whole units.

    The root is never taken in floating point: the floor is an exact integer
    square root and the rounding decision compares whole numbers.
    """
    if isinstance(annual_demand, bool) or not isinstance(annual_demand, int) or annual_demand < 0 or annual_demand > MAX_SAFE:
        raise ValueError("annualDemand must be a whole number of units, not negative, received %r" % (annual_demand,))
    if (
        isinstance(annual_production_rate, bool)
        or not isinstance(annual_production_rate, int)
        or annual_production_rate <= annual_demand
        or annual_production_rate > MAX_SAFE
    ):
        raise ValueError(
            "annualProductionRate must be a whole number greater than annualDemand, received %r"
            % (annual_production_rate,)
        )
    assert_same_currency(setup_cost, holding_cost)
    if setup_cost.minor < 0:
        raise ValueError("setupCost must not be negative, received %d" % setup_cost.minor)
    if holding_cost.minor <= 0:
        raise ValueError("holdingCost must be greater than zero, received %d" % holding_cost.minor)
    d, p, s = annual_demand, annual_production_rate, setup_cost.minor
    eight = 8 * d * s * p
    if eight > MAX_I64:
        raise ValueError(
            "annualDemand, setupCost and annualProductionRate are too large: 8 x D x S x P must stay within 2^63 - 1"
        )
    two = 2 * d * s * p
    m = holding_cost.minor * (p - d)
    n = integer_sqrt(two // m)
    odd = 2 * n + 1
    if mode == "down":
        return n
    if mode == "up":
        return n if n * n * m == two else n + 1
    if mode == "half-up":
        return n + 1 if odd * odd * m <= eight else n
    if mode == "half-even":
        half = odd * odd * m
        if half < eight:
            return n + 1
        if half > eight:
            return n
        return n if n % 2 == 0 else n + 1
    raise ValueError('unknown rounding mode "%s"' % (mode,))