Skip to main content

The purpose of this Python library is to provide implementations of advanced bracketed root-finding methods for single-variable functions.

Project description

pyroot

Abstract

The purpose of this Python library is to provide implementations of advanced bracketed root-finding methods for single-variable functions. These methods are meant to both guarantee convergence and also minimize the number of function calls made, even if extremely poor estimates of the root are initially provided or the function is not very well-behaved.

See our wiki for more information.

The following root-finding methods are implemented:

Note: The implementations may not precisely match specified methods. This is because a variety of additional features are incorporated to guarantee convergence of every method is rapid and tight, even in the face of initial estimates such as (-inf, inf). For example, the traditional bisection method fails to convergence to the correct order of magnitude rapidly e.g. it goes from (1e0, 1e300) to 5e299 instead of 1e150. Additionally, method's such as Brent's method may also produce "stagnant points", where the upper or lower bound of the root doesn't improve during iterations. For these reasons, modifications are made which generally improve convergence.

Example

from pyroot import solver, solver_table
from tabulate import tabulate  # https://pypi.org/project/tabulate/

inf = float("inf")

# A function whose root is being searched for.
def f(x):
    """x^3 - x^2 + 2x - 5 written with Horner's method."""
    return ((x - 1) * x + 2) * x - 5

# Use the default root-finder.
x = solver(f, -inf, +inf)
table = solver_table(f, -inf, +inf)

# Print the results.
print(f"x = {x}")
print(f"f(x) = {f(x)}")
print()
print(table)

Output:

x = 1.6398020042326555
f(x) = 0.0

  i              x               y
---  -------------  --------------
  0  -1.79769e+308  -inf
  1   1.79769e+308   inf
  2   0               -5
  3   1               -3
  4   4.09375         55.035
  5   2.54688         10.1277
  6   1.77344          0.979398
  7   1.65035          0.0720223
  8   1.63923         -0.00387468
  9   1.6398           1.76943e-05
 10   1.6398           1.31717e-11
 11   1.6398          -2.53042e-12
 12   1.6398           2.53042e-12
 13   1.6398           0
x = 1.6398020042326555

Rationale

Many other root-finding methods can be found elsewhere, so why choose pyroot?

Although it is true that other root-finding method implementations exist, many have the problems outlined in the note above. Although some other implementations may provide faster convergence under favorable circumstances, they most likely provide significantly slower convergence under unfavorable circumstances. This makes them even more unviable if function calls can be extremely expensive. Additionally, several methods are provided here which are not widely found elsewhere.

Another reason to use pyroot is that many of these root-finding implementations are a part of very large packages, such as scipy. This makes them significantly larger dependencies than pyroot, which is a single module you can add directly into your project without issues.

Usage

All of the methods involve the same base API, although some methods may further extend it e.g. the Newt-safe method includes an fprime parameter.

Solver Parameters

The solver takes the following arguments:

x = solver(f, x1, x2, *args, **kwargs, **options)

The required arguments for the solver API are the following 3 positional-only parameters:

  • f is the function whose root you are searching for. It must accept 1 float argument.
  • x1, x2 are the first two estimates for the root. Requires f(x1) and f(x2) have different signs.

The following 10 keyword-only parameters (**options) allow some customizability:

  • y1, y2 may be f(x1), f(x2) if known ahead of time, or approximately known.
  • x may be a better estimate of the root than x1 or x2, but f(x) has unknown sign.
  • method may be the string name of a bracketing method, or an implementation of one.
  • x_err, r_err controls how long the solver runs, representating the absolute and relative error.
  • x_tol, r_tol controls initial step-sizes, preventing slow initial convergence when the bracketing interval is significantly larger.
  • refine controls the number of additional iterations ran after x_err or r_err are reached. By default set to run 15 iterations, but usually only takes 3 iterations.
  • mean controls the behavior of bisection-like iterations. By default, employs tricks to improve convergence on large intervals.

Note: Nothing is included for termination based on the number of iterations. This is because most cases will terminate in less than 25 iterations already. If one truly wishes to terminate based on a set number of iterations, the solver_generator may be used to terminate based on a fixed number of iterations, or other termination conditions, such as the magnitude of f(x). If one does this, it should be noted that the last produced iteration need not be the best estimate of the root.

Method Parameters

Additional *args or **kwargs may be provided to be passed into the particular method, as follows:

# Passes *args, **kwargs into the method.
x = solver(f, x1, x2, *args, **kwargs, **options)

For example:

x = solver(f, x1, x2, fprime, method="newton")

Solver Generator / Table

The solver_generator provides the same API as the solver, but instead of just returning the final result, every iteration is yielded. This allows one to track iterations as they occur, send estimates in-between iterations, terminate early, and so on. The documentation includes examples of this combined with the tabulate package to allow prettier printing.

The solver_table provides the same API as the solver_generator, but instead of generating results, a stringified table of results is returned, using the tabulate package.

Full API Documentation

For a full description of the solver, run the following code:

from pyroot import solver

help(solver)

For a full description of a method, such as the Newt-safe method, run the following code:

from pyroot import methods_dict

help(methods_dict["newt safe"])

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

PyRoot-0.1.1.tar.gz (18.6 kB view details)

Uploaded Source

Built Distribution

PyRoot-0.1.1-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

Details for the file PyRoot-0.1.1.tar.gz.

File metadata

  • Download URL: PyRoot-0.1.1.tar.gz
  • Upload date:
  • Size: 18.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for PyRoot-0.1.1.tar.gz
Algorithm Hash digest
SHA256 6678638453105e7d9e3b2d359808ccaad6dcfe79d6b0f5f6d8f9f5374387fbcc
MD5 ea58d59b151028d3a4e5ba79a3c424dc
BLAKE2b-256 20341d9aa5f0d8068139b7ed63e29b521dc6a21bce857b7c07626275fdfed512

See more details on using hashes here.

File details

Details for the file PyRoot-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: PyRoot-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 19.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.7

File hashes

Hashes for PyRoot-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 996023f700649c96bf00bcecabcafd6944fe920160986e743a37f8d17baf5cf6
MD5 364f8d4db5663752635dfec52d66016f
BLAKE2b-256 7ef4ce0cf3128f0c9bdc8aa14b73339c750664ad2cba882c5e4a16c5055113ca

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page