void SchnyderLayout::schnyderEmbedding( GraphCopy& GC, GridLayout &gridLayout, adjEntry adjExternal) { NodeArray<int> &xcoord = gridLayout.x(); NodeArray<int> &ycoord = gridLayout.y(); node v; List<node> L; // (un)contraction order GraphCopy T = GraphCopy(GC); // the realizer tree (reverse direction of edges!!!) EdgeArray<int> rValues(T); // the realizer values // choose outer face a,b,c adjEntry adja; if (adjExternal != 0) { edge eG = adjExternal->theEdge(); edge eGC = GC.copy(eG); adja = (adjExternal == eG->adjSource()) ? eGC->adjSource() : eGC->adjTarget(); } else { adja = GC.firstEdge()->adjSource(); } adjEntry adjb = adja->faceCyclePred(); adjEntry adjc = adjb->faceCyclePred(); node a = adja->theNode(); node b = adjb->theNode(); node c = adjc->theNode(); node a_in_T = T.copy(GC.original(a)); node b_in_T = T.copy(GC.original(b)); node c_in_T = T.copy(GC.original(c)); contract(GC, a, b, c, L); realizer(GC, L, a, b, c, rValues, T); NodeArray<int> t1(T); NodeArray<int> t2(T); NodeArray<int> val(T, 1); NodeArray<int> P1(T); NodeArray<int> P3(T); NodeArray<int> v1(T); NodeArray<int> v2(T); subtreeSizes(rValues, 1, a_in_T, t1); subtreeSizes(rValues, 2, b_in_T, t2); prefixSum(rValues, 1, a_in_T, val, P1); prefixSum(rValues, 3, c_in_T, val, P3); // now Pi = depth of all nodes in Tree T(i) (depth[root] = 1) prefixSum(rValues, 2, b_in_T, t1, v1); // special treatment for a v1[a_in_T] = t1[a_in_T]; /* * v1[v] now is the sum of the * "count of nodes in t1" minus the "subtree size for node x" * for every node x on a path from b to v in t2 */ prefixSum(rValues, 3, c_in_T, t1, val); // special treatment for a val[a_in_T] = t1[a_in_T]; /* * val[v] now is the sum of the * "count of nodes in t1" minus the "subtree size for node x" * for every node x on a path from c to v in t3 */ // r1[v]=v1[v]+val[v]-t1[v] is the number of nodes in region 1 from v forall_nodes(v, T) { // calc v1' v1[v] += val[v] - t1[v] - P3[v]; }
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; }