#优化 #回调 #闭包 #高级 #lbfgs #计算 #化学

gosh-lbfgs

快速且安全的 Rust 实现版本,LBFGS 和 OWL-QN 算法从 Naoaki Okazaki 的 C 库 libLBFGS 端口移植而来

1 个不稳定版本

0.1.0 2022 年 5 月 16 日

#1144算法


gosh-optim 中使用

MIT/Apache

140KB
2K SLoC

LBFGS

Build Status GPL3 licensed

从 Naoaki Okazaki 的 C 库 libLBFGS 端口移植而来的快速且安全的 Rust 实现版本,包含 LBFGS 和 OWL-QN 算法。

请查看 rust-liblbfgs,它提供了围绕原始 C 代码的工作包装器。

动机

  • 将本地的 LBFGS 实现引入 Rust 社区。
  • 了解一个优秀的优化算法在现实世界中的实现方式。
  • 学习如何“在飞行中更换喷气发动机” URL
  • 通过 Rust 的高级抽象使其更具可维护性。
  • 改进以满足我在计算化学方面的需求。

待办事项

  • 与 rayon 并行
  • 支持 SIMD
  • 添加选项以禁用仅梯度优化的线搜索
  • 修复从 liblbfgs 继承的问题 URL

特性

  • 干净且安全的 Rust 实现。
  • OWL-QN 算法。
  • 基于闭包的回调接口。
  • 阻尼 L-BFGS 算法。

用法

// 0. Import the lib
use liblbfgs::lbfgs;

const N: usize = 100;

// 1. Initialize data
let mut x = [0.0 as f64; N];
for i in (0..N).step_by(2) {
    x[i] = -1.2;
    x[i + 1] = 1.0;
}

// 2. Defining how to evaluate function and gradient
let evaluate = |x: &[f64], gx: &mut [f64]| {
    let n = x.len();

    let mut fx = 0.0;
    for i in (0..n).step_by(2) {
        let t1 = 1.0 - x[i];
        let t2 = 10.0 * (x[i + 1] - x[i] * x[i]);
        gx[i + 1] = 20.0 * t2;
        gx[i] = -2.0 * (x[i] * gx[i + 1] + t1);
        fx += t1 * t1 + t2 * t2;
    }

    Ok(fx)
};

let prb = lbfgs()
    .with_max_iterations(5)
    .with_orthantwise(1.0, 0, 99) // enable OWL-QN
    .minimize(
        &mut x,                   // input variables
        evaluate,                 // define how to evaluate function
        |prgr| {                  // define progress monitor
            println!("iter: {:}", prgr.niter);
            false                 // returning true will cancel optimization
        }
    )
    .expect("lbfgs owlqn minimize");

println!("fx = {:}", prb.fx);

回调函数是本地的 Rust FnMut 闭包,可以捕获/更改环境中的变量。

完整的代码和注释可以在 examples/sample.rs 中找到。

运行示例

cargo run --example sample

依赖项

~9–20MB
~281K SLoC