1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
// docs // // Copyright (c) 1990, Jorge Nocedal // Copyright (c) 2007-2010 Naoaki Okazaki // Copyright (c) 2018-2019 Wenping Guo // All rights reserved. // //! Limited memory BFGS (L-BFGS) algorithm ported from liblbfgs //! //! # Example //! ``` //! // 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); //! ``` // [[file:~/Workspace/Programming/gosh-rs/lbfgs/lbfgs.note::*imports][imports:1]] use crate::core::*; mod lbfgs; pub mod line; pub mod math; pub use crate::lbfgs::*; pub(crate) mod core { pub use anyhow::*; pub use log::{debug, error, info, trace, warn}; } // imports:1 ends here // [[file:~/Workspace/Programming/gosh-rs/lbfgs/lbfgs.note::*lbfgs][lbfgs:1]] use crate::lbfgs::Lbfgs; pub fn lbfgs() -> Lbfgs { Lbfgs::default() } // lbfgs:1 ends here // [[file:~/Workspace/Programming/gosh-rs/lbfgs/lbfgs.note::*tests][tests:1]] /// Default test function (rosenbrock) adopted from liblbfgs sample.c pub fn default_evaluate() -> impl FnMut(&[f64], &mut [f64]) -> Result<f64> { move |arr_x: &[f64], gx: &mut [f64]| { let n = arr_x.len(); let mut fx = 0.0; for i in (0..n).step_by(2) { let t1 = 1.0 - arr_x[i]; let t2 = 10.0 * (arr_x[i + 1] - arr_x[i] * arr_x[i]); gx[i + 1] = 20.0 * t2; gx[i] = -2.0 * (arr_x[i] * gx[i + 1] + t1); fx += t1 * t1 + t2 * t2; } Ok(fx) } } /// Default progress monitor adopted from liblbfgs sample.c /// /// # Notes /// /// * Returning true will cancel the optimization process. /// pub fn default_progress() -> impl FnMut(&Progress) -> bool { move |prgr| { println!("Iteration {}, Evaluation {}:", prgr.niter, prgr.neval); println!( " fx = {:-12.6} xnorm = {:-12.6}, gnorm = {:-12.6}, ls = {}, step = {}", prgr.fx, prgr.xnorm, prgr.gnorm, prgr.ncall, prgr.step ); false } } // tests:1 ends here