A clean, robust, and easy-to-use Python package for finding roots of single-variable, real-valued functions using a suite of classic numerical algorithms.
- Consistent API: All solvers return a standardized RootResult object.
- Robust Error Handling: Solvers handle edge cases like convergence failure or bad inputs gracefully without crashing.
- Clear & Informative Output: The result object reports the root, success status, iterations, and diagnostic messages.
- Suite of Algorithms:
- Bracketing methods: bisection, secant, brentq (recommended)
- Derivative-based methods: newton, halley
Install using pip:
pip install pyrootfinder
Find the root of the function:
import pyrootfinder as rf
import math
# define the function
f = lambda x: x**3 - x - 2
# use a bracketing method (brent's method is highly recommended)
# root lies between 1 and 2
result_brent = rf.brentq(f, a=1, b=2)
print(result_brent)
# use a derivative-based method (newton's method)
f_prime = lambda x: 3*x**2 - 1
result_newton = rf.newton(f, x0=1.5, f_prime=f_prime)
print(result_newton)
---- Brent's (Brentq) Result (Success) ----
Root: 1.5213797068
Function Value: 0.000000e+00
Iterations: 9
Message: Convergence achieved.
-------------------------------------------
---- Newton-Raphson Result (Success) ----
Root: 1.5213797068
Function Value: -1.110223e-16
Iterations: 3
Message: Convergence achieved.
-----------------------------------------
The library is designed to fail gracefully. If a root cannot be found within the given bracket or iteration limit, a clear failure message is returned.
# find a root where none exists in the given bracket
result_fail = rf.bisection(lambda x: x**2 + 1, a=-10, b=10)
print(result_fail)
---- Bisection Result (Failed) ----
Message: Root not bracketed or multiple roots exist in [a, b].
Iterations: 0
-----------------------------------
All solvers return a RootResult object with attributes such as root, iterations, success, and message.
rf.bisection(f, a, b, tol=1e-8, max_iter=100)
rf.secant(f, a, b, tol=1e-8, max_iter=100)
rf.brentq(f, a, b, tol=1e-8, max_iter=100)
rf.newton(f, x0, f_prime, tol=1e-8, max_iter=100)
rf.halley(f, x0, f_prime, f_prime2, tol=1e-8, max_iter=100)
This repository is participating in Hacktoberfest. Contributions are welcome from developers of all experience levels. If you're new to open source, check out issues labeled good first issue
or help wanted
.
To contribute:
- Fork the repository
- Create a new branch
- Make your changes
- Submit a pull request
Please read the CONTRIBUTING.md and CODE_OF_CONDUCT.md before submitting.
If you have questions, suggestions, or feedback:
- Open an issue on GitHub
- Join discussions under relevant pull requests
- Refer to the documentation and examples in the repo
This project is licensed under the MIT License.