scijit.optimize.fmin_cobyla

scijit.optimize.fmin_cobyla(func, x0, cons, args=(), consargs=None, rhobeg=1.0, rhoend=0.0001, maxfun=1000, disp=None, catol=0.0002, *, callback=None, m_nlcon=-1, Aineq=None, bineq=None, Aeq=None, beq=None, lower=None, upper=None, full_output=False)

Minimize a function subject to nonlinear inequality constraints.

COBYLA builds a linear model of the objective and of every constraint from values alone, and minimizes it inside a trust region. No derivatives are required.

Callable from Python and from inside @njit.

Parameters:
funccallable

A plain @njit f(x, *args) -> value.

x0array_like

Initial guess. Any rank is flattened.

conscallable or sequence of callables

Constraint functions, feasible where the result is >= 0. Either one plain @njit c(x, *consargs) returning all of them at once, or a list or tuple of such functions returning a scalar or an array each. A tuple is the spelling that types inside @njit.

argstuple or ndarray, optional

Extra parameters for func, packed into one flat float64 buffer.

consargstuple, ndarray or None, optional

Extra parameters for cons. None (default) reuses args.

rhobegfloat, optional

Initial trust-region radius. Default 1.0.

rhoendfloat, optional

Final trust-region radius. Default 1e-4.

maxfunint, optional

Maximum objective evaluations. Default 1000.

dispint or None, optional

0, 1, 2, 3 or None; anything else is a ValueError. Truthy prints COBYLA failed to find a solution: and the message when the solve fails. The solver’s own per-iteration stream is not reproduced.

catolfloat or None, optional

Constraint-violation tolerance, reaching the solver as PRIMA’s ctol. It governs which point the solver returns, and it decides success: a solve leaving maxcv > catol reports success=False. Raising it trades feasibility for objective value. Default 2e-4. None resolves to sqrt(eps), 1.49e-08, which is what minimize(method='COBYLA') uses. A negative or nan value raises a UserWarning and the solver runs on sqrt(eps), while success and message still read the value as given, so a nan makes the violation test pass whatever maxcv is.

callbackNone, optional

Accepted only as None. See Notes. Keyword-only, as is every parameter after it, so ten is the largest number of positional arguments.

m_nlconint, optional

Number of nonlinear constraints. -1 (default) reads it from cons by evaluating the constraints once at x0.

Aineq, bineq, Aeq, beq, lower, upperndarray or None, optional

Linear constraints Aineq @ x <= bineq and Aeq @ x == beq, and simple bounds, all taken by PRIMA natively. None (default) for each leaves it unset.

full_outputbool, optional

False (default) returns x alone. True returns a CobylaResult. Compile-time constant inside @njit: it selects the return type.

Returns:
xndarray

The minimizer.

resultCobylaResult

Only with full_output=True. Namedtuple with fields x, fun, maxcv, message, nfev, status and success. status is PRIMA’s own exit code: 0 the trust-region radius reached its lower bound, 1 the target value was achieved, 2 a trust-region step failed to reduce the model, 3 maxfun was exhausted, 7 damaging rounding errors, and negative codes for NaN or infinity in x, in the objective, or in the models. success is True when maxcv <= catol and status is 0 or 1. nfev counts the one probe evaluation this routine makes before the solve as well as the solver’s own calls.

Raises:
TypeError

If cons is omitted, or is neither callable nor a sequence of callables.

ValueError

If func is not a plain @njit function; if disp is outside {0, 1, 2, 3, None}; or if callback is not None. The compiled entry point raises the same text as a TypingError wherever the argument’s type settles the refusal.

See also

scipy.optimize.fmin_cobyla

The scipy routine this mirrors.

scijit.optimize.fmin_slsqp

Constrained, gradient-based.

scijit.optimize.minimize

Reaches PRIMA’s unconstrained and bounded solvers by name.

Notes

The returned point is not scipy’s. scipy 1.16 replaced Powell’s COBYLA with pyprima, a Python translation of the same algorithm, while this wraps PRIMA itself. Measured on min x0**2 + x1**2 subject to x0 >= 1 from (3, 3): |dx| 1.18e-04 and |df| 1.38e-08, with PRIMA the nearer of the two to the true optimum, f - 1 being 6.8e-14 against scipy’s 1.4e-08.

catol moves the answer, so it is worth setting deliberately. On the problem above, the 2e-4 default returns fun = 0.999900005 at maxcv = 5.0e-05; catol=None returns 1.000000002 at maxcv = 0; catol=1e-2 returns 0.999003146 at maxcv = 5.0e-04; catol=1 returns 0.910296579 at maxcv = 5.0e-02.

args and consargs each pack into one flat float64 buffer, so they carry numbers rather than arbitrary objects.

scipy calls callback once per iteration, with either callback(xk) or callback(intermediate_result). Neither is served here: PRIMA’s cobyla takes a callback_fcn and src/prima/wrappers.f90 passes none, so the Fortran has no slot for one to arrive through.

disp prints the failure line and not the solver’s own per-iteration stream, which PRIMA emits from Fortran.

Aineq, bineq, Aeq, beq, lower and upper have no scipy counterpart; scipy’s COBYLA can express linear constraints and bounds only by folding them into cons. A scipy-shaped call leaves all six unset and behaves as scipy does. full_output has no scipy counterpart either: scipy returns x alone and discards fun, maxcv, nfev, status, message and success, which is what the False default reproduces.

Safe to call from a numba.prange loop. PRIMA reaches the callback through a Fortran module variable, which carries !$omp threadprivate and so resolves to one slot per thread.

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

Examples

Minimize x0**2 + x1**2 subject to x0 >= 1:

>>> import numpy as np
>>> from numba import njit
>>> from scijit.optimize import fmin_cobyla
>>> @njit
... def obj(x):
...     return x[0] ** 2 + x[1] ** 2
>>> @njit
... def cons(x):
...     return np.array([x[0] - 1.0])
>>> @njit
... def run():
...     return fmin_cobyla(obj, np.array([3.0, 3.0]), cons)
>>> np.round(run(), 4)
array([1., 0.])

With full_output, which must be a literal inside @njit:

>>> @njit
... def run_full():
...     return fmin_cobyla(obj, np.array([3.0, 3.0]), cons,
...                        full_output=True)
>>> res = run_full()
>>> round(res.fun, 9), res.status, res.success
(0.999900005, 0, True)
>>> round(res.maxcv, 9), res.nfev
(5e-05, 37)

A tuple of one-constraint functions, which is scipy’s own spelling:

>>> @njit
... def c_lo(x):
...     return x[0] - 1.0
>>> @njit
... def c_hi(x):
...     return 5.0 - x[1]
>>> @njit
... def run_pair():
...     return fmin_cobyla(obj, np.array([3.0, 3.0]), (c_lo, c_hi))
>>> np.round(run_pair(), 4)
array([1., 0.])