scijit.optimize.leastsq¶
- scijit.optimize.leastsq(func, x0, args=(), Dfun=None, full_output=False, col_deriv=False, ftol=1.49012e-08, xtol=1.49012e-08, gtol=0.0, maxfev=0, epsfcn=None, factor=100.0, diag=None, m=-1, validate=True)¶
Minimize the sum of squares of a set of residuals.
Wraps MINPACK’s
lmdif, Levenberg-Marquardt with a forward-difference Jacobian, orlmderwhen an analytic Jacobian is supplied.Callable from Python and from inside
@njit.- Parameters:
- funccallable
A plain
@njitf(x) -> residualsorf(x, args). The residual count is read from what it returns.- x0float or array_like
Initial parameter guess. A scalar, list or tuple is accepted. Any rank is FLATTENED.
- argstuple, optional
Extra parameters, passed to the callback as
f(x, *args), one per entry. Entries may be scalars or arrays and need not share a type. A non-tuple args is coerced to the ONE argument(args,).- Dfuncallable or None, optional
None(default) uses a forward-difference Jacobian (MINPACK lmdif). A plain@njitjac(x) -> (m, n)selects the analytic path (lmder); theiflagbranch and MINPACK’s column-major layout are handled internally. Its shape must be(m, n), or(n, m)withcol_deriv=True.- full_outputbool, optional
False(default) returns(x, ier).Truereturns(x, cov_x, infodict, mesg, ier). Must be a compile-time constant inside@njit: a literal, or left at its default.- col_derivbool, optional
A statement about Dfun, selecting a shape.
False(default) readsjac(x)as(m, n);Truereads it as(n, m). Ignored without Dfun. A runtime variable is fine.- ftolfloat, optional
Relative error desired in the sum of squares. Default 1.49012e-8.
- xtolfloat, optional
Relative error desired in the solution. Default 1.49012e-8.
- gtolfloat, optional
Orthogonality desired between the residual vector and the Jacobian columns. Default 0.0.
- maxfevint, optional
Maximum callback evaluations.
0(default) means200*(n+1), or100*(n+1)whenDfunis given.- epsfcnfloat or None, optional
Forward-difference step.
None(default) resolves to machine epsilon. Ignored on the Dfun path.- factorfloat, optional
Initial step bound, in
(0.1, 100). Default 100.- diagsequence or None, optional
Per-variable scale factors, all positive. An array, list or tuple. The first
x0.sizeentries are used and any others ignored.None(default) lets MINPACK derive them (mode = 1); a value selectsmode = 2.- mint, optional
Number of residuals.
-1(default) reads it from the callback by calling it once. A value skips that call.- validatebool, optional
True(default) raises when the returned solution is degenerate.Falsereports the same conditions through ier instead. The separate check that the callback wrotefvecat all is always on.
- Returns:
- xndarray, shape (n,)
The solution, 1-D.
- cov_xndarray of shape (n, n), or None
Only with
full_output=True.(J^T J)^-1, NOT scaled by the residual variance.Nonewhen ier is outside{1, 2, 3, 4}or the triangular factor is singular.- infodictLsqInfo or LsqInfoJ
Only with
full_output=True. Namedtuple with fieldsfvec,nfev,fjac,ipvtandqtf, plusnjevafternfevon the Dfun path, reached as attributes.fjachas shape(n, m)andipvtis 0-based.- mesgstr
Only with
full_output=True. The message matching ier.- ierint
MINPACK’s status.
1to4are the success set;5maxfev reached,6ftol too small,7xtol too small,8gtol too small.-1and-2are this package’s degenerate-solution codes, reachable only undervalidate=False:-1the residual is identically zero,-2the reported residual disagrees with a fresh evaluation at x.
- Raises:
- TypeError
If MINPACK reports
ier = 0, or ifnexceedsm. Also if Dfun returns an array of the wrong shape, or if diag has fewer entries than x0.- ValueError
If func or Dfun is not a plain
@njitfunction; if an args entry is neither a real number nor an array of real numbers; or, undervalidate=True, if the returned solution is degenerate.
See also
scipy.optimize.leastsqThe scipy routine this mirrors.
scijit.optimize.curve_fitFit a model to data, built on this.
scijit.optimize.rootmethod='lm'reaches the same driver.scijit.optimize.lsq_linearBounded LINEAR least squares.
Notes
infodict is a namedtuple rather than a dict.
info['nfev'],info.get('nfev'),info.keys(),info.values(),info.items()and'nfev' in infoall work, from Python and from inside@njit, and its field order is scipy’s key insertion order, so positional unpacking agrees too. Iterating it yields VALUES, where iterating a dict yields keys.nfevcounts the evaluation this package makes before the solver runs to check that the callback writesfvec, and MINPACK’s own count. The call that reads the residual count off the callback, the calls the degenerate-solution check makes when the final residual is all zero, and the call Dfun costs for its shape check are not counted, sonfevis lower than the number of times the callback ran by between one andn + 2.cov_x is
Nonein the two cases scipy returnsNone. Its type isOptional(float64[:, :]), which numba unwraps with a runtime check: code that indexes it keeps working wherever the covariance exists, and gets aTypeErrornaming the array type where it does not.Each args entry must be a real number or an array of real numbers. A mixed tuple is served:
(matrix, scale)reaches the callback as two separate parameters and returns[3., 3.]on the residualx - matrix.diagonal() * scale, which is what scipy returns on the same call. An entry of any other type raises.ier = 0raisesTypeError('Improper input parameters.'), scipy’s class and scipy’s text.args=Noneraises. scipy reads it as the one-item tuple(None,)and callsf(x, None), andNoneis not a real number.A diag with fewer entries than x0 raises before the solver runs. scipy reads past the end of the array instead, and what MINPACK then does depends on the values that happen to follow it.
cov_x is built by inverting the QR factor with a transcription of LAPACK
dtrti2. Measured againstscipy.linalg.lapack.dtrtri2026-08-10, five random well-conditioned upper-triangular matrices at each of fourteen sizes: bit identical forn <= 16, worst RELATIVE difference 9.766e-13 atn = 32and 6.194e-11 atn = 200, because the installeddtrtriblocks fromn = 32.validate has no scipy counterpart; its default reports a degenerate solution that scipy would return silently.
Safe to call from a
numba.prangeloop. MINPACK reaches the callback through a Fortran module variable, which carries!$omp threadprivateand so resolves to one slot per thread.https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html
Examples
Fit a straight line to noisy measurements by minimizing its residuals. The data arrays are built once and reach the residual through args, so no array is rebuilt on an evaluation:
>>> import numpy as np >>> from numba import njit >>> from scijit.optimize import leastsq >>> T = np.linspace(0.0, 4.0, 20) >>> rng = np.random.default_rng(1) >>> Y = 2.0 * T + 1.0 + rng.normal(0.0, 0.1, T.size) # noisy line >>> @njit ... def resid(p, t, y): ... return y - (p[0] * t + p[1]) >>> @njit ... def run(): ... return leastsq(resid, np.array([0.0, 0.0]), args=(T, Y)) >>> p, ier = run() >>> np.round(p, 3) array([1.984, 1.037]) >>> ier in (1, 2, 3, 4) True