use crate::mesh_error::MeshSieveError;
use crate::topology::sieve::strata::compute_strata;
use crate::topology::sieve::traversal_iter::{
ClosureBothIter, ClosureBothIterRef, ClosureIter, ClosureIterRef, StarIter, StarIterRef,
};
pub use crate::topology::cache::InvalidateCache;
pub trait Sieve: Default + InvalidateCache
where
Self::Point: Ord + std::fmt::Debug,
{
type Point: Copy + Eq + std::hash::Hash + Ord + std::fmt::Debug;
type Payload;
type ConeIter<'a>: Iterator<Item = (Self::Point, Self::Payload)>
where
Self: 'a;
type SupportIter<'a>: Iterator<Item = (Self::Point, Self::Payload)>
where
Self: 'a;
fn cone<'a>(&'a self, p: Self::Point) -> Self::ConeIter<'a>;
fn support<'a>(&'a self, p: Self::Point) -> Self::SupportIter<'a>;
fn add_arrow(&mut self, src: Self::Point, dst: Self::Point, payload: Self::Payload);
fn remove_arrow(&mut self, src: Self::Point, dst: Self::Point) -> Option<Self::Payload>;
fn base_points<'a>(&'a self) -> Box<dyn Iterator<Item = Self::Point> + 'a>;
fn cap_points<'a>(&'a self) -> Box<dyn Iterator<Item = Self::Point> + 'a>;
#[inline]
fn cone_points<'a>(&'a self, p: Self::Point) -> impl Iterator<Item = Self::Point> + 'a
where
Self: Sized,
{
self.cone(p).map(|(q, _)| q)
}
#[inline]
fn support_points<'a>(&'a self, p: Self::Point) -> impl Iterator<Item = Self::Point> + 'a
where
Self: Sized,
{
self.support(p).map(|(q, _)| q)
}
#[inline]
fn has_arrow(&self, src: Self::Point, dst: Self::Point) -> bool
where
Self: Sized,
{
self.cone_points(src).any(|q| q == dst)
}
fn points<'a>(&'a self) -> Box<dyn Iterator<Item = Self::Point> + 'a> {
use std::collections::HashSet;
let mut set = HashSet::new();
for p in self.base_points() {
set.insert(p);
}
for p in self.cap_points() {
set.insert(p);
}
Box::new(set.into_iter())
}
#[inline]
fn points_sorted(&self) -> Vec<Self::Point>
where
Self: Sized,
{
let mut v: Vec<_> = self.points().collect();
v.sort_unstable();
v
}
#[inline]
fn points_chart_order(&mut self) -> Result<Vec<Self::Point>, MeshSieveError>
where
Self: Sized,
{
self.chart_points()
}
fn closure_iter<'s, I>(&'s self, seeds: I) -> ClosureIter<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: Sized,
{
ClosureIter::new(self, seeds)
}
fn star_iter<'s, I>(&'s self, seeds: I) -> StarIter<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: Sized,
{
StarIter::new(self, seeds)
}
fn closure_both_iter<'s, I>(&'s self, seeds: I) -> ClosureBothIter<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: Sized,
{
ClosureBothIter::new(self, seeds)
}
fn closure<'s, I>(&'s self, seeds: I) -> Box<dyn Iterator<Item = Self::Point> + 's>
where
I: IntoIterator<Item = Self::Point>,
{
Box::new(self.closure_iter(seeds))
}
fn star<'s, I>(&'s self, seeds: I) -> Box<dyn Iterator<Item = Self::Point> + 's>
where
I: IntoIterator<Item = Self::Point>,
{
Box::new(self.star_iter(seeds))
}
fn closure_both<'s, I>(&'s self, seeds: I) -> Box<dyn Iterator<Item = Self::Point> + 's>
where
I: IntoIterator<Item = Self::Point>,
{
Box::new(self.closure_both_iter(seeds))
}
#[inline]
fn closure_iter_sorted<'s, I>(&'s self, seeds: I) -> ClosureIter<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: Sized,
{
ClosureIter::new_sorted(self, seeds)
}
#[inline]
fn star_iter_sorted<'s, I>(&'s self, seeds: I) -> StarIter<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: Sized,
{
StarIter::new_sorted(self, seeds)
}
#[inline]
fn closure_both_iter_sorted<'s, I>(&'s self, seeds: I) -> ClosureBothIter<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: Sized,
{
ClosureBothIter::new_sorted(self, seeds)
}
fn closure_sorted<'s, I>(&'s self, seeds: I) -> Box<dyn Iterator<Item = Self::Point> + 's>
where
I: IntoIterator<Item = Self::Point>,
{
Box::new(self.closure_iter_sorted(seeds))
}
fn star_sorted<'s, I>(&'s self, seeds: I) -> Box<dyn Iterator<Item = Self::Point> + 's>
where
I: IntoIterator<Item = Self::Point>,
{
Box::new(self.star_iter_sorted(seeds))
}
fn closure_both_sorted<'s, I>(&'s self, seeds: I) -> Box<dyn Iterator<Item = Self::Point> + 's>
where
I: IntoIterator<Item = Self::Point>,
{
Box::new(self.closure_both_iter_sorted(seeds))
}
#[inline]
fn closure_iter_ref<'s, I>(&'s self, seeds: I) -> ClosureIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
ClosureIterRef::new_ref(self, seeds)
}
#[inline]
fn star_iter_ref<'s, I>(&'s self, seeds: I) -> StarIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
StarIterRef::new_ref(self, seeds)
}
#[inline]
fn closure_both_iter_ref<'s, I>(&'s self, seeds: I) -> ClosureBothIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
ClosureBothIterRef::new_ref(self, seeds)
}
#[inline]
fn closure_iter_ref_sorted<'s, I>(&'s self, seeds: I) -> ClosureIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
ClosureIterRef::new_ref_sorted(self, seeds)
}
#[inline]
fn star_iter_ref_sorted<'s, I>(&'s self, seeds: I) -> StarIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
StarIterRef::new_ref_sorted(self, seeds)
}
#[inline]
fn closure_both_iter_ref_sorted<'s, I>(&'s self, seeds: I) -> ClosureBothIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
ClosureBothIterRef::new_ref_sorted(self, seeds)
}
#[inline]
fn closure_iter_ref_sorted_neighbors<'s, I>(&'s self, seeds: I) -> ClosureIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
ClosureIterRef::new_ref_sorted_neighbors(self, seeds)
}
#[inline]
fn star_iter_ref_sorted_neighbors<'s, I>(&'s self, seeds: I) -> StarIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
StarIterRef::new_ref_sorted_neighbors(self, seeds)
}
#[inline]
fn closure_both_iter_ref_sorted_neighbors<'s, I>(
&'s self,
seeds: I,
) -> ClosureBothIterRef<'s, Self>
where
I: IntoIterator<Item = Self::Point>,
Self: crate::topology::sieve::SieveRef + Sized,
{
ClosureBothIterRef::new_ref_sorted_neighbors(self, seeds)
}
fn meet<'s>(
&'s self,
a: Self::Point,
b: Self::Point,
) -> Box<dyn Iterator<Item = Self::Point> + 's>
where
Self::Point: Ord,
{
use std::collections::HashSet;
let mut ca: Vec<_> = self.closure(std::iter::once(a)).collect();
let mut cb: Vec<_> = self.closure(std::iter::once(b)).collect();
ca.sort_unstable();
cb.sort_unstable();
let mut cand: Vec<_> = ca
.into_iter()
.filter(|x| cb.binary_search(x).is_ok())
.collect();
cand.sort_unstable();
cand.dedup();
let cand_set: HashSet<_> = cand.iter().copied().collect();
let mut out: Vec<_> = cand
.into_iter()
.filter(|&x| {
let mut maximal = true;
for y in self.star(std::iter::once(x)) {
if y != x && cand_set.contains(&y) {
maximal = false; break;
}
}
maximal
})
.collect();
out.sort_unstable();
out.dedup();
Box::new(out.into_iter())
}
fn join<'s>(
&'s self,
a: Self::Point,
b: Self::Point,
) -> Box<dyn Iterator<Item = Self::Point> + 's>
where
Self::Point: Ord,
{
use std::collections::HashSet;
let mut sa: Vec<_> = self.star(std::iter::once(a)).collect();
let mut sb: Vec<_> = self.star(std::iter::once(b)).collect();
sa.sort_unstable();
sb.sort_unstable();
let mut cand: Vec<_> = sa
.into_iter()
.filter(|x| sb.binary_search(x).is_ok())
.collect();
cand.sort_unstable();
cand.dedup();
let cand_set: HashSet<_> = cand.iter().copied().collect();
let mut out: Vec<_> = cand
.into_iter()
.filter(|&x| {
let mut maximal = true;
for y in self.star(std::iter::once(x)) {
if y != x && cand_set.contains(&y) {
maximal = false; break;
}
}
maximal
})
.collect();
out.sort_unstable();
out.dedup();
Box::new(out.into_iter())
}
fn height(&mut self, p: Self::Point) -> Result<u32, MeshSieveError>
where
Self::Point: Ord,
Self: Sized,
{
let cache = compute_strata(&*self)?;
Ok(cache.height.get(&p).copied().unwrap_or(0))
}
fn depth(&mut self, p: Self::Point) -> Result<u32, MeshSieveError>
where
Self::Point: Ord,
Self: Sized,
{
let cache = compute_strata(&*self)?;
Ok(cache.depth.get(&p).copied().unwrap_or(0))
}
fn diameter(&mut self) -> Result<u32, MeshSieveError>
where
Self: Sized,
{
Ok(compute_strata(&*self)?.diameter)
}
fn height_stratum<'a>(
&'a mut self,
k: u32,
) -> Result<Box<dyn Iterator<Item = Self::Point> + 'a>, MeshSieveError>
where
Self: Sized,
{
let cache = compute_strata(&*self)?;
let items = cache.strata.get(k as usize).cloned().unwrap_or_default();
Ok(Box::new(items.into_iter()))
}
fn depth_stratum<'a>(
&'a mut self,
k: u32,
) -> Result<Box<dyn Iterator<Item = Self::Point> + 'a>, MeshSieveError>
where
Self::Point: Ord,
Self: Sized,
{
let cache = compute_strata(&*self)?;
let pts: Vec<_> = cache
.depth
.iter()
.filter_map(|(&p, &d)| if d == k { Some(p) } else { None })
.collect();
Ok(Box::new(pts.into_iter()))
}
fn chart_index(&mut self, p: Self::Point) -> Result<Option<usize>, MeshSieveError>
where
Self: Sized,
{
let cache = compute_strata(&*self)?;
Ok(cache.index_of(p))
}
fn chart_points(&mut self) -> Result<Vec<Self::Point>, MeshSieveError>
where
Self: Sized,
{
let cache = compute_strata(&*self)?;
Ok(cache.chart_points.clone())
}
fn add_point(&mut self, p: Self::Point)
where
Self: super::mutable::MutableSieve,
{
<Self as super::mutable::MutableSieve>::add_point(self, p)
}
fn remove_point(&mut self, p: Self::Point)
where
Self: super::mutable::MutableSieve,
{
<Self as super::mutable::MutableSieve>::remove_point(self, p)
}
fn add_base_point(&mut self, p: Self::Point)
where
Self: super::mutable::MutableSieve,
{
<Self as super::mutable::MutableSieve>::add_base_point(self, p)
}
fn add_cap_point(&mut self, p: Self::Point)
where
Self: super::mutable::MutableSieve,
{
<Self as super::mutable::MutableSieve>::add_cap_point(self, p)
}
fn remove_base_point(&mut self, p: Self::Point)
where
Self: super::mutable::MutableSieve,
{
<Self as super::mutable::MutableSieve>::remove_base_point(self, p)
}
fn remove_cap_point(&mut self, p: Self::Point)
where
Self: super::mutable::MutableSieve,
{
<Self as super::mutable::MutableSieve>::remove_cap_point(self, p)
}
fn set_cone(
&mut self,
p: Self::Point,
chain: impl IntoIterator<Item = (Self::Point, Self::Payload)>,
) where
Self: super::mutable::MutableSieve,
Self::Payload: Clone,
{
<Self as super::mutable::MutableSieve>::set_cone(self, p, chain)
}
fn add_cone(
&mut self,
p: Self::Point,
chain: impl IntoIterator<Item = (Self::Point, Self::Payload)>,
) where
Self: super::mutable::MutableSieve,
Self::Payload: Clone,
{
<Self as super::mutable::MutableSieve>::add_cone(self, p, chain)
}
fn set_support(
&mut self,
q: Self::Point,
chain: impl IntoIterator<Item = (Self::Point, Self::Payload)>,
) where
Self: super::mutable::MutableSieve,
Self::Payload: Clone,
{
<Self as super::mutable::MutableSieve>::set_support(self, q, chain)
}
fn add_support(
&mut self,
q: Self::Point,
chain: impl IntoIterator<Item = (Self::Point, Self::Payload)>,
) where
Self: super::mutable::MutableSieve,
Self::Payload: Clone,
{
<Self as super::mutable::MutableSieve>::add_support(self, q, chain)
}
fn reserve_cone(&mut self, p: Self::Point, additional: usize)
where
Self: super::mutable::MutableSieve,
{
<Self as super::mutable::MutableSieve>::reserve_cone(self, p, additional)
}
fn reserve_support(&mut self, q: Self::Point, additional: usize)
where
Self: super::mutable::MutableSieve,
{
<Self as super::mutable::MutableSieve>::reserve_support(self, q, additional)
}
fn restrict_base(&self, chain: impl IntoIterator<Item = Self::Point>) -> Self
where
Self: Sized + Default + super::mutable::MutableSieve,
Self::Payload: Clone,
{
use std::collections::HashMap;
let mut seeds: Vec<Self::Point> = Vec::new();
let mut out_counts: HashMap<Self::Point, usize> = HashMap::new();
let mut in_counts: HashMap<Self::Point, usize> = HashMap::new();
for p in chain {
seeds.push(p);
let mut deg = 0usize;
for (q, _) in self.cone(p) {
deg += 1;
*in_counts.entry(q).or_default() += 1;
}
if deg > 0 {
out_counts.insert(p, deg);
}
}
let mut out = Self::default();
for &p in &seeds {
Sieve::add_base_point(&mut out, p);
}
for &q in in_counts.keys() {
Sieve::add_cap_point(&mut out, q);
}
for (&p, &k) in &out_counts {
Sieve::reserve_cone(&mut out, p, k);
}
for (&q, &k) in &in_counts {
Sieve::reserve_support(&mut out, q, k);
}
for p in seeds {
for (q, pay) in self.cone(p) {
out.add_arrow(p, q, pay.clone());
}
}
out
}
fn restrict_cap(&self, chain: impl IntoIterator<Item = Self::Point>) -> Self
where
Self: Sized + Default + super::mutable::MutableSieve,
Self::Payload: Clone,
{
use std::collections::HashMap;
let mut seeds: Vec<Self::Point> = Vec::new();
let mut in_counts: HashMap<Self::Point, usize> = HashMap::new();
let mut out_counts: HashMap<Self::Point, usize> = HashMap::new();
for q in chain {
seeds.push(q);
let mut deg = 0usize;
for (p, _) in self.support(q) {
deg += 1;
*out_counts.entry(p).or_default() += 1;
}
if deg > 0 {
in_counts.insert(q, deg);
}
}
let mut out = Self::default();
for &q in &seeds {
Sieve::add_cap_point(&mut out, q);
}
for &p in out_counts.keys() {
Sieve::add_base_point(&mut out, p);
}
for (&q, &k) in &in_counts {
Sieve::reserve_support(&mut out, q, k);
}
for (&p, &k) in &out_counts {
Sieve::reserve_cone(&mut out, p, k);
}
for q in seeds {
for (p, pay) in self.support(q) {
out.add_arrow(p, q, pay.clone());
}
}
out
}
}