@@ -19,6 +19,9 @@ Author: Daniel Kroening, kroening@kroening.com
1919#include < ostream>
2020#include < cassert>
2121#include < algorithm>
22+ #include < queue>
23+
24+ #include " invariant.h"
2225
2326class empty_edget
2427{
@@ -226,6 +229,13 @@ class grapht
226229 // return value: number of SCCs
227230 std::size_t SCCs (std::vector<node_indext> &subgraph_nr);
228231
232+ bool is_dag () const
233+ {
234+ return empty () || !topsort ().empty ();
235+ }
236+
237+ std::list<node_indext> topsort () const ;
238+
229239 void output_dot (std::ostream &out) const ;
230240 void output_dot_node (std::ostream &out, node_indext n) const ;
231241
@@ -570,6 +580,52 @@ void grapht<N>::make_chordal()
570580 }
571581}
572582
583+ // / Find a topological order of the nodes if graph is DAG, return empty list for
584+ // / non-DAG or empty graph. Uses Kahn's algorithm running in O(#edges+#nodes).
585+ template <class N >
586+ std::list<typename grapht<N>::node_indext> grapht<N>::topsort() const
587+ {
588+ // list of topologically sorted nodes
589+ std::list<node_indext> nodelist;
590+ // queue of working set nodes with in-degree zero
591+ std::queue<node_indext> indeg0_nodes;
592+ // in-degree for each node
593+ std::vector<size_t > in_deg (nodes.size (), 0 );
594+
595+ // abstract graph as in-degree of each node
596+ for (node_indext idx=0 ; idx<nodes.size (); idx++)
597+ {
598+ in_deg[idx]=in (idx).size ();
599+ if (in_deg[idx]==0 )
600+ indeg0_nodes.push (idx);
601+ }
602+
603+ while (!indeg0_nodes.empty ())
604+ {
605+ node_indext source=indeg0_nodes.front ();
606+ indeg0_nodes.pop ();
607+ nodelist.push_back (source);
608+
609+ for (const auto &edge : out (source))
610+ {
611+ const node_indext target=edge.first ;
612+ INVARIANT (in_deg[target]!=0 , " in-degree of node cannot be zero here" );
613+
614+ // remove edge from graph, by decrementing the in-degree of target
615+ // outgoing edges from source will not be traversed again
616+ in_deg[target]--;
617+ if (in_deg[target]==0 )
618+ indeg0_nodes.push (target);
619+ }
620+ }
621+
622+ // if all nodes are sorted, the graph is acyclic
623+ // return empty list in case of cyclic graph
624+ if (nodelist.size ()!=nodes.size ())
625+ nodelist.clear ();
626+ return nodelist;
627+ }
628+
573629template <class N >
574630void grapht<N>::output_dot(std::ostream &out) const
575631{
0 commit comments