// computes topological numbering on the segments of the constraint graph. // Usage: If used on the basic (and vertex size) arcs, the numbering can be // used in order to serve as sorting criteria for respecting the given // embedding, e.g., when computing visibility arcs and allowing edges // with length 0. void CompactionConstraintGraphBase::computeTopologicalSegmentNum( NodeArray<int> &topNum) { NodeArray<int> indeg(*this); StackPure<node> sources; for(node v : nodes) { topNum[v] = 0; indeg[v] = v->indeg(); if(indeg[v] == 0) sources.push(v); } while(!sources.empty()) { node v = sources.pop(); edge e; forall_adj_edges(e,v) { if(e->source() != v) continue; node w = e->target(); if (topNum[w] < topNum[v] + 1) topNum[w] = topNum[v] + 1; if (--indeg[w] == 0) sources.push(w); } } }
int connectedComponents(const Graph &G, NodeArray<int> &component) { int nComponent = 0; component.fill(-1); StackPure<node> S; for(node v : G.nodes) { if (component[v] != -1) continue; S.push(v); component[v] = nComponent; while(!S.empty()) { node w = S.pop(); edge e; forall_adj_edges(e,w) { node x = e->opposite(w); if (component[x] == -1) { component[x] = nComponent; S.push(x); } } } ++nComponent; }
// extract and add external subgraph from stopnode to ancestors of the node with dfi root // to edgelist, nodeMarker is used as a visited flag. returns the endnode with lowest dfi. void FindKuratowskis::extractExternalSubgraphBundles( const node stop, int root, SListPure<edge>& externalSubgraph, int nodeMarker) { node v,temp; adjEntry adj; #ifdef OGDF_DEBUG forall_nodes(v,m_g) OGDF_ASSERT(m_wasHere[v]!=nodeMarker); #endif StackPure<node> stack; // stack for dfs-traversal ListConstIterator<node> it; stack.push(stop); while (!stack.empty()) { v = stack.pop(); if (m_wasHere[v]==nodeMarker) continue; // mark visited nodes m_wasHere[v]=nodeMarker; // search for unvisited nodes and add them to stack forall_adj(adj,v) { temp = adj->twinNode(); if (m_edgeType[adj->theEdge()]==EDGE_BACK_DELETED) continue; // go along backedges to ancestor (ignore virtual nodes) if (m_dfi[temp] < root && m_dfi[temp] > 0) { OGDF_ASSERT(m_edgeType[adj->theEdge()]==EDGE_BACK); externalSubgraph.pushBack(adj->theEdge()); } else if (v != stop && m_dfi[temp]>=m_dfi[v]) { // set flag and push unvisited nodes OGDF_ASSERT(m_edgeType[adj->theEdge()]==EDGE_BACK || m_edgeType[adj->theEdge()]==EDGE_DFS || m_edgeType[adj->theEdge()]==EDGE_BACK_DELETED); externalSubgraph.pushBack(adj->theEdge()); if (m_wasHere[temp] != nodeMarker) stack.push(temp); } } // descent to external active child bicomps for (it = m_separatedDFSChildList[v].begin(); it.valid(); ++it) { temp = *it; if (m_lowPoint[temp] >= root) break; stack.push(m_nodeFromDFI[-m_dfi[temp]]); } }
void LongestPathCompaction::applyLongestPaths( const CompactionConstraintGraph<int> &D, NodeArray<int> &pos) { const Graph &Gd = D.getGraph(); m_component.init(Gd); NodeArray<int> indeg(Gd); StackPure<node> sources; for(node v : Gd.nodes) { indeg[v] = v->indeg(); if(indeg[v] == 0) sources.push(v); } while(!sources.empty()) { node v = sources.pop(); int predComp = -1; // means "unset" bool isPseudoSource = true; edge e; forall_adj_edges(e,v) { if(e->source() != v) { // incoming edge if (D.cost(e) > 0) { isPseudoSource = false; node w = e->source(); // is tight? if (pos[w] + D.length(e) == pos[v]) { if (predComp == -1) predComp = m_component[w]; else if (predComp != m_component[w]) predComp = 0; // means "vertex is in no pseudo-comp. } } } else { // outgoing edge node w = e->target(); if (pos[w] < pos[v] + D.length(e)) pos[w] = pos[v] + D.length(e); if (--indeg[w] == 0) sources.push(w); } } if (predComp == -1) predComp = 0; if( isPseudoSource) { m_pseudoSources.pushFront(v); m_component[v] = m_pseudoSources.size(); } else { m_component[v] = predComp; } } }
// start DFS-traversal void BoyerMyrvoldInit::computeDFS() { // compute random edge costs EdgeArray<int> costs; EdgeComparer comp; if(m_randomness > 0 && m_edgeCosts != nullptr) { costs.init(m_g); int minCost = std::numeric_limits<int>::max(); int maxCost = std::numeric_limits<int>::min(); for(edge e : m_g.edges) { minCost = min(minCost, (*m_edgeCosts)[e]); maxCost = min(maxCost, (*m_edgeCosts)[e]); } std::uniform_real_distribution<> urd(-1, 1); for(edge e : m_g.edges) { costs[e] = minCost + (int)((1 - m_randomness) * ((*m_edgeCosts)[e] - minCost) + m_randomness * (maxCost - minCost) * urd(m_rand)); } comp.setCosts(&costs); } else if(m_edgeCosts != nullptr) { comp.setCosts(m_edgeCosts); } StackPure<adjEntry> stack; int nextDFI = 1; const int numberOfNodes = m_g.numberOfNodes(); SListPure<adjEntry> adjList; SListPure<node> list; m_g.allNodes(list); // get random dfs-tree, if wanted if (m_randomness > 0) { list.permute(); } for (node v : list) { if (v->degree() == 0) { m_dfi[v] = nextDFI; m_leastAncestor[v] = nextDFI; m_nodeFromDFI[nextDFI] = v; ++nextDFI; } else { adjList.clear(); m_g.adjEntries(v, adjList); adjList.quicksort(comp); m_g.sort(v, adjList); stack.push(v->firstAdj()); } } while (nextDFI <= numberOfNodes) { OGDF_ASSERT(!stack.empty()); adjEntry prnt = stack.pop(); node v = prnt->theNode(); // check, if node v was visited before. if (m_dfi[v] != 0) continue; // parentNode=nullptr on first node on connected component node parentNode = prnt->twinNode(); if (m_dfi[parentNode] == 0) parentNode = nullptr; // if not, mark node as visited and initialize NodeArrays m_dfi[v] = nextDFI; m_leastAncestor[v] = nextDFI; m_nodeFromDFI[nextDFI] = v; ++nextDFI; // push all adjacent nodes onto stack for(adjEntry adj : v->adjEdges) { edge e = adj->theEdge(); if (adj == prnt && parentNode != nullptr) continue; // check for self-loops and dfs- and dfs-parallel edges node w = adj->twinNode(); if (m_dfi[w] == 0) { m_edgeType[e] = EDGE_DFS; m_adjParent[w] = adj; m_link[CW][w] = adj; m_link[CCW][w] = adj; // found new dfs-edge: preorder stack.push(adj->twin()); } else if (w == v) { // found self-loop m_edgeType[e] = EDGE_SELFLOOP; } else { // node w already has been visited and is an dfs-ancestor of v OGDF_ASSERT(m_dfi[w] < m_dfi[v]); if (w == parentNode) { // found parallel edge of dfs-parent-edge m_edgeType[e] = EDGE_DFS_PARALLEL; } else { // found backedge m_edgeType[e] = EDGE_BACK; // set least Ancestor if (m_dfi[w] < m_leastAncestor[v]) m_leastAncestor[v] = m_dfi[w]; } } } } }