Exemplo n.º 1
0
bool FeasibleUpwardPlanarSubgraph::constructMergeGraph(
	GraphCopy &M,
	adjEntry adj_orig,
	const List<edge> &orig_edges)
{
	CombinatorialEmbedding Beta(M);

	//set ext. face of Beta
	adjEntry ext_adj = M.copy(adj_orig->theEdge())->adjSource();
	Beta.setExternalFace(Beta.rightFace(ext_adj));

	FaceSinkGraph fsg(Beta, M.copy(adj_orig->theNode()));
	SList<node> aug_nodes;
	SList<edge> aug_edges;
	SList<face> fList;
	fsg.possibleExternalFaces(fList); // use this method to call the methode checkForest()
	node v_ext = fsg.faceNodeOf(Beta.externalFace());

	OGDF_ASSERT(v_ext != 0);

	fsg.stAugmentation(v_ext, M, aug_nodes, aug_edges);

	//add the deleted edges
	for(edge eOrig: orig_edges) {
		node a = M.copy(eOrig->source());
		node b = M.copy(eOrig->target());
		M.newEdge(a, b);
	}
	return (isAcyclic(M));
}
Exemplo n.º 2
0
void UpwardPlanRep::initMe()
{
	m_Gamma.init(*this);
	isAugmented = false;

	FaceSinkGraph fsg(m_Gamma, s_hat);
	SList<face> extFaces;
	fsg.possibleExternalFaces(extFaces);

	OGDF_ASSERT(!extFaces.empty());

	face f_ext = nullptr;
	for(face f : extFaces) {
		if (f_ext == nullptr)
			f_ext = f;
		else {
			if (f_ext->size() < f->size())
				f_ext = f;
		}
	}
	m_Gamma.setExternalFace(f_ext);
	for(adjEntry adj : s_hat->adjEntries) {
		if (m_Gamma.rightFace(adj) == m_Gamma.externalFace()) {
			extFaceHandle = adj;
			break;
		}
	}

	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 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);
		}
	}
}
Exemplo n.º 5
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.º 6
0
bool FUPSSimple::constructMergeGraph(GraphCopy &M, adjEntry adj_orig, const List<edge> &orig_edges)
{
	CombinatorialEmbedding Beta(M);

	//set ext. face of Beta
	adjEntry ext_adj = M.copy(adj_orig->theEdge())->adjSource();
	Beta.setExternalFace(Beta.rightFace(ext_adj));

	//*************************** 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;
	*/

	FaceSinkGraph fsg(Beta, M.copy(adj_orig->theNode()));
	SList<node> aug_nodes;
	SList<edge> aug_edges;
	SList<face> fList;
	fsg.possibleExternalFaces(fList); // use this method to call the methode checkForest()
	node v_ext = fsg.faceNodeOf(Beta.externalFace());

	OGDF_ASSERT(v_ext != 0);

	fsg.stAugmentation(v_ext, M, aug_nodes, aug_edges);

	/*
	//------------------------------------debug
	GraphAttributes AG(M, 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/MergeFUPS.gml");
	*/


	OGDF_ASSERT(isStGraph(M));

	//add the deleted edges
	for(edge eOrig : orig_edges) {
		node a = M.copy(eOrig->source());
		node b = M.copy(eOrig->target());
		M.newEdge(a, b);
	}
	return (isAcyclic(M));
}
Exemplo n.º 7
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.º 8
0
void UpwardPlanRep::insertEdgePathEmbedded(edge eOrig, SList<adjEntry> crossedEdges, EdgeArray<int> &costOrig)
{
	removeSinkArcs(crossedEdges);

	//case the copy v of eOrig->source() is a sink switch
	//we muss remove the sink arcs incident to v, since after inserting eOrig, v is not a sink witch
	node v =  crossedEdges.front()->theNode();
	List<edge> outEdges;
	if (v->outdeg() == 1)
		v->outEdges(outEdges); // we delete these edges later

	m_eCopy[eOrig].clear();

	adjEntry adjSrc, adjTgt;
	SListConstIterator<adjEntry> it = crossedEdges.begin();

	// iterate over all adjacency entries in crossedEdges except for first
	// and last
	adjSrc = *it;
	List<adjEntry> dirtyList; // left and right face of the element of this list are modified
	for(++it; it.valid() && it.succ().valid(); ++it)
	{
		adjEntry adj = *it;

		bool isASourceArc = false, isASinkArc = false;
		if (m_isSinkArc[adj->theEdge()])
			isASinkArc = true;
		if (m_isSourceArc[adj->theEdge()])
			isASourceArc = true;

		int c = 0;
		if (original(adj->theEdge()) != nullptr)
			c = costOrig[original(adj->theEdge())];

		// split edge
		node u = m_Gamma.split(adj->theEdge())->source();
		if (!m_isSinkArc[adj->theEdge()] && !m_isSourceArc[adj->theEdge()])
			crossings = crossings + c; // crossing sink/source arcs cost nothing

		// determine target adjacency entry and source adjacency entry
		// in the next iteration step
		adjTgt = u->firstAdj();
		adjEntry adjSrcNext = adjTgt->succ();

		if (adjTgt != adj->twin())
			std::swap(adjTgt, adjSrcNext);

		edge e_split = adjTgt->theEdge(); // the new split edge
		if (e_split->source() != u)
			e_split = adjSrcNext->theEdge();

		if (isASinkArc)
			m_isSinkArc[e_split] = true;
		if (isASourceArc)
			m_isSourceArc[e_split] = true;

		// insert a new edge into the face
		edge eNew = m_Gamma.splitFace(adjSrc,adjTgt);
		m_eIterator[eNew] = GraphCopy::m_eCopy[eOrig].pushBack(eNew);
		m_eOrig[eNew] = eOrig;
		dirtyList.pushBack(eNew->adjSource());

		adjSrc = adjSrcNext;
	}

	// insert last edge
	edge eNew = m_Gamma.splitFace(adjSrc,*it);
	m_eIterator[eNew] = m_eCopy[eOrig].pushBack(eNew);
	m_eOrig[eNew] = eOrig;
	dirtyList.pushBack(eNew->adjSource());

	// remove the sink arc incident to v
	if(!outEdges.empty()) {
		edge e = outEdges.popFrontRet();
		if (m_isSinkArc[e])
			m_Gamma.joinFaces(e);
	}

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

	//computeSinkSwitches();
	FaceSinkGraph fsg(m_Gamma, s_hat);
	List<adjEntry> dummyList;
	FaceArray< List<adjEntry> > sinkSwitches(m_Gamma, dummyList);
	fsg.sinkSwitches(sinkSwitches);

	//construct sinkArc for the dirty faces
	for(adjEntry adj : dirtyList) {
		face fLeft = m_Gamma.leftFace(adj);
		face fRight = m_Gamma.rightFace(adj);
		List<adjEntry> switches = sinkSwitches[fLeft];

		OGDF_ASSERT(!switches.empty());

		constructSinkArcs(fLeft, switches.front()->theNode());

		OGDF_ASSERT(!switches.empty());

		switches = sinkSwitches[fRight];
		constructSinkArcs(fRight, switches.front()->theNode());
	}

	m_Gamma.setExternalFace(m_Gamma.rightFace(extFaceHandle));
	computeSinkSwitches();
}
Exemplo n.º 9
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();
}