use crate::{EvalCounts, Scalar};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum TrialKind {
Reflection,
Expansion,
OutsideContraction,
InsideContraction,
Shrink(usize),
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Trial<V, F: Scalar = f64> {
pub sequence: u64,
pub kind: TrialKind,
pub point: V,
pub cost: Option<F>,
pub accepted: Option<bool>,
pub counts_before: EvalCounts,
pub counts_after: EvalCounts,
}
pub(super) struct Trace<V, F: Scalar> {
pub enabled: bool,
pub sequence: u64,
pub trials: Vec<Trial<V, F>>,
}
impl<V: Clone, F: Scalar> Trace<V, F> {
pub fn evaluate<P: crate::CostFunction<Param = V, Output = F>>(
&mut self,
problem: &mut crate::Problem<P>,
point: &V,
kind: TrialKind,
) -> Result<F, P::Error> {
let before = *problem.counts();
let result = problem.cost(point);
if self.enabled {
self.sequence += 1;
self.trials.push(Trial {
sequence: self.sequence,
kind,
point: point.clone(),
cost: result.as_ref().ok().copied(),
accepted: None,
counts_before: before,
counts_after: *problem.counts(),
});
}
result
}
pub fn accept(&mut self, index: usize, accepted: bool) {
if self.enabled {
self.trials[index].accepted = Some(accepted);
}
}
}
impl<V, F: Scalar> Default for Trace<V, F> {
fn default() -> Self {
Self {
enabled: false,
sequence: 0,
trials: Vec::new(),
}
}
}