void DfsAcyclicSubgraph::callUML ( const GraphAttributes &AG, List<edge> &arcSet) { const Graph &G = AG.constGraph(); // identify hierarchies NodeArray<int> hierarchy(G,-1); int count = 0; int treeNum = -1; node v; forall_nodes(v,G) { if(hierarchy[v] == -1) { int n = dfsFindHierarchies(AG,hierarchy,count,v); if(n > 1) treeNum = count; ++count; } } arcSet.clear(); // perform DFS on the directed graph formed by generalizations NodeArray<int> number(G,0), completion(G); int nNumber = 0, nCompletion = 0; forall_nodes(v,G) { if(number[v] == 0) dfsBackedgesHierarchies(AG,v,number,completion,nNumber,nCompletion); } // collect all backedges within a hierarchy // and compute outdeg of each vertex within its hierarchy EdgeArray<bool> reversed(G,false); NodeArray<int> outdeg(G,0); edge e; forall_edges(e,G) { if(AG.type(e) != Graph::generalization || e->isSelfLoop()) continue; node src = e->source(), tgt = e->target(); outdeg[src]++; if (hierarchy[src] == hierarchy[tgt] && number[src] >= number[tgt] && completion[src] <= completion[tgt]) reversed[e] = true; } // topologial numbering of nodes within a hierarchy (for each hierarchy) NodeArray<int> numV(G); Queue<node> Q; int countV = 0; forall_nodes(v,G) if(outdeg[v] == 0) Q.append(v); while(!Q.empty()) { v = Q.pop(); numV[v] = countV++; forall_adj_edges(e,v) { node w = e->source(); if(w != v) { if(--outdeg[w] == 0) Q.append(w); } } }
int pred0(Node *n) { return (outdeg(n) >= 1 && indeg(n) >= 1); }
int pred1(Edge *e) { Node *n = &elem(e->src); return (outdeg(n) >= 1); }
int signature(Node *n) { return (min(1, outdeg(n)) << 1) | min(1, indeg(n)); }