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 fn add(&mut self, s: &[Vertex]) -> Option<(Dimension, usize)>;
25
26 fn add_iter<I: SortedIterator<Item = usize>>(
31 &mut self,
32 dim: Dimension,
33 iter: I,
34 ) -> Option<(Dimension, usize)>;
35
36 fn boundary_iterator(&'a self, dim: Dimension, idx: usize) -> Self::BoundaryIterator;
39
40 fn simplex_boundary<I: SortedIterator<Item = usize>>(
44 &'a self,
45 dim: Dimension,
46 simplex_iter: I,
47 ) -> Self::BoundaryIterator;
48
49 fn simplex_vertices(&self, dim: Dimension, idx: usize) -> Self::VertexIterator;
51}
52
53type SimplexKey = usize;
55
56#[derive(Default, Debug)]
57pub struct MapSimplicialComplex {
58 simplices_by_dim: Vec<Vec<SimplexKey>>,
61
62 key_to_idx: Vec<FxHashMap<SimplexKey, usize>>,
64
65 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 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 }
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}