scijit.optimize.nnls¶
- scijit.optimize.nnls(A, b, *, maxiter=None, validate=True)¶
Non-negative least squares.
min ||A x - b||_2subject tox >= 0, by the classical Lawson-Hanson active-set method. Callable from Python and from inside@njit; both entries run the same compiled core.- Parameters:
- Aarray_like, shape (m, n)
Coefficient matrix. Cast to float64 and copied to a contiguous buffer, so strided views are safe. Must be 2-D.
- barray_like, shape (m,)
Right-hand side, with
b.size == A.shape[0]. A 2-D b of one column is ravelled.- maxiterint or None, optional
Cap on the inner feasibility iterations.
Noneand0both mean3 * n; a negative value is a real budget and is exhausted at once. Keyword-only. See Notes for what the cap counts.- validatebool, optional
True(default) raisesRuntimeErrorwhen maxiter is reached.Falsereturns the current iterate instead.
- Returns:
- xndarray, shape (n,)
Non-negative solution vector.
- rnormfloat
Residual 2-norm
||A x - b||_2, not squared and not halved.
- Raises:
- ValueError
If A or b holds a non-finite entry; if A is not 2-D; if b has rank above 2, or rank 2 with more than one column; or if
b.size != A.shape[0]. The finiteness of both arrays is read before either shape is.- RuntimeError
If maxiter is reached, unless
validate=False.
See also
scipy.optimize.nnlsThe scipy routine this mirrors.
scijit.optimize.lsq_linearGeneral lower and upper bounds, not just
x >= 0.scijit.optimize.leastsqNonlinear least squares.
Notes
maxiter caps the INNER feasibility iterations of the Lawson-Hanson loop, where scipy’s caps the outer ones, so a small explicit maxiter can stop the two at different points, converging here while scipy raises
RuntimeError. The default and any cap large enough to converge agree.Inside
@njit, maxiter and validate may also be passed positionally: numba’s dispatcher does not enforce keyword-only. The Python entry enforces it.validate has no counterpart in scipy’s signature. scipy raises on non-convergence unconditionally, so the default reproduces scipy.
validate=Falsereturns the current iterate instead, for a run over many points where an exception would abort the whole loop.An A with zero rows returns
(zeros(n), 0.0), the same values on every call. With no equations the residual vector has length zero, so||A x - b||is 0 for any x; every non-negative x is a minimiser and the zero vector is the minimum-norm one among them. scipy 1.18 reads uninitialised memory on that input: consecutive calls toscipy.optimize.nnls(np.zeros((0, 3)), np.zeros(0))return a different x each time.Pure
@njit, no callback, no module state and no library handle, so it is safe to call from anumba.prangeloop.https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.nnls.html
Examples
>>> import numpy as np >>> from numba import njit >>> from scijit.optimize import nnls >>> A = np.array([[1.0, 0.0], [1.0, 0.0], [0.0, 1.0]]) >>> b = np.array([2.0, 1.0, -1.0]) >>> @njit ... def run(): ... return nnls(A, b) >>> x, rnorm = run() >>> x array([1.5, 0. ]) >>> round(rnorm, 10) 1.2247448714