Basin

Search documentation

Search the guides, solvers, and migration docs.

  • Guide
  • Visualizer
  • Benchmarks

Documentation

  • Overview
  • Getting started
  • Migrating from Argmin
  • Migrating to Basin 2.0
  • Migrating to Basin 3.0

Solvers

  • Choosing a solver
  • First-order
    • Gradient descent
    • Nonlinear CG
    • Stochastic gradient descent
    • Projected gradient descent
  • Quasi-Newton
    • BFGS
    • L-BFGS
    • L-BFGS-B
  • Derivative-free
    • Nelder–Mead
    • MADS
    • NEWUOA
    • BOBYQA
    • LINCOA
    • COBYLA
    • Solis–Wets
  • Trust-region
    • Trust-region Newton
  • Nonlinear least squares
    • Gauss–Newton
    • Levenberg–Marquardt
    • Levenberg–Marquardt QR
    • Bounded Levenberg–Marquardt
    • Trust-region reflective
  • Global and stochastic
    • DIRECT
    • Globalized bounded Nelder–Mead
    • Simulated annealing
    • CMA-ES
    • Bounded CMA-ES
    • Differential evolution
    • Particle swarm
    • Random search
    • Steady-state genetic algorithm
    • Basin-hopping
  • Memetic
    • CMA-ES with local search
    • Bounded CMA-ES with local search
    • DE with local search
    • Local-search chains
    • CMA-ES chains
    • Solis–Wets chains
  • General constrained
    • SLSQP
    • Barrier method
    • Augmented Lagrangian
  • Scalar minimization
    • Brent
    • Brent with derivatives
    • Golden-section search
  • Root finding
    • Bisection
    • Brent
    • Secant
    • Newton
    • Halley
    • TOMS 748
Navigation

Documentation

  • Overview
  • Getting started
  • Migrating from Argmin
  • Migrating to Basin 2.0
  • Migrating to Basin 3.0

Solvers

  • Choosing a solver
  • First-order
    • Gradient descent
    • Nonlinear CG
    • Stochastic gradient descent
    • Projected gradient descent
  • Quasi-Newton
    • BFGS
    • L-BFGS
    • L-BFGS-B
  • Derivative-free
    • Nelder–Mead
    • MADS
    • NEWUOA
    • BOBYQA
    • LINCOA
    • COBYLA
    • Solis–Wets
  • Trust-region
    • Trust-region Newton
  • Nonlinear least squares
    • Gauss–Newton
    • Levenberg–Marquardt
    • Levenberg–Marquardt QR
    • Bounded Levenberg–Marquardt
    • Trust-region reflective
  • Global and stochastic
    • DIRECT
    • Globalized bounded Nelder–Mead
    • Simulated annealing
    • CMA-ES
    • Bounded CMA-ES
    • Differential evolution
    • Particle swarm
    • Random search
    • Steady-state genetic algorithm
    • Basin-hopping
  • Memetic
    • CMA-ES with local search
    • Bounded CMA-ES with local search
    • DE with local search
    • Local-search chains
    • CMA-ES chains
    • Solis–Wets chains
  • General constrained
    • SLSQP
    • Barrier method
    • Augmented Lagrangian
  • Scalar minimization
    • Brent
    • Brent with derivatives
    • Golden-section search
  • Root finding
    • Bisection
    • Brent
    • Secant
    • Newton
    • Halley
    • TOMS 748

Levenberg–Marquardt QR

This Levenberg–Marquardt variant solves the damped linear least-squares problem with column-pivoted QR. It avoids forming the Gram matrix JᵀJ, while retaining the Cholesky variant’s damping choices and convergence rules.

API reference

PropertyRequirement
ObjectiveA smooth sum of squared residuals, or an adapted robust loss
EvaluationsResidual and Jacobian
SearchLocal, from one starting point
ConstraintsUnconstrained
ParametersAll four dense backends, with f32 or f64; no sparse QR

When to use it

Consider pivoted QR when forming normal equations loses too much accuracy, particularly for poorly conditioned dense Jacobians. Compare the Cholesky variant when sparse Jacobians are needed. QR changes the linear solve; it does not make a nonlinear fit globally optimal or remove sensitivity to parameter and residual scaling.

The method follows Madsen, Nielsen, and Tingleff (2004), §3.2, and MINPACK’s qrfac and qrsolv routines.

How it works

The solver factors the Jacobian with column pivoting and solves the stacked system [J; sqrt(μD)] h ≈ [-r; 0]. Diagonal regularization is applied through the QR solve rather than by constructing JᵀJ. The factorization can be reused while damping changes at the same iterate.

Scaled trust-region damping is the default, following the radius updates of Moré (1978) and MINPACK’s lmder with Basin’s bracketed parameter search. Nielsen damping is also available. Both variants use the same gain-ratio acceptance test and stopping settings as Cholesky LM.

Example

The same residual problem can run with either LM factorization. This example selects QR through with_pivoted_qr(); LevenbergMarquardtQr::new() is also available.

use basin::{DenseMatrix, Executor, Jacobian, LevenbergMarquardt, Residual};
use std::convert::Infallible;

struct Fit;

impl Residual for Fit {
    type Param = Vec<f64>;
    type Output = Vec<f64>;
    type Error = Infallible;

    fn residual(&self, x: &Self::Param) -> Result<Self::Output, Self::Error> {
        Ok(vec![x[0] - 1.0, 2.0 * (x[1] - 2.0)])
    }
}

impl Jacobian for Fit {
    type Jacobian = DenseMatrix;

    fn jacobian(&self, _: &Self::Param) -> Result<Self::Jacobian, Self::Error> {
        Ok(DenseMatrix::from_row_slice(2, 2, &[1.0, 0.0, 0.0, 2.0]))
    }
}

fn main() {
    let solver = LevenbergMarquardt::new()
        .with_pivoted_qr()
        .with_absolute_gradient_tolerance(1e-8);
    let result = Executor::from_start(Fit, solver, vec![0.0, 0.0])
        .max_iter(100)
        .run()
        .unwrap();

    assert!((result.param()[0] - 1.0).abs() < 1e-6);
    assert!((result.param()[1] - 2.0).abs() < 1e-6);
    assert!(result.cost() < 1e-12);
}

Practical considerations

Treat numerical rank as a solve safeguard

Rank is checked after regularization and column equilibration. The default relative threshold is epsilon(F) * (m + n) for m residuals and n parameters; with_relative_rank_tolerance changes it. This check concerns the regularized solve and does not establish that the original parameters are identifiable. There is no truncated solution or normal-equation fallback.

Nielsen damping increases after rank loss; trust-region damping uses rank loss to bound its parameter search. An unusable solve or exhausted retries can produce SolverFailed. For bounded problems needing minimum-norm steps under rank deficiency, compare trust-region reflective.

Keep damping and stopping choices explicit

The default absolute gradient threshold is 1e-8. The damping, optional progress tests, and numerical no-progress safeguard behave as described in the LM guide. A small damped step does not establish stationarity. Put iteration and evaluation budgets on the executor, and inspect both termination and fit quality.

Implementation

Levenberg–Marquardt QR publishes matching parameters and cost through PointState. It computes the gradient internally; the state does not expose it through GradientState. Residuals, Jacobians, and model caches belong to the solver. Fresh runs reset them, while exact solver-and-state checkpoints retain them.

For ordinary residuals, the reported cost is 0.5 * sum(r[i]^2). The solver requires Residual and Jacobian, without a CostFunction implementation. Wrapping the problem in RobustLeastSquares selects a robust loss and residual scale. The adapter supplies a safeguarded model, while costs and convergence use the robust objective and its gradient. Custom Jacobians additionally need ScaleRowsInPlace for robust losses.

Supported dense pairs are Vec<F>/DenseMatrix<F>, nalgebra::DVector<F>/DMatrix<F>, ndarray::Array1<F>/Array2<F>, and faer::Col<F>/Mat<F>, with F = f32 or f64. The default Vec path needs no BLAS/LAPACK provider.

Sparse Jacobians are unsupported: the sparse backends do not provide the required numerical column pivoting. The dense paths use pure Rust. Use LevenbergMarquardtQr::default() for f32.

References

  1. Madsen, K., Nielsen, H. B., and Tingleff, O. (2004). Methods for Non-Linear Least Squares Problems (2nd ed.). Informatics and Mathematical Modelling, Technical University of Denmark.
  2. Moré, J. J. (1978). The Levenberg-Marquardt algorithm: Implementation and theory. In Numerical Analysis (pp. 105–116). Springer. doi:10.1007/BFb0067700.

Basin v3.1.0 — numerical optimization for Rust.

GitHub docs.rs crates.io