scijit.optimize.root_scalar

scijit.optimize.root_scalar(f, args=(), method=None, bracket=None, fprime=None, fprime2=None, x0=None, x1=None, xtol=None, rtol=None, maxiter=None, validate=False)

Scalar root-finder dispatcher.

One entry point over the eight scalar root-finders, selected by name or by what was supplied.

Callback style A: f, fprime and fprime2 are plain @njit functions f(x) -> float.

Parameters:
f@njit function f(x) -> float

Function whose root is wanted.

argstuple, optional

Extra arguments for f, unpacked into every call as f(x, *args). A non-tuple is taken as a single extra argument. Default (). Reaches fprime and fprime2 too.

methodstr or None, optional

'brentq', 'brenth', 'bisect', 'ridder', 'toms748', 'secant', 'newton' or 'halley', matched case-insensitively. None (default) selects from what was supplied: bracket gives 'brentq'; x0 with fprime and fprime2 gives 'halley', with fprime alone 'newton', with x1 'secant', and on its own 'newton'. Any other name raises ValueError.

bracketsequence of two floats or None, optional

Interval bracketing a root, for 'brentq', 'brenth', 'bisect', 'ridder' and 'toms748'. f(a, *args) and f(b, *args) must not have the same sign. A longer sequence uses its first two entries.

fprime@njit function fprime(x) -> float or None, optional

First derivative, for 'newton' and 'halley'. 'newton' without one differences f forward instead.

fprime2@njit function fprime2(x) -> float or None, optional

Second derivative, required by 'halley'.

x0float or None, optional

Starting guess, for 'secant', 'newton' and 'halley'.

x1float or None, optional

Second starting guess, for 'secant'. Without it the secant loop invents one from x0.

xtolfloat or None, optional

Absolute tolerance. None (default) gives each method its own: 2e-12 for the five bracketing methods, and 1.48e-8 for 'secant', 'newton' and 'halley', where it is that method’s tol.

rtolfloat or None, optional

Relative tolerance. None (default) gives 4 * eps for the bracketing methods and 0.0 for the other three.

maxiterint or None, optional

Iteration cap. None (default) gives 100 for the bracketing methods and 50 for the other three.

validatebool, optional

False (default) returns converged=False when the chosen method reaches maxiter. True raises RuntimeError instead, which is what the individual solvers in this module do. See Notes.

Returns:
resRootResults

A namedtuple whose fields are reached by attribute, by index or by unpacking.

rootfloat

Root estimate.

iterationsint

Iterations used.

function_callsint

Evaluations of f. Counts every one, including the ones a solver discards. For newton() with derivatives it also counts the derivative evaluations.

convergedbool

True if a tolerance test was met before maxiter.

flagstr

'converged', or 'convergence error'.

methodstr

The method that produced the result, by name.

Raises:
ValueError

If method is not one of the eight names; if neither bracket nor x0 is given and method is None; if a bracketing method gets no bracket, or an open method no x0, or 'halley' no fprime or fprime2; or if the chosen method rejects its bracket.

RuntimeError

If the chosen method reaches maxiter and validate=True. The default validate=False returns converged=False instead.

See also

scipy.optimize.root_scalar

The scipy routine this mirrors.

scijit.optimize.brentq

method='brentq', chosen for a bracket.

scijit.optimize.newton

The three open methods, called directly.

scijit.optimize.root

Systems of equations rather than one scalar.

Notes

validate has no counterpart in scipy’s root_scalar signature. scipy overrides the chosen method’s disp to False (optimize/_root_scalar.py:249), so its root_scalar never raises on non-convergence whatever the method would do on its own. The default validate=False here reproduces that; validate=True is the additive setting, and it is what the individual solvers default to.

A RootResults is returned always, as scipy’s root_scalar does. scipy has no full_output on this routine. Its object is a dict subclass that neither unpacks nor indexes by integer, where this namedtuple does both; the field names and their order are the same.

bracket is a tuple or an array inside @njit. A python list is not typeable as an argument to compiled code.

scipy also accepts an options dict, which is how toms748’s k is reachable through that front end. It is not available here; toms748() takes k directly.

A NaN function value raises ValueError, as it does in the underlying solvers. scipy catches that same exception inside root_scalar and returns a RootResults whose iterations is nan and whose flag is the exception text.

Pure @njit, safe to call from a numba.prange loop.

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.root_scalar.html

Examples

>>> from numba import njit
>>> from scijit.optimize import root_scalar
>>> @njit
... def f(x):
...     return x * x - 2.0
>>> @njit
... def run():
...     return root_scalar(f, bracket=(0.0, 2.0))
>>> res = run()
>>> round(res.root, 12), res.converged, res.method
(1.414213562373, True, 'brentq')

A derivative selects Newton-Raphson, and both select Halley:

>>> @njit
... def fp(x):
...     return 2.0 * x
>>> @njit
... def run2():
...     return root_scalar(f, x0=1.0, fprime=fp)
>>> res2 = run2()
>>> round(res2.root, 12), res2.iterations, res2.method
(1.414213562373, 5, 'newton')