holos_tda/program/model.rs
1use crate::{
2 AtlasArtifact, BasisClassId, CertificateLimits, ClassCorrespondence, Diagram, EdgeKey,
3 ExplainedDiagram, IntervalGroupId, ReductionGuardKind, Result, RipsParams,
4 SparseDistanceMatrix,
5};
6
7/// One atom in a compiled sparse persistence program.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct ProgramAtomInfo {
10 /// Stable position in the program decomposition.
11 pub id: usize,
12 /// Original labeled vertices in ascending order.
13 pub vertices: Vec<usize>,
14 /// Original labeled edges in ascending endpoint order.
15 pub edges: Vec<EdgeKey>,
16 /// Vertices shared with another atom.
17 pub separator_vertices: Vec<usize>,
18 /// Whether the atom can contain positive-dimensional homology.
19 pub cyclic: bool,
20}
21
22/// Structural and algebraic size of a compiled program.
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct ProgramSummary {
25 /// Vertex-biconnected atoms, including bridge atoms.
26 pub atoms: usize,
27 /// Atoms that contain a graph cycle.
28 pub cyclic_atoms: usize,
29 /// Distinct articulation vertices.
30 pub articulation_vertices: usize,
31 /// Wider zero-filtration simplex separators used by the program.
32 pub zero_simplex_separators: usize,
33 /// Largest separator used by the program.
34 pub widest_separator: usize,
35 /// Candidate vertex sets checked during bounded separator search.
36 pub separator_candidates_checked: usize,
37 /// Whether bounded separator search visited every candidate in scope.
38 pub separator_search_complete: bool,
39 /// Edges in the largest cyclic atom.
40 pub largest_cyclic_atom_edges: usize,
41 /// Distinct reduction guards before transitive removal.
42 pub complete_guards: usize,
43 /// Result-sensitive guards across all cyclic atoms.
44 pub guards: usize,
45}
46
47/// Exact work charged to one program evaluation or update.
48#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
49pub struct ProgramWork {
50 /// Listed edges compared with the current program input.
51 pub edges_checked: usize,
52 /// Edges read by the H0 computation.
53 pub h0_edges_scanned: usize,
54 /// Result-sensitive algebraic guards checked.
55 pub guards_checked: usize,
56 /// Cyclic atoms containing a changed edge.
57 pub atoms_touched: usize,
58 /// Touched atoms reused without reduction.
59 pub atoms_reused: usize,
60 /// Touched atoms repaired by reducing a suffix.
61 pub atoms_repaired: usize,
62 /// Touched atoms whose explained state was rebuilt without suffix repair.
63 pub atoms_rebuilt: usize,
64 /// Boundary columns retained during reduction repair.
65 pub reduction_columns_reused: usize,
66 /// Boundary columns processed during reduction repair.
67 pub reduction_columns_reduced: usize,
68 /// Sparse column additions performed during reduction repair.
69 pub reduction_column_additions: usize,
70}
71
72/// Why a program update changed execution state.
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74#[non_exhaustive]
75pub enum ProgramEventKind {
76 /// The labeled vertex set changed.
77 VertexSetChanged,
78 /// The complete listed edge set changed.
79 EdgeSetChanged,
80 /// An edge crossed the fixed threshold.
81 ThresholdCrossing,
82 /// A result-sensitive algebraic guard failed.
83 GuardFailed,
84 /// A touched cyclic atom rebuilt its explained state.
85 AtomRebuilt,
86 /// A touched cyclic atom repaired a reduction suffix.
87 ReductionSuffixRepaired,
88 /// A wider separator stopped being a zero-filtration simplex.
89 SeparatorContractChanged,
90}
91
92/// One event reported by a program update.
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub struct ProgramEvent {
95 /// Kind of change.
96 pub kind: ProgramEventKind,
97 /// Affected atom, when one exists.
98 pub atom: Option<usize>,
99 /// Affected edge, when one exists.
100 pub edge: Option<EdgeKey>,
101 /// Failed guard kind, when one exists.
102 pub guard: Option<ReductionGuardKind>,
103}
104
105/// How a program produced an updated result.
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub enum ProgramUpdateMode {
108 /// All touched atoms retained their checked reductions.
109 Reused,
110 /// At least one touched atom was repaired or rebuilt locally.
111 Repaired,
112 /// The graph topology or threshold membership changed.
113 Recompiled,
114}
115
116/// Control over exact relations to the preceding class spaces.
117#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
118#[non_exhaustive]
119pub enum CorrespondenceMode {
120 /// Return exact relations on every common filtered subcomplex.
121 #[default]
122 Exact,
123 /// Keep the exact current state. Leave correspondence empty.
124 Omit,
125}
126
127/// Algebraic relation between class spaces across one update.
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129#[non_exhaustive]
130pub enum ContinuationKind {
131 /// One old space maps bijectively to one new space.
132 Isomorphism,
133 /// One old space contributes to several new spaces.
134 Split,
135 /// Several old spaces contribute to one new space.
136 Merge,
137 /// Several old and new spaces share exact basis vectors.
138 Mixing,
139 /// A new space has no exact old basis vector.
140 Birth,
141 /// An old space has no exact new basis vector.
142 Death,
143 /// A proper subset of the vectors has an exact declared continuation.
144 Ambiguous,
145}
146
147/// One exact equality between an old and new canonical basis vector.
148#[derive(Debug, Clone, Copy, PartialEq, Eq)]
149pub struct BasisTransport {
150 /// Old basis identifier.
151 pub old: BasisClassId,
152 /// New basis identifier.
153 pub new: BasisClassId,
154 /// Nonzero coefficient in the shared prime field.
155 pub coefficient: u32,
156}
157
158/// One path-relative class-space continuation record.
159#[derive(Debug, Clone, PartialEq, Eq)]
160pub struct ClassContinuation {
161 /// Algebraic shape of the relation.
162 pub kind: ContinuationKind,
163 /// Old class spaces in the connected relation component.
164 pub old_spaces: Vec<IntervalGroupId>,
165 /// New class spaces in the connected relation component.
166 pub new_spaces: Vec<IntervalGroupId>,
167 /// Exact shared canonical basis vectors.
168 pub transport: Vec<BasisTransport>,
169}
170
171/// Diagram-only evaluation from unchanged program certificates.
172#[derive(Debug, Clone)]
173pub struct ProgramEvaluation {
174 /// Exact H0 and H1 diagram.
175 pub diagram: Diagram,
176 /// Work charged to the evaluation.
177 pub work: ProgramWork,
178}
179
180/// How a diagram-only state produced an updated diagram.
181#[derive(Debug, Clone, Copy, PartialEq, Eq)]
182pub enum ProgramDiagramUpdateMode {
183 /// Existing checked regions produced the updated diagram.
184 Reused,
185 /// A complete compositional program was compiled as the exact fallback.
186 Recompiled,
187}
188
189/// Result of advancing a diagram-only program state.
190#[derive(Debug, Clone)]
191pub struct ProgramDiagramUpdate {
192 /// Exact H0 and H1 diagram at the new input.
193 pub diagram: Diagram,
194 /// How the diagram was produced.
195 pub mode: ProgramDiagramUpdateMode,
196 /// Topology or region events encountered during the update.
197 pub events: Vec<ProgramEvent>,
198 /// Exact work charged to the update.
199 pub work: ProgramWork,
200}
201
202/// Result of advancing a persistence program.
203#[derive(Debug, Clone)]
204pub struct ProgramUpdate {
205 /// Exact diagram and canonical H1 class spaces at the new input.
206 pub result: ExplainedDiagram,
207 /// How the program produced this result.
208 pub mode: ProgramUpdateMode,
209 /// Events encountered during the update.
210 pub events: Vec<ProgramEvent>,
211 /// Algebraic class-space continuation records.
212 pub continuation: Vec<ClassContinuation>,
213 /// Exact linear relations on common filtered subcomplexes.
214 pub correspondence: Vec<ClassCorrespondence>,
215 /// Exact work charged to the update.
216 pub work: ProgramWork,
217}
218
219/// Immutable state from which a program can be restored or branched.
220#[derive(Debug, Clone)]
221pub struct ProgramCheckpoint {
222 pub(super) program: PersistenceProgram,
223}
224
225impl ProgramCheckpoint {
226 /// Program state stored by this checkpoint.
227 pub fn program(&self) -> &PersistenceProgram {
228 &self.program
229 }
230
231 /// Advance independent alternatives from this checkpoint.
232 pub fn branch(&self, alternatives: &[SparseDistanceMatrix]) -> Result<Vec<ProgramBranch>> {
233 self.program.branch(alternatives)
234 }
235
236 /// Advance alternatives with explicit correspondence control.
237 pub fn branch_with(
238 &self,
239 alternatives: &[SparseDistanceMatrix],
240 correspondence_mode: CorrespondenceMode,
241 ) -> Result<Vec<ProgramBranch>> {
242 self.program.branch_with(alternatives, correspondence_mode)
243 }
244}
245
246/// One independently advanced program branch.
247#[derive(Debug, Clone)]
248pub struct ProgramBranch {
249 /// Position of the alternative in the input batch.
250 pub index: usize,
251 /// Exact update from the shared branch point.
252 pub update: ProgramUpdate,
253 pub(super) program: PersistenceProgram,
254}
255
256/// Stateful diagram evaluation with lazy materialization of class spaces.
257#[derive(Debug, Clone)]
258pub struct ProgramDiagramState {
259 pub(super) program: PersistenceProgram,
260 pub(super) graph: SparseDistanceMatrix,
261 pub(super) diagram: Diagram,
262 pub(super) dirty: bool,
263}
264
265impl ProgramBranch {
266 /// Program at the end of this branch.
267 pub fn program(&self) -> &PersistenceProgram {
268 &self.program
269 }
270
271 /// Consume this branch and return its program.
272 pub fn into_program(self) -> PersistenceProgram {
273 self.program
274 }
275
276 /// Consume this branch and return its update and program.
277 pub fn into_parts(self) -> (ProgramUpdate, PersistenceProgram) {
278 (self.update, self.program)
279 }
280}
281
282#[derive(Debug, Clone)]
283pub(crate) struct ProgramAtomState {
284 pub(crate) info_index: usize,
285 pub(crate) vertices: Vec<usize>,
286 pub(crate) edges: Vec<EdgeKey>,
287 pub(crate) edge_positions: Vec<usize>,
288 pub(crate) artifact: AtlasArtifact,
289 pub(crate) certified_graph: SparseDistanceMatrix,
290 pub(crate) region: crate::CertifiedReductionRegion,
291 pub(crate) explained: ExplainedDiagram,
292}
293
294/// Exact H0 and H1 program compiled over sparse graph atoms.
295#[derive(Debug, Clone)]
296pub struct PersistenceProgram {
297 pub(super) params: RipsParams,
298 pub(super) limits: CertificateLimits,
299 pub(super) graph: SparseDistanceMatrix,
300 pub(super) topology: Vec<EdgeKey>,
301 pub(super) active: Vec<bool>,
302 pub(super) separator_edges: Vec<EdgeKey>,
303 pub(super) h0_deaths: Vec<EdgeKey>,
304 pub(super) h0_essential: usize,
305 pub(super) atoms: Vec<ProgramAtomInfo>,
306 pub(super) states: Vec<ProgramAtomState>,
307 pub(super) summary: ProgramSummary,
308 pub(super) result: ExplainedDiagram,
309}