scijit.optimize.minimize_scalar

scijit.optimize.minimize_scalar(fun, bracket=None, bounds=None, args=(), method=None, tol=None, maxiter=None)

Scalar minimizer dispatcher.

One entry point over the three scalar minimizers, selected by name or by whether bounds was given.

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

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

Function to minimize.

bracketsequence of two or three floats or None, optional

For 'brent' and 'golden'. Two entries are seed points for a downhill bracket search and the minimum may land outside them. Three are a bracket used directly, and must satisfy xa < xb < xc and f(xb) < f(xa), f(xb) < f(xc). None (default) seeds the search from 0.0 and 1.0.

boundssequence of two floats or None, optional

Hard bounds for 'bounded', which searches inside them. Mandatory for that method and refused by the other two.

argstuple, optional

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

methodstr or None, optional

'brent', 'golden' or 'bounded' (fminbound()), matched case-insensitively. None (default) is 'brent', or 'bounded' when bounds is given. Anything else raises ValueError. Inside @njit it must be a literal string written at the call site, because it selects the return type. See Notes.

tolfloat or None, optional

Tolerance on the minimizer position, relative for 'brent' and 'golden' and absolute for 'bounded'. None (default) gives each method its own default: 1.48e-8 for 'brent', sqrt(eps) = 1.4901161193847656e-08 for 'golden', 1e-5 for 'bounded'. A value overrides all three, and supplying one for 'bounded' warns.

maxiterint or None, optional

None (default) gives each method its own default: 500 for 'brent', 5000 for 'golden', 500 for 'bounded'. It counts iterations for 'brent' and 'golden' and function evaluations for 'bounded', which passes it as maxfun.

Returns:
resMinimizeScalarResult or MinimizeScalarResultBounded

A namedtuple whose fields are reached by attribute, by index or by unpacking. 'brent' and 'golden' give the six fields below; 'bounded' gives those six and status.

funfloat

f at the minimum.

messagestr

Text for the outcome. See Notes.

nfevint

Evaluations of f, including the ones spent bracketing for 'brent' and 'golden'. 'bounded' does no bracketing.

nitint

Iterations ('brent', 'golden') or function evaluations ('bounded').

statusint

'bounded' only. 0 on success, 1 for maxfun reached and 2 for NaN.

successbool

False if the cap ran out or the result is NaN.

xfloat

Position of the minimum.

Raises:
ValueError

Unknown method; bounds given to 'brent' or 'golden'; bounds missing for 'bounded', or holding other than two elements, or not finite, or lower above upper; a bracket whose length is neither 2 nor 3, or whose three points are not ordered or do not bracket a minimum; or a negative tol on 'brent', which 'golden' accepts.

TypeError

If args is not a tuple, or bracket or bounds is not a sequence.

numba.TypingError

From inside @njit: method held in a variable, method that is not a string, an unknown method, or a bounds that is missing or is a tuple of other than two elements. See Notes.

Warns:
RuntimeWarning

If tol is supplied to method='bounded'.

See also

scipy.optimize.minimize_scalar

The scipy routine this mirrors.

scijit.optimize.brent

method='brent', the default.

scijit.optimize.golden

method='golden'.

scijit.optimize.fminbound

method='bounded'.

scijit.optimize.minimize

Several variables rather than one.

Notes

Three methods are named: 'brent', 'golden' and 'bounded', matched case-insensitively. scipy accepts a CALLABLE in the method argument as a fourth dispatch, which is not expressible inside @njit.

Inside @njit, method must be a literal string written at the call site. It selects the return type, since 'bounded' carries status and the other two do not, and a compiled function has one return type per signature. A method held in a variable raises numba.TypingError naming the constraint. From Python any string works. Two further refusals move to the same place inside @njit, because both are decidable while the call compiles: an unknown method, and a bounds that is missing or is a tuple of other than two elements. A bounds ARRAY of the wrong length is not decidable there and raises ValueError while the code runs.

A failed bracket search returns success=False with the best of the three bracket points, which is what scipy’s minimize_scalar does. brent() and golden() raise on the same input, which is also what scipy does; the two front ends deliberately differ.

bracket and bounds are tuples or arrays inside @njit. A python list is not typeable as an argument to compiled code.

maxiter is the one member of scipy’s options dict that is reachable. scipy’s disp travels in the same dict and has no counterpart here.

x and fun are Python floats. scipy returns numpy.float64 in both fields.

message is scipy’s, including its (using xtol = ...) line, whenever tol is known while the call compiles. It is known when the argument is omitted, which is every default call, and it is always known from Python. A tol written explicitly at an @njit call site is NOT: numba makes literals of ints, bools and strings but not of floats, so the value arrives typed float64 with the number gone, and the message is scipy’s first two lines without the third.

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

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

Examples

>>> from numba import njit
>>> from scijit.optimize import minimize_scalar
>>> @njit
... def q(x):
...     return (x - 1.5) ** 2 + 0.5
>>> @njit
... def run():
...     return minimize_scalar(q, bracket=(0.0, 3.0))
>>> res = run()
>>> round(res.x, 8), round(res.fun, 8), res.success
(1.5, 0.5, True)
>>> @njit
... def run_bounded():
...     return minimize_scalar(q, bounds=(0.0, 3.0))
>>> res = run_bounded()
>>> round(res.x, 8), res.nfev, res.status
(1.5, 6, 0)