use super::NR::{NR, solve_linear_system};
use crate::numerical::BVP_Damp::BVP_utils::elapsed_time;
use log::info;
use nalgebra::{DMatrix, DVector};
use std::time::Instant;
impl NR {
pub fn step_trust_region(&mut self) -> (i32, Option<DVector<f64>>) {
let now = Instant::now();
let bounds_vec = self.bounds_vec.clone();
let method = self.linear_sys_method.clone().unwrap();
let parameters = self.parameters.clone().unwrap();
let eta_min = parameters.get("eta_min").unwrap();
let eta_max = parameters.get("eta_max").unwrap();
let ro_threshold0 = parameters.get("ro_threshold0").unwrap();
let ro_threshold1 = parameters.get("ro_threshold1").unwrap();
let C0 = parameters.get("C0").unwrap();
let M = parameters.get("M").unwrap();
let d = parameters.get("d").unwrap();
let m = parameters.get("m").unwrap();
let mut parameters_mut = self.parameters.clone().unwrap();
let mu = parameters_mut.get_mut("mu").unwrap();
let y = self.y.clone();
let Fy = self.evaluate_function(y.clone());
let Jy = self.evaluate_jacobian(y.clone());
let old_norm = Fy.norm_squared();
let delta = mu.clone() * old_norm.powf(*d);
info!("delta = {}", delta);
info!("norm = {}", old_norm);
if old_norm < self.tolerance {
let y_result = y.clone();
info!("Solution found!");
return (1, Some(y_result));
}
let b = -Jy.transpose() * &Fy;
let step = self
.solve_trust_region_subproblem(method, &Jy, &b, delta, *m)
.unwrap();
let mut y_new = y.clone() + &step;
y_new = self.clip(&y_new, &bounds_vec);
let Fy_new = self.evaluate_function(y_new.clone());
let actual_reduction = Fy.norm_squared() - Fy_new.norm_squared();
let predicted_reduction = Fy.norm_squared() - (Fy.clone() + Jy * &step).norm_squared();
let rho = actual_reduction / (predicted_reduction + 1e-12);
info!("rho is: {}", rho);
let elapsed = now.elapsed();
elapsed_time(elapsed);
let y_result = if rho > *C0 { y_new.clone() } else { y.clone() };
if rho < *ro_threshold0 {
*mu = *eta_min * *mu;
info!("mu decreased: {}", mu);
self.parameters = Some(parameters_mut);
return (0, Some(y_result));
} else if (rho >= *ro_threshold0) && (rho <= *ro_threshold1) {
*mu = *mu;
self.parameters = Some(parameters_mut);
return (0, Some(y_result));
} else {
*mu = M.min(*eta_max * *mu);
self.parameters = Some(parameters_mut);
return (0, Some(y_result));
}
}
fn solve_trust_region_subproblem_dogleg(
&self,
J: &DMatrix<f64>,
F: &DVector<f64>,
B: &DMatrix<f64>,
H: &DMatrix<f64>,
delta: f64,
) -> DVector<f64> {
let pU: DVector<f64> = DVector::zeros(0);
pU
}
fn solve_trust_region_subproblem(
&self,
method: String,
Jy: &DMatrix<f64>,
Ft: &DVector<f64>,
delta: f64,
m: f64,
) -> Result<DVector<f64>, String> {
let B = Jy.clone().transpose() * Jy.clone();
Ok(DVector::zeros(Jy.nrows()))
}
}