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}