void CPlanarSubClusteredST::call(const ClusterGraph &CG, EdgeArray<bool>& inST) { initialize(CG); inST.fill(false); //representationsgraphs for every cluster, on clustergraph ClusterArray<Graph*> l_clusterRepGraph(CG, 0); computeRepresentationGraphs(CG, l_clusterRepGraph); //now we compute the spanning trees on the representation graphs //we should save the selection info on the original edge //are statically on the repgraphedges (we only have edge -> repedge //information) but ClusterArray< EdgeArray<bool> > l_inTree(CG); cluster c; forall_clusters(c, CG) { l_inTree[c].init(*l_clusterRepGraph[c], false); //compute STs NodeArray<bool> visited(*l_clusterRepGraph[c], false); dfsBuildSpanningTree(l_clusterRepGraph[c]->firstNode(), l_inTree[c], visited); }//forallclusters
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); } } }
void UpwardPlanarSubgraphSimple::dfsBuildSpanningTree( node v, SListPure<edge> &treeEdges, NodeArray<bool> &visited) { visited[v] = true; for(adjEntry adj : v->adjEntries) { edge e = adj->theEdge(); node w = e->target(); if(w == v) continue; if(!visited[w]) { treeEdges.pushBack(e); dfsBuildSpanningTree(w,treeEdges,visited); } } }
void UpwardPlanarSubgraphSimple::dfsBuildSpanningTree( node v, SListPure<edge> &treeEdges, NodeArray<bool> &visited) { visited[v] = true; edge e; forall_adj_edges(e,v) { node w = e->target(); if(w == v) continue; if(!visited[w]) { treeEdges.pushBack(e); dfsBuildSpanningTree(w,treeEdges,visited); } }
//we should later provide a minimum st to allow weights on edges void CPlanarSubClusteredST::dfsBuildSpanningTree( node v, EdgeArray<bool> &treeEdges, NodeArray<bool> &visited) { OGDF_ASSERT(isConnected(*(v->graphOf()))); visited[v] = true; for(adjEntry adj : v->adjEntries) { edge e = adj->theEdge(); node w = adj->twinNode(); if(w == v) continue; if(!visited[w]) { treeEdges[e] = true; // m_genDebug++; //debugonly dfsBuildSpanningTree(w,treeEdges,visited); } } }
void CPlanarSubClusteredST::call(const ClusterGraph &CG, EdgeArray<bool>& inST) { initialize(CG); inST.fill(false); //representationsgraphs for every cluster, on clustergraph ClusterArray<Graph*> l_clusterRepGraph(CG, nullptr); computeRepresentationGraphs(CG, l_clusterRepGraph); //now we compute the spanning trees on the representation graphs //we should save the selection info on the original edge //are statically on the repgraphedges (we only have edge -> repedge //information) but ClusterArray< EdgeArray<bool> > l_inTree(CG); for(cluster c : CG.clusters) { l_inTree[c].init(*l_clusterRepGraph[c], false); //compute STs NodeArray<bool> visited(*l_clusterRepGraph[c], false); dfsBuildSpanningTree(l_clusterRepGraph[c]->firstNode(), l_inTree[c], visited); } OGDF_ASSERT(isConnected(CG.constGraph())); //compute the subclustered graph by constructing a spanning tree //using only the representation edges used in STs on the repgraphs NodeArray<bool> visited(CG, false); dfsBuildOriginalST(CG.constGraph().firstNode(), l_inTree, inST, visited); //unregister the edgearrays to avoid destructor failure after //representation graph deletion for(cluster c : CG.clusters) { l_inTree[c].init(); } deleteRepresentationGraphs(CG, l_clusterRepGraph); }
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)); }