use lbfgsbrs::lbfgsb::{LbfgsbMinimizer, LbfgsbParameters};
use env_logger;
use log;
fn main() {
env_logger::init();
log::info!("Solving sample problem (Rosenbrock test fcn).");
log::info!(" (f = 0.0 at the optimal solution.)\n\0");
let n = 1000;
let mut x: Vec<f64> = vec![3.0; n];
let f = |x: &Vec<f64>| -> f64 {
let mut f = 0.25 * (x[0] - 1.0).powi(2);
for i in 1..n {
let t = x[i] - x[i-1].powi(2);
f += t.powi(2);
}
f * 4.0
};
let g = |x: &Vec<f64>| -> Vec<f64> {
let mut grad = vec![0.0; n];
let mut t1 = x[1] - x[0].powi(2);
grad[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].powi(2);
grad[i] = 8.0 * t2 - 16.0 * x[i] * t1;
}
grad[n-1] = 8.0 * t1;
grad
};
let params = LbfgsbParameters {
m: 10,
factr: 0.0,
pgtol: 0.0,
time_limit: 0.2,
max_iter: 1000,
};
let mut optimizer = LbfgsbMinimizer::new(&mut x, &f, &g, Some(params));
for i in (0..n).step_by(2) {
optimizer.set_lower_bound(i, 1.0);
optimizer.set_upper_bound(i, 100.0);
}
for i in (1..n).step_by(2) {
optimizer.set_lower_bound(i, -100.0);
optimizer.set_upper_bound(i, 100.0);
}
match optimizer.minimize() {
Ok(_) => {
log::trace!("Optimization successful");
},
Err(e) => {
log::warn!("Error during optimization: {:?}", e);
},
}
let solution = optimizer.get_x();
log::info!("Optimization complete.");
log::trace!("Final X = {:?}", solution);
let solution_slice = [&solution[..10], &solution[n-10..]].concat();
let ref_final_x = vec![1.0000000000000000, 0.9999999999999298, 1.0000000000000000, 1.0000000000001319, 1.0000000000001259, 1.0000000000004210, 1.0000000000002660, 1.0000000000007556, 1.0000000000006632, 1.0000000000007858, 1.0027613236431623, 1.0055302721945152, 1.0110911282976183, 1.0223052697237622, 1.0451080645051254, 1.0922508664949420, 1.1930119553596639, 1.4232775256318961, 2.0257189149696382, 4.1035371224629555];
let mut all_match = true;
for i in 0..ref_final_x.len() {
if (solution_slice[i] - ref_final_x[i]).abs() >= 1e-12 {
log::info!("Mismatch at index {}: expected {}, got {}",
i, ref_final_x[i], solution_slice[i]);
all_match = false;
}
}
if all_match {
log::info!("All values match the reference solution within tolerance of 1e-12");
} else {
log::info!("Some values don't match the reference solution!");
}
log::info!("Objective value: {}", f(&solution));
}