Skip to content

prefect.utilities.math

bounded_poisson_interval(lower_bound, upper_bound)

Bounds Poisson "inter-arrival times" to a range.

Unlike clamped_poisson_interval this does not take a target average interval. Instead, the interval is predetermined and the average is calculated as their midpoint. This allows Poisson intervals to be used in cases where a lower bound must be enforced.

Source code in src/prefect/utilities/math.py
60
61
62
63
64
65
66
67
68
69
70
71
72
def bounded_poisson_interval(lower_bound, upper_bound):
    """
    Bounds Poisson "inter-arrival times" to a range.

    Unlike `clamped_poisson_interval` this does not take a target average interval.
    Instead, the interval is predetermined and the average is calculated as their
    midpoint. This allows Poisson intervals to be used in cases where a lower bound
    must be enforced.
    """
    average = (float(lower_bound) + float(upper_bound)) / 2.0
    upper_rv = exponential_cdf(upper_bound, average)
    lower_rv = exponential_cdf(lower_bound, average)
    return poisson_interval(average, lower_rv, upper_rv)

clamped_poisson_interval(average_interval, clamping_factor=0.3)

Bounds Poisson "inter-arrival times" to a range defined by the clamping factor.

The upper bound for this random variate is: average_interval * (1 + clamping_factor). A lower bound is picked so that the average interval remains approximately fixed.

Source code in src/prefect/utilities/math.py
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def clamped_poisson_interval(average_interval, clamping_factor=0.3):
    """
    Bounds Poisson "inter-arrival times" to a range defined by the clamping factor.

    The upper bound for this random variate is: average_interval * (1 + clamping_factor).
    A lower bound is picked so that the average interval remains approximately fixed.
    """
    if clamping_factor <= 0:
        raise ValueError("`clamping_factor` must be >= 0.")

    upper_clamp_multiple = 1 + clamping_factor
    upper_bound = average_interval * upper_clamp_multiple
    lower_bound = max(0, average_interval * lower_clamp_multiple(upper_clamp_multiple))

    upper_rv = exponential_cdf(upper_bound, average_interval)
    lower_rv = exponential_cdf(lower_bound, average_interval)
    return poisson_interval(average_interval, lower_rv, upper_rv)

lower_clamp_multiple(k)

Computes a lower clamp multiple that can be used to bound a random variate drawn from an exponential distribution.

Given an upper clamp multiple k (and corresponding upper bound k * average_interval), this function computes a lower clamp multiple c (corresponding to a lower bound c * average_interval) where the probability mass between the lower bound and the median is equal to the probability mass between the median and the upper bound.

Source code in src/prefect/utilities/math.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def lower_clamp_multiple(k):
    """
    Computes a lower clamp multiple that can be used to bound a random variate drawn
    from an exponential distribution.

    Given an upper clamp multiple `k` (and corresponding upper bound k * average_interval),
    this function computes a lower clamp multiple `c` (corresponding to a lower bound
    c * average_interval) where the probability mass between the lower bound and the
    median is equal to the probability mass between the median and the upper bound.
    """
    if k >= 50:
        # return 0 for large values of `k` to prevent numerical overflow
        return 0.0

    return math.log(max(2**k / (2**k - 1), 1e-10), 2)

poisson_interval(average_interval, lower=0, upper=1)

Generates an "inter-arrival time" for a Poisson process.

Draws a random variable from an exponential distribution using the inverse-CDF method. Can optionally be passed a lower and upper bound between (0, 1] to clamp the potential output values.

Source code in src/prefect/utilities/math.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def poisson_interval(average_interval, lower=0, upper=1):
    """
    Generates an "inter-arrival time" for a Poisson process.

    Draws a random variable from an exponential distribution using the inverse-CDF
    method. Can optionally be passed a lower and upper bound between (0, 1] to clamp
    the potential output values.
    """

    # note that we ensure the argument to the logarithm is stabilized to prevent
    # calling log(0), which results in a DomainError
    return -math.log(max(1 - random.uniform(lower, upper), 1e-10)) * average_interval