Skip to content

Commit d82b23c

Browse files
authored
Add exponential decay (#189)
* added exponential decay * updated docstring * fixed flake8
1 parent a33a3f2 commit d82b23c

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

backoff/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@
1414
"""
1515
from backoff._decorator import on_exception, on_predicate
1616
from backoff._jitter import full_jitter, random_jitter
17-
from backoff._wait_gen import constant, expo, fibo, runtime
17+
from backoff._wait_gen import constant, expo, fibo, runtime, decay
1818

1919
__all__ = [
2020
'on_predicate',
2121
'on_exception',
2222
'constant',
2323
'expo',
24+
'decay',
2425
'fibo',
2526
'runtime',
2627
'full_jitter',

backoff/_wait_gen.py

+30
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# coding:utf-8
22

33
import itertools
4+
import math
45
from typing import Any, Callable, Generator, Iterable, Optional, Union
56

67

@@ -31,6 +32,35 @@ def expo(
3132
yield max_value
3233

3334

35+
def decay(
36+
initial_value: float = 1,
37+
decay_factor: float = 1,
38+
min_value: Optional[float] = None
39+
) -> Generator[float, Any, None]:
40+
41+
"""Generator for exponential decay[1]:
42+
43+
Args:
44+
initial_value: initial quantity
45+
decay_factor: exponential decay constant.
46+
min_value: The minimum value to yield. Once the value in the
47+
true exponential sequence is lower than this, the value
48+
of min_value will forever after be yielded.
49+
50+
[1] https://en.wikipedia.org/wiki/Exponential_decay
51+
"""
52+
# Advance past initial .send() call
53+
yield # type: ignore[misc]
54+
t = 0
55+
while True:
56+
a = initial_value * math.e ** (-t * decay_factor)
57+
if min_value is None or a > min_value:
58+
yield a
59+
t += 1
60+
else:
61+
yield min_value
62+
63+
3464
def fibo(max_value: Optional[int] = None) -> Generator[int, None, None]:
3565
"""Generator for fibonaccial decay.
3666

tests/test_wait_gen.py

+29
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
11
# coding:utf-8
22
import backoff
3+
import math
4+
5+
6+
def test_decay():
7+
gen = backoff.decay()
8+
gen.send(None)
9+
for i in range(10):
10+
assert math.e ** -i == next(gen)
11+
12+
13+
def test_decay_init100():
14+
gen = backoff.decay(initial_value=100)
15+
gen.send(None)
16+
for i in range(10):
17+
assert 100 * math.e ** -i == next(gen)
18+
19+
20+
def test_decay_init100_decay3():
21+
gen = backoff.decay(initial_value=100, decay_factor=3)
22+
gen.send(None)
23+
for i in range(10):
24+
assert 100 * math.e ** (-i * 3) == next(gen)
25+
26+
27+
def test_decay_init100_decay3_min5():
28+
gen = backoff.decay(initial_value=100, decay_factor=3, min_value=5)
29+
gen.send(None)
30+
for i in range(10):
31+
assert max(100 * math.e ** (-i * 3), 5) == next(gen)
332

433

534
def test_expo():

0 commit comments

Comments
 (0)