guppy/petgraph_support/
topo.rsuse petgraph::{
graph::IndexType,
prelude::*,
visit::{
GraphRef, IntoNeighborsDirected, IntoNodeIdentifiers, NodeCompactIndexable, VisitMap,
Visitable, Walker,
},
};
use std::marker::PhantomData;
#[derive(Clone, Debug)]
pub struct TopoWithCycles<Ix> {
reverse_index: Box<[usize]>,
_phantom: PhantomData<Ix>,
}
impl<Ix: IndexType> TopoWithCycles<Ix> {
pub fn new<G>(graph: G) -> Self
where
G: GraphRef
+ Visitable<NodeId = NodeIndex<Ix>>
+ IntoNodeIdentifiers
+ IntoNeighborsDirected<NodeId = NodeIndex<Ix>>
+ NodeCompactIndexable,
G::Map: VisitMap<NodeIndex<Ix>>,
{
let mut dfs = DfsPostOrder::empty(graph);
dfs.stack.extend(
graph
.node_identifiers()
.filter(move |&a| graph.neighbors_directed(a, Incoming).next().is_none()),
);
let mut topo: Vec<NodeIndex<Ix>> = dfs.iter(graph).collect();
topo.reverse();
let mut reverse_index = vec![0; topo.len()];
topo.iter().enumerate().for_each(|(topo_ix, node_ix)| {
reverse_index[node_ix.index()] = topo_ix;
});
Self {
reverse_index: reverse_index.into_boxed_slice(),
_phantom: PhantomData,
}
}
#[inline]
pub fn sort_nodes(&self, nodes: &mut [NodeIndex<Ix>]) {
nodes.sort_unstable_by_key(|node_ix| self.topo_ix(*node_ix))
}
#[inline]
pub fn topo_ix(&self, node_ix: NodeIndex<Ix>) -> usize {
self.reverse_index[node_ix.index()]
}
}