From 06586d7ca60661ac06f1b587e35734136b1e9517 Mon Sep 17 00:00:00 2001 From: Dibbu-cell Date: Wed, 1 Oct 2025 23:16:13 +0530 Subject: [PATCH 1/4] brent's_method --- maths/numerical_analysis/brent's_method.py | 89 ++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 maths/numerical_analysis/brent's_method.py diff --git a/maths/numerical_analysis/brent's_method.py b/maths/numerical_analysis/brent's_method.py new file mode 100644 index 000000000000..d1b3912ac068 --- /dev/null +++ b/maths/numerical_analysis/brent's_method.py @@ -0,0 +1,89 @@ +import math +from collections.abc import Callable + +def brent_method( + f: Callable[[float], float], + a: float, + b: float, + tol: float = 1e-14, + max_iter: int = 100 +) -> float: + """ + Root finding using Brent's method. + + >>> brent_method(lambda x: x**3 - 1, -5, 5) + 1.0 + >>> brent_method(lambda x: x**2 - 4*x + 3, 0, 2) + 1.0 + >>> brent_method(lambda x: x**2 - 4*x + 3, 2, 4) + 3.0 + >>> brent_method(lambda x: x**2 - 4*x + 3, 4, 1000) + Traceback (most recent call last): + ... + ValueError: Root is not bracketed. + """ + + fa = f(a) + fb = f(b) + if fa * fb >= 0: + raise ValueError("Root is not bracketed.") + + if abs(fa) < abs(fb): + a, b = b, a + fa, fb = fb, fa + + c = a + fc = fa + d = e = b - a + mflag = True + + for _ in range(max_iter): + if fb == 0: + return b + if fa != fc and fb != fc: + # Inverse quadratic interpolation + s = ( + a * fb * fc / ((fa - fb) * (fa - fc)) + + b * fa * fc / ((fb - fa) * (fb - fc)) + + c * fa * fb / ((fc - fa) * (fc - fb)) + ) + else: + # Secant method + s = b - fb * (b - a) / (fb - fa) + + conditions = [ + not ((3 * a + b) / 4 < s < b if b > a else b < s < (3 * a + b) / 4), + mflag and abs(s - b) >= abs(b - c) / 2, + not mflag and abs(s - b) >= abs(c - d) / 2, + mflag and abs(b - c) < tol, + not mflag and abs(c - d) < tol, + ] + if any(conditions): + s = (a + b) / 2 + mflag = True + else: + mflag = False + + fs = f(s) + d, c = c, b + fc = fb + + if fa * fs < 0: + b = s + fb = fs + else: + a = s + fa = fs + + if abs(fa) < abs(fb): + a, b = b, a + fa, fb = fb, fa + + if abs(b - a) < tol or fb == 0: + return b + + return b + +if __name__ == "__main__": + from doctest import testmod + testmod() \ No newline at end of file From 56d6f970a90eb5536f3a95dd1e10cc20e5965481 Mon Sep 17 00:00:00 2001 From: Dibbu-cell Date: Wed, 1 Oct 2025 23:52:20 +0530 Subject: [PATCH 2/4] barents --- .../{brent's_method.py => brents_method.py} | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) rename maths/numerical_analysis/{brent's_method.py => brents_method.py} (97%) diff --git a/maths/numerical_analysis/brent's_method.py b/maths/numerical_analysis/brents_method.py similarity index 97% rename from maths/numerical_analysis/brent's_method.py rename to maths/numerical_analysis/brents_method.py index d1b3912ac068..3ebf0ffd5e96 100644 --- a/maths/numerical_analysis/brent's_method.py +++ b/maths/numerical_analysis/brents_method.py @@ -1,4 +1,3 @@ -import math from collections.abc import Callable def brent_method( @@ -34,7 +33,7 @@ def brent_method( c = a fc = fa - d = e = b - a + d = b - a # Only d is used, e removed mflag = True for _ in range(max_iter): @@ -86,4 +85,4 @@ def brent_method( if __name__ == "__main__": from doctest import testmod - testmod() \ No newline at end of file + testmod() From 0aeb7f758880005017dc3b6899066cb6842aa9e1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 18:29:15 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- maths/numerical_analysis/brents_method.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/maths/numerical_analysis/brents_method.py b/maths/numerical_analysis/brents_method.py index 3ebf0ffd5e96..4fddf02ab868 100644 --- a/maths/numerical_analysis/brents_method.py +++ b/maths/numerical_analysis/brents_method.py @@ -1,11 +1,12 @@ from collections.abc import Callable + def brent_method( f: Callable[[float], float], a: float, b: float, tol: float = 1e-14, - max_iter: int = 100 + max_iter: int = 100, ) -> float: """ Root finding using Brent's method. @@ -42,9 +43,9 @@ def brent_method( if fa != fc and fb != fc: # Inverse quadratic interpolation s = ( - a * fb * fc / ((fa - fb) * (fa - fc)) + - b * fa * fc / ((fb - fa) * (fb - fc)) + - c * fa * fb / ((fc - fa) * (fc - fb)) + a * fb * fc / ((fa - fb) * (fa - fc)) + + b * fa * fc / ((fb - fa) * (fb - fc)) + + c * fa * fb / ((fc - fa) * (fc - fb)) ) else: # Secant method @@ -83,6 +84,8 @@ def brent_method( return b + if __name__ == "__main__": from doctest import testmod + testmod() From e3f1eae4edb139aa979b2800369dc13b2279c407 Mon Sep 17 00:00:00 2001 From: Dibbu-cell Date: Thu, 2 Oct 2025 00:13:19 +0530 Subject: [PATCH 4/4] brents3 --- maths/numerical_analysis/brents_method.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/numerical_analysis/brents_method.py b/maths/numerical_analysis/brents_method.py index 3ebf0ffd5e96..90fa41133500 100644 --- a/maths/numerical_analysis/brents_method.py +++ b/maths/numerical_analysis/brents_method.py @@ -39,7 +39,7 @@ def brent_method( for _ in range(max_iter): if fb == 0: return b - if fa != fc and fb != fc: + if fc not in {fa, fb}: # Inverse quadratic interpolation s = ( a * fb * fc / ((fa - fb) * (fa - fc)) + @@ -85,4 +85,4 @@ def brent_method( if __name__ == "__main__": from doctest import testmod - testmod() + testmod() \ No newline at end of file