Skip to main content

holos_tda/program_trace/
model.rs

1use std::fmt;
2
3use crate::classes::IntervalGroupId;
4use crate::{
5    ClassContinuation, ClassCorrespondence, Diagram, Error, PersistenceProgram, ProgramArtifact,
6    ProgramDecodeLimits, ProgramEvent, ProgramUpdateMode, ProgramWork, SparseDistanceMatrix,
7};
8
9/// Failure while producing, decoding, or checking a program trace.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct ProgramTraceError {
12    message: String,
13}
14
15impl ProgramTraceError {
16    pub(crate) fn new(message: impl Into<String>) -> Self {
17        Self {
18            message: message.into(),
19        }
20    }
21
22    /// Description of the violated trace rule.
23    pub fn message(&self) -> &str {
24        &self.message
25    }
26}
27
28impl fmt::Display for ProgramTraceError {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        write!(f, "program trace: {}", self.message)
31    }
32}
33
34impl std::error::Error for ProgramTraceError {}
35
36/// Decoder limits applied before trace collections are allocated.
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38#[non_exhaustive]
39pub struct ProgramTraceDecodeLimits {
40    /// Largest accepted envelope in bytes.
41    pub max_bytes: usize,
42    /// Largest accepted update count.
43    pub max_steps: usize,
44    /// Largest accepted vertices in one graph.
45    pub max_vertices: usize,
46    /// Largest accepted edges across all embedded graphs.
47    pub max_total_edges: usize,
48    /// Largest accepted event count across all steps.
49    pub max_events: usize,
50    /// Largest accepted continuation-record count across all steps.
51    pub max_continuations: usize,
52    /// Largest accepted basis-transport count across all steps.
53    pub max_transports: usize,
54    /// Largest accepted correspondence-record count across all steps.
55    pub max_correspondences: usize,
56    /// Largest accepted correspondence-vector count across all steps.
57    pub max_correspondence_vectors: usize,
58    /// Largest accepted correspondence-term count across all steps.
59    pub max_correspondence_terms: usize,
60    /// Largest accepted bars across all step diagrams.
61    pub max_bars: usize,
62    /// Largest accepted bytes across all program checkpoints.
63    pub max_checkpoint_bytes: usize,
64    /// Limits for each nested program artifact.
65    pub program: ProgramDecodeLimits,
66}
67
68impl Default for ProgramTraceDecodeLimits {
69    fn default() -> Self {
70        Self {
71            max_bytes: 1 << 30,
72            max_steps: 10_000_000,
73            max_vertices: 1_000_000,
74            max_total_edges: 200_000_000,
75            max_events: 100_000_000,
76            max_continuations: 100_000_000,
77            max_transports: 200_000_000,
78            max_correspondences: 100_000_000,
79            max_correspondence_vectors: 200_000_000,
80            max_correspondence_terms: 400_000_000,
81            max_bars: 100_000_000,
82            max_checkpoint_bytes: 1 << 30,
83            program: ProgramDecodeLimits::default(),
84        }
85    }
86}
87
88/// One graph update and its declared result.
89#[derive(Debug, Clone)]
90pub struct ProgramTraceStep {
91    pub(crate) graph: SparseDistanceMatrix,
92    pub(crate) mode: ProgramUpdateMode,
93    pub(crate) work: ProgramWork,
94    pub(crate) events: Vec<ProgramEvent>,
95    pub(crate) continuation: Vec<ClassContinuation>,
96    pub(crate) correspondence: Vec<ClassCorrespondence>,
97    pub(crate) diagram: Diagram,
98    pub(crate) checkpoint: Option<ProgramArtifact>,
99}
100
101impl ProgramTraceStep {
102    /// Updated graph embedded in the trace.
103    pub fn graph(&self) -> &SparseDistanceMatrix {
104        &self.graph
105    }
106
107    /// Declared execution mode.
108    pub fn mode(&self) -> ProgramUpdateMode {
109        self.mode
110    }
111
112    /// Exact work charged by the producer.
113    pub fn work(&self) -> ProgramWork {
114        self.work
115    }
116
117    /// Declared topology and algebraic events.
118    pub fn events(&self) -> &[ProgramEvent] {
119        &self.events
120    }
121
122    /// Declared class-space continuation records.
123    pub fn continuation(&self) -> &[ClassContinuation] {
124        &self.continuation
125    }
126
127    /// Exact class-space relations on common filtered subcomplexes.
128    pub fn correspondence(&self) -> &[ClassCorrespondence] {
129        &self.correspondence
130    }
131
132    /// Exact diagram at this step.
133    pub fn diagram(&self) -> &Diagram {
134        &self.diagram
135    }
136
137    /// New full checkpoint, present only after repair or recompilation.
138    pub fn checkpoint(&self) -> Option<&ProgramArtifact> {
139        self.checkpoint.as_ref()
140    }
141}
142
143/// Sequence of program updates with nested proofs.
144#[derive(Debug, Clone)]
145pub struct ProgramTraceArtifact {
146    pub(crate) initial_graph: SparseDistanceMatrix,
147    pub(crate) initial_program: ProgramArtifact,
148    pub(crate) steps: Vec<ProgramTraceStep>,
149}
150
151/// One replayed program step.
152#[derive(Debug, Clone)]
153pub struct VerifiedProgramTraceStep {
154    /// Execution mode.
155    pub mode: ProgramUpdateMode,
156    /// Work counts.
157    pub work: ProgramWork,
158    /// Topology and algebraic events.
159    pub events: Vec<ProgramEvent>,
160    /// Class-space continuation.
161    pub continuation: Vec<ClassContinuation>,
162    /// Exact class-space correspondence.
163    pub correspondence: Vec<ClassCorrespondence>,
164    /// Exact diagram.
165    pub diagram: Diagram,
166}
167
168/// Result of verifying a program trace.
169#[derive(Debug, Clone)]
170pub struct VerifiedProgramTrace {
171    /// Initial diagram and H1 class spaces.
172    pub initial_result: crate::ExplainedDiagram,
173    /// Update steps.
174    pub steps: Vec<VerifiedProgramTraceStep>,
175    /// Ready program at the final graph.
176    pub final_program: PersistenceProgram,
177}
178
179#[derive(Default)]
180pub(crate) struct TraceTotals {
181    pub(crate) events: usize,
182    pub(crate) continuations: usize,
183    pub(crate) transports: usize,
184    pub(crate) correspondences: usize,
185    pub(crate) correspondence_vectors: usize,
186    pub(crate) correspondence_terms: usize,
187    pub(crate) bars: usize,
188    pub(crate) checkpoint_bytes: usize,
189}
190
191pub(crate) struct TraceHeader {
192    pub(crate) step_count: usize,
193    pub(crate) initial_program_bytes: usize,
194}
195
196pub(crate) struct StepCounts {
197    pub(crate) events: usize,
198    pub(crate) continuations: usize,
199    pub(crate) correspondences: usize,
200    pub(crate) bars: usize,
201    pub(crate) checkpoint_bytes: usize,
202}
203
204pub(crate) struct DecodedStepBody {
205    pub(crate) events: Vec<ProgramEvent>,
206    pub(crate) continuation: Vec<ClassContinuation>,
207    pub(crate) correspondence: Vec<ClassCorrespondence>,
208    pub(crate) diagram: Diagram,
209}
210
211pub(crate) struct CorrespondenceHeader {
212    pub(crate) old_space: IntervalGroupId,
213    pub(crate) new_space: IntervalGroupId,
214    pub(crate) scale: f64,
215    pub(crate) old_rank: usize,
216    pub(crate) new_rank: usize,
217    pub(crate) old_image_rank: usize,
218    pub(crate) new_image_rank: usize,
219    pub(crate) relation_rank: usize,
220    pub(crate) basis_count: usize,
221}
222
223impl From<crate::ProgramUpdate> for VerifiedProgramTraceStep {
224    fn from(update: crate::ProgramUpdate) -> Self {
225        Self {
226            mode: update.mode,
227            work: update.work,
228            events: update.events,
229            continuation: update.continuation,
230            correspondence: update.correspondence,
231            diagram: update.result.diagram,
232        }
233    }
234}
235
236impl From<ProgramTraceError> for Error {
237    fn from(error: ProgramTraceError) -> Self {
238        Self::InvalidInput(error.to_string())
239    }
240}