| Crates.io | lbfgsb-rs-pure |
| lib.rs | lbfgsb-rs-pure |
| version | 0.1.1 |
| created_at | 2025-11-03 09:16:43.962216+00 |
| updated_at | 2025-11-03 09:31:06.688279+00 |
| description | A safe, idiomatic Rust port of the L-BFGS-B limited-memory quasi-Newton optimization algorithm (v3.0) for bound-constrained numerical optimization. |
| homepage | https://github.com/nholle/lbfgsb-rs |
| repository | https://github.com/nholle/lbfgsb-rs |
| max_upload_size | |
| id | 1914297 |
| size | 218,478 |
A safe, idiomatic Rust port of the L-BFGS-B optimization algorithm (version 3.0).
L-BFGS-B is a limited-memory quasi-Newton optimization algorithm for solving large-scale bound-constrained optimization problems. This crate provides a faithful Rust implementation of the algorithm, ported from the C reference implementation.
The algorithm is particularly well-suited for:
Add to your Cargo.toml:
[dependencies]
lbfgsb-rs-pure = "0.1.0"
use lbfgsb_rs_pure::LBFGSB;
fn main() {
let n = 25; // problem size
let m = 5; // number of corrections to approximate Hessian
// Set bounds: [1, 100] for even indices, [-100, 100] for odd
let mut lower = vec![0.0; n];
let mut upper = vec![0.0; n];
for i in (0..n).step_by(2) {
lower[i] = 1.0;
upper[i] = 100.0;
}
for i in (1..n).step_by(2) {
lower[i] = -100.0;
upper[i] = 100.0;
}
// Starting point
let mut x = vec![3.0; n];
// Create solver
let mut solver = LBFGSB::new(m)
.with_pgtol(1e-5)
.with_max_iter(1000);
// Minimize (Rosenbrock function)
let sol = solver.minimize(&mut x, &lower, &upper, &mut |x: &[f64]| {
let mut f = (x[0] - 1.0) * (x[0] - 1.0);
for i in 1..n {
let diff = x[i] - x[i - 1] * x[i - 1];
f += 4.0 * diff * diff;
}
// Compute gradient
let mut g = vec![0.0; n];
let mut t1 = x[1] - x[0] * x[0];
g[0] = 2.0 * (x[0] - 1.0) - 16.0 * x[0] * t1;
for i in 1..(n - 1) {
let t2 = t1;
t1 = x[i + 1] - x[i] * x[i];
g[i] = 8.0 * t2 - 16.0 * x[i] * t1;
}
g[n - 1] = 8.0 * t1;
(f, g)
}).unwrap();
println!("Status: {:?}", sol.status);
println!("Iterations: {}", sol.iterations);
println!("F(x) = {:.9e}", sol.f);
}
use lbfgsb_rs::{LBFGSB, IterationControl};
let mut solver = LBFGSB::new(5).with_pgtol(0.0); // Disable default stopping
let sol = solver.minimize_with_callback(
&mut x,
&lower,
&upper,
&mut |x| (f, grad), // Your objective function
&mut |info, x| {
// Custom stopping: max 100 evaluations or relative gradient < 1e-10
if info.n_func_evals >= 100 {
return IterationControl::StopCustom;
}
if info.proj_grad_norm <= (info.f.abs() + 1.0) * 1e-10 {
return IterationControl::StopConverged;
}
IterationControl::Continue
},
).unwrap();
use std::time::Instant;
use lbfgsb_rs::IterationControl;
let start = Instant::now();
let time_limit = 0.5; // seconds
let sol = solver.minimize_with_callback(
&mut x, &lower, &upper,
&mut |x| (f, grad),
&mut |info, _| {
if start.elapsed().as_secs_f64() > time_limit {
IterationControl::StopCustom
} else {
IterationControl::Continue
}
},
).unwrap();
Three example drivers demonstrate different features:
# Basic usage
cargo run --example driver1
# Custom stopping criteria (max evaluations, relative gradient)
cargo run --example driver2
# Time-controlled optimization
cargo run --example driver3
# Run all examples
./scripts/run_all_examples.sh
See docs/EXAMPLES.md for detailed documentation.
LBFGSBMain solver struct with builder pattern configuration:
new(m: usize) - Create solver with m limited-memory correctionswith_pgtol(tol: f64) - Set projected gradient tolerance (default: 1e-6)with_max_iter(n: usize) - Set maximum iterations (default: 1000)with_verbose(v: bool) - Enable verbose output (default: false)minimize - Simple API with default stopping criteriaminimize_with_callback - Advanced API with iteration callbacksIterationInfoInformation passed to callbacks:
pub struct IterationInfo {
pub iteration: usize, // Current iteration
pub f: f64, // Objective value
pub proj_grad_norm: f64, // ||projected gradient||_inf
pub n_func_evals: usize, // Total f/g evaluations
pub n_segments: usize, // Cauchy search segments
pub n_skipped: usize, // Skipped BFGS updates
pub n_active: usize, // Active bounds at GCP
}
IterationControlControl flow returned by callbacks:
Continue - Continue optimizationStopConverged - Stop with converged statusStopCustom - Stop with custom reasonSolutionResult returned by solver:
pub struct Solution {
pub x: Vec<f64>, // Final point
pub f: f64, // Final objective value
pub iterations: usize, // Number of iterations
pub status: Status, // Termination status
}
StatusTermination status:
Converged - Gradient tolerance satisfiedMaxIter - Maximum iterations reachedLineSearchFailure - Line search failedNumericalFailure - Numerical issues detected# Run unit tests
cargo test
# Run with verbose output
cargo test -- --nocapture
# Build release version
cargo build --release
All 13 unit tests pass, covering BLAS operations, line search, linear algebra, and subalgorithms.
lbfgsb-rs-pure/
├── src/
│ ├── lib.rs # Public API and types
│ ├── solver.rs # High-level LBFGS-B solver
│ ├── blas.rs # Level-1 BLAS operations
│ ├── linpack.rs # Cholesky factorization
│ ├── linesearch.rs # Line search routines
│ └── subalgorithms.rs # Core L-BFGS-B subalgorithms
├── examples/
│ ├── driver1.rs # Basic usage example
│ ├── driver2.rs # Custom stopping criteria
│ └── driver3.rs # Time-controlled optimization
├── docs/
│ ├── EXAMPLES.md # Example documentation
│ ├── COMPARISON.md # C vs Rust comparison
│ ├── PORTING_STATUS.md # Porting details
│ └── DRIVER_PORT_SUMMARY.md
├── scripts/
│ ├── run_all_examples.sh # Run all examples
│ └── verify.sh # Verification script
├── tests_archive/ # Archived development tests
└── L-BFGS-B-C/ # Original C reference
More information: L-BFGS-B Wikipedia
Comprehensive documentation is available in the docs/ directory:
This crate and the repository are provided under the BSD 3-Clause License. See the top-level LICENSE file for the full license text and copyright notice. The original L-BFGS-B C reference implementation is published under the BSD 3-Clause License as well.
The original L-BFGS-B algorithm was developed by:
This Rust port maintains algorithmic fidelity while providing a modern, safe API.
If you use this software in research, please cite the original L-BFGS-B papers listed above.
Contributions are welcome! Areas for potential improvement:
This Rust port is based on the L-BFGS-B-C version by Stephen Becker, which itself is based on the original Fortran code.