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

Migrating to Basin 3.0

Basin 3.0 makes constraint declarations optional. This guide describes the development API on main; Basin 2.0 remains the published stable release. For an upgrade from Basin 1.x, first follow the Basin 2.0 migration guide, then apply these changes.

Plain objectives and residuals

Implement CostFunction and any derivatives your solver needs. A problem used with unconstrained solvers no longer needs an empty constraint declaration. Remove implementations whose only purpose was returning NoConstraints::EMPTY. Residual, NonlinearEqualityValues, NonlinearInequalityValues, and ConstraintJacobian also stand alone.

Unconstrained solvers now ignore declared constraints. Passing a problem with box bounds to GradientDescent optimizes its objective without enforcing those bounds. Use ProjectedGradientDescent or another compatible constrained solver to enforce them. The same rule applies to unbounded solver modes and least squares: a declaration alone does not make an algorithm respect constraints.

Declare constraints directly

The former ProblemConstraints trait is now Constraints. Its associated type is Set, and its getter is constraints. The former Constraints data container is now ConstraintSet.

Add this implementation alongside your objective and derivative implementations:

use basin::{BoxBounds, ConstraintDescription, ConstraintSet, Constraints};

struct ShiftedSphere {
    lower: Vec<f64>,
    upper: Vec<f64>,
}

impl Constraints for ShiftedSphere {
    type Set = ConstraintSet<BoxBounds<Vec<f64>>>;

    fn constraints(&self) -> <Self::Set as ConstraintDescription>::Borrowed<'_> {
        ConstraintSet::new().with_bounds(BoxBounds::new(
            Some(&self.lower),
            Some(&self.upper),
        ))
    }
}

The borrowed view still supports bounds, matrices, and right-hand sides stored in independent fields. If you store the whole set, return self.constraints.borrowed() instead. Builders preserve existing blocks and change the set’s type. Constrained solvers still require the complete declaration and reject unsupported blocks; a box-only solver cannot consume additional nonlinear constraints. Validation and callback error handling are unchanged.

Attach a set to an existing objective

Constrained::new(objective, set) remains a convenience adapter. Its objective needs no empty declaration, and callbacks can be implemented independently. The supplied set becomes the complete declaration, replacing any declaration on the inner objective. Combine blocks in one ConstraintSet before wrapping when they must all be enforced.

FiniteDiff, BoundedFiniteDiff, and RobustLeastSquares continue forwarding constraint declarations when their inner problem implements Constraints. Their unconstrained evaluation paths also work without a declaration.

Update generic bounds

P: CostFunction and P: Residual no longer imply constraint metadata. Add P: Constraints wherever generic code reads P::Set or calls constraints(). For example, replace a bound such as P: CostFunction<Constraints = NoConstraints> with P: CostFunction + Constraints<Set = NoConstraints> only when your code needs that explicit restriction. Unconstrained solvers no longer require it.

Replace qualified calls to ProblemConstraints::constraint_set with Constraints::constraints, and Constraints::new() on the old data container with ConstraintSet::new().

Sampling and composed solvers

SamplingBounds no longer requires a NoConstraints declaration. Its box controls sampling rather than feasibility. SamplingDomain still explicitly reinterprets a box-constrained problem as a sampling domain.

RelaxedInner remains available for box-constrained compositions that need its problem transformation and conversion to ConstraintSolveError. Existing uses remain valid. Execution budgets, evaluation accounting, and state ownership are unchanged. Constraint sets retain their serialized fields and layout; formats that embed Rust struct names may need the new ConstraintSet name.

Basin v3.1.0 — numerical optimization for Rust.

GitHub docs.rs crates.io