scijit.optimize.fmin_powell¶
- scijit.optimize.fmin_powell(func, x0, args=(), xtol=0.0001, ftol=0.0001, maxiter=None, maxfun=None, full_output=0, disp=1, retall=0, callback=None, direc=None)¶
Minimize a function using Powell’s direction-set method.
Derivative-free. Minimizes along a set of directions that is updated each sweep, using a scalar Brent line search.
Callable from Python and from inside
@njit. Both entries run the same compiled core, so they cannot disagree.- Parameters:
- funccallable
A plain
@njitfunc(x, *args) -> float.- x0array_like
Initial guess. Any rank is flattened.
- argstuple or ndarray, optional
Extra parameters. A tuple is unpacked into separate arguments after x, so
args=(a, b)callsfunc(x, a, b). Its elements may be of any type a compiled call accepts, arrays and strings included. Default(), which callsfunc(x). An ndarray or a list arrives as ONE argument instead,func(x, args). See Notes.- xtolfloat, optional
Line-search tolerance. Default 1e-4. The inner Brent search runs at
xtol * 100.- ftolfloat, optional
Relative convergence tolerance on f between sweeps. Default 1e-4.
- maxiter, maxfunint, float or None, optional
Sweep and evaluation budgets.
None(default) meansN*1000for BOTH, but supplying only ONE leaves the OTHER unbounded rather than at the default.np.infis accepted and means unbounded.- full_outputbool, optional
False(default) returns xopt alone.Truereturns the 6-tuple. Compile-time constant inside@njit: it selects the return type.- dispint, optional
1(default) prints a summary. The status line appears only on success and becomes aRuntimeWarningotherwise; the counters print either way.0is silent, and is what aprangesweep wants: see Notes.- retallbool, optional
Append
allvecsto the return. Compile-time constant.- callbackcallable or None, optional
Called once per iteration as
callback(xk), with a copy of the current iterate. A plain Python function may instead be writtencallback(intermediate_result)and is handed an object carryingxandfun. RaisingStopIterationstops the run and returns the current best. From inside@njitthe callback is an@njitcallback(xk).- direcarray_like or None, optional
(N, N)initial direction set.None(default) is the identity.
- Returns:
- xoptndarray
The minimizer.
- foptfloat
func(xopt, args). Withfull_output.- direcndarray, shape (N, N)
The final direction set. With
full_output.- iterint
Sweeps performed. With
full_output.- funcallsint
Objective evaluations used. With
full_output.- warnflagint
0converged,1maxfun reached,2maxiter reached,3the search entered a NaN region. Withfull_output.- allvecslist of ndarray
The best point after each sweep,
iter + 1entries of shape(N,), the first being x0. Withretall. From inside@njitthis is anumba.typed.Listof the same arrays.
- Raises:
- ValueError
Empty x0, a direc whose shape is not
(N, N), a maxfun at or below zero, or a callback that is neither a callable nor an@njitfunction. A maxiter of0or below does NOT raise: one sweep runs andwarnflagis 2.
- Warns:
- OptimizeWarning
A direc that is not full rank.
See also
scipy.optimize.fmin_powellThe scipy routine this mirrors.
scijit.optimize.fminDerivative-free, simplex.
scijit.optimize.fmin_bfgsUses a gradient.
scijit.optimize.minimizemethod='Powell'reaches the same core.
Notes
Covers scipy’s
_minimize_powellalong its unbounded path only, wherebounds=None.warnflag4, the out-of-bounds code, therefore never appears.full_output and retall must be compile-time literals inside
@njit: they select the return type.callback takes a plain Python function or an
@njitfunction, and both halt onStopIteration. The Python spelling reaches the compiled core through anumba.objmodeblock over a module-level slot: it takes the GIL once per iteration, and two concurrent solves that both install one overwrite each other, so aprangeloop over it serializes and is not reentrant.Two differences from scipy follow from the compiled path. A plain Python callable cannot be an argument of a compiled function, so a call written inside
@njitpasses the@njitspelling and a Python one is refused by numba. And numba matches no exception class,except StopIterationbeing aTypingErroron 0.66, so any exception raised inside an@njitcallback stops the run the wayStopIterationdoes, where scipy propagates it. A Python callback keeps scipy’s behaviour: onlyStopIterationhalts, and anything else reaches the caller.A direc whose shape is not
(N, N)raises ValueError here. scipy does not check the shape: a short one raises IndexError from inside the sweep and a wide one runs with the extra columns ignored.An empty x0 raises ValueError here, and so does a maxfun at or below zero. scipy refuses both too, through its private
_MaxFuncCallError, which subclassesRuntimeErrorand is not importable; the empty x0 reaches it because the default maxfun ofN*1000is zero whenNis zero.dispreproduces scipy’s summary and scipy’s warning, at scipy’s default, so a bare call writes to stdout and warns on a limit path. The warning takes the GIL through anumba.objmodeblock and the printing through Python’s stdout, so withdispset aprangeloop over this routine still gives the right answer but serializes.disp=0is the parallel path.Under retall,
allvecsis a python list of 1-D arrays, as scipy’s is. From inside@njitit is anumba.typed.Listof the same arrays.args is unpacked into the objective’s argument list,
func(x, *args), which is scipy’s contract. An ndarray or a list args reaches func as ONE argument instead. scipy accepts neither spelling at this name, so the one-argument form is additive and no scipy-shaped call reaches it.Pure
@njit, so it is safe to call from anumba.prangeloop withdisp=0and with callback left atNoneor given as an@njitfunction.https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin_powell.html
Examples
>>> import numpy as np >>> from numba import njit >>> from scijit.optimize import fmin_powell >>> @njit ... def rosen(x): ... s = 0.0 ... for i in range(x.size - 1): ... s += 100.0 * (x[i + 1] - x[i] ** 2) ** 2 + (1.0 - x[i]) ** 2 ... return s >>> @njit ... def run(): ... return fmin_powell(rosen, np.array([0.0, 0.0]), (), disp=0) >>> np.round(run(), 8) array([1., 1.])