use crate::{
EvalCounts, OptimizationResult, Problem, Scalar, State, TerminationReport,
};
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct Context<F: Scalar = f64> {
pub outer_iteration: u64,
pub member: Option<usize>,
pub resumed: bool,
pub initial_scale: Option<F>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum Status {
Pending,
Returned,
CallbackError,
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct Record<F: Scalar = f64> {
pub sequence: u64,
pub context: Context<F>,
pub counts_before: EvalCounts,
pub counts_after: Option<EvalCounts>,
pub status: Status,
pub report: Option<TerminationReport<F>>,
}
pub(crate) fn run<P, S, F, E>(
trace: &mut Option<Vec<Record<F>>>,
problem: &mut Problem<P>,
context: Context<F>,
dispatch: impl FnOnce(&mut Problem<P>) -> Result<OptimizationResult<S>, E>,
) -> Result<OptimizationResult<S>, E>
where
F: Scalar,
S: State<Float = F>,
{
let index = trace.as_mut().map(|records| {
let index = records.len();
records.push(Record {
sequence: index as u64,
context,
counts_before: *problem.counts(),
counts_after: None,
status: Status::Pending,
report: None,
});
index
});
let result = dispatch(problem);
if let Some(index) = index {
let record = &mut trace.as_mut().unwrap()[index];
record.counts_after = Some(*problem.counts());
if let Ok(result) = &result {
record.status = Status::Returned;
record.report = Some(result.report.clone());
} else {
record.status = Status::CallbackError;
}
}
result
}