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(); }
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; }
void UpwardPlanRep::constructSinkArcs(face f, node t) { List<adjEntry> srcList; if (f != m_Gamma.externalFace()) { for(adjEntry adj : f->entries) { node v = adj->theNode(); if (v == adj->theEdge()->target() && v == adj->faceCyclePred()->theEdge()->target() && v != t) { srcList.pushBack(adj); // XXX: where is adjTgt used later? // do we have to set adjTgt = adj (top-sink-switch of f) if v != t? } } // contruct the sink arcs while(!srcList.empty()) { adjEntry adjSrc = srcList.popFrontRet(); edge eNew; if (t->degree() == 0) eNew = m_Gamma.addEdgeToIsolatedNode(adjSrc, t); else { adjEntry adjTgt = getAdjEntry(m_Gamma, t, m_Gamma.rightFace(adjSrc)); eNew = m_Gamma.splitFace(adjSrc, adjTgt); } m_isSinkArc[eNew] = true; } } else { for(adjEntry adj : f->entries) { node v = adj->theNode(); OGDF_ASSERT(s_hat != nullptr); if (v->outdeg() == 0 && v != t_hat) srcList.pushBack(adj); } // contruct the sink arcs while(!srcList.empty()) { adjEntry adjSrc = srcList.popFrontRet(); adjEntry adjTgt; if (adjSrc->theNode() == adjSrc->theEdge()->source()) // on the right face part of the ext. face adjTgt = extFaceHandle; else adjTgt = extFaceHandle->cyclicPred(); // on the left face part auto eNew = m_Gamma.splitFace(adjSrc, adjTgt); m_isSinkArc[eNew] = true; } } }
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; }
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(); }