use crate::core::math::{Scalar, ScaleInPlace, VectorLen};
use crate::core::problem::EvalCounts;
use crate::core::state::{CountsMirror, RhoState, State};
pub struct SolisWetsState<V, F = f64> {
pub(crate) x: V,
pub(crate) cost: Option<F>,
pub(crate) bias: V,
pub(crate) rho: F,
pub(crate) num_success: u32,
pub(crate) num_failure: u32,
pub(crate) best_param: Option<V>,
pub(crate) best_cost: F,
pub(crate) best_iter: u64,
pub(crate) best_cost_evals: u64,
pub(crate) iter: u64,
pub(crate) cost_evals: u64,
}
impl<V, F> SolisWetsState<V, F>
where
V: Clone + VectorLen + ScaleInPlace<F>,
F: Scalar,
{
pub fn new(x: V, rho: F) -> Self {
assert!(
rho > F::zero(),
"SolisWetsState requires rho > 0, got {:?}",
rho
);
assert!(x.vec_len() >= 1, "SolisWetsState requires a non-empty x");
let mut bias = x.clone();
bias.scale_in_place(F::zero());
Self {
x,
cost: None,
bias,
rho,
num_success: 0,
num_failure: 0,
best_param: None,
best_cost: F::infinity(),
best_iter: 0,
best_cost_evals: 0,
iter: 0,
cost_evals: 0,
}
}
}
impl<V, F: Scalar> SolisWetsState<V, F> {
pub fn rho(&self) -> F {
self.rho
}
pub fn bias(&self) -> &V {
&self.bias
}
pub fn success_count(&self) -> u32 {
self.num_success
}
pub fn failure_count(&self) -> u32 {
self.num_failure
}
}
impl<V: Clone, F: Scalar> State for SolisWetsState<V, F> {
type Param = V;
type Float = F;
fn iter(&self) -> u64 {
self.iter
}
fn increment_iter(&mut self) {
self.iter += 1;
}
fn cost_evals(&self) -> u64 {
self.cost_evals
}
fn param(&self) -> &V {
&self.x
}
fn cost(&self) -> F {
self.cost
.expect("SolisWetsState::cost read before Solver::init evaluated the start point")
}
fn best_param(&self) -> &V {
self.best_param
.as_ref()
.expect("SolisWetsState::best_param read before Solver::init populated it")
}
fn best_cost(&self) -> F {
self.best_cost
}
fn best_iter(&self) -> u64 {
self.best_iter
}
fn best_cost_evals(&self) -> u64 {
self.best_cost_evals
}
fn update_best(&mut self) {
if let Some(c) = self.cost {
if self.best_param.is_none() || c < self.best_cost {
self.best_param = Some(self.x.clone());
self.best_cost = c;
self.best_iter = self.iter;
self.best_cost_evals = self.cost_evals;
}
}
}
fn reset_best(&mut self) {
self.best_param = None;
self.best_cost = F::infinity();
self.best_iter = 0;
self.best_cost_evals = 0;
}
}
impl<V, F> CountsMirror for SolisWetsState<V, F>
where
SolisWetsState<V, F>: State,
{
fn mirror(&mut self, delta: &EvalCounts) {
self.cost_evals = delta.total_work();
}
}
impl<V: Clone, F: Scalar> RhoState for SolisWetsState<V, F> {
fn rho(&self) -> F {
self.rho
}
}