1use super::*;
2use crate::simplex_overlap::simplex_interior_overlap;
3use crate::{
4 ambient_space::common_space,
5 convex_hull::ConvexHull,
6 partial_simplicial_complex::{LabelledPartialSimplicialComplex, PartialSimplicialComplex},
7 simplex::Simplex,
8 simplex_collection::{InteriorOrBoundarySimplexCollection, LabelledSimplexCollection},
9 simplicial_complex::{LabelledSimplicialComplex, SimplicialComplex},
10 simplicial_disjoint_union::{LabelledSimplicialDisjointUnion, SimplicialDisjointUnion},
11};
12use rayon::iter::{IntoParallelIterator, ParallelIterator};
13use std::collections::{HashMap, HashSet};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16enum VennLabel {
17 Left,
18 Middle,
19 Right,
20}
21
22fn simplex_venn<'f, FS: OrderedRingSignature + FieldSignature>(
23 left_simplex: &Simplex<'f, FS>,
24 right_simplex: &Simplex<'f, FS>,
25) -> LabelledPartialSimplicialComplex<'f, FS, VennLabel>
26where
27 FS::Set: Hash,
28{
29 let ambient_space =
30 common_space(left_simplex.ambient_space(), right_simplex.ambient_space()).unwrap();
31
32 if !simplex_interior_overlap(left_simplex, right_simplex) {
34 return LabelledPartialSimplicialComplex::<'f, FS, VennLabel>::new_labelled_unchecked(
35 ambient_space,
36 HashMap::from([
37 (left_simplex.clone(), VennLabel::Left),
38 (right_simplex.clone(), VennLabel::Right),
39 ]),
40 );
41 }
42
43 let overlap = ConvexHull::intersect(
44 &ConvexHull::from_simplex(left_simplex.clone()),
45 &ConvexHull::from_simplex(right_simplex.clone()),
46 );
47
48 if overlap
50 .to_simplicial_complex()
51 .interior()
52 .simplexes()
53 .is_empty()
54 {
55 return LabelledPartialSimplicialComplex::<'f, FS, VennLabel>::new_labelled_unchecked(
56 ambient_space,
57 HashMap::from([
58 (left_simplex.clone(), VennLabel::Left),
59 (right_simplex.clone(), VennLabel::Right),
60 ]),
61 );
62 }
63
64 let mut self_ext = overlap.clone();
65 for pt in left_simplex.points() {
66 self_ext.extend_by_point(pt.clone());
67 }
68 let self_parts = self_ext.to_simplicial_complex().interior().into_simplexes();
69
70 let mut other_ext = overlap.clone();
71 for pt in right_simplex.points() {
72 other_ext.extend_by_point(pt.clone());
73 }
74 let other_parts = other_ext
75 .to_simplicial_complex()
76 .interior()
77 .into_simplexes();
78
79 let all_parts = self_parts.union(&other_parts);
80 LabelledPartialSimplicialComplex::<'f, FS, VennLabel>::new_labelled_unchecked(
81 ambient_space,
82 all_parts
83 .into_iter()
84 .map(|spx| {
85 let label = match (self_parts.contains(spx), other_parts.contains(spx)) {
86 (true, false) => VennLabel::Left,
87 (true, true) => VennLabel::Middle,
88 (false, true) => VennLabel::Right,
89 (false, false) => {
90 unreachable!()
91 }
92 };
93 (spx.clone(), label)
94 })
95 .collect(),
96 )
97}
98
99impl<'f, FS: OrderedRingSignature + FieldSignature, T: Eq + Clone + Send + Sync>
100 LabelledSimplicialDisjointUnion<'f, FS, T>
101where
102 FS::Set: Hash,
103{
104 pub(crate) fn subtract_raw<S: Eq + Clone + Send + Sync>(
105 &self,
106 other: &LabelledSimplicialDisjointUnion<'f, FS, S>,
107 ) -> LabelledSimplicialDisjointUnion<'f, FS, T> {
108 let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
109
110 Self::new_labelled_unchecked(
111 ambient_space,
112 self.labelled_simplexes()
113 .into_iter()
114 .collect::<Vec<_>>()
115 .into_par_iter()
116 .map(|(self_spx, self_spx_label)| {
117 let mut self_leftover = HashSet::from([self_spx.clone()]);
118 for other_spx in other.simplexes() {
119 self_leftover = self_leftover
120 .into_iter()
121 .flat_map(|self_leftover_spx| {
122 simplex_venn(&self_leftover_spx, other_spx)
123 .subset_by_label(&VennLabel::Left)
124 .into_simplexes()
125 })
126 .collect();
127 }
128 self_leftover
129 .into_iter()
130 .map(|spx| (spx, self_spx_label.clone()))
131 .collect::<Vec<_>>()
132 })
133 .flatten()
134 .collect(),
135 )
136 }
137
138 pub(crate) fn intersect_raw<S: Eq + Clone + Send + Sync>(
139 &self,
140 other: &LabelledSimplicialDisjointUnion<'f, FS, S>,
141 ) -> LabelledSimplicialDisjointUnion<'f, FS, (T, S)> {
142 let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
143 LabelledSimplicialDisjointUnion::new_labelled_unchecked(ambient_space, {
144 let mut simplexes = HashMap::new();
145 for (self_spx, self_spx_label) in self.labelled_simplexes() {
146 for (other_spx, other_spx_label) in other.labelled_simplexes() {
147 for spx in simplex_venn(self_spx, other_spx)
148 .subset_by_label(&VennLabel::Middle)
149 .into_simplexes()
150 {
151 simplexes.insert(spx, (self_spx_label.clone(), other_spx_label.clone()));
152 }
153 }
154 }
155 simplexes
156 })
157 }
158
159 pub(crate) fn union_raw(&self, other: &Self) -> SimplicialDisjointUnion<'f, FS> {
160 let ambient_space = common_space(self.ambient_space(), other.ambient_space()).unwrap();
161 let mut simplexes = HashSet::new();
162 for spx in Self::subtract_raw(other, self).into_simplexes() {
163 simplexes.insert(spx);
164 }
165 for spx in self.simplexes() {
166 simplexes.insert(spx.clone());
167 }
168 Self::new_unchecked(ambient_space, simplexes)
169 }
170}
171
172pub trait Difference<Other> {
173 type Output;
174 fn difference(&self, other: &Other) -> Self::Output;
175}
176
177pub trait Intersect<Other> {
178 type Output;
179 fn intersect(&self, other: &Other) -> Self::Output;
180}
181
182pub trait Union<Other> {
183 type Output;
184 fn union(&self, other: &Other) -> Self::Output;
185}
186
187impl<
188 'f,
189 FS: OrderedRingSignature + FieldSignature,
190 T: Eq + Clone + Send + Sync,
191 S: Eq + Clone + Send + Sync,
192> Difference<LabelledSimplicialDisjointUnion<'f, FS, S>>
193 for LabelledSimplicialDisjointUnion<'f, FS, T>
194where
195 FS::Set: Hash,
196{
197 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
198
199 fn difference(&self, other: &LabelledSimplicialDisjointUnion<'f, FS, S>) -> Self::Output {
200 self.subtract_raw(other)
201 .refine_into_partial_simplicial_complex()
202 .simplify()
203 }
204}
205
206impl<
207 'f,
208 FS: OrderedRingSignature + FieldSignature,
209 T: Eq + Clone + Send + Sync,
210 S: Eq + Clone + Send + Sync,
211> Difference<LabelledPartialSimplicialComplex<'f, FS, S>>
212 for LabelledSimplicialDisjointUnion<'f, FS, T>
213where
214 FS::Set: Hash,
215{
216 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
217
218 fn difference(&self, other: &LabelledPartialSimplicialComplex<'f, FS, S>) -> Self::Output {
219 self.difference(&other.clone().into_simplicial_disjoint_union())
220 }
221}
222
223impl<
224 'f,
225 FS: OrderedRingSignature + FieldSignature,
226 T: Eq + Clone + Send + Sync,
227 S: Eq + Clone + Send + Sync,
228> Difference<LabelledSimplicialDisjointUnion<'f, FS, S>>
229 for LabelledPartialSimplicialComplex<'f, FS, T>
230where
231 FS::Set: Hash,
232{
233 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
234
235 fn difference(&self, other: &LabelledSimplicialDisjointUnion<'f, FS, S>) -> Self::Output {
236 self.clone()
237 .into_simplicial_disjoint_union()
238 .difference(other)
239 }
240}
241
242impl<
243 'f,
244 FS: OrderedRingSignature + FieldSignature,
245 T: Eq + Clone + Send + Sync,
246 S: Eq + Clone + Send + Sync,
247> Difference<LabelledPartialSimplicialComplex<'f, FS, S>>
248 for LabelledPartialSimplicialComplex<'f, FS, T>
249where
250 FS::Set: Hash,
251{
252 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
253
254 fn difference(&self, other: &LabelledPartialSimplicialComplex<'f, FS, S>) -> Self::Output {
255 self.clone()
256 .into_simplicial_disjoint_union()
257 .difference(&other.clone().into_simplicial_disjoint_union())
258 }
259}
260
261impl<
262 'f,
263 FS: OrderedRingSignature + FieldSignature,
264 T: Eq + Clone + Send + Sync,
265 S: Eq + Clone + Send + Sync,
266> Difference<LabelledSimplicialComplex<'f, FS, S>> for LabelledSimplicialDisjointUnion<'f, FS, T>
267where
268 FS::Set: Hash,
269{
270 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
271
272 fn difference(&self, other: &LabelledSimplicialComplex<'f, FS, S>) -> Self::Output {
273 self.difference(&other.clone().into_simplicial_disjoint_union())
274 }
275}
276
277impl<
278 'f,
279 FS: OrderedRingSignature + FieldSignature,
280 T: Eq + Clone + Send + Sync,
281 S: Eq + Clone + Send + Sync,
282> Difference<LabelledSimplicialComplex<'f, FS, S>> for LabelledPartialSimplicialComplex<'f, FS, T>
283where
284 FS::Set: Hash,
285{
286 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
287
288 fn difference(&self, other: &LabelledSimplicialComplex<'f, FS, S>) -> Self::Output {
289 self.clone()
290 .into_simplicial_disjoint_union()
291 .difference(&other.clone().into_simplicial_disjoint_union())
292 }
293}
294
295impl<
296 'f,
297 FS: OrderedRingSignature + FieldSignature,
298 T: Eq + Clone + Send + Sync,
299 S: Eq + Clone + Send + Sync,
300> Difference<LabelledSimplicialDisjointUnion<'f, FS, S>> for LabelledSimplicialComplex<'f, FS, T>
301where
302 FS::Set: Hash,
303{
304 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
305
306 fn difference(&self, other: &LabelledSimplicialDisjointUnion<'f, FS, S>) -> Self::Output {
307 self.clone()
308 .into_simplicial_disjoint_union()
309 .difference(other)
310 }
311}
312
313impl<
314 'f,
315 FS: OrderedRingSignature + FieldSignature,
316 T: Eq + Clone + Send + Sync,
317 S: Eq + Clone + Send + Sync,
318> Difference<LabelledPartialSimplicialComplex<'f, FS, S>> for LabelledSimplicialComplex<'f, FS, T>
319where
320 FS::Set: Hash,
321{
322 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
323
324 fn difference(&self, other: &LabelledPartialSimplicialComplex<'f, FS, S>) -> Self::Output {
325 self.clone()
326 .into_simplicial_disjoint_union()
327 .difference(&other.clone().into_simplicial_disjoint_union())
328 }
329}
330
331impl<
332 'f,
333 FS: OrderedRingSignature + FieldSignature,
334 T: Eq + Clone + Send + Sync,
335 S: Eq + Clone + Send + Sync,
336> Difference<LabelledSimplicialComplex<'f, FS, S>> for LabelledSimplicialComplex<'f, FS, T>
337where
338 FS::Set: Hash,
339{
340 type Output = LabelledPartialSimplicialComplex<'f, FS, T>;
341
342 fn difference(&self, other: &LabelledSimplicialComplex<'f, FS, S>) -> Self::Output {
343 self.clone()
344 .into_simplicial_disjoint_union()
345 .difference(&other.clone().into_simplicial_disjoint_union())
346 }
347}
348
349impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<SimplicialDisjointUnion<'f, FS>>
350 for SimplicialDisjointUnion<'f, FS>
351where
352 FS::Set: Hash,
353{
354 type Output = PartialSimplicialComplex<'f, FS>;
355
356 fn intersect(&self, other: &SimplicialDisjointUnion<'f, FS>) -> Self::Output {
357 self.intersect_raw(other)
358 .forget_labels()
359 .refine_into_partial_simplicial_complex()
360 .simplify()
361 }
362}
363
364impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<PartialSimplicialComplex<'f, FS>>
365 for SimplicialDisjointUnion<'f, FS>
366where
367 FS::Set: Hash,
368{
369 type Output = PartialSimplicialComplex<'f, FS>;
370
371 fn intersect(&self, other: &PartialSimplicialComplex<'f, FS>) -> Self::Output {
372 self.intersect(&other.clone().into_simplicial_disjoint_union())
373 }
374}
375
376impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<SimplicialDisjointUnion<'f, FS>>
377 for PartialSimplicialComplex<'f, FS>
378where
379 FS::Set: Hash,
380{
381 type Output = PartialSimplicialComplex<'f, FS>;
382
383 fn intersect(&self, other: &SimplicialDisjointUnion<'f, FS>) -> Self::Output {
384 self.clone()
385 .into_simplicial_disjoint_union()
386 .intersect(other)
387 }
388}
389
390impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<PartialSimplicialComplex<'f, FS>>
391 for PartialSimplicialComplex<'f, FS>
392where
393 FS::Set: Hash,
394{
395 type Output = PartialSimplicialComplex<'f, FS>;
396
397 fn intersect(&self, other: &PartialSimplicialComplex<'f, FS>) -> Self::Output {
398 self.clone()
399 .into_simplicial_disjoint_union()
400 .intersect(&other.clone().into_simplicial_disjoint_union())
401 }
402}
403
404impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<SimplicialDisjointUnion<'f, FS>>
405 for SimplicialComplex<'f, FS>
406where
407 FS::Set: Hash,
408{
409 type Output = PartialSimplicialComplex<'f, FS>;
410
411 fn intersect(&self, other: &SimplicialDisjointUnion<'f, FS>) -> Self::Output {
412 self.clone()
413 .into_simplicial_disjoint_union()
414 .intersect(other)
415 }
416}
417
418impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<PartialSimplicialComplex<'f, FS>>
419 for SimplicialComplex<'f, FS>
420where
421 FS::Set: Hash,
422{
423 type Output = PartialSimplicialComplex<'f, FS>;
424
425 fn intersect(&self, other: &PartialSimplicialComplex<'f, FS>) -> Self::Output {
426 self.clone()
427 .into_simplicial_disjoint_union()
428 .intersect(&other.clone().into_simplicial_disjoint_union())
429 }
430}
431
432impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<SimplicialComplex<'f, FS>>
433 for SimplicialDisjointUnion<'f, FS>
434where
435 FS::Set: Hash,
436{
437 type Output = PartialSimplicialComplex<'f, FS>;
438
439 fn intersect(&self, other: &SimplicialComplex<'f, FS>) -> Self::Output {
440 self.intersect(&other.clone().into_simplicial_disjoint_union())
441 }
442}
443
444impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<SimplicialComplex<'f, FS>>
445 for PartialSimplicialComplex<'f, FS>
446where
447 FS::Set: Hash,
448{
449 type Output = PartialSimplicialComplex<'f, FS>;
450
451 fn intersect(&self, other: &SimplicialComplex<'f, FS>) -> Self::Output {
452 self.clone()
453 .into_simplicial_disjoint_union()
454 .intersect(&other.clone().into_simplicial_disjoint_union())
455 }
456}
457
458impl<'f, FS: OrderedRingSignature + FieldSignature> Intersect<SimplicialComplex<'f, FS>>
459 for SimplicialComplex<'f, FS>
460where
461 FS::Set: Hash,
462{
463 type Output = SimplicialComplex<'f, FS>;
464
465 fn intersect(&self, other: &SimplicialComplex<'f, FS>) -> Self::Output {
466 self.clone()
467 .into_simplicial_disjoint_union()
468 .intersect(&other.clone().into_simplicial_disjoint_union())
469 .try_into_simplicial_complex()
470 .unwrap()
471 }
472}
473
474impl<'f, FS: OrderedRingSignature + FieldSignature> Union<SimplicialDisjointUnion<'f, FS>>
475 for SimplicialDisjointUnion<'f, FS>
476where
477 FS::Set: Hash,
478{
479 type Output = PartialSimplicialComplex<'f, FS>;
480
481 fn union(&self, other: &SimplicialDisjointUnion<'f, FS>) -> Self::Output {
482 self.union_raw(other)
483 .refine_into_partial_simplicial_complex()
484 .simplify()
485 }
486}
487
488impl<'f, FS: OrderedRingSignature + FieldSignature> Union<PartialSimplicialComplex<'f, FS>>
489 for SimplicialDisjointUnion<'f, FS>
490where
491 FS::Set: Hash,
492{
493 type Output = PartialSimplicialComplex<'f, FS>;
494
495 fn union(&self, other: &PartialSimplicialComplex<'f, FS>) -> Self::Output {
496 self.union(&other.clone().into_simplicial_disjoint_union())
497 }
498}
499
500impl<'f, FS: OrderedRingSignature + FieldSignature> Union<SimplicialDisjointUnion<'f, FS>>
501 for PartialSimplicialComplex<'f, FS>
502where
503 FS::Set: Hash,
504{
505 type Output = PartialSimplicialComplex<'f, FS>;
506
507 fn union(&self, other: &SimplicialDisjointUnion<'f, FS>) -> Self::Output {
508 self.clone().into_simplicial_disjoint_union().union(other)
509 }
510}
511
512impl<'f, FS: OrderedRingSignature + FieldSignature> Union<PartialSimplicialComplex<'f, FS>>
513 for PartialSimplicialComplex<'f, FS>
514where
515 FS::Set: Hash,
516{
517 type Output = PartialSimplicialComplex<'f, FS>;
518
519 fn union(&self, other: &PartialSimplicialComplex<'f, FS>) -> Self::Output {
520 self.clone()
521 .into_simplicial_disjoint_union()
522 .union(&other.clone().into_simplicial_disjoint_union())
523 }
524}
525
526impl<'f, FS: OrderedRingSignature + FieldSignature> Union<SimplicialDisjointUnion<'f, FS>>
527 for SimplicialComplex<'f, FS>
528where
529 FS::Set: Hash,
530{
531 type Output = PartialSimplicialComplex<'f, FS>;
532
533 fn union(&self, other: &SimplicialDisjointUnion<'f, FS>) -> Self::Output {
534 self.clone().into_simplicial_disjoint_union().union(other)
535 }
536}
537
538impl<'f, FS: OrderedRingSignature + FieldSignature> Union<PartialSimplicialComplex<'f, FS>>
539 for SimplicialComplex<'f, FS>
540where
541 FS::Set: Hash,
542{
543 type Output = PartialSimplicialComplex<'f, FS>;
544
545 fn union(&self, other: &PartialSimplicialComplex<'f, FS>) -> Self::Output {
546 self.clone()
547 .into_simplicial_disjoint_union()
548 .union(&other.clone().into_simplicial_disjoint_union())
549 }
550}
551
552impl<'f, FS: OrderedRingSignature + FieldSignature> Union<SimplicialComplex<'f, FS>>
553 for SimplicialDisjointUnion<'f, FS>
554where
555 FS::Set: Hash,
556{
557 type Output = PartialSimplicialComplex<'f, FS>;
558
559 fn union(&self, other: &SimplicialComplex<'f, FS>) -> Self::Output {
560 self.union(&other.clone().into_simplicial_disjoint_union())
561 }
562}
563
564impl<'f, FS: OrderedRingSignature + FieldSignature> Union<SimplicialComplex<'f, FS>>
565 for PartialSimplicialComplex<'f, FS>
566where
567 FS::Set: Hash,
568{
569 type Output = PartialSimplicialComplex<'f, FS>;
570
571 fn union(&self, other: &SimplicialComplex<'f, FS>) -> Self::Output {
572 self.clone()
573 .into_simplicial_disjoint_union()
574 .union(&other.clone().into_simplicial_disjoint_union())
575 }
576}
577
578impl<'f, FS: OrderedRingSignature + FieldSignature> Union<SimplicialComplex<'f, FS>>
579 for SimplicialComplex<'f, FS>
580where
581 FS::Set: Hash,
582{
583 type Output = SimplicialComplex<'f, FS>;
584
585 fn union(&self, other: &SimplicialComplex<'f, FS>) -> Self::Output {
586 self.clone()
587 .into_simplicial_disjoint_union()
588 .union(&other.clone().into_simplicial_disjoint_union())
589 .try_into_simplicial_complex()
590 .unwrap()
591 }
592}
593
594