use crate::{ArgminOp, IterState};
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
#[derive(Clone, Serialize, Deserialize)]
pub struct ArgminResult<O: ArgminOp> {
pub operator: O,
pub state: IterState<O>,
}
impl<O: ArgminOp> ArgminResult<O> {
pub fn new(operator: O, state: IterState<O>) -> Self {
ArgminResult { operator, state }
}
}
impl<O> std::fmt::Display for ArgminResult<O>
where
O: ArgminOp,
O::Param: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
writeln!(f, "ArgminResult:")?;
writeln!(f, " param: {:?}", self.state.get_param())?;
writeln!(f, " cost: {}", self.state.get_cost())?;
writeln!(f, " iters: {}", self.state.get_iter())?;
writeln!(
f,
" termination: {}",
self.state.get_termination_reason()
)?;
writeln!(f, " time: {:?}", self.state.get_time())?;
Ok(())
}
}
impl<O: ArgminOp> PartialEq for ArgminResult<O> {
fn eq(&self, other: &ArgminResult<O>) -> bool {
(self.state.get_cost() - other.state.get_cost()).abs() < std::f64::EPSILON
}
}
impl<O: ArgminOp> Eq for ArgminResult<O> {}
impl<O: ArgminOp> Ord for ArgminResult<O> {
fn cmp(&self, other: &ArgminResult<O>) -> Ordering {
let t = self.state.get_cost() - other.state.get_cost();
if t.abs() < std::f64::EPSILON {
Ordering::Equal
} else if t > 0.0 {
Ordering::Greater
} else {
Ordering::Less
}
}
}
impl<O: ArgminOp> PartialOrd for ArgminResult<O> {
fn partial_cmp(&self, other: &ArgminResult<O>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MinimalNoOperator;
send_sync_test!(argmin_result, ArgminResult<MinimalNoOperator>);
}