scijit.optimize.ridder

scijit.optimize.ridder(f, a, b, args=(), xtol=2e-12, rtol=8.881784197001252e-16, maxiter=100, full_output=False, disp=True)

Ridders’ method.

Exponential-correction bracketer (the classic zriddr): each iteration evaluates f twice and converges quadratically, so it often beats bisection while keeping a guaranteed bracket.

Callback style A: f is a plain @njit f(x) -> float.

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

Continuous function whose root is wanted.

a, bfloat

Bracket endpoints. f(a) and f(b) must not have the same sign; if they do, ValueError is raised. Either endpoint being an exact root returns immediately with iterations = 0.

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 ().

xtolfloat, optional

Absolute tolerance on the bracket width. Default 2e-12. Must be positive; ValueError otherwise.

rtolfloat, optional

Relative tolerance; convergence when |b - a| < xtol + rtol * |x|. Default 4 * eps, which is also its floor. A smaller value raises ValueError.

maxiterint, optional

Iteration cap. Default 100. Each iteration costs two f evaluations. Negative raises ValueError.

full_outputbool, optional

False (default) returns the root alone. True returns (x, RootResults). Inside @njit it must be a compile-time constant; see Notes.

dispbool, optional

True (default) raises RuntimeError when the iteration limit is reached. False returns converged=False instead.

Returns:
xfloat

The estimated root, when full_output is False.

(x, res)tuple of (float, RootResults)

When full_output is True. res 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 f(a) and f(b) have the same sign; if f returns NaN at any iterate; if xtol <= 0; if rtol is below 4 * eps; or if maxiter < 0.

RuntimeError

If maxiter is reached, unless disp=False.

numba.core.errors.TypingError

From inside @njit, if full_output is a runtime variable.

See also

scipy.optimize.ridder

The scipy routine this mirrors.

scijit.optimize.brentq

Usually fewer evaluations.

scijit.optimize.bisect

Slower, and uses only the sign of f.

Notes

full_output selects the RETURN SHAPE, and a compiled function has one return type per signature, so inside @njit the flag has to be readable when the call compiles. A literal, an omitted default and a module-level constant all are; a variable is not, and raises TypingError naming the constraint. From Python a runtime value is fine.

The result is a namedtuple, where scipy’s is a dict subclass. See RootResults.

iterations is 0 when a or b is an exact root. scipy’s C returns before assigning that field and reports an indeterminate value read from uninitialised memory.

The convergence test uses |x| where scipy uses x. scipy’s in-loop tolerance is xtol + rtol * xn with no absolute value, which is negative for a root at a large negative x: at xn = -1e10 and the default rtol it is -4.4e-06, and |b - a| never falls below it, so scipy runs to maxiter unless some f(xn) is exactly zero. This converges there instead.

Pure @njit, prange-safe.

Examples

>>> from numba import njit
>>> from scijit.optimize import ridder
>>> @njit
... def f(x):
...     return x * x - 2.0
>>> @njit
... def run():
...     return ridder(f, 0.0, 2.0)
>>> round(run(), 12)
1.414213562372
>>> @njit
... def run_full():
...     return ridder(f, 0.0, 2.0, full_output=True)
>>> x, res = run_full()
>>> round(x, 12), res.converged, res.method
(1.414213562372, True, 'ridder')