wolf_graph/algo/
topological_sort.rs1use std::marker::PhantomData;
2
3use anyhow::Result;
4
5use crate::{DFSVisitor, DepthFirstSearch, EdgeID, Error, NodeID, Nodes, VisitableGraph};
6
7pub trait TopologicalSort {
9 type Graph: VisitableGraph;
10
11 fn topological_sort_opt(&self, roots: &Nodes, roots_only: bool) -> Result<Vec<NodeID>>;
13
14 fn topological_sort(&self) -> Result<Vec<NodeID>> {
16 self.topological_sort_opt(&Nodes::new(), false)
17 }
18
19 fn is_dag(&self) -> bool {
20 self.topological_sort().is_ok()
21 }
22}
23
24impl<G> TopologicalSort for G
25where
26 G: VisitableGraph,
27{
28 type Graph = G;
29
30 fn topological_sort_opt(&self, roots: &Nodes, roots_only: bool) -> Result<Vec<NodeID>> {
31 let mut visitor = TopologicalSortVisitor::with_capacity(self.node_count());
32 self.depth_first_search_opt(&mut visitor, roots, roots_only, None::<EdgeID>)
33 }
34}
35
36pub struct TopologicalSortVisitor<Graph>
37where
38 Graph: VisitableGraph,
39{
40 order: Vec<NodeID>,
41 graph: PhantomData<Graph>,
42}
43
44impl<Graph> TopologicalSortVisitor<Graph>
45where
46 Graph: VisitableGraph,
47{
48 pub fn with_capacity(capacity: usize) -> Self {
49 Self {
50 order: Vec::with_capacity(capacity),
51 graph: PhantomData
52 }
53 }
54}
55
56impl<Graph> DFSVisitor for TopologicalSortVisitor<Graph>
57where
58 Graph: VisitableGraph,
59{
60 type Graph = Graph;
61 type Output = Vec<NodeID>;
62
63 fn back_edge(&mut self, _graph: &Self::Graph, _edge: &EdgeID) -> Result<Option<Self::Output>> {
64 Err(Error::NotADAG.into())
65 }
66
67 fn finish_node(&mut self, _graph: &Self::Graph, node: &NodeID) -> Result<Option<Self::Output>> {
68 self.order.push(node.clone());
69 Ok(None)
70 }
71
72 fn finish(&mut self, _graph: &Self::Graph) -> Result<Self::Output> {
73 Ok(self.order.clone().into_iter().rev().collect())
74 }
75}