Skip to content

Commit ead646c

Browse files
Add Brent’s Method for root finding with descriptive parameters
1 parent 13a414d commit ead646c

1 file changed

Lines changed: 30 additions & 28 deletions

File tree

maths/numerical_analysis/brent_method.py

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,19 @@
2323

2424

2525
def brent_method(
26-
f: Callable[[float], float],
27-
a: float,
28-
b: float,
26+
func: Callable[[float], float],
27+
left_bound: float,
28+
right_bound: float,
2929
tol: float = 1e-7,
3030
max_iter: int = 100,
3131
) -> float:
3232
"""
3333
Find a root of the function f in the interval [a, b] using Brent's method.
3434
3535
Args:
36-
f: The function for which we are trying to find a root.
37-
a: The start of the interval.
38-
b: The end of the interval.
36+
func: The function for which we are trying to find a root.
37+
left_bound: The start of the interval.
38+
right_bound: The end of the interval.
3939
tol: The allowed error of the result.
4040
max_iter: Maximum number of iterations.
4141
@@ -46,55 +46,57 @@ def brent_method(
4646
ValueError: If f(a) and f(b) do not have opposite signs.
4747
RuntimeError: If the root is not found within max_iter iterations.
4848
"""
49-
fa = f(a)
50-
fb = f(b)
49+
fa = func(left_bound)
50+
fb = func(right_bound)
5151
if fa * fb >= 0:
5252
raise ValueError("f(a) and f(b) must have different signs")
5353

5454
if abs(fa) < abs(fb):
55-
a, b = b, a
55+
left_bound, right_bound = right_bound, left_bound
5656
fa, fb = fb, fa
5757

58-
c, fc = a, fa
59-
d = e = b - a
58+
c, fc = left_bound, fa
59+
d = e = right_bound - left_bound
6060

6161
for _ in range(max_iter):
6262
if fb == 0:
63-
return b
63+
return right_bound
6464
if fc not in (fa, fb):
6565
# Inverse quadratic interpolation
6666
s = (
67-
a * fb * fc / ((fa - fb) * (fa - fc))
68-
+ b * fa * fc / ((fb - fa) * (fb - fc))
67+
left_bound * fb * fc / ((fa - fb) * (fa - fc))
68+
+ right_bound * fa * fc / ((fb - fa) * (fb - fc))
6969
+ c * fa * fb / ((fc - fa) * (fc - fb))
7070
)
7171
else:
7272
# Secant Method
73-
s = b - fb * (b - a) / (fb - fa)
73+
s = right_bound - fb * (right_bound - left_bound) / (fb - fa)
7474

7575
conditions = [
76-
not ((3 * a + b) / 4 < s < b) if b > a else not (b < s < (3 * a + b) / 4),
77-
(e is not None and abs(s - b) >= abs(e / 2)),
76+
not ((3 * left_bound + right_bound) / 4 < s < right_bound)
77+
if right_bound > left_bound
78+
else not (right_bound < s < (3 * left_bound + right_bound) / 4),
79+
(e is not None and abs(s - right_bound) >= abs(e / 2)),
7880
(d is not None and abs(d) >= abs(e / 2)),
79-
abs(b - a) < tol,
81+
abs(right_bound - left_bound) < tol,
8082
]
8183
if any(conditions):
82-
s = (a + b) / 2 # Bisection method
83-
e = d = b - a
84+
s = (left_bound + right_bound) / 2 # Bisection method
85+
e = d = right_bound - left_bound
8486
else:
8587
d = e
86-
e = b - s
88+
e = right_bound - s
8789

88-
fs = f(s)
89-
c, fc = b, fb
90+
fs = func(s)
91+
c, fc = right_bound, fb
9092
if fa * fs < 0:
91-
b, fb = s, fs
93+
right_bound, fb = s, fs
9294
else:
93-
a, fa = s, fs
95+
left_bound, fa = s, fs
9496
if abs(fa) < abs(fb):
95-
a, b = b, a
97+
left_bound, right_bound = right_bound, left_bound
9698
fa, fb = fb, fa
97-
if abs(b - a) < tol:
98-
return b
99+
if abs(right_bound - left_bound) < tol:
100+
return right_bound
99101

100102
raise RuntimeError("Maximum number of iterations reached without convergence")

0 commit comments

Comments
 (0)