use std::error::Error;
use num_traits::Float;
use strafe_type::{Finite64, FloatConstraint};
use crate::funcs::{
opt::{Optim, OptimOptions, OptimResponse},
optimize::optimize,
};
pub struct Brent {
pub lower_bound: Finite64,
pub upper_bound: Finite64,
pub optim_options: OptimOptions,
}
impl Default for Brent {
fn default() -> Self {
Self {
lower_bound: (-100).into(),
upper_bound: 100.into(),
optim_options: OptimOptions {
parscale: None,
fnscale: 1.0,
abstol: f64::neg_infinity(),
reltol: f64::epsilon().sqrt(),
maxit: 100,
},
}
}
}
impl Optim for Brent {
type ParameterType = f64;
fn optim(
&mut self,
_par: Self::ParameterType,
min_func: &dyn Fn(Self::ParameterType) -> f64,
) -> Result<OptimResponse<Self::ParameterType>, Box<dyn Error>> {
let f = |p: f64| min_func(p) / self.optim_options.fnscale;
let (par, val) = optimize(
&f,
self.lower_bound.unwrap(),
self.upper_bound.unwrap(),
self.optim_options.reltol,
false,
);
Ok(OptimResponse {
parameters: par,
value: val * self.optim_options.fnscale,
function_count: 0,
gradient_count: 0,
convergence: true,
})
}
}