use super::*;
pub trait DiGraphProperties<'a>: GraphBasics<'a> {
fn in_edges(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<HashSet<<Self as GraphBasics<'a>>::EdgeIndex>>;
fn in_edge_count(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<usize>;
fn out_edges(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<HashSet<<Self as GraphBasics<'a>>::EdgeIndex>>;
fn out_edge_count(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<usize>;
fn in_neighbours(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<HashSet<<Self as GraphBasics<'a>>::NodeIndex>>;
fn out_neighbours(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<HashSet<<Self as GraphBasics<'a>>::NodeIndex>>;
fn in_neighbour_count(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<usize>;
fn out_neighbour_count(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<usize>;
fn strongly_connected_components(&'a self) -> Vec<Vec<usize>>;
fn is_strongly_connected(&'a self) -> bool {
self.strongly_connected_components().len() == 1
}
fn strong_component(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<Vec<usize>>;
fn extract_strong_component(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<Self::Subgraph>;
fn condense(&'a self) -> DiGraph<(), ()>;
fn condense_with<F1, F2, N, E>(&'a self, node_collate: F1, edge_collate: F2) -> DiGraph<N, E>
where
F1: Fn(&[<Self as GraphBasics<'_>>::NodeRef]) -> N,
F2: Fn(&[<Self as GraphBasics<'_>>::EdgeRef]) -> E,
N: Clone + Eq + Hash,
E: Clone + Eq + Hash,
{
let sccs = self.strongly_connected_components();
let mut dag = DiGraph::new();
dag.add_nodes(sccs.iter().map(|c| {
node_collate(
c.iter()
.map(|i| self.node((*i).into()).unwrap())
.collect::<Vec<_>>()
.as_slice(),
)
}));
for ((u_index, u), (v_index, v)) in sccs.iter().enumerate().tuple_combinations() {
let mut fwd = HashSet::new();
let mut rev = HashSet::new();
u.iter().cartesian_product(v.iter()).for_each(|(i, j)| {
let (f, r) = self.edges_connecting((*i).into(), (*j).into()).unwrap();
fwd.extend(f);
rev.extend(r);
});
if !fwd.is_empty() {
dag.add_edge(
edge_collate(
&self
.edge_iter(fwd.into_iter())
.filter_map(|x| x)
.collect::<Vec<_>>(),
),
[u_index],
[v_index],
)
.unwrap();
}
if !rev.is_empty() {
dag.add_edge(
edge_collate(
&self
.edge_iter(rev.into_iter())
.filter_map(|x| x)
.collect::<Vec<_>>(),
),
[v_index],
[u_index],
)
.unwrap();
}
}
dag
}
fn weakly_connected_components(&'a self) -> Vec<Vec<usize>>;
fn is_weakly_connected(&'a self) -> bool {
self.weakly_connected_components().len() == 1
}
fn weak_component(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<Vec<usize>>;
fn extract_weak_component(
&'a self,
node_index: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<Self::Subgraph>;
fn in_degree(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<usize>;
fn out_degree(&'a self, node_index: <Self as GraphBasics<'a>>::NodeIndex) -> Option<usize>;
fn in_degree_sequence(&'a self) -> Vec<usize> {
(0..self.node_count())
.map(|n| self.in_edge_count(n.into()).unwrap())
.collect()
}
fn out_degree_sequence(&'a self) -> Vec<usize> {
(0..self.node_count())
.map(|n| self.out_edge_count(n.into()).unwrap())
.collect()
}
type Subgraph;
fn source(
&'a self,
edge_index: <Self as GraphBasics<'a>>::EdgeIndex,
) -> Option<HashSet<<Self as GraphBasics<'a>>::NodeIndex>>;
fn target(
&'a self,
edge_index: <Self as GraphBasics<'a>>::EdgeIndex,
) -> Option<HashSet<<Self as GraphBasics<'a>>::NodeIndex>>;
fn edges_connecting(
&'a self,
a: <Self as GraphBasics<'a>>::NodeIndex,
b: <Self as GraphBasics<'a>>::NodeIndex,
) -> Option<(
Vec<<Self as GraphBasics<'a>>::EdgeIndex>,
Vec<<Self as GraphBasics<'a>>::EdgeIndex>,
)> {
let aset = self.out_edges(a)?;
let bset = self.in_edges(b)?;
let out1 = aset.intersection(&bset).map(|e| *e).collect::<Vec<_>>();
let aset = self.in_edges(a)?;
let bset = self.out_edges(b)?;
let out2 = aset.intersection(&bset).map(|e| *e).collect::<Vec<_>>();
let out = (out1, out2);
Some(out)
}
}
pub trait DirectedHypergraphProperties<'a, N, E>:
DiGraphProperties<'a> + HypergraphBasics<'a>
{
fn in_order(&'a self, edge_index: <Self as GraphBasics<'a>>::EdgeIndex) -> Option<usize>;
fn out_order(&'a self, edge_index: <Self as GraphBasics<'a>>::EdgeIndex) -> Option<usize>;
fn in_order_sequence(&'a self) -> Vec<usize> {
(0..self.edge_count())
.map(|e| self.in_order(e.into()).unwrap())
.collect()
}
fn out_order_sequence(&'a self) -> Vec<usize> {
(0..self.edge_count())
.map(|e| self.out_order(e.into()).unwrap())
.collect()
}
fn in_rank(&'a self) -> usize {
(0..self.edge_count())
.map(|e| self.in_order(e.into()).unwrap())
.max()
.unwrap_or(0)
}
fn out_rank(&'a self) -> usize {
(0..self.edge_count())
.map(|e| self.out_order(e.into()).unwrap())
.max()
.unwrap_or(0)
}
fn digraph_view(&'a self) -> DiGraph<&'a N, &'a E>;
fn edges_mapping(
&'a self,
a: &[<Self as GraphBasics<'a>>::NodeIndex],
b: &[<Self as GraphBasics<'a>>::NodeIndex],
) -> Option<Vec<<Self as GraphBasics<'a>>::EdgeIndex>> {
if a.is_empty() || b.is_empty() {
return Some(Vec::new());
}
let mut wset = self.out_edges(a[0])?;
for &node_index in &a[1..] {
let eset = self.out_edges(node_index)?;
wset.retain(|x| eset.contains(x));
}
for &node_index in b {
let eset = self.in_edges(node_index)?;
wset.retain(|x| eset.contains(x));
}
Some(wset.into_iter().collect())
}
}