Exemplo n.º 1
0
UpwardPlanRep::UpwardPlanRep(const GraphCopy &GC, ogdf::adjEntry adj_ext) :
	GraphCopy(GC),
	isAugmented(false),
	t_hat(nullptr),
	extFaceHandle(nullptr),
	crossings(0)
{
	OGDF_ASSERT(adj_ext != nullptr);
	OGDF_ASSERT(hasSingleSource(*this));

	m_isSourceArc.init(*this, false);
	m_isSinkArc.init(*this, false);
	hasSingleSource(*this, s_hat);
	m_Gamma.init(*this);

	//compute the ext. face;
	node v = copy(GC.original(adj_ext->theNode()));
	extFaceHandle = copy(GC.original(adj_ext->theEdge()))->adjSource();
	if (extFaceHandle->theNode() != v)
		extFaceHandle = extFaceHandle->twin();
	m_Gamma.setExternalFace(m_Gamma.rightFace(extFaceHandle));

	for(adjEntry adj : s_hat->adjEntries)
		m_isSourceArc[adj->theEdge()] = true;

	computeSinkSwitches();
}
Exemplo n.º 2
0
UpwardPlanRep::UpwardPlanRep(const CombinatorialEmbedding &Gamma) :
	GraphCopy(Gamma.getGraph()),
	isAugmented(false),
	t_hat(nullptr),
	extFaceHandle(nullptr),
	crossings(0)
{
	OGDF_ASSERT(Gamma.externalFace() != nullptr);
	OGDF_ASSERT(hasSingleSource(*this));
	OGDF_ASSERT(isSimple(*this));

	m_isSourceArc.init(*this, false);
	m_isSinkArc.init(*this, false);
	hasSingleSource(*this, s_hat);
	m_Gamma.init(*this);

	//compute the ext. face;
	adjEntry adj;
	node v = this->original(s_hat);
	adj = getAdjEntry(Gamma, v, Gamma.externalFace());
	adj = this->copy(adj->theEdge())->adjSource();
	m_Gamma.setExternalFace(m_Gamma.rightFace(adj));

	//outputFaces(Gamma);

	computeSinkSwitches();
}
Exemplo n.º 3
0
Module::ReturnType FeasibleUpwardPlanarSubgraph::call(
	const Graph &G,
	GraphCopy &FUPS,
	adjEntry &extFaceHandle,
	List<edge> &delEdges,
	bool multisources)
{
	FUPS = GraphCopy(G);
	delEdges.clear();
	node s_orig;
	hasSingleSource(G, s_orig);
	List<edge> nonTreeEdges_orig;
	getSpanTree(FUPS, nonTreeEdges_orig, true, multisources);
	CombinatorialEmbedding Gamma(FUPS);
	nonTreeEdges_orig.permute(); // random order

	//insert nonTreeEdges
	while (!nonTreeEdges_orig.empty()) {
		// make identical copy GC of Fups
		//and insert e_orig in GC
		GraphCopy GC = FUPS;
		edge e_orig = nonTreeEdges_orig.popFrontRet();
		//node a = GC.copy(e_orig->source());
		//node b = GC.copy(e_orig->target());
		GC.newEdge(e_orig);

		if (UpwardPlanarity::upwardPlanarEmbed_singleSource(GC)) { //upward embedded the fups and check feasibility
			CombinatorialEmbedding Beta(GC);

			//choose a arbitrary feasibel ext. face
			FaceSinkGraph fsg(Beta, GC.copy(s_orig));
			SList<face> ext_faces;
			fsg.possibleExternalFaces(ext_faces);
			OGDF_ASSERT(!ext_faces.empty());
			Beta.setExternalFace(ext_faces.front());

			GraphCopy M = GC; // use a identical copy of GC to constrcut the merge graph of GC
			adjEntry extFaceHandle_cur = getAdjEntry(Beta, GC.copy(s_orig), Beta.externalFace());
			adjEntry adj_orig = GC.original(extFaceHandle_cur->theEdge())->adjSource();

			if (constructMergeGraph(M, adj_orig, nonTreeEdges_orig)) {
				FUPS = GC;
				extFaceHandle = FUPS.copy(GC.original(extFaceHandle_cur->theEdge()))->adjSource();
				continue;
			}
			else {
				//Beta is not feasible
				delEdges.pushBack(e_orig);
			}
		}
		else {
			// not ok, GC is not feasible
			delEdges.pushBack(e_orig);
		}
	}

	return Module::retFeasible;
}
Exemplo n.º 4
0
void UpwardPlanarSubgraphSimple::call(const Graph &G, List<edge> &delEdges)
{
	delEdges.clear();

	// We construct an auxiliary graph H which represents the current upward
	// planar subgraph.
	Graph H;
	NodeArray<node> mapToH(G);

	for(node v : G.nodes)
		mapToH[v] = H.newNode();


	// We currently support only single-source acyclic digraphs ...
	node s;
	hasSingleSource(G,s);

	OGDF_ASSERT(s != 0);
	OGDF_ASSERT(isAcyclic(G));

	// We start with a spanning tree of G rooted at the single source.
	NodeArray<bool> visitedNode(G,false);
	SListPure<edge> treeEdges;
	dfsBuildSpanningTree(s,treeEdges,visitedNode);


	// Mark all edges in the spanning tree so they can be skipped in the
	// loop below and add (copies of) them to H.
	EdgeArray<bool> visitedEdge(G,false);
	SListConstIterator<edge> it;
	for(it = treeEdges.begin(); it.valid(); ++it) {
		edge eG = *it;
		visitedEdge[eG] = true;
		H.newEdge(mapToH[eG->source()],mapToH[eG->target()]);
	}


	// Add subsequently the remaining edges to H and test if the resulting
	// graph is still upward planar. If not, remove the edge again from H
	// and add it to delEdges.

	for(edge eG : G.edges)
	{
		if(visitedEdge[eG] == true)
			continue;

		edge eH = H.newEdge(mapToH[eG->source()],mapToH[eG->target()]);

		if (UpwardPlanarity::isUpwardPlanar_singleSource(H) == false) {
			H.delEdge(eH);
			delEdges.pushBack(eG);
		}
	}

}
Exemplo n.º 5
0
void FUPSSimple::getSpanTree(GraphCopy &GC, List<edge> &delEdges, bool random)
{
	if (GC.numberOfNodes() == 1)
		return; // nothing to do

	node s;
	hasSingleSource(GC, s);
	NodeArray<bool> visited(GC, false);
	EdgeArray<bool> isTreeEdge(GC,false);
	List<node> toDo;

	//mark the incident edges e1..e_i of super source s and the incident edges of the target node of the edge e1.._e_i as tree edge.
	visited[s] = true;
	for(adjEntry adj : s->adjEdges) {
		isTreeEdge[adj] = true;
		visited[adj->theEdge()->target()];
		for(adjEntry adjTmp : adj->theEdge()->target()->adjEdges) {
			isTreeEdge[adjTmp] = true;
			node tgt = adjTmp->theEdge()->target();
			if (!visited[tgt]) {
				toDo.pushBack(tgt);
				visited[tgt] = true;
			}
		}
	}

	//traversing with dfs
	for(node start : toDo) {
		for(adjEntry adj : start->adjEdges) {
			node v = adj->theEdge()->target();
			if (!visited[v])
				dfs_visit(GC, adj->theEdge(), visited, isTreeEdge, random);
		}
	}

	// delete all non tree edgesEdges to obtain a span tree
	List<edge> l;
	for(edge e : GC.edges) {
		if (!isTreeEdge[e])
			l.pushBack(e);
	}
	while (!l.empty()) {
		edge e = l.popFrontRet();
		delEdges.pushBack(GC.original(e));
		GC.delEdge(e);
	}
}
Exemplo n.º 6
0
void FeasibleUpwardPlanarSubgraph::getSpanTree(GraphCopy &GC, List<edge> &delEdges, bool random, bool multisource)
{
	delEdges.clear();
	if (GC.numberOfNodes() == 1)
		return; // nothing to do
	node s;
	hasSingleSource(GC, s);
	NodeArray<bool> visited(GC, false);
	EdgeArray<bool> isTreeEdge(GC,false);
	List<node> toDo;

	// the original graph is a multisource graph. The sources are connected with the super source s.
	// so do not delete the incident edges of s
	if (multisource){
		// put all incident edges of the source to treeEdges
		for(adjEntry adj : s->adjEdges) {
			isTreeEdge[adj->theEdge()] = true;
			visited[adj->theEdge()->target()];
			toDo.pushBack(adj->theEdge()->target());
		}
	}
	else
		toDo.pushBack(s);


	//traversing with dfs
	for(node start : toDo) {
		for(adjEntry adj : start->adjEdges) {
			node v = adj->theEdge()->target();
			if (!visited[v])
				dfs_visit(GC, adj->theEdge(), visited, isTreeEdge, random);
		}
	}

	// delete all non tree edgesEdges to obtain a span tree
	List<edge> l;
	for(edge e : GC.edges) {
		if (!isTreeEdge[e])
			l.pushBack(e);
	}
	while (!l.empty()) {
		edge e = l.popFrontRet();
		delEdges.pushBack(GC.original(e));
		GC.delEdge(e);
	}
}
Exemplo n.º 7
0
void UpwardPlanRep::computeSinkSwitches()
{
	OGDF_ASSERT(m_Gamma.externalFace() != nullptr);

	if (s_hat == nullptr)
		hasSingleSource(*this, s_hat);
	FaceSinkGraph fsg(m_Gamma, s_hat);
	List<adjEntry> dummyList;
	FaceArray< List<adjEntry> > sinkSwitches(m_Gamma, dummyList);
	fsg.sinkSwitches(sinkSwitches);
	m_sinkSwitchOf.init(*this, nullptr);

	for(face f : m_Gamma.faces) {
		List<adjEntry> switches = sinkSwitches[f];
		ListIterator<adjEntry> it = switches.begin();
		for (it = it.succ(); it.valid(); ++it) {
			m_sinkSwitchOf[(*it)->theNode()] = (*it);
		}
	}
}
void FeasibleUpwardPlanarSubgraph::getSpanTree(GraphCopy &GC, List<edge> &delEdges, bool random, bool multisource)
{
	delEdges.clear();
	if (GC.numberOfNodes() == 1)
		return; // nothing to do
	node s;
	hasSingleSource(GC, s);
	NodeArray<bool> visited(GC, false);
	EdgeArray<bool> isTreeEdge(GC,false);
	List<node> toDo;

	// the original graph is a multisource graph. The sources are connected with the super source s.
	// so do not delete the incident edges of s
	if (multisource){
		// put all incident edges of the source to treeEdges
		adjEntry adj;
		forall_adj(adj, s) {
			isTreeEdge[adj->theEdge()] = true;
			visited[adj->theEdge()->target()];
			toDo.pushBack(adj->theEdge()->target());
		}
	}
Exemplo n.º 9
0
void UpwardPlanarSubgraphSimple::call(GraphCopy &GC, List<edge> &delEdges)
{
	const Graph &G = GC.original();
	delEdges.clear();

	// We construct an auxiliary graph H which represents the current upward
	// planar subgraph.
	Graph H;
	NodeArray<node> mapToH(G,nullptr);
	NodeArray<node> mapToG(H,nullptr);

	for(node v : G.nodes)
		mapToG[ mapToH[v] = H.newNode() ] = v;


	// We currently support only single-source acyclic digraphs ...
	node s;
	hasSingleSource(G,s);

	OGDF_ASSERT(s != 0);
	OGDF_ASSERT(isAcyclic(G));

	// We start with a spanning tree of G rooted at the single source.
	NodeArray<bool> visitedNode(G,false);
	SListPure<edge> treeEdges;
	dfsBuildSpanningTree(s,treeEdges,visitedNode);


	// Mark all edges in the spanning tree so they can be skipped in the
	// loop below and add (copies of) them to H.
	EdgeArray<bool> visitedEdge(G,false);
	SListConstIterator<edge> it;
	for(it = treeEdges.begin(); it.valid(); ++it) {
		edge eG = *it;
		visitedEdge[eG] = true;
		H.newEdge(mapToH[eG->source()],mapToH[eG->target()]);
	}


	// Add subsequently the remaining edges to H and test if the resulting
	// graph is still upward planar. If not, remove the edge again from H
	// and add it to delEdges.

	SList<Tuple2<node,node> > augmented;
	GraphCopySimple graphAcyclicTest(G);

	for(edge eG : G.edges)
	{
		// already treated ?
		if(visitedEdge[eG] == true)
			continue;

		// insert edge into H
		edge eH = H.newEdge(mapToH[eG->source()],mapToH[eG->target()]);

		node superSink;
		SList<edge> augmentedEdges;
		if (UpwardPlanarity::upwardPlanarAugment_singleSource(H,superSink,augmentedEdges) == false) {
			// if H is no longer upward planar, remove eG from subgraph
			H.delEdge(eH);
			delEdges.pushBack(eG);

		} else {
			// add augmented edges as node-pair to tmpAugmented and remove
			// all augmented edges from H again
			SList<Tuple2<node,node> > tmpAugmented;
			SListConstIterator<edge> it;
			for(it = augmentedEdges.begin(); it.valid(); ++it) {
				node v = mapToG[(*it)->source()];
				node w = mapToG[(*it)->target()];

				if (v && w)
					tmpAugmented.pushBack(Tuple2<node,node>(v,w));

				H.delEdge(*it);
			}

			if (mapToG[superSink] == nullptr)
				H.delNode(superSink);

			//****************************************************************
			// The following is a simple workaround to assure the following
			// property of the upward planar subgraph:
			//   The st-augmented upward planar subgraph plus the edges not
			//   in the subgraph must be acyclic. (This is a special property
			//   of the embedding, not the augmentation.)
			// The upward-planar embedding function gives us ANY upward-planar
			// embedding. We check if the property above holds with this
			// embedding. If it doesn't, we have actually no idea if another
			// embedding would do.
			// The better solution would be to incorporate the acyclicity
			// property into the upward-planarity test, but this is compicated.
			//****************************************************************

			// test if original graph plus augmented edges is still acyclic
			if(checkAcyclic(graphAcyclicTest,tmpAugmented) == true) {
				augmented = tmpAugmented;

			} else {
				// if not, remove eG from subgraph
				H.delEdge(eH);
				delEdges.pushBack(eG);
			}
		}

	}

	// remove edges not in the subgraph from GC
	ListConstIterator<edge> itE;
	for(itE = delEdges.begin(); itE.valid(); ++itE)
		GC.delEdge(GC.copy(*itE));

	// add augmented edges to GC
	SListConstIterator<Tuple2<node,node> > itP;
	for(itP = augmented.begin(); itP.valid(); ++itP) {
		node v = (*itP).x1();
		node w = (*itP).x2();

		GC.newEdge(GC.copy(v),GC.copy(w));
	}

	// add super sink to GC
	node sGC = nullptr;
	SList<node> sinks;
	for(node v : GC.nodes) {
		if(v->indeg() == 0)
			sGC = v;
		if(v->outdeg() == 0)
			sinks.pushBack(v);
	}

	node superSinkGC = GC.newNode();
	SListConstIterator<node> itV;
	for(itV = sinks.begin(); itV.valid(); ++itV)
		GC.newEdge(*itV,superSinkGC);

	// add st-edge to GC, so that we now have a planar st-digraph
	GC.newEdge(sGC,superSinkGC);

	OGDF_ASSERT(isAcyclic(GC));
	OGDF_ASSERT(isPlanar(GC));
}
Module::ReturnType OutputUpwardEdgeInserter::insertAll(UpwardPlanRep &UPR,
														List<edge> &toInsert,		
														EdgeArray<int>  &costOrig)
{
	if (toInsert.empty())
		return Module::retFeasible;

	List<edge> l;
	int size_new = toInsert.size();
	int size_old = 0;
	while (size_old != size_new) {
		size_old = size_new;
		while (!toInsert.empty()) {
			edge e_orig = toInsert.popFrontRet();
			SList<adjEntry> path;
			
			/*
			//debug
			cout << endl;
			cout << "  insertion path for e_orig :" << e_orig << ";  e_UPR: (" << UPR.copy(e_orig->source()) << "," 
				 << UPR.copy(e_orig->target()) << ")" << endl;
			*/

			minFIP(UPR, toInsert, costOrig, e_orig, path);						

			
			/*
			//--------------------------------------debug					
			forall_slistiterators(adjEntry, it, path) {
				cout << (*it)->theEdge() << ";  node: " << (*it)->theNode() << endl;
			}
			//--------------------------------------end debug
			*/
			
			List<edge> lEdges = toInsert, lTmp = l;
			lEdges.conc(lTmp);
			bool ok = isConstraintFeasible(UPR, lEdges, e_orig, path);						
			if (ok) {
				UPR.insertEdgePathEmbedded(e_orig, path, costOrig);				
				
				OGDF_ASSERT(isUpwardPlanar(UPR));			
				OGDF_ASSERT(isSimple(UPR));
				OGDF_ASSERT(isConnected(UPR));
				OGDF_ASSERT(hasSingleSource(UPR));

			}
			else 
				l.pushBack(e_orig);
			
			/*
			if (false) {
			//---------------------------------------------------debug		
			//UPR.outputFaces(UPR.getEmbedding());
			//UPR.writeGML("c:/temp/bug5.gml");

			LayerBasedUPRLayout uprLayout;
			Graph GTmp( (const Graph &) UPR);
			CombinatorialEmbedding embTmp(GTmp);
			node tTmp = 0;
			//GTmp.writeGML("c:/temp/bug4.gml");
			hasSingleSink(GTmp, tTmp);
			OGDF_ASSERT(tTmp != 0);
			embTmp.setExternalFace(embTmp.rightFace(tTmp->firstAdj()));
			//adjEntry adjTmp = GCTmp.copy(UPR.extFaceHandle->theEdge())->adjTarget();
			UpwardPlanRep upr_bug(embTmp);
			adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
			node s_upr_bug = upr_bug.newNode();
			upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
			upr_bug.m_isSourceArc.init(upr_bug, false);
			upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
			upr_bug.s_hat = s_upr_bug;
			upr_bug.augment();
		
			GraphAttributes GA_UPR_tmp(GTmp, GraphAttributes::nodeGraphics|
					GraphAttributes::edgeGraphics|
					GraphAttributes::nodeColor|
					GraphAttributes::edgeColor|
					GraphAttributes::nodeLabel|
					GraphAttributes::edgeLabel
					);
			GA_UPR_tmp.setAllHeight(30.0);
			GA_UPR_tmp.setAllWidth(30.0);	

			uprLayout.call(upr_bug, GA_UPR_tmp);				
			
			// label the nodes with their index
			node z;
			forall_nodes(z, GA_UPR_tmp.constGraph()) {			
				char str[255];
				sprintf_s(str, 255, "%d", z->index()); 	// convert to string	
				GA_UPR_tmp.labelNode(z) = str;		
				GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
				GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);				
			}
			edge eee;
			forall_edges(eee, GA_UPR_tmp.constGraph()) {
				DPolyline &line = GA_UPR_tmp.bends(eee);
				ListIterator<DPoint> it;
				for(it = line.begin(); it.valid(); it++) {		
					(*it).m_y = -(*it).m_y;	
					(*it).m_x = -(*it).m_x;
				}
			}
			GA_UPR_tmp.writeGML("c:/temp/UPR_int.gml");	
			//cout << "face of UPR_int :" << endl;
			//upr_bug.outputFaces(upr_bug.getEmbedding());
			//end -----------------------------------------------debug
			}
			*/

		}
		size_new = l.size();
		toInsert = l;
		l.clear();
	}
	
	/*
	 * some edges cannot be inserted, so use heuristic insertion methods
	 */
	if (!toInsert.empty()) {

		//cout << endl << "\a\a\a\a\aheuristical call!! " << endl;

		edge e_orig = toInsert.popFrontRet();

		/*
		cout << endl;
		cout << "heuristical insertion path for e_orig :" << e_orig << ";  e_UPR: (" << UPR.copy(e_orig->source()) << "," 
			<< UPR.copy(e_orig->target()) << ")" <<  endl;
		*/

		
			/*
			if (false) {
			//---------------------------------------------------debug		
			//UPR.outputFaces(UPR.getEmbedding());
			//UPR.writeGML("c:/temp/bug5.gml");

			LayerBasedUPRLayout uprLayout;
			Graph GTmp( (const Graph &) UPR);
			CombinatorialEmbedding embTmp(GTmp);
			node tTmp = 0;
			//GTmp.writeGML("c:/temp/bug4.gml");
			hasSingleSink(GTmp, tTmp);
			OGDF_ASSERT(tTmp != 0);
			embTmp.setExternalFace(embTmp.rightFace(tTmp->firstAdj()));
			//adjEntry adjTmp = GCTmp.copy(UPR.extFaceHandle->theEdge())->adjTarget();
			UpwardPlanRep upr_bug(embTmp);
			adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
			node s_upr_bug = upr_bug.newNode();
			upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
			upr_bug.m_isSourceArc.init(upr_bug, false);
			upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
			upr_bug.s_hat = s_upr_bug;
			upr_bug.augment();
		
			GraphAttributes GA_UPR_tmp(GTmp, GraphAttributes::nodeGraphics|
					GraphAttributes::edgeGraphics|
					GraphAttributes::nodeColor|
					GraphAttributes::edgeColor|
					GraphAttributes::nodeLabel|
					GraphAttributes::edgeLabel
					);
			GA_UPR_tmp.setAllHeight(30.0);
			GA_UPR_tmp.setAllWidth(30.0);	

			uprLayout.call(upr_bug, GA_UPR_tmp);				
			
			// label the nodes with their index
			node z;
			forall_nodes(z, GA_UPR_tmp.constGraph()) {			
				char str[255];
				sprintf_s(str, 255, "%d", z->index()); 	// convert to string	
				GA_UPR_tmp.labelNode(z) = str;		
				GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
				GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);				
			}
			edge eee;
			forall_edges(eee, GA_UPR_tmp.constGraph()) {
				DPolyline &line = GA_UPR_tmp.bends(eee);
				ListIterator<DPoint> it;
				for(it = line.begin(); it.valid(); it++) {		
					(*it).m_y = -(*it).m_y;	
					(*it).m_x = -(*it).m_x;
				}
			}
			GA_UPR_tmp.writeGML("c:/temp/UPR_int.gml");	
			//cout << "face of UPR_int :" << endl;
			//upr_bug.outputFaces(upr_bug.getEmbedding());
			//end -----------------------------------------------debug
			}
			*/		

		SList<adjEntry> path;
		constraintFIP(UPR, toInsert, costOrig, e_orig, path);	

		/*
		//--------------------------------------debug
		
		forall_slistiterators(adjEntry, it, path) {
			cout << (*it)->theEdge() << ";  node: " << (*it)->theNode() << endl;; 
		}
		//--------------------------------------end debug
		*/

		UPR.insertEdgePathEmbedded(e_orig, path, costOrig);		
		
		OGDF_ASSERT(isUpwardPlanar(UPR));

		return insertAll(UPR, toInsert, costOrig);
	}	
	return Module::retFeasible;
}
Exemplo n.º 11
0
void FUPSSimple::computeFUPS(UpwardPlanRep &UPR, List<edge> &delEdges)
{
	const Graph &G = UPR.original();
	GraphCopy FUPS(G);
	node s_orig;
	hasSingleSource(G, s_orig);
	List<edge> nonTreeEdges_orig;
	bool random = (m_nRuns != 0);

	getSpanTree(FUPS, nonTreeEdges_orig, random);

	CombinatorialEmbedding Gamma(FUPS);

	if (random)
		nonTreeEdges_orig.permute(); // random order

	adjEntry extFaceHandle = nullptr;

	//insert nonTreeEdges
	while (!nonTreeEdges_orig.empty()) {

	/*
	//------------------------------------debug
	GraphAttributes AG(FUPS, GraphAttributes::nodeGraphics|
						GraphAttributes::edgeGraphics|
						GraphAttributes::nodeColor|
						GraphAttributes::edgeColor|
						GraphAttributes::nodeLabel|
						GraphAttributes::edgeLabel
						);
	// label the nodes with their index
	for(node v : AG.constGraph().nodes) {
		AG.label(v) = to_string(v->index());
	}
	AG.writeGML("c:/temp/spannTree.gml");
	*/

		// make identical copy FUPSCopy of FUPS
		//and insert e_orig in FUPSCopy
		GraphCopy FUPSCopy((const GraphCopy &) FUPS);
		edge e_orig = nonTreeEdges_orig.popFrontRet();
		FUPSCopy.newEdge(e_orig);

		if (UpwardPlanarity::upwardPlanarEmbed_singleSource(FUPSCopy)) { //upward embedded the fups and check feasibility
			CombinatorialEmbedding Beta(FUPSCopy);

			//choose a arbitrary feasibel ext. face
			FaceSinkGraph fsg(Beta, FUPSCopy.copy(s_orig));
			SList<face> ext_faces;
			fsg.possibleExternalFaces(ext_faces);

			OGDF_ASSERT(!ext_faces.empty());

			Beta.setExternalFace(ext_faces.front());


#if 0
			//*************************** debug ********************************
			cout << endl << "FUPS : " << endl;
			for(face ff : Beta.faces) {
				cout << "face " << ff->index() << ": ";
				adjEntry adjNext = ff->firstAdj();
				do {
					cout << adjNext->theEdge() << "; ";
					adjNext = adjNext->faceCycleSucc();
				} while(adjNext != ff->firstAdj());
				cout << endl;
			}
			if (Beta.externalFace() != 0)
				cout << "ext. face of the graph is: " << Beta.externalFace()->index() << endl;
			else
				cout << "no ext. face set." << endl;
#endif

			GraphCopy M((const GraphCopy &) FUPSCopy); // use a identical copy of FUPSCopy to construct the merge graph of FUPSCopy
			adjEntry extFaceHandle_cur = getAdjEntry(Beta, FUPSCopy.copy(s_orig), Beta.externalFace());
			adjEntry adj_orig = FUPSCopy.original(extFaceHandle_cur->theEdge())->adjSource();

			List<edge> missingEdges = nonTreeEdges_orig, listTmp = delEdges;
			missingEdges.conc(listTmp);
			if (constructMergeGraph(M, adj_orig, missingEdges)) {
				FUPS = FUPSCopy;
				extFaceHandle = FUPS.copy(FUPSCopy.original(extFaceHandle_cur->theEdge()))->adjSource();
				continue;
			}
			else {
				//Beta is not feasible
				delEdges.pushBack(e_orig);
			}
		}
		else {
			// not ok, GC is not feasible
			delEdges.pushBack(e_orig);
		}
	}
	UpwardPlanRep fups_tmp (FUPS, extFaceHandle);
	UPR = fups_tmp;
}
Exemplo n.º 12
0
Module::ReturnType SubgraphUpwardPlanarizer::doCall(UpwardPlanRep &UPR,
		const EdgeArray<int>  &cost,
		const EdgeArray<bool> &forbid)
{
	const Graph &G = UPR.original();
	GraphCopy GC(G);

	//reverse some edges in order to obtain a DAG
	List<edge> feedBackArcSet;
	m_acyclicMod.get().call(GC, feedBackArcSet);
	for(edge e : feedBackArcSet) {
		GC.reverseEdge(e);
	}

	OGDF_ASSERT(isSimple(G));

	//mapping cost
	EdgeArray<int> cost_GC(GC);
	for(edge e : GC.edges) {
		if (forbid[GC.original(e)])
			cost_GC[e] = numeric_limits<int>::max();
		else
			cost_GC[e] = cost[GC.original(e)];
	}

	// tranform to single source graph by adding a super source s_hat and connect it with the other sources
	EdgeArray<bool> sourceArcs(GC, false);
	node s_hat = GC.newNode();
	for(node v : GC.nodes) {
		if (v->indeg() == 0 && v != s_hat) {
			edge e_tmp = GC.newEdge(s_hat, v);
			cost_GC[e_tmp] = 0; // crossings source arcs cause not cost
			sourceArcs[e_tmp] = true;
		}
	}


	/*
	//------------------------------------------------debug
	GraphAttributes AG_GC(GC, GraphAttributes::nodeGraphics|
						GraphAttributes::edgeGraphics|
						GraphAttributes::nodeColor|
						GraphAttributes::edgeColor|
						GraphAttributes::nodeLabel|
						GraphAttributes::edgeLabel
						);
	AG_GC.setAllHeight(30.0);
	AG_GC.setAllWidth(30.0);
	for(node z : AG_GC.constGraph().nodes) {
		AG_GC.label(z) = to_string(z->index());
	}
	AG_GC.writeGML("c:/temp/GC.gml");
	// --------------------------------------------end debug
	*/

	BCTree BC(GC);
	const Graph &bcTree = BC.bcTree();

	GraphCopy G_dummy;
	G_dummy.createEmpty(G);
	NodeArray<GraphCopy> biComps(bcTree, G_dummy); // bicomps of G; init with an empty graph
	UpwardPlanRep UPR_dummy;
	UPR_dummy.createEmpty(G);
	NodeArray<UpwardPlanRep> uprs(bcTree, UPR_dummy); // the upward planarized representation of the bicomps; init with an empty UpwarPlanRep

	constructComponentGraphs(BC, biComps);

	for(node v : bcTree.nodes) {

		if (BC.typeOfBNode(v) == BCTree::CComp)
			continue;

		GraphCopy &block = biComps[v];

		OGDF_ASSERT(m_subgraph.valid());

		// construct a super source for this block
		node s, s_block;
		hasSingleSource(block, s);
		s_block = block.newNode();
		block.newEdge(s_block, s); //connect s

		UpwardPlanRep bestUPR;

		//upward planarize if not upward planar
		if (!UpwardPlanarity::upwardPlanarEmbed_singleSource(block)) {

			for (int i = 0; i < m_runs; i++) {// i multistarts
				UpwardPlanRep UPR_tmp;
				UPR_tmp.createEmpty(block);
				List<edge> delEdges;

				m_subgraph.get().call(UPR_tmp, delEdges);

				OGDF_ASSERT( isSimple(UPR_tmp) );
				UPR_tmp.augment();

				//mark the source arcs of block
				UPR_tmp.m_isSourceArc[UPR_tmp.copy(s_block->firstAdj()->theEdge())] = true;
				for (adjEntry adj_tmp : UPR_tmp.copy(s_block->firstAdj()->theEdge()->target())->adjEntries) {
					edge e_tmp = UPR_tmp.original(adj_tmp->theEdge());
					if (e_tmp != nullptr && block.original(e_tmp) != nullptr && sourceArcs[block.original(e_tmp)])
						UPR_tmp.m_isSourceArc[adj_tmp->theEdge()] = true;
				}

				//assign "crossing cost"
				EdgeArray<int> cost_Block(block);
				for (edge e : block.edges) {
					if (block.original(e) == nullptr || GC.original(block.original(e)) == nullptr)
						cost_Block[e] = 0;
					else
						cost_Block[e] = cost_GC[block.original(e)];
				}

				/*
				if (false) {
					//---------------------------------------------------debug
					LayerBasedUPRLayout uprLayout;
					UpwardPlanRep upr_bug(UPR_tmp.getEmbedding());
					adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
					node s_upr_bug = upr_bug.newNode();
					upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
					upr_bug.m_isSourceArc.init(upr_bug, false);
					upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
					upr_bug.s_hat = s_upr_bug;
					upr_bug.augment();

					GraphAttributes GA_UPR_tmp(UPR_tmp, GraphAttributes::nodeGraphics|
							GraphAttributes::edgeGraphics|
							GraphAttributes::nodeColor|
							GraphAttributes::edgeColor|
							GraphAttributes::nodeLabel|
							GraphAttributes::edgeLabel
							);
					GA_UPR_tmp.setAllHeight(30.0);
					GA_UPR_tmp.setAllWidth(30.0);

					uprLayout.call(upr_bug, GA_UPR_tmp);

					// label the nodes with their index
					for(node z : GA_UPR_tmp.constGraph().nodes) {
						GA_UPR_tmp.label(z) = to_string(z->index());
						GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
						GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);
					}
					for(edge eee : GA_UPR_tmp.constGraph().edges) {
						DPolyline &line = GA_UPR_tmp.bends(eee);
						ListIterator<DPoint> it;
						for(it = line.begin(); it.valid(); it++) {
							(*it).m_y = -(*it).m_y;
							(*it).m_x = -(*it).m_x;
						}
					}
					GA_UPR_tmp.writeGML("c:/temp/UPR_tmp_fups.gml");
					cout << "UPR_tmp/fups faces:";
					UPR_tmp.outputFaces(UPR_tmp.getEmbedding());
					//end -----------------------------------------------debug
				}
				*/

				delEdges.permute();
				m_inserter.get().call(UPR_tmp, cost_Block, delEdges);

				if (i != 0) {
					if (UPR_tmp.numberOfCrossings() < bestUPR.numberOfCrossings()) {
						//cout << endl << "new cr_nr:" << UPR_tmp.numberOfCrossings() << " old  cr_nr : " << bestUPR.numberOfCrossings() << endl;
						bestUPR = UPR_tmp;
					}
				}
				else
					bestUPR = UPR_tmp;
			}//for
		}
		else { //block is upward planar
			CombinatorialEmbedding Gamma(block);
			FaceSinkGraph fsg((const CombinatorialEmbedding &) Gamma, s_block);
			SList<face> faceList;
			fsg.possibleExternalFaces(faceList);
			Gamma.setExternalFace(faceList.front());

			UpwardPlanRep UPR_tmp(Gamma);
			UPR_tmp.augment();

			//mark the source arcs of  block
			UPR_tmp.m_isSourceArc[UPR_tmp.copy(s->firstAdj()->theEdge())] = true;
			for (adjEntry adj_tmp : UPR_tmp.copy(s->firstAdj()->theEdge()->target())->adjEntries) {
				edge e_tmp = UPR_tmp.original(adj_tmp->theEdge());
				if (e_tmp != nullptr && block.original(e_tmp) != nullptr && sourceArcs[block.original(e_tmp)])
					UPR_tmp.m_isSourceArc[adj_tmp->theEdge()] = true;
			}

			bestUPR = UPR_tmp;

			/*
			//debug
			//---------------------------------------------------debug
			GraphAttributes GA_UPR_tmp(UPR_tmp, GraphAttributes::nodeGraphics|
					GraphAttributes::edgeGraphics|
					GraphAttributes::nodeColor|
					GraphAttributes::edgeColor|
					GraphAttributes::nodeLabel|
					GraphAttributes::edgeLabel
					);
			GA_UPR_tmp.setAllHeight(30.0);
			GA_UPR_tmp.setAllWidth(30.0);

			// label the nodes with their index
			for(node z : GA_UPR_tmp.constGraph().nodes) {
				GA_UPR_tmp.label(z) = to_string(z->index());
				GA_UPR_tmp.y(z)=-GA_UPR_tmp.y(z);
				GA_UPR_tmp.x(z)=-GA_UPR_tmp.x(z);
			}
			for(edge eee : GA_UPR_tmp.constGraph().edges) {
				DPolyline &line = GA_UPR_tmp.bends(eee);
				ListIterator<DPoint> it;
				for(it = line.begin(); it.valid(); it++) {
					(*it).m_y = -(*it).m_y;
					(*it).m_x = -(*it).m_x;
				}
			}
			GA_UPR_tmp.writeGML("c:/temp/UPR_tmp_fups.gml");
			cout << "UPR_tmp/fups faces:";
			UPR_tmp.outputFaces(UPR_tmp.getEmbedding());
			//end -----------------------------------------------debug
			*/

		}
		uprs[v] = bestUPR;
	}

	// compute the number of crossings
	int nr_cr = 0;
	for(node v : bcTree.nodes) {
		if (BC.typeOfBNode(v) != BCTree::CComp)
			nr_cr = nr_cr + uprs[v].numberOfCrossings();
	}

	//merge all component to a graph
	node parent_BC = BC.bcproper(s_hat);
	NodeArray<bool> nodesDone(bcTree, false);
	dfsMerge(GC, BC, biComps, uprs, UPR, nullptr, parent_BC, nodesDone); // start with the component which contains the super source s_hat

	//augment to single sink graph
	UPR.augment();

	//set crossings
	UPR.crossings = nr_cr;


	//------------------------------------------------debug
	/*
	LayerBasedUPRLayout uprLayout;
	UpwardPlanRep upr_bug(UPR.getEmbedding());
	adjEntry adj_bug = upr_bug.getAdjEntry(upr_bug.getEmbedding(), upr_bug.getSuperSource(), upr_bug.getEmbedding().externalFace());
	node s_upr_bug = upr_bug.newNode();
	upr_bug.getEmbedding().splitFace(s_upr_bug, adj_bug);
	upr_bug.m_isSourceArc.init(upr_bug, false);
	upr_bug.m_isSourceArc[s_upr_bug->firstAdj()->theEdge()] = true;
	upr_bug.s_hat = s_upr_bug;
	upr_bug.augment();
	GraphAttributes AG(UPR, GraphAttributes::nodeGraphics|
						GraphAttributes::edgeGraphics|
						GraphAttributes::nodeColor|
						GraphAttributes::edgeColor|
						GraphAttributes::nodeLabel|
						GraphAttributes::edgeLabel
						);
	AG.setAllHeight(30.0);
	AG.setAllWidth(30.0);

	uprLayout.call(upr_bug, AG);

	for(node v : AG.constGraph().nodes) {
		int idx;
		idx = v->index();


		if (UPR.original(v) != 0)
			idx = UPR.original(v)->index();


		AG.label(v) = to_string(idx);
		if (UPR.isDummy(v))
			AG.fillColor(v) = "#ff0000";
		AG.y(v)=-AG.y(v);
	}
	// label the edges with their index
	for(edge e : AG.constGraph().edges) {
		AG.label(e) = to_string(e->index());
		if (UPR.isSourceArc(e))
			AG.strokeColor(e) = "#00ff00";
		if (UPR.isSinkArc(e))
			AG.strokeColor(e) = "#ff0000";

		DPolyline &line = AG.bends(e);
		ListIterator<DPoint> it;
		for(it = line.begin(); it.valid(); it++) {
			(*it).m_y = -(*it).m_y;
		}
	}
	AG.writeGML("c:/temp/upr_res.gml");
	//cout << "UPR_RES";
	//UPR.outputFaces(UPR.getEmbedding());
	//cout << "Mapping :" << endl;
	//for(node v : UPR.nodes) {
	//	if (UPR.original(v) != 0) {
	//		cout << "node UPR  " << v << "   node G  " << UPR.original(v) << endl;
	//	}
	//}
	// --------------------------------------------end debug
	*/

	OGDF_ASSERT(hasSingleSource(UPR));
	OGDF_ASSERT(isSimple(UPR));
	OGDF_ASSERT(isAcyclic(UPR));
	OGDF_ASSERT(UpwardPlanarity::isUpwardPlanar_singleSource(UPR));

/*
	for(edge eee : UPR.original().edges) {
		if (UPR.isReversed(eee))
			cout << endl << eee << endl;
	}
*/
	return Module::retFeasible;
}
Exemplo n.º 13
0
void UpwardPlanRep::augment()
{
	if (isAugmented)
		return;

	OGDF_ASSERT(hasSingleSource(*this));

	List<adjEntry> switches;

	hasSingleSource(*this, s_hat);
	OGDF_ASSERT(this == &m_Gamma.getGraph());

	for(adjEntry adj : s_hat->adjEntries)
		m_isSourceArc[adj->theEdge()] = true;

	FaceSinkGraph fsg(m_Gamma, s_hat);
	List<adjEntry> dummyList;
	FaceArray< List<adjEntry> > sinkSwitches(m_Gamma, dummyList);
	fsg.sinkSwitches(sinkSwitches);
	m_sinkSwitchOf.init(*this, nullptr);

	List<Tuple2<adjEntry, adjEntry>> list;
	for(face f : m_Gamma.faces) {
		adjEntry adj_top;
		switches = sinkSwitches[f];
		if (switches.empty() || f == m_Gamma.externalFace())
			continue;
		else
			adj_top = switches.popFrontRet(); // first switch in the list is a top sink switch

		while (!switches.empty()) {
			adjEntry adj = switches.popFrontRet();
			Tuple2<adjEntry, adjEntry> pair(adj, adj_top);
			list.pushBack(pair);
		}
	}
	// construct sink arcs
	// for the ext. face
	extFaceHandle = getAdjEntry(m_Gamma, s_hat, m_Gamma.externalFace());
	node t = this->newNode();
	switches = sinkSwitches[m_Gamma.externalFace()];

	OGDF_ASSERT(!switches.empty());

	while (!switches.empty()) {
		adjEntry adj = switches.popFrontRet();
		edge e_new;
		if (t->degree() == 0) {
			e_new = m_Gamma.addEdgeToIsolatedNode(adj, t);
		}
		else {
			adjEntry adjTgt = getAdjEntry(m_Gamma, t, m_Gamma.rightFace(adj));
			e_new = m_Gamma.splitFace(adj, adjTgt);
		}
		m_isSinkArc[e_new] = true;
		m_Gamma.setExternalFace(m_Gamma.rightFace(extFaceHandle));
	}

	/*
	* set ext. face handle
	* we add a additional node t_hat and an addtional edge e=(t, t_hat)
	* e will never been crossed. we use e as the ext. face handle
	*/
	t_hat = this->newNode();
	adjEntry adjSource = getAdjEntry(m_Gamma, t, m_Gamma.externalFace());
	extFaceHandle = m_Gamma.addEdgeToIsolatedNode(adjSource, t_hat)->adjTarget();
	m_isSinkArc[extFaceHandle->theEdge()] = true; // not really a sink arc !! TODO??

	m_Gamma.setExternalFace(m_Gamma.rightFace(extFaceHandle));

	//for int. faces
	while (!list.empty()) {
		Tuple2<adjEntry, adjEntry> pair = list.popFrontRet();

		edge e_new = nullptr;
		if (pair.x2()->theNode()->degree() == 0 ) {
			e_new = m_Gamma.addEdgeToIsolatedNode(pair.x1(), pair.x2()->theNode());
		}
		else {
			adjEntry adjTgt = getAdjEntry(m_Gamma, pair.x2()->theNode(), m_Gamma.rightFace(pair.x1()));
			if(!m_Gamma.getGraph().searchEdge(pair.x1()->theNode(),adjTgt->theNode())) // post-hoi-ming bugfix: prohibit the same edge twice...
				e_new = m_Gamma.splitFace(pair.x1(), adjTgt);
		}
		if(e_new!=nullptr)
			m_isSinkArc[e_new] = true;
	}

	isAugmented = true;

	OGDF_ASSERT(isSimple(*this));

	computeSinkSwitches();
}