Skip to main content

holos_tda/persistent_coordinate_artifact/
model.rs

1use std::fmt;
2
3use crate::circular::SelectedCircularCoordinate;
4use crate::{
5    Bar, CriticalPair, IntegralCocycleTerm, PersistenceCycleTerm, PersistenceTriangleTerm,
6    PersistentClass, PersistentClassArtifact, SparseDistanceMatrix,
7};
8
9/// Failure while constructing or encoding a selected-coordinate artifact.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct PersistentCoordinateArtifactError {
12    pub(super) message: String,
13}
14
15impl PersistentCoordinateArtifactError {
16    pub(crate) fn new(message: impl Into<String>) -> Self {
17        Self {
18            message: message.into(),
19        }
20    }
21
22    /// Return the violated artifact rule.
23    pub fn message(&self) -> &str {
24        &self.message
25    }
26}
27
28impl fmt::Display for PersistentCoordinateArtifactError {
29    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
30        write!(
31            formatter,
32            "persistent coordinate artifact: {}",
33            self.message
34        )
35    }
36}
37
38impl std::error::Error for PersistentCoordinateArtifactError {}
39
40/// Structural counts for one selected persistent-coordinate artifact.
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
42pub struct PersistentCoordinateArtifactSummary {
43    /// Number of labeled source vertices.
44    pub vertices: usize,
45    /// Number of weighted source edges.
46    pub source_edges: usize,
47    /// Number of nonzero integer lift terms.
48    pub integral_terms: usize,
49    /// Number of potential values.
50    pub potential_values: usize,
51}
52
53/// A harmonic coordinate bound to one checked persistent H1 class artifact.
54///
55/// The class artifact supplies the complete weighted source, interval, exact
56/// canonical cocycle, and birth cycle. This type stores only the selected
57/// coordinate's integer lift and harmonic values.
58#[derive(Debug, Clone)]
59pub struct PersistentCoordinateArtifact {
60    pub(super) class_artifact: PersistentClassArtifact,
61    pub(super) coordinate: SelectedCircularCoordinate,
62}
63
64impl PersistentCoordinateArtifact {
65    /// Return the immutable persistent-class artifact carried by this result.
66    pub fn class_artifact(&self) -> &PersistentClassArtifact {
67        &self.class_artifact
68    }
69
70    /// Return the complete weighted source graph.
71    pub fn source(&self) -> &SparseDistanceMatrix {
72        self.class_artifact.source()
73    }
74
75    /// Return the selected persistent class.
76    pub fn class(&self) -> &PersistentClass {
77        self.class_artifact.class()
78    }
79
80    /// Return the selected persistence interval.
81    pub fn interval(&self) -> Bar {
82        self.class().interval
83    }
84
85    /// Return the selected critical pair.
86    pub fn critical_pair(&self) -> &CriticalPair {
87        self.class_artifact.critical_pair()
88    }
89
90    /// Return the checked birth cycle.
91    pub fn cycle(&self) -> &[PersistenceCycleTerm] {
92        self.class_artifact.cycle()
93    }
94
95    /// Return the checked finite-death bounding chain.
96    pub fn bounding_chain(&self) -> &[PersistenceTriangleTerm] {
97        self.class_artifact.bounding_chain()
98    }
99
100    /// Return the prime field of the selected source.
101    pub fn modulus(&self) -> u32 {
102        self.coordinate.modulus
103    }
104
105    /// Return the fixed representative scale.
106    pub fn scale(&self) -> f64 {
107        self.coordinate.scale
108    }
109
110    /// Return the nonzero field multiplier used by the integral lift.
111    pub fn field_multiplier(&self) -> u32 {
112        self.coordinate.field_multiplier
113    }
114
115    /// Return the checked integer cocycle used for the harmonic coordinate.
116    pub fn integral(&self) -> &[IntegralCocycleTerm] {
117        &self.coordinate.integral
118    }
119
120    /// Return the divisibility of the integer cohomology class.
121    pub fn divisibility(&self) -> u64 {
122        self.coordinate.divisibility
123    }
124
125    /// Return the gauge-fixed real vertex potential.
126    pub fn potential(&self) -> &[f64] {
127        &self.coordinate.potential
128    }
129
130    /// Return the circle-valued phase at each labeled vertex.
131    pub fn phase(&self) -> &[f64] {
132        &self.coordinate.phase
133    }
134
135    /// Return the squared unweighted harmonic energy.
136    pub fn energy(&self) -> f64 {
137        self.coordinate.energy
138    }
139
140    /// Return the maximum absolute harmonic residual.
141    pub fn max_residual(&self) -> f64 {
142        self.coordinate.max_residual
143    }
144
145    /// Return the residual divided by the source infinity norm.
146    pub fn relative_residual(&self) -> f64 {
147        self.coordinate.relative_residual
148    }
149
150    /// Return the conjugate-gradient iteration count.
151    pub fn iterations(&self) -> usize {
152        self.coordinate.iterations
153    }
154
155    /// Return the residual tolerance used by the producer.
156    pub fn tolerance(&self) -> f64 {
157        self.coordinate.tolerance
158    }
159
160    /// Return structural counts without encoding the artifact.
161    pub fn summary(&self) -> PersistentCoordinateArtifactSummary {
162        PersistentCoordinateArtifactSummary {
163            vertices: self.source().len(),
164            source_edges: self.source().num_edges(),
165            integral_terms: self.integral().len(),
166            potential_values: self.potential().len(),
167        }
168    }
169}