filtration_domination/
simplicial_complex.rs

1use rustc_hash::FxHashMap;
2use sorted_iter::assume::AssumeSortedByItemExt;
3use sorted_iter::SortedIterator;
4use std::collections::hash_map::Entry;
5
6pub type Vertex = usize;
7pub type Dimension = usize;
8
9pub trait SimplicialComplex<'a> {
10    type BoundaryIterator: Iterator<Item = usize> + 'a;
11
12    type VertexIterator: Iterator<Item = Vertex>;
13
14    fn new(max_vertices: Vertex, max_dim: Dimension) -> Self;
15
16    fn max_dimension(&self) -> Dimension;
17
18    fn n_cells(&self, dim: Dimension) -> usize;
19
20    /// Add a simplex, given by a vector of vertices, to the simplicial complex.
21    /// The vector of vertices must be ordered, and the facets of the simplex must be already in the simplicial complex.
22    /// Returns an option, with no value if the simplex is already in the simplex,
23    /// and with the dimension and the index of its basis otherwise.
24    fn add(&mut self, s: &[Vertex]) -> Option<(Dimension, usize)>;
25
26    /// Add a simplex, given by a iterator that produces vertices, to the simplicial complex.
27    /// The iterator must produce ordered items.
28    /// The iterator must produce exactly dim + 1 items.
29    /// The boundaries of the simplex must have been added before.
30    fn add_iter<I: SortedIterator<Item = usize>>(
31        &mut self,
32        dim: Dimension,
33        iter: I,
34    ) -> Option<(Dimension, usize)>;
35
36    /// Returns an iterator over the boundary of the simplex of the given index.
37    /// The iterator returns the indexes of the simplexes in the boundary.
38    fn boundary_iterator(&'a self, dim: Dimension, idx: usize) -> Self::BoundaryIterator;
39
40    /// Returns an iterator over the boundary of the given simplex.
41    /// Unlike `boundary_iterator`, the simplex may not be in the simplicial complex,
42    /// but it faces must be.
43    fn simplex_boundary<I: SortedIterator<Item = usize>>(
44        &'a self,
45        dim: Dimension,
46        simplex_iter: I,
47    ) -> Self::BoundaryIterator;
48
49    /// Returns an iterator over the vertices of the simplex of the given index.
50    fn simplex_vertices(&self, dim: Dimension, idx: usize) -> Self::VertexIterator;
51}
52
53/// A SimplexKey encodes a simplex as a non-negative integer.
54type SimplexKey = usize;
55
56#[derive(Default, Debug)]
57pub struct MapSimplicialComplex {
58    /// Associates a simplex id to its key.
59    /// The ith-element of the vector contains the simplices of the dimension i.
60    simplices_by_dim: Vec<Vec<SimplexKey>>,
61
62    /// Associates a simplex key to its index in the vector of its dimension in simplices_by_dim.
63    key_to_idx: Vec<FxHashMap<SimplexKey, usize>>,
64
65    /// Maximum number of vertices.
66    max_n: Vertex,
67}
68
69impl MapSimplicialComplex {
70    pub fn new(max_vertices: Vertex, max_dim: Dimension) -> Self {
71        let mut s = MapSimplicialComplex {
72            max_n: max_vertices,
73            ..Default::default()
74        };
75        s.simplices_by_dim.resize(max_dim + 1, Default::default());
76        s.key_to_idx.resize(max_dim + 1, Default::default());
77        s
78    }
79
80    /// Get the simplex key from a stream of vertices.
81    fn simplex_to_key<I: SortedIterator<Item = usize>>(&self, iter: I) -> SimplexKey {
82        let mut k: SimplexKey = 0;
83        let mut exp: SimplexKey = 1;
84        for v in iter {
85            k += v * exp;
86            exp *= self.max_n;
87        }
88        k
89    }
90
91    fn add_simplex_key_check_boundaries(
92        &mut self,
93        dim: Dimension,
94        key: SimplexKey,
95    ) -> Option<(Dimension, usize)> {
96        if dim > 0 {
97            let it = SimplexKeyBoundaryIterator::new(self.max_n, dim, key);
98
99            for facet_key in it {
100                assert!(
101                    self.has_simplex_key(dim - 1, &facet_key),
102                    "Adding a simplex requires that its boundaries have been added before."
103                )
104            }
105        }
106        self.add_simplex_key(dim, key)
107    }
108
109    fn add_simplex_key(&mut self, dim: Dimension, key: SimplexKey) -> Option<(Dimension, usize)> {
110        match self.key_to_idx[dim].entry(key) {
111            Entry::Occupied(_) => None,
112            Entry::Vacant(entry) => {
113                if dim == 0 {
114                    assert!(
115                        self.simplices_by_dim[0].len() < self.max_n,
116                        "Exceeded the maximum number of vertices."
117                    );
118                }
119                let idx = self.simplices_by_dim[dim].len();
120
121                self.simplices_by_dim[dim].push(key);
122                entry.insert(idx);
123
124                Some((dim, idx))
125            }
126        }
127    }
128
129    fn has_simplex_key(&self, dim: Dimension, k: &SimplexKey) -> bool {
130        self.key_to_idx[dim].contains_key(k)
131    }
132}
133
134impl<'a> SimplicialComplex<'a> for MapSimplicialComplex {
135    type BoundaryIterator = MapBoundaryIterator<'a>;
136    type VertexIterator = SimplexKeyVertexIterator;
137
138    fn new(max_n: Vertex, max_dim: Dimension) -> Self {
139        Self::new(max_n, max_dim)
140    }
141
142    fn max_dimension(&self) -> Dimension {
143        self.simplices_by_dim.len() - 1
144    }
145
146    fn n_cells(&self, dim: Dimension) -> usize {
147        self.simplices_by_dim[dim].len()
148    }
149
150    fn add(&mut self, s: &[Vertex]) -> Option<(Dimension, usize)> {
151        assert!(is_sorted(s), "To add a simplex it must be sorted first.");
152
153        let dim = s.len() - 1;
154        let k = self.simplex_to_key(s.iter().copied().assume_sorted_by_item());
155
156        self.add_simplex_key_check_boundaries(dim, k)
157    }
158
159    fn add_iter<I: SortedIterator<Item = usize>>(
160        &mut self,
161        dim: Dimension,
162        iter: I,
163    ) -> Option<(Dimension, usize)> {
164        let key = self.simplex_to_key(iter);
165        self.add_simplex_key_check_boundaries(dim, key)
166    }
167
168    fn boundary_iterator(&'a self, dim: Dimension, idx: usize) -> Self::BoundaryIterator {
169        MapBoundaryIterator::new(self, dim, self.simplices_by_dim[dim][idx])
170    }
171
172    fn simplex_boundary<I: SortedIterator<Item = usize>>(
173        &'a self,
174        dim: Dimension,
175        simplex_iter: I,
176    ) -> Self::BoundaryIterator {
177        MapBoundaryIterator::new(self, dim, self.simplex_to_key(simplex_iter))
178    }
179
180    fn simplex_vertices(&self, dim: Dimension, idx: usize) -> Self::VertexIterator {
181        SimplexKeyVertexIterator::new(dim, self.simplices_by_dim[dim][idx], self.max_n)
182    }
183}
184
185pub struct MapBoundaryIterator<'a> {
186    complex: &'a MapSimplicialComplex,
187
188    simplex_key_iterator: SimplexKeyBoundaryIterator,
189}
190
191impl MapBoundaryIterator<'_> {
192    fn new(
193        complex: &'_ MapSimplicialComplex,
194        dimension: Dimension,
195        key: SimplexKey,
196    ) -> MapBoundaryIterator<'_> {
197        MapBoundaryIterator {
198            complex,
199            simplex_key_iterator: SimplexKeyBoundaryIterator::new(complex.max_n, dimension, key),
200        }
201    }
202}
203
204impl Iterator for MapBoundaryIterator<'_> {
205    type Item = usize;
206
207    fn next(&mut self) -> Option<Self::Item> {
208        if self.simplex_key_iterator.dimension == 0 {
209            return None;
210        }
211
212        let next_key = self.simplex_key_iterator.next();
213        if let Some(key) = next_key {
214            let facet_dimension = self.simplex_key_iterator.dimension - 1;
215            Some(self.complex.key_to_idx[facet_dimension][&key])
216        } else {
217            None
218        }
219    }
220}
221
222struct SimplexKeyBoundaryIterator {
223    dimension: Dimension,
224    max_n: Vertex,
225    iteration: Dimension,
226    current_power: Vertex,
227    left_to_process: SimplexKey,
228    processed: SimplexKey,
229}
230
231impl SimplexKeyBoundaryIterator {
232    fn new(max_n: Vertex, dimension: Dimension, key: SimplexKey) -> SimplexKeyBoundaryIterator {
233        SimplexKeyBoundaryIterator {
234            max_n,
235            dimension,
236            iteration: 0,
237            left_to_process: key,
238            processed: 0,
239            current_power: 1,
240        }
241    }
242}
243
244impl Iterator for SimplexKeyBoundaryIterator {
245    type Item = SimplexKey;
246
247    fn next(&mut self) -> Option<Self::Item> {
248        if self.iteration == self.dimension + 1 {
249            return None;
250        }
251        let next_power = self.current_power * self.max_n;
252        let removed_v = self.left_to_process % self.max_n;
253
254        self.left_to_process /= self.max_n;
255        let face = self.left_to_process * self.current_power + self.processed;
256
257        self.processed += removed_v * self.current_power;
258
259        self.current_power = next_power;
260        self.iteration += 1;
261        Some(face)
262    }
263}
264
265pub struct SimplexKeyVertexIterator {
266    key: usize,
267    vertices_left: usize,
268    modulo: usize,
269}
270
271impl SimplexKeyVertexIterator {
272    fn new(dim: usize, key: usize, modulo: usize) -> SimplexKeyVertexIterator {
273        SimplexKeyVertexIterator {
274            key,
275            vertices_left: dim + 1,
276            modulo,
277        }
278    }
279}
280
281impl Iterator for SimplexKeyVertexIterator {
282    type Item = Vertex;
283
284    fn next(&mut self) -> Option<Self::Item> {
285        if self.vertices_left == 0 {
286            return None;
287        }
288        let v = self.key % self.modulo;
289        self.key /= self.modulo;
290        self.vertices_left -= 1;
291        Some(v)
292    }
293}
294
295pub(crate) fn is_sorted<T: Ord>(data: &[T]) -> bool {
296    data.windows(2).all(|w| w[0] <= w[1])
297}
298
299#[cfg(test)]
300mod tests {
301    use crate::simplicial_complex::MapSimplicialComplex;
302    use crate::simplicial_complex::SimplicialComplex;
303
304    #[test]
305    fn simplex_add_one_by_one() {
306        let mut s = MapSimplicialComplex::new(10, 10);
307        s.add(&[0usize]);
308        s.add(&[1usize]);
309        s.add(&[2usize]);
310        s.add(&[0usize, 1usize]);
311        s.add(&[1usize, 2usize]);
312        s.add(&[0usize, 2usize]);
313        s.add(&[0usize, 1usize, 2usize]);
314        // No errors should have been raised.
315    }
316
317    #[test]
318    fn boundary_iterator_happy_case() {
319        let mut s = MapSimplicialComplex::new(10, 10);
320        s.add(&[0usize]);
321        s.add(&[1usize]);
322        s.add(&[2usize]);
323        s.add(&[0usize, 1usize]);
324        s.add(&[1usize, 2usize]);
325        s.add(&[0usize, 2usize]);
326        let (dim, idx) = s.add(&[0usize, 1usize, 2usize]).unwrap();
327        let it = s.boundary_iterator(dim, idx);
328        let result: Vec<_> = it.collect();
329        assert_eq!(vec![1, 2, 0], result);
330    }
331
332    #[test]
333    fn vertices_iterator_happy_case() {
334        let mut s = MapSimplicialComplex::new(10, 10);
335        s.add(&[0usize]);
336        s.add(&[1usize]);
337        s.add(&[2usize]);
338        s.add(&[0usize, 1usize]);
339        s.add(&[1usize, 2usize]);
340        s.add(&[0usize, 2usize]);
341        let (dim, idx) = s.add(&[0usize, 1usize, 2usize]).unwrap();
342        let vertices: Vec<usize> = s.simplex_vertices(dim, idx).collect();
343        assert_eq!(vertices, [0, 1, 2]);
344    }
345}