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)); }
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); } } }
int main() { struct node *END; int A,B; int c1,c2; //adjaceny graph struct node *adj[MAX_VERT+5]; struct node *t; struct order *values; int i,j; int *visited; int NV,NE; int ncases; scanf("%d",&ncases); while(ncases) { scanf("%d %d",&NV,&NE); END=(struct node*)malloc(sizeof(*END)); END->next=END; //points each node to the END node for(i=0;i<=NV;i++) { adj[i]=END; } for(i=0;i<NE;i++) { scanf("%d %d",&A,&B); c1=A;c2=B; t=(struct node*)malloc(sizeof(*t)); t->V=c2;t->next=adj[c1];adj[c1]=t; } // print_adj(adj,NV); values=pre_post(adj,NV); // for(i=1;i<=NV;i++) { // printf("%2d ",i); // } // printf("\n"); // for(i=1;i<=NV;i++) { // printf("%2d ",values[i].pre); // } // printf("\n"); // for(i=1;i<=NV;i++) { // printf("%2d ",values[i].post); // } // printf("\n"); // printf("Checking cyclic\n"); if(isAcyclic(adj,values,NV)) { printf("1 "); } else { printf("-1 "); } // printf("\n"); ncases--; } printf("\n"); return 0; }
// test if graphAcyclicTest plus edges in tmpAugmented is acyclic // removes added edges again bool UpwardPlanarSubgraphSimple::checkAcyclic( GraphCopySimple &graphAcyclicTest, SList<Tuple2<node,node> > &tmpAugmented) { SListPure<edge> added; SListConstIterator<Tuple2<node,node> > it; for(it = tmpAugmented.begin(); it.valid(); ++it) added.pushBack(graphAcyclicTest.newEdge( graphAcyclicTest.copy((*it).x1()), graphAcyclicTest.copy((*it).x2()))); bool acyclic = isAcyclic(graphAcyclicTest); SListConstIterator<edge> itE; for(itE = added.begin(); itE.valid(); ++itE) graphAcyclicTest.delEdge(*itE); return acyclic; }
bool splitOffAnchoredAcyclic(RoseBuild &rose, const NGHolder &h, const CompileContext &cc) { if (!cc.grey.allowAnchoredAcyclic) { return false; } if (!isAnchored(h)) { DEBUG_PRINTF("fail, not anchored\n"); return false; } if (!isAcyclic(h)) { DEBUG_PRINTF("fail, not acyclic\n"); return false; } if (rose.addAnchoredAcyclic(h)) { return true; } else { DEBUG_PRINTF("failed to add anchored nfa\n"); return false; } }
void aiContext::getTimeSampling(int i, aiTimeSamplingData& dst) { auto ts = m_archive.getTimeSampling(i); auto tst = ts->getTimeSamplingType(); dst.numTimes = (int)ts->getNumStoredTimes(); if (tst.isUniform() || tst.isCyclic()) { int numCycles = int(m_archive.getMaxNumSamplesForTimeSamplingIndex(i) / tst.getNumSamplesPerCycle()); dst.type = tst.isUniform() ? aiTimeSamplingType_Uniform : aiTimeSamplingType_Cyclic; dst.interval = (float)tst.getTimePerCycle(); dst.startTime = (float)ts->getStoredTimes()[0]; dst.endTime = dst.startTime + dst.interval * (numCycles - 1); dst.numTimes = (int)ts->getNumStoredTimes(); dst.times = const_cast<double*>(&ts->getStoredTimes()[0]); } else if (tst.isAcyclic()) { dst.type = aiTimeSamplingType_Acyclic; dst.startTime = (float)ts->getSampleTime(0); dst.endTime = (float)ts->getSampleTime(ts->getNumStoredTimes() - 1); dst.numTimes = (int)ts->getNumStoredTimes(); dst.times = const_cast<double*>(&ts->getStoredTimes()[0]); } }
void OptimalRanking::doCall( const Graph& G, NodeArray<int> &rank, EdgeArray<bool> &reversed, const EdgeArray<int> &length, const EdgeArray<int> &costOrig) { MinCostFlowReinelt<int> mcf; // construct min-cost flow problem GraphCopy GC; GC.createEmpty(G); // compute connected component of G NodeArray<int> component(G); int numCC = connectedComponents(G,component); // intialize the array of lists of nodes contained in a CC Array<List<node> > nodesInCC(numCC); for(node v : G.nodes) nodesInCC[component[v]].pushBack(v); EdgeArray<edge> auxCopy(G); rank.init(G); for(int i = 0; i < numCC; ++i) { GC.initByNodes(nodesInCC[i], auxCopy); makeLoopFree(GC); for(edge e : GC.edges) if(reversed[GC.original(e)]) GC.reverseEdge(e); // special cases: if(GC.numberOfNodes() == 1) { rank[GC.original(GC.firstNode())] = 0; continue; } else if(GC.numberOfEdges() == 1) { edge e = GC.original(GC.firstEdge()); rank[e->source()] = 0; rank[e->target()] = length[e]; continue; } EdgeArray<int> lowerBound(GC,0); EdgeArray<int> upperBound(GC,mcf.infinity()); EdgeArray<int> cost(GC); NodeArray<int> supply(GC); for(edge e : GC.edges) cost[e] = -length[GC.original(e)]; for(node v : GC.nodes) { int s = 0; edge e; forall_adj_edges(e,v) { if(v == e->source()) s += costOrig[GC.original(e)]; else s -= costOrig[GC.original(e)]; } supply[v] = s; } OGDF_ASSERT(isAcyclic(GC) == true); // find min-cost flow EdgeArray<int> flow(GC); NodeArray<int> dual(GC); #ifdef OGDF_DEBUG bool feasible = #endif mcf.call(GC, lowerBound, upperBound, cost, supply, flow, dual); OGDF_ASSERT(feasible); for(node v : GC.nodes) rank[GC.original(v)] = dual[v]; } }
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)); }
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)); }
newEdge(m_topNode[c], vH); newEdge(vH, m_bottomNode[c]); } forall_clusters(c,CG) { if(c != CG.rootCluster()) { cluster u = c->parent(); newEdge(m_topNode[u], m_topNode[c]); newEdge(m_bottomNode[c], m_bottomNode[u]); newEdge(m_topNode[c], m_bottomNode[c]); } } OGDF_ASSERT(isAcyclic(*this)); // preparation for improved test for cycles m_aeLevel.init(*this, -1); int count = 0; assignAeLevel(CG.rootCluster(), count); m_aeVisited.init(*this, false); // Add adjacency edges edge e; forall_edges(e, G) { edge eH = addEdge(m_copy[e->source()], m_copy[e->target()], true); m_copyEdge[e].pushBack(eH); m_origEdge[eH] = e;
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; }