use optirs_core::optimizers::{Adam, Lion, Optimizer, SGD};
use scirs2_core::ndarray::Array1;
use std::collections::HashMap;
#[allow(dead_code)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Lion Optimizer Example");
println!("=====================");
let objective_fn = |x: &Array1<f64>| -> f64 { x[0].powi(2) + x[1].powi(2) };
let gradient_fn =
|x: &Array1<f64>| -> Array1<f64> { Array1::from_vec(vec![2.0 * x[0], 2.0 * x[1]]) };
let initial_params = Array1::from_vec(vec![5.0, 3.0]);
let learning_rate = 0.1;
let num_iterations = 50;
let mut optimizers: HashMap<String, Box<dyn Optimizer<f64, scirs2_core::ndarray::Ix1>>> =
HashMap::new();
optimizers.insert("Lion".to_string(), Box::new(Lion::new(learning_rate)));
optimizers.insert("Adam".to_string(), Box::new(Adam::new(learning_rate)));
optimizers.insert("SGD".to_string(), Box::new(SGD::new(learning_rate)));
println!(
"Starting optimization from x = [{}, {}]",
initial_params[0], initial_params[1]
);
println!("Target minimum is at x = [0.0, 0.0]");
println!("Learning rate = {}", learning_rate);
println!("Number of iterations = {}", num_iterations);
println!();
for (name, optimizer) in optimizers.iter_mut() {
println!("Running {} optimizer:", name);
println!("Iteration | x | y | Function Value");
println!("------------------------------------------------");
let mut params = initial_params.clone();
let initial_value = objective_fn(¶ms);
println!(
"{:>9} | {:>9.4} | {:>9.4} | {:>13.6}",
0, params[0], params[1], initial_value
);
for i in 1..=num_iterations {
let gradients = gradient_fn(¶ms);
params = optimizer.step(¶ms, &gradients)?;
let value = objective_fn(¶ms);
if i % 10 == 0 || i == 1 {
println!(
"{:>9} | {:>9.4} | {:>9.4} | {:>13.6}",
i, params[0], params[1], value
);
}
}
println!("Final parameters: x = [{:.6}, {:.6}]", params[0], params[1]);
println!("Final function value: {:.6}", objective_fn(¶ms));
println!();
}
println!("Optimization complete!");
Ok(())
}
#[test]
#[allow(dead_code)]
fn test_lion_convergence() {
let mut optimizer = Lion::new(0.05); let mut params = Array1::from_vec(vec![10.0, -5.0]);
for _ in 0..1000 {
let gradients = Array1::from_vec(vec![2.0 * params[0], 2.0 * params[1]]);
params = optimizer.step(¶ms, &gradients).expect("unwrap failed");
}
assert!(f64::abs(params[0]) < 1.0);
assert!(f64::abs(params[1]) < 1.0);
}