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