use optimization_engine::{panoc::*, *};
fn rosenbrock_cost(a: f64, b: f64, u: &[f64]) -> f64 {
(a - u[0]).powi(2) + b * (u[1] - u[0].powi(2)).powi(2)
}
fn rosenbrock_grad(a: f64, b: f64, u: &[f64], grad: &mut [f64]) {
grad[0] = 2.0 * u[0] - 2.0 * a - 4.0 * b * u[0] * (-u[0].powi(2) + u[1]);
grad[1] = b * (-2.0 * u[0].powi(2) + 2.0 * u[1]);
}
fn main() {
let tolerance = 1e-6;
let mut a_param = 1.0;
let mut b_param = 100.0;
let n_dim_u = 2;
let lbfgs_memory = 10;
let max_iters = 100;
let mut u = [-1.5, 0.9];
let mut radius = 1.0;
let mut panoc_cache = PANOCCache::new(n_dim_u, tolerance, lbfgs_memory);
let mut idx = 0;
while idx < 100 {
b_param *= 1.01;
a_param -= 1e-3;
radius += 0.001;
let df = |u: &[f64], grad: &mut [f64]| -> Result<(), SolverError> {
rosenbrock_grad(a_param, b_param, u, grad);
Ok(())
};
let f = |u: &[f64], c: &mut f64| -> Result<(), SolverError> {
*c = rosenbrock_cost(a_param, b_param, u);
Ok(())
};
let bounds = constraints::Ball2::new(None, radius);
let problem = Problem::new(&bounds, df, f);
let mut panoc = PANOCOptimizer::new(problem, &mut panoc_cache).with_max_iter(max_iters);
let status = panoc.solve(&mut u).unwrap();
idx += 1;
println!(
"parameters: (a={:.4}, b={:.4}, r={:.4}), iters = {}",
a_param,
b_param,
radius,
status.iterations()
);
println!("u = {:#.6?}", u);
}
}