void UpwardPlanarSubgraphModule::callAndDelete( GraphCopy &GC, List<edge> &delOrigEdges) { List<edge> delEdges; call(GC, delEdges); ListConstIterator<edge> it; for(it = delEdges.begin(); it.valid(); ++it) { edge eCopy = *it; delOrigEdges.pushBack(GC.original(eCopy)); GC.delEdge(eCopy); } }
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); } }
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); } }
Module::ReturnType PlanarSubgraphModule::callAndDelete( GraphCopy &PG, const List<edge> &preferedEdges, List<edge> &delOrigEdges, bool preferedImplyPlanar) { List<edge> delEdges; ReturnType retValue = call(PG, preferedEdges, delEdges, preferedImplyPlanar); if(isSolution(retValue)) { ListConstIterator<edge> it; for(it = delEdges.begin(); it.valid(); ++it) { edge eCopy = *it; delOrigEdges.pushBack(PG.original(eCopy)); PG.delEdge(eCopy); } } return retValue; }
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)); }
/* * Construct the realiszer and the Tree T * rValues = realizer value * T = Tree */ void SchnyderLayout::realizer( GraphCopy& G, const List<node>& L, node a, node b, node c, EdgeArray<int>& rValues, GraphCopy& T) { int i = 0; edge e; NodeArray<int> ord(G, 0); // ordering: b,c,L,a ord[b] = i++; ord[c] = i++; for(node v : L) { ord[v] = i++; // enumerate V(G) } ord[a] = i++; // remove all edges (they will be re-added later with different orientation) while (T.numberOfEdges() > 0) { e = T.firstEdge(); T.delEdge(e); } for(node v : L) { node u = T.copy(G.original(v)); // u is copy of v in T adjEntry adj = nullptr; for(adjEntry adjRun : v->adjEdges) { if (ord[adjRun->twinNode()] > ord[v]) { adj = adjRun; break; } } adjEntry adj1 = adj; while (ord[adj1->twinNode()] > ord[v]) { adj1 = adj1->cyclicSucc(); } e = T.newEdge(T.copy(G.original(adj1->twinNode())), u); rValues[e] = 2; adjEntry adj2 = adj; while (ord[adj2->twinNode()] > ord[v]) { adj2 = adj2->cyclicPred(); } e = T.newEdge(T.copy(G.original(adj2->twinNode())), u); rValues[e] = 3; for (adj = adj1->cyclicSucc(); adj != adj2; adj = adj->cyclicSucc()) { e = T.newEdge(u, T.copy(G.original(adj->twinNode()))); rValues[e] = 1; } } // special treatement of a,b,c node a_in_T = T.copy(G.original(a)); node b_in_T = T.copy(G.original(b)); node c_in_T = T.copy(G.original(c)); // all edges to node a get realizer value 1 for(adjEntry adj : a->adjEdges) { e = T.newEdge(a_in_T, T.copy(G.original(adj->twinNode()))); rValues[e] = 1; } // rest of outer triangle (reciprocal linked, realizer values 2 and 3) e = T.newEdge(b_in_T, a_in_T); rValues[e] = 2; e = T.newEdge(b_in_T, c_in_T); rValues[e] = 2; e = T.newEdge(c_in_T, a_in_T); rValues[e] = 3; e = T.newEdge(c_in_T, b_in_T); rValues[e] = 3; }