//insert a copy for original node v void SimpleIncNodeInserter::insertCopyNode(node v, Graph::NodeType vTyp) { OGDF_ASSERT(m_planRep->copy(v) == 0) //insert a new node copy node vCopy = m_planRep->newCopy(v, vTyp); if (v->degree() == 0) return; //insert all adjacent edges to already inserted nodes adjEntry adjOrig = v->firstAdj(); do { node wOrig = adjOrig->twinNode(); node wCopy = m_planRep->copy(wOrig); edge e = adjOrig->theEdge(); if (wCopy && (m_planRep->chain(e).size() == 0)) { //inserted edge copy //edge eCopy; //newCopy can cope with zero value for adjEntry if (v == e->source()) /* eCopy = */ m_planRep->newCopy(vCopy, wCopy->firstAdj(), e); else /* eCopy = */ m_planRep->newCopy(wCopy, vCopy->firstAdj(), e); //TODO: update component number in planrepinc }//if edge to be inserted adjOrig = adjOrig->cyclicSucc(); } while (adjOrig != v->firstAdj()); }//insertCopyNode
void LCA::dfs(const Graph &G, node root) { OGDF_ASSERT(isSimple(G)); OGDF_ASSERT(isArborescence(G)); List< std::pair<node,int> > todo; List< adjEntry > adjStack; int dfscounter = 0; todo.pushBack(std::pair<node,int>(root, 0)); adjStack.pushBack(root->firstAdj()); while (!todo.empty()) { const node u = todo.back().first; const int level = todo.back().second; adjEntry adj = adjStack.popBackRet(); m_euler[dfscounter] = u; m_level[dfscounter] = level; m_representative[u] = dfscounter; while (adj && adj->theEdge()->source() != u) { adj = adj->succ(); } if (adj) { node v = adj->twinNode(); adjStack.pushBack(adj->succ()); todo.pushBack(std::pair<node,int>(v, level + 1)); adjStack.pushBack(v->firstAdj()); } else { todo.popBack(); } ++dfscounter; } }
void EmbedderOptimalFlexDraw::optimizeOverEmbeddings( StaticPlanarSPQRTree &T, node parent, node mu, int bends, NodeArray<int> cost[], NodeArray<long long> embedding[]) { cost[bends][mu] = numeric_limits<int>::max(); long long embeddingsCount = T.numberOfNodeEmbeddings(mu); for (long long currentEmbedding = 0; currentEmbedding < embeddingsCount; ++currentEmbedding) { T.embed(mu, currentEmbedding); Skeleton &skeleton = T.skeleton(mu); Graph skeletonGraph = skeleton.getGraph(); ConstCombinatorialEmbedding skeletonEmbedding(skeletonGraph); NodeArray<node> vertexNode(skeletonGraph); EdgeArray<node> edgeNode(skeletonGraph); FaceArray<node> faceNode(skeletonEmbedding); Graph N; EdgeArray<int> upper(N); EdgeArray<int> perUnitCost(N); NodeArray<int> supply(N); createNetwork( parent, mu, bends, cost, embedding, skeleton, edgeNode, N, upper, perUnitCost, supply); EdgeArray<int> lower(N, 0); EdgeArray<int> flow(N); NodeArray<int> dual(N); m_minCostFlowComputer.get().call(N, lower, upper, perUnitCost, supply, flow, dual); int currentCost = 0; for (edge e = N.firstEdge(); e != nullptr; e = e->succ()) currentCost += perUnitCost[e] * flow[e]; for (adjEntry adj = mu->firstAdj(); adj != nullptr; adj = adj->succ()) currentCost += cost[0][adj->twinNode()]; if (currentCost < cost[bends][mu]) { cost[bends][mu] = currentCost; embedding[bends][mu] = currentEmbedding; } } }
forall_nodes(v, primalGraph) { edge ePrimal = v->firstAdj()->theEdge(); edge eDual = m_dualEdge[ePrimal]; face fDual = rightFace(eDual->adjSource()); if(ePrimal->source()==v) fDual = leftFace(eDual->adjSource()); m_dualFace[v] = fDual; m_primalNode[fDual] = v; }
//compute a drawing of the clique around node center and save its size //the call to circular will later be replaced by an dedicated computation DRect UMLGraph::circularBound(node center) { //TODO: hier computecliqueposition(0,...) benutzen, rest weglassen DRect bb; CircularLayout cl; Graph G; GraphAttributes AG(G); NodeArray<node> umlOriginal(G); //TODO: we need to assure that the circular drawing //parameters fit the drawing parameters of the whole graph //umlgraph clique parameter members? OGDF_ASSERT(center->degree() > 0) node lastNode = nullptr; node firstNode = nullptr; adjEntry ae = center->firstAdj(); do { node w = ae->twinNode(); node v = G.newNode(); umlOriginal[v] = w; if (!firstNode) firstNode = v; AG.width(v) = width(w); AG.height(v) = height(w); ae = ae->cyclicSucc(); if (lastNode != nullptr) G.newEdge(lastNode, v); lastNode = v; } while (ae != center->firstAdj()); G.newEdge(lastNode, firstNode); cl.call(AG); for(node v : G.nodes) { m_cliqueCirclePos[umlOriginal[v]] = DPoint(AG.x(v), AG.y(v)); } bb = AG.boundingBox(); return bb; }//circularBound
//************************************************************* // checks whether node is a proper dummy node // proper dummy means that node is marked as dummy and // incident edges have at least one common input graph bool SimDraw::isProperDummy(node v) const { if(!isDummy(v)) return false; int sgb = m_GA.subGraphBits(v->firstAdj()->theEdge()); edge e; forall_adj_edges(e, v) sgb &= m_GA.subGraphBits(e); return (sgb != 0); } // end isProperDummy
forall_nodes(v,PG) { if (PG.typeOf(v) == PlanRepUML::dummy && v->degree() == 4) { adjEntry adj = v->firstAdj(); edge e1 = adj->theEdge(); edge e2 = adj->succ()->theEdge(); if (PG.typeOf(e1) == Graph::generalization && PG.typeOf(e2) == Graph::generalization) return false; } }
void EmbedderOptimalFlexDraw::computePrincipalSplitComponentCost( StaticPlanarSPQRTree &T, NodeArray<int> cost[], NodeArray<long long> embedding[], node parent, node mu) { for (adjEntry adj = mu->firstAdj(); adj != nullptr; adj = adj->succ()) if (adj->twinNode() != parent) computePrincipalSplitComponentCost(T, cost, embedding, mu, adj->twinNode()); for (int bends = 0; bends < 4; ++bends) optimizeOverEmbeddings(T, parent, mu, bends, cost, embedding); }
void PlanRep::removeCrossing(node v) { OGDF_ASSERT(v->degree() == 4) OGDF_ASSERT(isCrossingType(v)) adjEntry a1 = v->firstAdj(); adjEntry b1 = a1->cyclicSucc(); adjEntry a2 = b1->cyclicSucc(); adjEntry b2 = a2->cyclicSucc(); removeUnnecessaryCrossing(a1, a2, b1, b2); }//removeCrossing
void CombinatorialEmbedding::removeDeg1(node v) { OGDF_ASSERT(v->degree() == 1); adjEntry adj = v->firstAdj(); face f = m_rightFace[adj]; if (f->entries.m_adjFirst == adj || f->entries.m_adjFirst == adj->twin()) f->entries.m_adjFirst = adj->faceCycleSucc(); f->m_size -= 2; m_pGraph->delNode(v); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); }
void MinCut::contraction(node t, node s) { /* * The contraction of the two nodes \as and \a t is performed as follows: * in the first step, all edges between \a s and \a t are deleted, and all edges incident * to \a s are redirected to \a t. Then, node \a s is deleted and the adjacency list of \a t * is checked for parallel edges. If k parallel edges are found, k-1 of them are deleted * and their weights are added to the edge that is left. */ // Step 1: redirecting edges and deleting node \a s adjEntry adj = s->firstAdj(); while (adj != 0) { adjEntry succ = adj->succ(); edge e = adj->theEdge(); if (e->source() == t || e->target() == t) { m_GC.delEdge(e); } else if (e->source() == s) { m_GC.moveSource(e,t); } else { m_GC.moveTarget(e,t); } adj = succ; } m_GC.delNode(s); /* * Because of technical problems that occur when deleting edges and thus adjacency entries in a loop, * a NodeArray is filled with the edges incident to node \a t. * This NodeArray is checked for entries with more than one edge, which corresponds * to parallel edges. */ // NodeArray containing parallel edges NodeArray<List<edge> > adjNodes(m_GC); forall_adj(adj,t) { adjNodes[adj->twinNode()].pushBack(adj->theEdge()); }
// calculates the lowpoints void BoyerMyrvoldInit::computeLowPoints() { node w; adjEntry adj,lastAdj; for (int i = m_g.numberOfNodes(); i >= 1; --i) { const node v = m_nodeFromDFI[i]; // initialize lowpoints with least Ancestors and highpoints with dfi of node m_lowPoint[v] = m_leastAncestor[v]; if (m_embeddingGrade > BoyerMyrvoldPlanar::doNotFind) m_highestSubtreeDFI[v] = i; // set the lowPoint of v by minimizing over its children lowPoints // create virtual vertex for each child adj = v->firstAdj(); while (adj) { lastAdj = adj; adj = adj->succ(); // avoid self-loops, parallel- and backedges if (m_edgeType[lastAdj->theEdge()] != EDGE_DFS) continue; w = lastAdj->twinNode(); // avoid parent dfs-node if (m_dfi[w] <= i) continue; // set lowPoints and highpoints if (m_lowPoint[w] < m_lowPoint[v]) m_lowPoint[v] = m_lowPoint[w]; if (m_embeddingGrade > BoyerMyrvoldPlanar::doNotFind && m_highestSubtreeDFI[w] > m_highestSubtreeDFI[v]) m_highestSubtreeDFI[v] = m_highestSubtreeDFI[w]; // create virtual vertex for each dfs-child createVirtualVertex(lastAdj); } } }
void EmbedderOptimalFlexDraw::createNetwork( node parent, node mu, int bends, NodeArray<int> cost[], NodeArray<long long> embedding[], Skeleton &skeleton, EdgeArray<node> &edgeNode, Graph &N, EdgeArray<int> &upper, EdgeArray<int> &perUnitCost, NodeArray<int> &supply) { Graph skeletonGraph = skeleton.getGraph(); ConstCombinatorialEmbedding skeletonEmbedding(skeletonGraph); NodeArray<node> vertexNode(skeletonGraph); FaceArray<node> faceNode(skeletonEmbedding); for (node v = skeletonGraph.firstNode(); v != nullptr; v = v->succ()) { vertexNode[v] = N.newNode(); supply[vertexNode[v]] = 4 - skeleton.original(v)->degree() - v->degree(); } if (parent != nullptr) { node s = skeleton.referenceEdge()->source(); node t = skeleton.referenceEdge()->target(); supply[vertexNode[s]] = 2 - s->degree(); supply[vertexNode[t]] = 2 - t->degree(); } for (edge e = skeletonGraph.firstEdge(); e != nullptr; e = e->succ()) { if (skeleton.isVirtual(e)) { edgeNode[e] = N.newNode(); PertinentGraph H; skeleton.owner().pertinentGraph(skeleton.twinTreeNode(e), H); node s = H.original(e)->source(); node t = H.original(e)->target(); supply[edgeNode[e]] = s->degree() + t->degree() - 2; } } for (face f = skeletonEmbedding.firstFace(); f != nullptr; f = f->succ()) { faceNode[f] = N.newNode(); supply[faceNode[f]] = 4; } if (parent != nullptr) { face f1 = nullptr; face f2 = nullptr; for (adjEntry adj : skeletonEmbedding.externalFace()->entries) { if (adj->theEdge() == skeleton.referenceEdge()) { f1 = skeletonEmbedding.rightFace(adj); f2 = skeletonEmbedding.leftFace(adj); break; } } PertinentGraph H; skeleton.owner().pertinentGraph(mu, H); node s = skeleton.referenceEdge()->source(); node t = skeleton.referenceEdge()->target(); supply[faceNode[f1]] = H.original(s)->degree() + H.original(t)->degree() - 2 + bends; supply[faceNode[f2]] = -bends; } else { supply[faceNode[skeletonEmbedding.externalFace()]] = -4; } for (face f = skeletonEmbedding.firstFace(); f != nullptr; f = f->succ()) { for (adjEntry adj = f->firstAdj(); adj != nullptr; adj = adj->succ()) { edge e1 = N.newEdge(faceNode[f], vertexNode[adj->theNode()]); upper[e1] = 1; perUnitCost[e1] = 0; edge e2 = N.newEdge(vertexNode[adj->theNode()], faceNode[f]); upper[e2] = 1; perUnitCost[e2] = 0; } } for (face f = skeletonEmbedding.firstFace(); f != nullptr; f = f->succ()) { for (adjEntry adj = f->firstAdj(); adj != nullptr; adj = adj->succ()) { edge e = N.newEdge(edgeNode[adj->theEdge()], faceNode[f]); upper[e] = numeric_limits<int>::max(); perUnitCost[e] = 0; } } for (face f = skeletonEmbedding.firstFace(); f != nullptr; f = f->succ()) { for (adjEntry adj = f->firstAdj(); adj != nullptr; adj = adj->succ()) { if (skeleton.isVirtual(adj->theEdge())) { node mu = skeleton.twinTreeNode(adj->theEdge()); edge e0 = N.newEdge(faceNode[f], edgeNode[adj->theEdge()]); upper[e0] = 1; perUnitCost[e0] = cost[0][mu]; edge e1 = N.newEdge(faceNode[f], edgeNode[adj->theEdge()]); upper[e1] = 1; perUnitCost[e0] = cost[1][mu] - cost[0][mu]; edge e2 = N.newEdge(faceNode[f], edgeNode[adj->theEdge()]); upper[e2] = 1; perUnitCost[e2] = cost[2][mu] - cost[1][mu]; edge e3 = N.newEdge(faceNode[f], edgeNode[adj->theEdge()]); upper[e3] = 1; perUnitCost[e3] = cost[3][mu] - cost[2][mu]; for (adjEntry adj= mu->firstAdj(); adj != nullptr; adj = adj->succ()) { if (adj->twinNode() != mu) { perUnitCost[e0] -= cost[0][adj->twinNode()]; perUnitCost[e1] -= cost[0][adj->twinNode()]; perUnitCost[e2] -= cost[0][adj->twinNode()]; perUnitCost[e3] -= cost[0][adj->twinNode()]; } } } else { edge e0 = N.newEdge(faceNode[f], edgeNode[adj->theEdge()]); upper[e0] = 1; perUnitCost[e0] = m_cost[0][adj->theEdge()]; edge e1 = N.newEdge(faceNode[f], edgeNode[adj->theEdge()]); upper[e1] = 1; perUnitCost[e1] = m_cost[1][adj->theEdge()] - m_cost[0][adj->theEdge()]; edge e2 = N.newEdge(faceNode[f], edgeNode[adj->theEdge()]); upper[e2] = 1; perUnitCost[e2] = m_cost[2][adj->theEdge()] - m_cost[1][adj->theEdge()]; edge e3 = N.newEdge(faceNode[f], edgeNode[adj->theEdge()]); upper[e3] = 1; perUnitCost[e3] = m_cost[3][adj->theEdge()] - m_cost[2][adj->theEdge()]; } } } }