Skip to main content

fpm_rs/reconstruction/
trace.rs

1//! Algorithm-neutral execution history for every reconstruction.
2
3use serde::{Deserialize, Serialize};
4
5/// Universal information recorded after one complete reconstruction iteration.
6#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
7#[serde(deny_unknown_fields)]
8pub struct IterationRecord {
9    /// One-based iteration number.
10    pub iteration: usize,
11    /// Universal scalar optimized or reported by the algorithm.
12    pub objective: f64,
13    /// Seconds elapsed from the start of this reconstruction, including any
14    /// elapsed time restored from a checkpoint.
15    pub elapsed_seconds: f64,
16}
17
18/// One scalar emitted by an algorithm-specific iteration metric.
19#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
20#[serde(deny_unknown_fields)]
21pub struct AlgorithmMetricRecord {
22    /// One-based iteration number.
23    pub iteration: usize,
24    /// Stable algorithm-owned namespace, for example `"admm"`.
25    pub namespace: String,
26    /// Stable metric name within `namespace`.
27    pub metric: String,
28    /// Finite scalar metric value.
29    pub value: f64,
30}
31
32/// Execution trace recorded for every reconstruction, independently of
33/// diagnostic callbacks.
34#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
35#[serde(deny_unknown_fields)]
36pub struct ReconstructionTrace {
37    /// Universal objective and elapsed time, one record per completed iteration.
38    pub iterations: Vec<IterationRecord>,
39    /// Optional algorithm-owned scalar metrics keyed by iteration and namespace.
40    pub algorithm_metrics: Vec<AlgorithmMetricRecord>,
41}
42
43impl ReconstructionTrace {
44    /// Returns the last completed iteration's objective, or `None` for an empty trace.
45    pub fn final_objective(&self) -> Option<f64> {
46        self.iterations.last().map(|record| record.objective)
47    }
48}