// 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);
		}
	}
}
Beispiel #2
0
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;
    }
Beispiel #3
0
// 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]]);
		}
	}
Beispiel #4
0
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;
		}
	}
}
Beispiel #5
0
// 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];
				}
			}
		}
	}
}