use crate::traits::{Directed, DirectedEdge, FiniteDigraph, FiniteGraph, GraphIterator, GraphType, Undirected};
pub struct FilteredGraph<'a, G, P>
where
G: GraphType<'a>,
P: for<'r> Fn(&'r G::Edge) -> bool,
{
graph: &'a G,
predicate: P,
}
#[derive(Clone)]
pub struct Filtered<I>(I);
impl<'a, G, P, I> GraphIterator<FilteredGraph<'a, G, P>> for Filtered<I>
where
G: GraphType<'a>,
P: for<'r> Fn(&'r G::Edge) -> bool,
I: GraphIterator<G, Item = (G::Edge, G::Node)>,
{
type Item = I::Item;
fn next(&mut self, g: &FilteredGraph<'a, G, P>) -> Option<Self::Item> {
while let Some((e, v)) = self.0.next(g.graph) {
if (g.predicate)(&e) {
return Some((e, v));
}
}
None
}
}
#[derive(Clone)]
pub struct FilteredIncidentIt<I>(I);
impl<'a, G, P, I> GraphIterator<FilteredGraph<'a, G, P>> for FilteredIncidentIt<I>
where
G: Directed<'a>,
P: for<'r> Fn(&'r G::Edge) -> bool,
I: GraphIterator<G, Item = (G::DirectedEdge, G::Node)>,
{
type Item = I::Item;
fn next(&mut self, g: &FilteredGraph<'a, G, P>) -> Option<Self::Item> {
while let Some((e, v)) = self.0.next(g.graph) {
if (g.predicate)(&e.edge()) {
return Some((e, v));
}
}
None
}
}
#[derive(Clone)]
pub struct FilterWrapIt<I>(I);
impl<'a, G, P, I> GraphIterator<FilteredGraph<'a, G, P>> for FilterWrapIt<I>
where
G: GraphType<'a>,
P: for<'r> Fn(&'r G::Edge) -> bool,
I: GraphIterator<G>,
{
type Item = I::Item;
fn next(&mut self, g: &FilteredGraph<'a, G, P>) -> Option<I::Item> {
self.0.next(g.graph)
}
fn size_hint(&self, g: &FilteredGraph<'a, G, P>) -> (usize, Option<usize>) {
self.0.size_hint(g.graph)
}
fn count(self, g: &FilteredGraph<'a, G, P>) -> usize {
self.0.count(g.graph)
}
}
#[derive(Clone)]
pub struct FilterEdgeIt<I>(I);
impl<'a, G, P> GraphIterator<FilteredGraph<'a, G, P>> for FilterEdgeIt<G::EdgeIt>
where
G: FiniteGraph<'a>,
P: for<'r> Fn(&'r G::Edge) -> bool,
{
type Item = G::Edge;
fn next(&mut self, g: &FilteredGraph<'a, G, P>) -> Option<G::Edge> {
while let Some(e) = self.0.next(g.graph) {
if (g.predicate)(&e) {
return Some(e);
}
}
None
}
}
pub struct FilterNeighIter<'a, I, P> {
it: I,
predicate: &'a P,
}
impl<'a, I, P, N, E> Iterator for FilterNeighIter<'a, I, P>
where
P: for<'r> Fn(&'r E) -> bool,
I: Iterator<Item = (E, N)>,
{
type Item = (E, N);
fn next(&mut self) -> Option<Self::Item> {
while let Some((e, v)) = self.it.next() {
if (self.predicate)(&e) {
return Some((e, v));
}
}
None
}
}
impl<'a, G, P> GraphType<'a> for FilteredGraph<'a, G, P>
where
G: GraphType<'a>,
P: 'a + for<'r> Fn(&'r G::Edge) -> bool,
{
type Node = G::Node;
type Edge = G::Edge;
}
impl<'a, G, P> FiniteGraph<'a> for FilteredGraph<'a, G, P>
where
G: FiniteGraph<'a>,
P: 'a + for<'r> Fn(&'r G::Edge) -> bool,
{
type NodeIt = FilterWrapIt<G::NodeIt>;
type EdgeIt = FilterEdgeIt<G::EdgeIt>;
fn num_nodes(&self) -> usize {
self.graph.num_nodes()
}
fn num_edges(&self) -> usize {
Iterator::count(self.graph.edges().filter(&self.predicate))
}
fn nodes_iter(&'a self) -> Self::NodeIt {
FilterWrapIt(self.graph.nodes_iter())
}
fn edges_iter(&self) -> Self::EdgeIt {
FilterEdgeIt(self.graph.edges_iter())
}
fn enodes(&'a self, e: Self::Edge) -> (Self::Node, Self::Node) {
debug_assert!((self.predicate)(&e), "Edge has been filtered");
self.graph.enodes(e)
}
}
impl<'a, G, P> FiniteDigraph<'a> for FilteredGraph<'a, G, P>
where
G: FiniteDigraph<'a>,
P: 'a + for<'r> Fn(&'r G::Edge) -> bool,
{
fn src(&'a self, e: Self::Edge) -> Self::Node {
debug_assert!((self.predicate)(&e), "Edge has been filtered");
self.graph.src(e)
}
fn snk(&'a self, e: Self::Edge) -> Self::Node {
debug_assert!((self.predicate)(&e), "Edge has been filtered");
self.graph.snk(e)
}
}
impl<'a, G, P> Undirected<'a> for FilteredGraph<'a, G, P>
where
G: Undirected<'a>,
P: 'a + for<'r> Fn(&'r G::Edge) -> bool,
{
type NeighIt = Filtered<G::NeighIt>;
fn neigh_iter(&'a self, u: Self::Node) -> Self::NeighIt {
Filtered(self.graph.neigh_iter(u))
}
}
impl<'a, G, P> Directed<'a> for FilteredGraph<'a, G, P>
where
G: Directed<'a>,
P: 'a + for<'r> Fn(&'r G::Edge) -> bool,
{
type OutIt = Filtered<G::OutIt>;
type InIt = Filtered<G::InIt>;
type IncidentIt = FilteredIncidentIt<G::IncidentIt>;
type DirectedEdge = G::DirectedEdge;
fn out_iter(&'a self, u: Self::Node) -> Self::OutIt {
Filtered(self.graph.out_iter(u))
}
fn in_iter(&'a self, u: Self::Node) -> Self::InIt {
Filtered(self.graph.in_iter(u))
}
fn incident_iter(&'a self, u: Self::Node) -> Self::IncidentIt {
FilteredIncidentIt(self.graph.incident_iter(u))
}
}
pub fn filter<'a, G, P>(graph: &'a G, predicate: P) -> FilteredGraph<'a, G, P>
where
G: GraphType<'a>,
P: for<'r> Fn(&'r G::Edge) -> bool,
{
FilteredGraph { graph, predicate }
}