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.2.0.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

PyRoot-0.2.0-py3-none-any.whl (16.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: PyRoot-0.2.0.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.5

File hashes

Hashes for PyRoot-0.2.0.tar.gz
Algorithm Hash digest
SHA256 54432f9faa23a8f237127537f7fe2710662328249a1efa19375e764c182b9d89
MD5 5c385e32f52692c1e92f1547391c77b3
BLAKE2b-256 1f52504bb4849066d06cd7b4e015d68e66fdfeab8d361b95d64df8df97ae64c1

See more details on using hashes here.

File details

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

File metadata

  • Download URL: PyRoot-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.5

File hashes

Hashes for PyRoot-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e606090d26fb5a964305966f9c137688d5b6a08b1316a5fa92e74496108a0570
MD5 f0db397eb575f4a19e49b7a97183b130
BLAKE2b-256 b72b70bce7bd3f1985bdd1e677d63598961347538e2bd4a15140b7cf8d3e86b4

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