scijit.optimize.fixed_point

scijit.optimize.fixed_point(f, x0, args=(), xtol=1e-08, maxiter=500, method='del2', validate=True, full_output=False)

Scalar fixed point of f, a point where f(x) == x.

Uses Steffensen’s method with Aitken’s delta-squared acceleration under the default method='del2'.

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

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

The iteration map. Note this is f(x) = x, not f(x) = 0 – for a root use brentq() or newton().

x0float

Starting point. Scalar only: one return type per function.

argstuple, optional

Extra arguments for f, unpacked into every call as f(x, *args). Must be a tuple; anything else raises TypeError. Default ().

xtolfloat, optional

Relative convergence tolerance on (p - p0) / p0, falling back to the absolute value when p0 == 0. Default 1e-8.

maxiterint, optional

Iteration cap. Default 500.

method{‘del2’, ‘iteration’}, optional

'del2' (default) applies Aitken’s del-squared acceleration; 'iteration' runs the plain map. Any other value raises KeyError. Inside @njit it must be a compile-time constant.

validatebool, optional

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

full_outputbool, optional

False (default) returns the fixed point alone. True returns (x, FixedPointResults). Inside @njit it must be a compile-time constant. See Notes.

Returns:
xfloat

The fixed point, when full_output is False.

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

When full_output is True.

Raises:
ValueError

If x0 is not finite.

TypeError

If args is not a tuple.

KeyError

If method is neither 'del2' nor 'iteration'.

RuntimeError

If maxiter is reached, unless validate=False.

See also

scipy.optimize.fixed_point

The scipy routine this mirrors.

scijit.optimize.brentq

For f(x) == 0 rather than f(x) == x.

Notes

scipy’s fixed_point returns the fixed point itself and publishes no result object and no full_output. The bare call here returns what scipy’s returns. full_output is ADDITIVE: it exposes the iteration counts and the convergence flag that this package computes anyway, under a keyword no scipy-shaped call passes.

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.

validate has no counterpart in scipy’s signature. scipy raises on non-convergence unconditionally, so the default reproduces scipy and validate=False is the additive escape, for a sweep where an exception would end a run over thousands of points.

x0 is scalar only. scipy also accepts an array, which is not expressible here: a numba function has one return type.

The bare call returns a Python float. scipy returns a 0-d ndarray under method='del2' and a numpy.float64 under method='iteration', and neither boxes out of compiled code.

iterations and function_calls have no scipy counterpart to agree or disagree with: scipy’s fixed_point reports no counter of any kind. Under method='del2' they are related, function_calls == 2 * iterations, because the accelerated map evaluates f twice per iteration; under method='iteration' they are equal.

maxiter=0 raises RuntimeError here. scipy raises UnboundLocalError on the same input, because it formats the iterate into the failure message and the loop never bound it.

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

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

Examples

The fixed point of cosine, where cos(x) == x:

>>> import numpy as np
>>> from numba import njit
>>> from scijit.optimize import fixed_point
>>> @njit
... def g(x):
...     return np.cos(x)
>>> @njit
... def run():
...     return fixed_point(g, 1.0)
>>> round(run(), 10)
0.7390851332
>>> @njit
... def run_full():
...     return fixed_point(g, 1.0, full_output=True)
>>> x, res = run_full()
>>> round(x, 10), res.converged
(0.7390851332, True)