Coverage for /usr/local/lib/python3.12/site-packages/prefect/utilities/math.py: 24%
25 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-12-05 11:21 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-12-05 11:21 +0000
1import math 1a
2import random 1a
5def poisson_interval( 1a
6 average_interval: float, lower: float = 0, upper: float = 1
7) -> float:
8 """
9 Generates an "inter-arrival time" for a Poisson process.
11 Draws a random variable from an exponential distribution using the inverse-CDF
12 method. Can optionally be passed a lower and upper bound between (0, 1] to clamp
13 the potential output values.
14 """
16 # note that we ensure the argument to the logarithm is stabilized to prevent
17 # calling log(0), which results in a DomainError
18 return -math.log(max(1 - random.uniform(lower, upper), 1e-10)) * average_interval
21def exponential_cdf(x: float, average_interval: float) -> float: 1a
22 ld = 1 / average_interval
23 return 1 - math.exp(-ld * x)
26def lower_clamp_multiple(k: float) -> float: 1a
27 """
28 Computes a lower clamp multiple that can be used to bound a random variate drawn
29 from an exponential distribution.
31 Given an upper clamp multiple `k` (and corresponding upper bound k * average_interval),
32 this function computes a lower clamp multiple `c` (corresponding to a lower bound
33 c * average_interval) where the probability mass between the lower bound and the
34 median is equal to the probability mass between the median and the upper bound.
35 """
36 if k >= 50:
37 # return 0 for large values of `k` to prevent numerical overflow
38 return 0.0
40 return math.log(max(2**k / (2**k - 1), 1e-10), 2)
43def clamped_poisson_interval( 1a
44 average_interval: float, clamping_factor: float = 0.3
45) -> float:
46 """
47 Bounds Poisson "inter-arrival times" to a range defined by the clamping factor.
49 The upper bound for this random variate is: average_interval * (1 + clamping_factor).
50 A lower bound is picked so that the average interval remains approximately fixed.
51 """
52 if clamping_factor <= 0:
53 raise ValueError("`clamping_factor` must be >= 0.")
55 upper_clamp_multiple = 1 + clamping_factor
56 upper_bound = average_interval * upper_clamp_multiple
57 lower_bound = max(0, average_interval * lower_clamp_multiple(upper_clamp_multiple))
59 upper_rv = exponential_cdf(upper_bound, average_interval)
60 lower_rv = exponential_cdf(lower_bound, average_interval)
61 return poisson_interval(average_interval, lower_rv, upper_rv)
64def bounded_poisson_interval(lower_bound: float, upper_bound: float) -> float: 1a
65 """
66 Bounds Poisson "inter-arrival times" to a range.
68 Unlike `clamped_poisson_interval` this does not take a target average interval.
69 Instead, the interval is predetermined and the average is calculated as their
70 midpoint. This allows Poisson intervals to be used in cases where a lower bound
71 must be enforced.
72 """
73 average = (float(lower_bound) + float(upper_bound)) / 2.0
74 upper_rv = exponential_cdf(upper_bound, average)
75 lower_rv = exponential_cdf(lower_bound, average)
76 return poisson_interval(average, lower_rv, upper_rv)