archimedes.optimize.least_squares¶
- archimedes.optimize.least_squares(func: Callable[[T, Any], T], x0: T, args: Sequence[Any] = (), method: str = 'hess-lm', bounds: tuple[T, T] | None = None, options: dict | None = None) OptimizeResult ¶
Solve nonlinear least squares problems
Minimize the sum of squares of residuals:
minimize 0.5 * ||r(x)||² subject to lb <= x <= ub
This function provides access to both custom least-squares algorithms and standard SciPy methods, with full PyTree parameter structure support and automatic differentiation. The custom
"hess-lm"
method can provide superior performance for system identification and parameter estimation problems.- Parameters:
func (callable) – Residual function with signature
func(x, *args) -> residuals
, whereresiduals
is an array-like object. The parameterx
can be any PyTree structure matchingx0
.x0 (PyTree) –
Initial parameter guess. Can be a flat array, nested dictionary, dataclass, or any PyTree structure. The solution preserves this exact structure.
Examples:
# Physical system parameters x0 = { "dynamics": {"mass": 1.0, "damping": 0.1}, "sensor": {"bias": 0.0, "scale": 1.0} } # Simple array x0 = np.array([1.0, 0.1, 0.0, 1.0])
args (tuple, optional) – Extra arguments passed to the residual function.
method (str, optional) –
Least-squares method to use. Default is
"hess-lm"
. Available methods:- Archimedes Methods:
"hess-lm"
(default): Custom Levenberg-Marquardt with direct Hessian. Supports box constraints and specialized convergence criteria.
- SciPy Methods:
"trf"
: Trust Region Reflective, robust for large problems"dogbox"
: Dog-leg method in rectangular trust regions"lm"
: Standard SciPy Levenberg-Marquardt (unconstrained only)
bounds (tuple of (PyTree, PyTree), optional) –
Box constraints specified as
(lower_bounds, upper_bounds)
with the same PyTree structure asx0
. Use-np.inf
andnp.inf
for unbounded variables.Examples:
# PyTree bounds for physical constraints bounds = ( {"dynamics": {"mass": 0.1, "damping": 0.0}}, # Lower bounds {"dynamics": {"mass": 10.0, "damping": 1.0}} # Upper bounds ) # Array bounds bounds = (np.array([0.1, 0.0]), np.array([10.0, 1.0]))
options (dict, optional) – Method-specific options. For
"hess-lm"
, seelm_solve()
documentation. For SciPy methods, seescipy.optimize.least_squares
documentation.
- Returns:
result – Optimization result with preserved PyTree structure:
x
: Solution parameters (same PyTree structure asx0
)success
: Whether optimization converged successfullystatus
: Termination status (LMStatus for “hess-lm”)message
: Descriptive termination messagefun
: Final residual vectorcost
: Final objective value (0.5 * ||residuals||²)nfev
: Number of function evaluationsnit
: Number of iterationsAdditional method-specific fields
- Return type:
OptimizeResult
Notes
PyTree Parameter Organization:
PyTree support enables natural organization of complex parameter structures:
# Organized system parameters params = { "mechanical": { "mass": 1.0, "damping": {"viscous": 0.1, "coulomb": 0.05}, "stiffness": {"linear": 100.0, "cubic": 0.001} }, "electrical": { "resistance": 10.0, "inductance": 0.01, "capacitance": 1e-6 }, "initial_conditions": np.array([0.0, 0.0]) } # After optimization - same structure preserved result = least_squares(residuals_func, params) optimized_params = result.x # Maintains full nested structure
Custom Hessian Method (
"hess-lm"
):The default method leverages specialized Hessian approximations for efficient parameter estimation. This method solves the damped normal equations directly using a Cholesky factorization instead of the typical QR approach. This can improve performance for problems such as parameter estimation where there are many residuals compared to the number of parameters. This method also handles box constraints by switching to a quadratic programming solver ([OSQP](https://osqp.org/)) when bounds are active.
Key options passed via
options
dict:# Common options for custom LM method lm_options = { "ftol": 1e-6, # Function tolerance "xtol": 1e-6, # Parameter tolerance "gtol": 1e-6, # Gradient tolerance "max_nfev": 200, # Maximum function evaluations "lambda0": 1e-3, # Initial damping parameter } result = least_squares(func, x0, method="hess-lm", options=lm_options)
Examples
>>> import archimedes as arc >>> import numpy as np >>> >>> def rosenbrock(x): ... return np.hstack([100 * (x[1] - x[0]**2), 1 - x[0]]) >>> >>> x0 = np.array([0.0, 0.0]) >>> bounds = (np.array([0.0, 0.0]), np.array([0.8, 2.0])) >>> result = arc.optimize.least_squares(rosenbrock, x0, bounds=bounds) >>> print(result.x) # Optimized parameters [0.79999903 0.63998596]
See also
lm_solve
Direct access to custom Levenberg-Marquardt algorithm
minimize
General nonlinear programming with multiple solver options
scipy.optimize.least_squares
SciPy’s least-squares interface