A numerical optimization library for Rust, inspired by argmin. It pairs a
small generic core, problem traits you implement, a pluggable termination layer,
and a driver loop (Executor), with a growing set of solvers spanning
first-order, derivative-free, nonlinear least-squares, and evolutionary methods.
Solvers are generic over the linear-algebra backend, constraints are
first-class, and the default build compiles to wasm32-unknown-unknown with no
BLAS/LAPACK or threads.
Narrative documentation lives at basin.bz/docs; the rustdoc reference is at docs.rs/basin. There is also an in-browser solver visualizer and a benchmarks site comparing Basin against competing crates and across backends and solvers.
cargo add basinBasin works on plain Vec<f64> out of the box. Linear-algebra backends are
opt-in, one feature each:
cargo add basin --features nalgebra # or: ndarray, faerImplement CostFunction (and Gradient, when the solver needs derivatives),
then hand the problem, a solver, and an initial state to the Executor:
use basin::{BasicState, CostFunction, Executor, Gradient, GradientDescent, GradientTolerance};
use std::convert::Infallible;
struct Rosenbrock;
impl CostFunction for Rosenbrock {
type Param = Vec<f64>;
type Output = f64;
type Error = Infallible;
fn cost(&self, x: &Vec<f64>) -> Result<f64, Self::Error> {
Ok((1.0 - x[0]).powi(2) + 100.0 * (x[1] - x[0].powi(2)).powi(2))
}
}
impl Gradient for Rosenbrock {
type Gradient = Vec<f64>;
fn gradient(&self, x: &Vec<f64>) -> Result<Vec<f64>, Self::Error> {
Ok(vec![
-2.0 * (1.0 - x[0]) - 400.0 * x[0] * (x[1] - x[0].powi(2)),
200.0 * (x[1] - x[0].powi(2)),
])
}
}
let result = Executor::new(Rosenbrock, GradientDescent::new(1e-3), BasicState::new(vec![-1.2, 1.0]))
.max_iter(50_000).terminate_on(GradientTolerance(1e-6))
.run()
.unwrap();
println!("x = {:?}, f = {}, stopped: {:?}", result.param(), result.cost(), result.reason);Termination criteria are framework-level: the same ones compose across solvers, and they are bound to the state a solver actually exposes --- so asking for a gradient tolerance on a derivative-free solver is a compile error, not a runtime surprise.
- First-order/quasi-Newton: gradient descent (with momentum and pluggable line searches), BFGS, L-BFGS, L-BFGS-B.
- Derivative-free: Nelder--Mead, Brent (1D).
- Nonlinear least squares: Gauss--Newton, Levenberg--Marquardt, trust-region reflective.
- Global/stochastic: random search, CMA-ES, a steady-state genetic algorithm, and memetic combinations.
- Constrained: box bounds via projected gradient descent, bounded Nelder--Mead, L-BFGS-B, and bounded CMA-ES; log-barrier and augmented Lagrangian wrappers for more general constraints.
See Solvers for which backends each one supports.
Parameters and linear algebra are generic over the backend. Vec<f64> needs no
features; nalgebra, ndarray, and faer are enabled one feature each, each
pinning a single major version. First-order and derivative-free solvers run on
any backend; linear-algebra-heavy solvers may require a specific one and say so
in their docs.
The default build is wasm-friendly: no BLAS/LAPACK and no threads. Parallelism
and BLAS-backed paths are behind opt-in features (parallel).
The public API is still iterating and breaking changes are expected. WebAssembly
bindings (basin-wasm) power the visualizer but are not published to a package
registry yet.
Basin owes a substantial intellectual debt to argmin: the overall shape of the
crate: the Executor driver loop, the Solver / Problem trait split,
per-solver State, and the pluggable termination layer is borrowed from it, and
several solver implementations and test-problem conventions were modeled on
argmin's. Thanks to the argmin authors and contributors for a library that is a
pleasure to learn from.
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
