Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

NonPlanarCore.h
Go to the documentation of this file.
1 
33 #pragma once
34 
35 #include <ogdf/basic/Queue.h>
40 
41 namespace ogdf {
42 
44 
64 template<typename TCost = int>
66  template<typename T>
67  friend class GlueMap;
68 
69 public:
74  struct CutEdge {
75  const edge e;
76  const bool dir;
77 
78  CutEdge(edge paramEdge, bool directed) : e(paramEdge), dir(directed) {};
79  };
80 
91  explicit NonPlanarCore(const Graph& G, bool nonPlanarityGuaranteed = false);
92 
98  NonPlanarCore(const Graph& G, const EdgeArray<TCost>& weight,
99  bool nonPlanarityGuaranteed = false);
100 
108  NonPlanarCore(const Graph& G, const EdgeArray<TCost>& weight,
109  MinSTCutModule<TCost>* minSTCutModule, bool nonPlanarityGuaranteed = false);
110 
112  const Graph& core() const { return m_graph; }
113 
115  const Graph& originalGraph() const { return *m_pOriginal; }
116 
118  node original(node v) const { return m_orig[v]; }
119 
122  List<edge> res;
123  if (isVirtual(e)) {
124  EdgeArray<edge> origEdgesOfThisSTComponent(*mapE(e));
125  for (edge eInCop : origEdgesOfThisSTComponent.graphOf()->edges) {
126  if (origEdgesOfThisSTComponent[eInCop] != nullptr) {
127  res.pushBack(origEdgesOfThisSTComponent[eInCop]);
128  }
129  }
130  } else {
131  res.pushBack(realEdge(e));
132  }
133  return res;
134  }
135 
137  bool isVirtual(edge e) const { return m_real[e] == nullptr; }
138 
140  edge realEdge(edge e) const { return m_real[e]; }
141 
146  const EdgeArray<TCost>& cost() const { return m_cost; }
147 
152  node tNode(edge e) const { return m_tNode[e]; }
153 
158  node sNode(edge e) const { return m_sNode[e]; }
159 
163  EdgeArray<edge>* mapE(edge e) const { return m_mapE[e]; }
164 
169  TCost cost(edge e) const { return m_cost[e]; }
170 
172  const List<CutEdge>& mincut(edge e) const { return m_mincut[e]; }
173 
174  // destructor
175  virtual ~NonPlanarCore();
176 
178 
184  void retransform(const GraphCopy& planarCore, GraphCopy& planarGraph, bool pCisPlanar = true);
185 
186 protected:
188  void call(const Graph& G, const EdgeArray<TCost>* weight, MinSTCutModule<TCost>* minSTCutModule,
189  bool nonPlanarityGuaranteed);
190 
199  void getAllMultiedges(List<edge>& winningEdges, List<edge>& losingEdges);
200 
217  void traversingPath(const Skeleton& Sv, edge eS, List<CutEdge>& path, NodeArray<node>& mapV,
218  edge coreEdge, const EdgeArray<TCost>* weight_src, MinSTCutModule<TCost>* minSTCutModule);
219 
228  void splitEdgeIntoSections(edge e, List<node>& splitdummies);
229 
234  void removeSplitdummies(List<node>& splitdummies);
235 
243  void normalizeCutEdgeDirection(edge coreEdge);
244 
252  void importEmbedding(edge e);
253 
260  void markCore(NodeArray<bool>& mark);
261 
266  void inflateCrossing(node v);
267 
275  void getMincut(edge e, List<edge>& cut);
276 
285  void glue(edge eWinner, edge eLoser);
286 
293  void glueMincuts(edge eWinner, edge eLoser);
294 
297 
300 
306 
312 
315 
318 
321 
324 
327 
330 
333 
336 
339 
342 };
343 
347 template<typename TCost>
348 class GlueMap {
349 public:
359  GlueMap(edge eWinner, edge eLoser, NonPlanarCore<TCost>& npc);
360 
364  void mapLoserToNewWinnerEdge(edge eInLoser);
365 
369  void mapLoserToWinnerNode(node vInLoser, node vInWinner);
370 
374  void mapLoserToNewWinnerNode(node vInLoser);
375 
386  void reorder(node vLoser, bool sameDirection, bool isTNodeOfPNode);
387 
394 
399  const Graph& getLoserGraph() const { return *m_gLoser; }
400 
401 protected:
407  const edge m_eLoser;
411  const Graph* m_gLoser;
424 };
425 
426 template<typename TCost>
427 NonPlanarCore<TCost>::NonPlanarCore(const Graph& G, bool nonPlanarityGuaranteed)
428  : m_pOriginal(&G)
429  , m_orig(m_graph)
430  , m_real(m_graph, nullptr)
431  , m_mincut(m_graph)
432  , m_cost(m_graph)
433  , m_T(G)
434  , m_mapV(m_graph, nullptr)
435  , m_mapE(m_graph, nullptr)
436  , m_underlyingGraphs(m_graph, nullptr)
437  , m_sNode(m_graph)
438  , m_tNode(m_graph) {
439  MinSTCutBFS<TCost> minSTCutBFS;
440  call(G, nullptr, &minSTCutBFS, nonPlanarityGuaranteed);
441 }
442 
443 template<typename TCost>
445  MinSTCutModule<TCost>* minSTCutModule, bool nonPlanarityGuaranteed)
446  : m_pOriginal(&G)
447  , m_orig(m_graph)
448  , m_real(m_graph, nullptr)
449  , m_mincut(m_graph)
450  , m_cost(m_graph)
451  , m_T(G)
452  , m_mapV(m_graph, nullptr)
453  , m_mapE(m_graph, nullptr)
454  , m_underlyingGraphs(m_graph, nullptr)
455  , m_sNode(m_graph)
456  , m_tNode(m_graph) {
457  call(G, &weight, minSTCutModule, nonPlanarityGuaranteed);
458 }
459 
460 template<typename TCost>
462  bool nonPlanarityGuaranteed)
463  : m_pOriginal(&G)
464  , m_orig(m_graph)
465  , m_real(m_graph, nullptr)
466  , m_mincut(m_graph)
467  , m_cost(m_graph)
468  , m_T(G)
469  , m_mapV(m_graph, nullptr)
470  , m_mapE(m_graph, nullptr)
471  , m_underlyingGraphs(m_graph, nullptr)
472  , m_sNode(m_graph)
473  , m_tNode(m_graph) {
474  MinSTCutDijkstra<TCost> minSTCutDijkstra;
475  call(G, &weight, &minSTCutDijkstra, nonPlanarityGuaranteed);
476 }
477 
478 template<typename TCost>
480  for (auto pointer : m_mapE) {
481  delete pointer;
482  }
483  for (auto pointer : m_mapV) {
484  delete pointer;
485  }
486  for (auto pointer : m_underlyingGraphs) {
487  delete pointer;
488  }
489 }
490 
491 template<typename TCost>
492 void NonPlanarCore<TCost>::call(const Graph& G, const EdgeArray<TCost>* weight,
493  MinSTCutModule<TCost>* minSTCutModule, bool nonPlanarityGuaranteed) {
494  if (!nonPlanarityGuaranteed && isPlanar(G)) {
495  return;
496  }
497  OGDF_ASSERT(!isPlanar(G));
499 
500  // mark tree nodes in the core
501  NodeArray<bool> mark;
502  markCore(mark);
503 
504  NodeArray<node> map(G, nullptr);
505  NodeArray<node> mapAux(G, nullptr);
506  const Graph& tree = m_T.tree();
507 
508  for (node v : tree.nodes) {
509  if (!mark[v]) {
510  continue;
511  }
512 
513  Skeleton& S = m_T.skeleton(v);
514 
515  for (edge e : S.getGraph().edges) {
516  node src = S.original(e->source());
517  node tgt = S.original(e->target());
518 
519  if (tgt == src) {
520  continue;
521  }
522 
523  if (map[src] == nullptr) {
524  m_orig[map[src] = m_graph.newNode()] = S.original(e->source());
525  }
526 
527  if (map[tgt] == nullptr) {
528  m_orig[map[tgt] = m_graph.newNode()] = S.original(e->target());
529  }
530 
531  if (S.isVirtual(e)) {
532  node w = S.twinTreeNode(e);
533 
534  if (!mark[w]) {
535  // new virtual edge in core graph
536  edge lastCreatedEdge = m_graph.newEdge(map[src], map[tgt]);
537  m_real[lastCreatedEdge] = nullptr;
538  traversingPath(S, e, m_mincut[lastCreatedEdge], mapAux, lastCreatedEdge, weight,
539  minSTCutModule);
540  }
541  } else {
542  // new real edge in core graph
543  edge lastCreatedEdge = m_graph.newEdge(map[src], map[tgt]);
544  m_real[lastCreatedEdge] = S.realEdge(e);
545  traversingPath(S, e, m_mincut[lastCreatedEdge], mapAux, lastCreatedEdge, weight,
546  minSTCutModule);
547  }
548  }
549  }
550 
551  if (weight != nullptr) {
552  for (edge e : m_graph.edges) {
553  TCost cost(0);
554  for (auto cutEdge : m_mincut[e]) {
555  cost += (*weight)[cutEdge.e];
556  }
557  m_cost[e] = cost;
558  }
559  } else {
560  for (edge e : m_graph.edges) {
561  m_cost[e] = m_mincut[e].size();
562  }
563  }
564 
565  List<node> allNodes;
566  m_graph.allNodes(allNodes);
567 
568  // The while loop is used to eliminate multiedges from the core. We're pruning P-Nodes.
569  List<edge> winningMultiEdges;
570  List<edge> losingMultiEdges;
571  getAllMultiedges(winningMultiEdges, losingMultiEdges);
572  while (!winningMultiEdges.empty() && !losingMultiEdges.empty()) {
573  edge winningMultiEdge = winningMultiEdges.popFrontRet();
574  edge losingMultiEdge = losingMultiEdges.popFrontRet();
575 #ifdef OGDF_DEBUG
576  int sizeOfWinCut = m_mincut[winningMultiEdge].size();
577  int sizeOfLosCut = m_mincut[losingMultiEdge].size();
578 #endif
579 
580  glue(winningMultiEdge, losingMultiEdge);
581  glueMincuts(winningMultiEdge, losingMultiEdge);
582 
583  OGDF_ASSERT(m_mincut[winningMultiEdge].size() == sizeOfWinCut + sizeOfLosCut);
584  delete m_underlyingGraphs[losingMultiEdge];
585  delete m_mapV[losingMultiEdge];
586  delete m_mapE[losingMultiEdge];
587  m_real[winningMultiEdge] = nullptr;
588  m_real[losingMultiEdge] = nullptr;
589  m_graph.delEdge(losingMultiEdge);
590  }
591  // The for loop is used to eliminate deg 2 nodes from the core. We're pruning S-Nodes.
592  for (node v : allNodes) {
593  if (v->degree() != 2) {
594  continue;
595  }
596  edge outEdge = v->firstAdj()->theEdge();
597  edge inEdge = v->lastAdj()->theEdge();
598 
599  if (m_cost[inEdge] > m_cost[outEdge]) {
600  std::swap(inEdge, outEdge);
601  }
602  // We join the embeddings of the underlying embeddings/graphs of both edges
603  // so that outEdge gets integrated into inEdge
604  glue(inEdge, outEdge);
605 
606  m_real[inEdge] = nullptr;
607  m_real[outEdge] = nullptr;
608 
609  adjEntry adjSource = inEdge->adjSource()->cyclicSucc();
610  adjEntry adjTarget = (outEdge->target() == v ? outEdge->adjSource()->cyclicSucc()
611  : outEdge->adjTarget()->cyclicSucc());
612  if (inEdge->target() != v) {
613  adjSource = adjTarget;
614  adjTarget = inEdge->adjTarget()->cyclicSucc();
615  }
616  m_graph.move(inEdge, adjSource, ogdf::Direction::before, adjTarget, ogdf::Direction::before);
617  delete m_underlyingGraphs[outEdge];
618  delete m_mapV[outEdge];
619  delete m_mapE[outEdge];
620  m_graph.delNode(v);
621  }
622 
623 
624  if (nonPlanarityGuaranteed) {
625  OGDF_ASSERT(!isPlanar(m_graph));
626  }
627 }
628 
629 template<typename TCost>
631  const Graph& tree = m_T.tree();
632 
633  // We mark every tree node that belongs to the core
634  mark.init(tree, true); // start with all nodes and unmark planar leaves
635  NodeArray<int> degree(tree);
636 
637  Queue<node> Q;
638 
639  for (node v : tree.nodes) {
640  degree[v] = v->degree();
641  if (degree[v] <= 1) { // also append deg-0 node (T has only one node)
642  Q.append(v);
643  }
644  }
645 
646  while (!Q.empty()) {
647  node v = Q.pop();
648 
649  // if v has a planar skeleton
650  if (m_T.typeOf(v) != SPQRTree::NodeType::RNode || isPlanar(m_T.skeleton(v).getGraph())) {
651  mark[v] = false; // unmark this leaf
652 
653  node w = nullptr;
654  for (adjEntry adj : v->adjEntries) {
655  node x = adj->twinNode();
656  if (mark[x]) {
657  w = x;
658  break;
659  }
660  }
661 
662  if (w != nullptr) {
663  --degree[w];
664  if (degree[w] == 1) {
665  Q.append(w);
666  }
667  }
668  }
669  }
670 }
671 
672 struct QueueEntry {
673  QueueEntry(node p, node v) : m_parent(p), m_current(v) { }
674 
677 };
678 
679 template<typename TCost>
681  NodeArray<node>& mapV, edge coreEdge, const EdgeArray<TCost>* weight_src,
682  MinSTCutModule<TCost>* minSTCutModule) {
683  List<CutEdge>& currPath = path;
684 
685  // Build the graph representing the planar st-component
686  Graph* h_pointer = new Graph();
687  Graph& H = *h_pointer;
688 
689  EdgeArray<edge>* mapE_src_pointer = new EdgeArray<edge>(H, nullptr);
690  EdgeArray<edge>& mapE_src = *mapE_src_pointer;
691  NodeArray<node>* mapV_src_pointer = new NodeArray<node>(H, nullptr);
692  NodeArray<node>& mapV_src = *mapV_src_pointer;
693  SListPure<node> nodes;
694  SListPure<edge> multedges;
695 
696  if (Sv.isVirtual(eS)) {
698  Q.append(QueueEntry(Sv.treeNode(), Sv.twinTreeNode(eS)));
699 
700  while (!Q.empty()) {
701  QueueEntry x = Q.pop();
702  node parent = x.m_parent;
703  node current = x.m_current;
704 
705  const Skeleton& S = m_T.skeleton(current);
706  for (edge e : S.getGraph().edges) {
707  if (S.isVirtual(e)) {
708  continue;
709  }
710 
711  node src = S.original(e->source());
712  node tgt = S.original(e->target());
713 
714  if (mapV[src] == nullptr) {
715  nodes.pushBack(src);
716  mapV[src] = H.newNode();
717  mapV_src[mapV[src]] = src;
718  }
719  if (mapV[tgt] == nullptr) {
720  nodes.pushBack(tgt);
721  mapV[tgt] = H.newNode();
722  mapV_src[mapV[tgt]] = tgt;
723  }
724 
725  edge e_new = H.newEdge(mapV[src], mapV[tgt]);
726  mapE_src[e_new] = S.realEdge(e);
727  OGDF_ASSERT(mapE_src[e_new]->source() != nullptr);
728  }
729 
730  for (adjEntry adj : current->adjEntries) {
731  node w = adj->twinNode();
732  if (w != parent) {
733  Q.append(QueueEntry(current, w));
734  }
735  }
736  }
737  } else {
738  nodes.pushBack(Sv.original(eS->source()));
739  nodes.pushBack(Sv.original(eS->target()));
740  mapV[Sv.original(eS->source())] = H.newNode();
741  mapV_src[mapV[Sv.original(eS->source())]] = Sv.original(eS->source());
742  mapV[Sv.original(eS->target())] = H.newNode();
743  mapV_src[mapV[Sv.original(eS->target())]] = Sv.original(eS->target());
744  mapE_src[H.newEdge(mapV[Sv.original(eS->source())], mapV[Sv.original(eS->target())])] =
745  Sv.realEdge(eS);
746  }
747  // add st-edge
748  edge e_st = H.newEdge(mapV[Sv.original(eS->source())], mapV[Sv.original(eS->target())]);
749  m_sNode[coreEdge] = mapV[Sv.original(eS->source())];
750  m_tNode[coreEdge] = mapV[Sv.original(eS->target())];
751 
752  // Compute planar embedding of H
753 #ifdef OGDF_DEBUG
754  bool ok =
755 #endif
756  planarEmbed(H);
757  OGDF_ASSERT(ok);
759 
760  // we rearange the adj Lists of s and t, so that adj(e_st) is the first adj
761  List<adjEntry> adjListFront;
762  List<adjEntry> adjListBack;
763  e_st->source()->allAdjEntries(adjListFront);
764  if (adjListFront.front() != e_st->adjSource()) {
765  adjListFront.split(adjListFront.search(e_st->adjSource()), adjListFront, adjListBack);
766  adjListFront.concFront(adjListBack);
767  H.sort(e_st->source(), adjListFront);
768  }
769 
770  e_st->target()->allAdjEntries(adjListFront);
771  if (adjListFront.front() != e_st->adjTarget()) {
772  adjListFront.split(adjListFront.search(e_st->adjTarget()), adjListFront, adjListBack,
774  adjListFront.concFront(adjListBack);
775  H.sort(e_st->target(), adjListFront);
776  }
777 
778  if (Sv.isVirtual(eS)) {
779  List<edge> edgeList;
780  if (weight_src != nullptr) {
781  EdgeArray<TCost> weight(H);
782  for (edge e : H.edges) {
783  if (e != e_st) {
784  weight[e] = (*weight_src)[mapE_src[e]];
785  }
786  }
787  minSTCutModule->call(H, weight, e_st->source(), e_st->target(), edgeList, e_st);
788  } else {
789  minSTCutModule->call(H, e_st->source(), e_st->target(), edgeList, e_st);
790  }
791  auto it = edgeList.begin();
792  for (; it != edgeList.end(); it++) {
793  currPath.pushBack(CutEdge(mapE_src[*it], minSTCutModule->direction(*it)));
794  }
795  } else {
796  OGDF_ASSERT(Sv.realEdge(eS) != nullptr);
797  currPath.pushFront(CutEdge(Sv.realEdge(eS), true));
798  }
799  H.delEdge(e_st);
800 
801  OGDF_ASSERT(m_underlyingGraphs[coreEdge] == nullptr);
802  m_underlyingGraphs[coreEdge] = h_pointer;
803  OGDF_ASSERT(m_mapE[coreEdge] == nullptr);
804  m_mapE[coreEdge] = mapE_src_pointer;
805  OGDF_ASSERT(m_mapV[coreEdge] == nullptr);
806  m_mapV[coreEdge] = mapV_src_pointer;
807 #ifdef OGDF_DEBUG
808  for (node v : H.nodes) {
809  OGDF_ASSERT(mapV_src[v] != nullptr);
810  }
811  for (edge e : H.edges) {
812  OGDF_ASSERT(mapE_src[e] != nullptr);
813  }
814 #endif
815 
816  for (node v : nodes) {
817  mapV[v] = nullptr;
818  }
819 }
820 
821 template<typename TCost>
823  winningEdges.clear();
824  losingEdges.clear();
825  SListPure<edge> edges;
826  EdgeArray<int> minIndex(m_graph), maxIndex(m_graph);
827  parallelFreeSortUndirected(m_graph, edges, minIndex, maxIndex);
828 
829  SListConstIterator<edge> it = edges.begin();
830  edge ePrev = *it, e;
831  for (it = ++it; it.valid(); ++it, ePrev = e) {
832  e = *it;
833  if (minIndex[ePrev] == minIndex[e] && maxIndex[ePrev] == maxIndex[e]) {
834  winningEdges.pushFront(ePrev);
835  losingEdges.pushFront(e);
836  }
837  }
838 }
839 
840 template<typename TCost>
841 void NonPlanarCore<TCost>::glue(edge eWinner, edge eLoser) {
842  GlueMap<TCost> map(eWinner, eLoser, *this);
843 
844  // true iff this glueing is about a PNode (so a glueing at two common nodes)
845  bool thisIsAboutAPNode = false;
846  if (eLoser->isParallelUndirected(eWinner)) {
847  thisIsAboutAPNode = true;
848  }
849 
850  // find the s- and t-nodes in their skeleton for both of the edges
851  node sWinner = m_sNode[eWinner];
852  node tWinner = m_tNode[eWinner];
853  node sLoser = m_sNode[eLoser];
854  node tLoser = m_tNode[eLoser];
855 
856  bool sameDirection {!eWinner->isInvertedDirected(eLoser)};
857 
858  // we get a list of all nodes of the loser graph
859  List<node> allNodesButSt;
860  map.getLoserGraph().allNodes(allNodesButSt);
861 
862 #ifdef OGDF_DEBUG
863  bool ok = true;
864 #endif
865 
866  // for both s and t of eLoser we check if it's either the s or the t node of eWinner
867  // if one of it is, we delete it from the list of nodes, that are to be added
868  // otherwise it stays in 'allNodesButSt' to be added later
869  if (eLoser->source() == eWinner->source() || eLoser->source() == eWinner->target()) {
870 #ifdef OGDF_DEBUG
871  ok =
872 #endif
873  allNodesButSt.removeFirst(sLoser);
874  OGDF_ASSERT(ok);
875  if (eLoser->source() == eWinner->source()) {
876  map.mapLoserToWinnerNode(sLoser, sWinner);
877  } else {
878  map.mapLoserToWinnerNode(sLoser, tWinner);
879  }
880  OGDF_ASSERT(!allNodesButSt.search(sLoser).valid());
881  }
882  if (eLoser->target() == eWinner->source() || eLoser->target() == eWinner->target()) {
883 #ifdef OGDF_DEBUG
884  ok =
885 #endif
886  allNodesButSt.removeFirst(tLoser);
887  OGDF_ASSERT(ok);
888  if (eLoser->target() == eWinner->source()) {
889  map.mapLoserToWinnerNode(tLoser, sWinner);
890  } else {
891  map.mapLoserToWinnerNode(tLoser, tWinner);
892  }
893  OGDF_ASSERT(!allNodesButSt.search(tLoser).valid());
894  }
895 
896 
897  // insert the remaining nodes of the loser graph into the winner graph
898  for (node v : allNodesButSt) {
900  }
901 
902  // insert all edges of the loser graph into the the winner graph
903  for (edge e : map.getLoserGraph().edges) {
905  }
906 
907  // reorder the adjEntries of every node of the loser graph in the winner graph,
908  // to match the embedding in the loser graph
909  List<node> allNodes = allNodesButSt;
910  allNodes.pushBack(sLoser);
911  allNodes.pushBack(tLoser);
912  for (node v : allNodes) {
913  map.reorder(v, sameDirection, (tLoser == v && thisIsAboutAPNode));
914  }
915  if (!thisIsAboutAPNode) {
916  if (eWinner->source() == eLoser->source()) {
917  m_sNode[eWinner] = map.getWinnerNodeOfLoserNode(tLoser);
918  }
919  if (eWinner->target() == eLoser->source()) {
920  m_tNode[eWinner] = map.getWinnerNodeOfLoserNode(tLoser);
921  }
922  if (eWinner->source() == eLoser->target()) {
923  m_sNode[eWinner] = map.getWinnerNodeOfLoserNode(sLoser);
924  }
925  if (eWinner->target() == eLoser->target()) {
926  m_tNode[eWinner] = map.getWinnerNodeOfLoserNode(sLoser);
927  }
928  }
929 }
930 
931 template<typename TCost>
932 void NonPlanarCore<TCost>::retransform(const GraphCopy& planarCore, GraphCopy& planarGraph,
933  bool pCisPlanar) {
934 #ifdef OGDF_DEBUG
935  GraphCopy copyCore(planarCore);
936  copyCore.removePseudoCrossings();
937  OGDF_ASSERT(copyCore.numberOfNodes() == planarCore.numberOfNodes());
938 #endif
939  m_endGraph = &planarGraph;
940  m_planarCore = &planarCore;
941  OGDF_ASSERT(!pCisPlanar || m_planarCore->genus() == 0);
942  m_endGraph->clear();
943  m_endGraph->setOriginalGraph(*m_pOriginal);
944  List<node> allNodes;
945  m_pOriginal->allNodes(allNodes);
946  EdgeArray<edge> eCopy(*m_pOriginal, nullptr);
947  NodeArray<node> nCopy(*m_pOriginal, nullptr);
948  m_endGraph->insert(allNodes.begin(), allNodes.end(), filter_any_edge, nCopy, eCopy);
949 
950 #ifdef OGDF_DEBUG
951  for (node v : m_endGraph->nodes) {
952  List<adjEntry> adjEntries;
953  v->allAdjEntries(adjEntries);
954  OGDF_ASSERT(v->degree() == adjEntries.size());
955  }
956 #endif
957 
958  // For every node of the core we rearrange the adjacency order of the corresponding endGraph node
959  // according to the planarized core.
960  for (node v : m_planarCore->nodes) {
961  if (m_planarCore->isDummy(v)) {
962  continue;
963  }
964  List<adjEntry> pcOrder;
965  v->allAdjEntries(pcOrder);
966  List<adjEntry> newOrder;
967  node coreNode = m_planarCore->original(v);
968  OGDF_ASSERT(coreNode != nullptr);
969  for (adjEntry adjPC : v->adjEntries) {
970  edge coreEdge = m_planarCore->original(adjPC->theEdge());
971  EdgeArray<edge>& mapE = *m_mapE[coreEdge];
972  NodeArray<node>& mapV = *m_mapV[coreEdge];
973  node stNode = (mapV[m_sNode[coreEdge]] == original(coreNode) ? m_sNode[coreEdge]
974  : m_tNode[coreEdge]);
975  // find the node of emb which represents the same node v represents
976  for (adjEntry adjEmb : stNode->adjEntries) {
977  if (adjEmb->theEdge()->source() == adjEmb->theNode()) {
978  newOrder.pushBack(m_endGraph->copy(mapE[adjEmb->theEdge()])->adjSource());
979  } else {
980  newOrder.pushBack(m_endGraph->copy(mapE[adjEmb->theEdge()])->adjTarget());
981  }
982  }
983  }
984  m_endGraph->sort(m_endGraph->copy(original(coreNode)), newOrder);
985  }
986  if (!pCisPlanar) {
987  for (edge e : m_graph.edges) {
988  importEmbedding(e);
989  }
990  return;
991  } else {
992  List<node> splitdummies;
993  for (edge e : m_graph.edges) {
994  // for every edge from the core we ensure, that the embedding of the subgraph it describes
995  // is the same in both the original and the end graph
996  importEmbedding(e);
997  // reverse all cut edges, which are not the same direction as e
998  normalizeCutEdgeDirection(e);
999  // to ensure the right order of the inserted crossings, we insert dummy nodes
1000  // to split the edge in sections, each of which only has one crossing
1001  splitEdgeIntoSections(e, splitdummies);
1002  }
1003 
1004  // now we can start and insert the crossings of the planar core into the end graph.
1005  // a node represents a crossing if it's a dummy
1006  for (node v : m_planarCore->nodes) {
1007  if (m_planarCore->isDummy(v)) {
1008  inflateCrossing(v);
1009  }
1010  }
1011  OGDF_ASSERT(m_endGraph->genus() == 0);
1012 
1013  removeSplitdummies(splitdummies);
1014  for (edge e : m_graph.edges) {
1015  normalizeCutEdgeDirection(e);
1016  }
1017  }
1018 }
1019 
1020 template<typename TCost>
1022  for (auto cutE : m_mincut[coreEdge]) {
1023  if (!cutE.dir) {
1024  for (edge e : m_endGraph->chain(cutE.e)) {
1025  m_endGraph->reverseEdge(e);
1026  }
1027  }
1028  }
1029 }
1030 
1031 template<typename TCost>
1033  for (node v : splitdummies) {
1034  edge eIn = v->firstAdj()->theEdge();
1035  edge eOut = v->lastAdj()->theEdge();
1036  if (eIn->target() == v) {
1037  m_endGraph->unsplit(eIn, eOut);
1038  } else {
1039  m_endGraph->unsplit(eOut, eIn);
1040  }
1041  }
1042 }
1043 
1044 template<typename TCost>
1046  List<edge> chain = m_planarCore->chain(e);
1047  int chainSize = chain.size();
1048  while (chainSize > 2) {
1049  for (CutEdge cutEdge : mincut(e)) {
1050  splitdummies.pushBack(m_endGraph->split(m_endGraph->copy(cutEdge.e))->source());
1051  }
1052  chainSize--;
1053  }
1054 #ifdef OGDF_DEBUG
1055  for (CutEdge cutEdge : mincut(e)) {
1056  if (chain.size() < 3) {
1057  OGDF_ASSERT(m_endGraph->chain(cutEdge.e).size() == 1);
1058  } else {
1059  OGDF_ASSERT(m_endGraph->chain(cutEdge.e).size() == chain.size() - 1);
1060  }
1061  OGDF_ASSERT(m_endGraph->original(m_endGraph->chain(cutEdge.e).front()) == cutEdge.e);
1062  }
1063 #endif
1064 }
1065 
1066 template<typename TCost>
1068  const Graph& embG = *m_underlyingGraphs[e];
1069  // a map from the nodes of the emb to those in the end graph
1070  const EdgeArray<edge>& mapE_toOrig = *m_mapE[e];
1071  // bc the edges of the end graph are split for the crossing insertion,
1072  // a map of the emb might have more than one edge in the endgraph, we just
1073  // map the AdjEntries of both source and target of each edge of emb
1074  // to AdjEntries in the end graph
1075  const NodeArray<node>& mapV_toOrig = *m_mapV[e];
1076  AdjEntryArray<adjEntry> mapA_toFinal(embG, nullptr);
1077  for (auto it = mapE_toOrig.begin(); it != mapE_toOrig.end(); it++) {
1078  OGDF_ASSERT(it.key() != nullptr);
1079  OGDF_ASSERT((*it) != nullptr);
1080  OGDF_ASSERT((*it)->graphOf() == m_pOriginal);
1081  mapA_toFinal[it.key()->adjSource()] = m_endGraph->chain(*it).front()->adjSource();
1082  mapA_toFinal[it.key()->adjTarget()] = m_endGraph->chain(*it).back()->adjTarget();
1083  }
1084  node s(m_sNode[e]), t(m_tNode[e]);
1085  List<node> nodesOfEmb;
1086  embG.allNodes(nodesOfEmb);
1087  // for every node of emb we order the adjEntries of the corresponding node
1088  // in the end graph, so that both match
1089  for (node v : nodesOfEmb) {
1090  if (v == s || v == t) {
1091  continue;
1092  }
1093  List<adjEntry> rightAdjOrder;
1094  for (adjEntry adj = v->firstAdj(); adj; adj = adj->succ()) {
1095  rightAdjOrder.pushBack(mapA_toFinal[adj]);
1096  }
1097  m_endGraph->sort(m_endGraph->copy(mapV_toOrig[v]), rightAdjOrder);
1098  }
1099 }
1100 
1101 template<typename TCost>
1103  // we want e1 and e2 to be these two edges
1104  // ^
1105  // |
1106  // e2-->v--->
1107  // ^
1108  // |
1109  // e1
1110  edge e1 = v->firstAdj()->theEdge();
1111  while (e1->target() != v) {
1112  e1 = e1->adjSource()->succ()->theEdge();
1113  }
1114  edge e2 = e1->adjTarget()->succ()->theEdge();
1115  while (e2->target() != v) {
1116  e2 = e2->adjSource()->cyclicSucc()->theEdge();
1117  }
1118  if (e1 == e2->adjTarget()->cyclicSucc()->theEdge()) {
1119  edge help = e1;
1120  e1 = e2;
1121  e2 = help;
1122  }
1123  OGDF_ASSERT(e2 == e1->adjTarget()->cyclicSucc()->theEdge());
1124  List<edge> e1cut;
1125  getMincut(e1, e1cut);
1126  List<edge> e2cut;
1127  getMincut(e2, e2cut);
1128  OGDF_ASSERT(e1 != e2);
1129  OGDF_ASSERT(e1cut.size() > 0);
1130  OGDF_ASSERT(e2cut.size() > 0);
1131  // the actual crossing insertion
1132  // for (auto it1 = e1cut.begin(); it1.valid(); it1++)
1133  for (int i = 0; i < e1cut.size(); i++) {
1134  auto it1 = e1cut.get(i);
1135  edge crossingEdge = *it1;
1136  for (int j = 0; j < e2cut.size(); j++) {
1137  auto it2 = e2cut.get(j);
1138  edge crossedEdge = *it2;
1139  m_endGraph->insertCrossing(*it1, crossedEdge, true);
1140  OGDF_ASSERT(crossedEdge == *it2);
1141  e2cut.insertAfter(crossedEdge, it2);
1142  e2cut.del(it2);
1143  }
1144  OGDF_ASSERT(crossingEdge != *it1);
1145  e1cut.insertAfter(crossingEdge, it1);
1146  e1cut.del(it1);
1147  }
1148 }
1149 
1150 template<typename TCost>
1152  OGDF_ASSERT(e->graphOf() == m_planarCore);
1153 
1154  cut.clear();
1155  // chain is a list of the edges of the planar core, that represent e
1156  List<edge> chain = m_planarCore->chain(m_planarCore->original(e));
1157  // this is the main part of this function:
1158  // as we know, the cut edges are split by splitdummies to partition the edge,
1159  // such that every crossing on the edge has its own section to be inserted into (denoted by pos)
1160  // cut_pre stores the first section for every cut edge
1161  for (CutEdge eCut : mincut(m_planarCore->original(e))) {
1162  OGDF_ASSERT(m_endGraph->chain(eCut.e).size() + 1 >= chain.size());
1163  // while iterating we have to differentiate between already inserted crossings and splitdummies
1164  // we can do that, by only counting the deg 2 nodes we pass while iterating through the chain of the cut edge
1165  auto it = m_endGraph->chain(eCut.e).begin();
1166  for (int i = 0; i < chain.pos(chain.search(e)); i++) {
1167  it++;
1168  while ((*it)->source()->degree() == 4) {
1169  it++;
1170  OGDF_ASSERT(it.valid());
1171  }
1172  }
1173  cut.pushBack(*(it));
1174  }
1175  // cut is the result of this function
1176 }
1177 
1178 template<typename TCost>
1180 #ifdef OGDF_DEBUG
1181  if (eWinner->adjSource()->theNode() == eLoser->adjSource()->theNode()) {
1182  OGDF_ASSERT(eWinner->adjSource()->theNode() == eLoser->adjSource()->theNode());
1183  OGDF_ASSERT(eWinner->adjTarget()->theNode() == eLoser->adjTarget()->theNode());
1184  } else {
1185  OGDF_ASSERT(eWinner->adjSource()->theNode() == eLoser->adjTarget()->theNode());
1186  OGDF_ASSERT(eWinner->adjTarget()->theNode() == eLoser->adjSource()->theNode());
1187  }
1188 #endif
1189  List<CutEdge> wincut = m_mincut[eWinner];
1190 
1191  List<CutEdge> losecut = m_mincut[eLoser];
1192 
1193  if (eWinner->source() == eLoser->target()) {
1194  List<CutEdge> newLosecut;
1195  for (auto cutEit = losecut.begin(); cutEit != losecut.end(); cutEit++) {
1196  newLosecut.pushBack(CutEdge((*cutEit).e, !(*cutEit).dir));
1197  }
1198  losecut = newLosecut;
1199  }
1200 
1201  wincut.conc(losecut);
1202  m_mincut[eWinner] = wincut;
1203  m_cost[eWinner] += m_cost[eLoser];
1204 }
1205 
1206 template<typename TCost>
1208  : m_npc(npc), m_eWinner(eWinner), m_eLoser(eLoser) {
1210 
1211  OGDF_ASSERT(m_npc.m_underlyingGraphs[m_eLoser] != nullptr);
1212  OGDF_ASSERT(m_npc.m_underlyingGraphs[m_eWinner] != nullptr);
1213 
1214  m_gLoser = m_npc.m_underlyingGraphs[m_eLoser];
1215  m_gWinner = m_npc.m_underlyingGraphs[m_eWinner];
1216 
1218 
1219  OGDF_ASSERT(m_npc.m_mapV[m_eWinner] != nullptr);
1220  OGDF_ASSERT(m_npc.m_mapV[m_eLoser] != nullptr);
1221 
1222  m_mapVwinner = m_npc.m_mapV[m_eWinner];
1223  m_mapVloser = m_npc.m_mapV[m_eLoser];
1224 
1225  OGDF_ASSERT(m_npc.m_mapE[m_eWinner] != nullptr);
1226  OGDF_ASSERT(m_npc.m_mapE[m_eLoser] != nullptr);
1227 
1228  m_mapEwinner = m_npc.m_mapE[m_eWinner];
1229  m_mapEloser = m_npc.m_mapE[m_eLoser];
1230 
1231  OGDF_ASSERT(m_mapEloser->graphOf() == m_gLoser);
1232  OGDF_ASSERT(m_mapVloser->graphOf() == m_gLoser);
1233 
1234  OGDF_ASSERT(m_mapEwinner->graphOf() == m_gWinner);
1235  OGDF_ASSERT(m_mapVwinner->graphOf() == m_gWinner);
1236 
1237  m_mapE_l2w = EdgeArray<edge>(*m_gLoser, nullptr);
1238  m_mapV_l2w = NodeArray<node>(*m_gLoser, nullptr);
1239 }
1240 
1241 template<typename TCost>
1243  edge newEdge = m_gWinner->newEdge(m_mapV_l2w[loser->source()], m_mapV_l2w[loser->target()]);
1244  m_mapE_l2w[loser] = newEdge;
1245  (*m_mapEwinner)[newEdge] = (*m_mapEloser)[loser];
1246 }
1247 
1248 template<typename TCost>
1250  m_mapV_l2w[loser] = winner;
1251  (*m_mapVwinner)[winner] = (*m_mapVloser)[loser];
1252 }
1253 
1254 template<typename TCost>
1256  node newNode = m_gWinner->newNode();
1257  m_mapV_l2w[loser] = newNode;
1258  (*m_mapVwinner)[newNode] = (*m_mapVloser)[loser];
1259 }
1260 
1261 template<typename TCost>
1262 void GlueMap<TCost>::reorder(node vLoser, bool sameDirection, bool isTNodeOfPNode) {
1263  node vWinner = m_mapV_l2w[vLoser];
1264  List<adjEntry> rightAdjOrder;
1265  List<adjEntry> wrongAdjOrder;
1266  vWinner->allAdjEntries(wrongAdjOrder);
1267  OGDF_ASSERT(wrongAdjOrder.size() == vWinner->degree());
1268 
1269  OGDF_ASSERT(vLoser->degree() <= vWinner->degree());
1270  // for every adjEntry of v in the "right" graph (the embedding which we want to get into the "wrong" graph)
1271  // we search for the corresponding adjEntry in the list of adjEntries of the "wrong" v
1272  for (adjEntry adj : vLoser->adjEntries) {
1273  OGDF_ASSERT(m_mapE_l2w[adj->theEdge()] != nullptr);
1274  edge edgeInWinner = m_mapE_l2w[adj->theEdge()];
1275  adjEntry adj_in = (adj->theEdge()->adjSource() == adj ? edgeInWinner->adjSource()
1276  : edgeInWinner->adjTarget());
1277  rightAdjOrder.pushBack(adj_in);
1278  }
1279  List<adjEntry> adjOrder;
1280  vWinner->allAdjEntries(adjOrder);
1281  OGDF_ASSERT(vLoser->degree() <= adjOrder.size());
1282  if (!sameDirection) {
1283  rightAdjOrder.reverse();
1284  }
1285  if (adjOrder.size() == rightAdjOrder.size()) {
1286  adjOrder = rightAdjOrder;
1287  } else {
1288  List<adjEntry> helpList;
1289  adjOrder.split(adjOrder.get(adjOrder.size() - rightAdjOrder.size()), adjOrder, helpList);
1290  if (isTNodeOfPNode) {
1291  adjOrder.concFront(rightAdjOrder);
1292  } else {
1293  adjOrder.conc(rightAdjOrder);
1294  }
1295  }
1296  m_gWinner->sort(vWinner, adjOrder);
1297 }
1298 }
ogdf::NonPlanarCore::getMincut
void getMincut(edge e, List< edge > &cut)
Get the mincut of e with respect to its position in the chain of its original edge.
Definition: NonPlanarCore.h:1151
ogdf
The namespace for all OGDF objects.
Definition: AugmentationModule.h:36
ogdf::NonPlanarCore::m_planarCore
const GraphCopy * m_planarCore
A pointer to a copy of the core, in which crossings are replaced by dummy nodes.
Definition: NonPlanarCore.h:305
ogdf::Skeleton::isVirtual
virtual bool isVirtual(edge e) const =0
Returns true iff e is a virtual edge.
ogdf::Queue::append
iterator append(const E &x)
Adds x at the end of queue.
Definition: Queue.h:319
ogdf::NonPlanarCore::CutEdge::dir
const bool dir
true, iff the edge is directed from the s partition to the t partion
Definition: NonPlanarCore.h:76
ogdf::GlueMap::m_eWinner
const edge m_eWinner
The core edge that will survive.
Definition: NonPlanarCore.h:405
ogdf::NonPlanarCore::original
List< edge > original(edge e) const
Returns the edges of the original graph, which are represented by e in the core.
Definition: NonPlanarCore.h:121
ogdf::NonPlanarCore::glue
void glue(edge eWinner, edge eLoser)
Glues together the skeletons of eWinner and eLoser for pruned P- and S-nodes.
Definition: NonPlanarCore.h:841
ogdf::GlueMap::m_mapEwinner
EdgeArray< edge > * m_mapEwinner
A map from the edges of the winner graph to the original graph, to denote the original of each edge.
Definition: NonPlanarCore.h:413
ogdf::StaticSPQRTree
Linear-time implementation of static SPQR-trees.
Definition: StaticSPQRTree.h:73
ogdf::internal::GraphRegisteredArray< EdgeElement, Value, WithDefault >::graphOf
Graph * graphOf() const
Returns a pointer to the associated graph.
Definition: Graph_d.h:658
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:54
ogdf::List::conc
void conc(List< E > &L2)
Appends L2 to this list and makes L2 empty.
Definition: List.h:1657
ogdf::GlueMap::reorder
void reorder(node vLoser, bool sameDirection, bool isTNodeOfPNode)
This method reorders the adjacency order of vLoser's counterpart in the winner graph according to the...
Definition: NonPlanarCore.h:1262
ogdf::GlueMap::getLoserGraph
const Graph & getLoserGraph() const
Getter for m_gLoser.
Definition: NonPlanarCore.h:399
ogdf::NonPlanarCore::m_graph
Graph m_graph
The core.
Definition: NonPlanarCore.h:296
ogdf::AdjElement::theNode
node theNode() const
Returns the node whose adjacency list contains this element.
Definition: Graph_d.h:159
ogdf::MinSTCutModule::direction
virtual bool direction(edge e)
Returns the direction of e in the cut.
Definition: MinSTCutModule.h:87
ogdf::EdgeElement::isParallelUndirected
bool isParallelUndirected(edge e) const
Returns true iff edge e is parallel to this (undirected) edge (or if it is the same edge)
Definition: Graph_d.h:421
ogdf::NonPlanarCore::realEdge
edge realEdge(edge e) const
Returns the edge of the orginal graph, which is represented by e or nullptr iff e is virtual.
Definition: NonPlanarCore.h:140
ogdf::Skeleton::realEdge
virtual edge realEdge(edge e) const =0
Returns the real edge that corresponds to skeleton edge e.
ogdf::NonPlanarCore::importEmbedding
void importEmbedding(edge e)
This method asserts that all parts of the end graph that are represented by edge e internally have th...
Definition: NonPlanarCore.h:1067
ogdf::NonPlanarCore
Non-planar core reduction.
Definition: NonPlanarCore.h:65
ogdf::NodeElement::lastAdj
adjEntry lastAdj() const
Returns the last entry in the adjacency list.
Definition: Graph_d.h:282
ogdf::List::split
void split(iterator it, List< E > &L1, List< E > &L2, Direction dir=Direction::before)
Splits the list at element it into lists L1 and L2.
Definition: List.h:1677
ogdf::List::popFrontRet
E popFrontRet()
Removes the first element from the list and returns it.
Definition: List.h:1581
ogdf::NonPlanarCore::call
void call(const Graph &G, const EdgeArray< TCost > *weight, MinSTCutModule< TCost > *minSTCutModule, bool nonPlanarityGuaranteed)
The private method behind the constructors.
Definition: NonPlanarCore.h:492
StaticSPQRTree.h
Declaration of class StaticSPQRTree.
ogdf::Graph::allNodes
void allNodes(CONTAINER &nodeContainer) const
Returns a container with all nodes of the graph.
Definition: Graph_d.h:1028
ogdf::SListIteratorBase
Encapsulates a pointer to an ogdf::SList element.
Definition: SList.h:41
ogdf::NonPlanarCore::glueMincuts
void glueMincuts(edge eWinner, edge eLoser)
Glues together the mincuts of the winner and the loser edge.
Definition: NonPlanarCore.h:1179
ogdf::NonPlanarCore::markCore
void markCore(NodeArray< bool > &mark)
Marks all nodes of the underlying SPQRTree and prunes planar leaves until the marked nodes span a tre...
Definition: NonPlanarCore.h:630
ogdf::MinSTCutBFS
Min-st-cut algorithm, that calculates the cut by doing a depth first search over the dual graph of of...
Definition: MinSTCutBFS.h:54
ogdf::NonPlanarCore::cost
TCost cost(edge e) const
Returns the cost of e, which is the number of original edges crossed, if e is crossed,...
Definition: NonPlanarCore.h:169
ogdf::EdgeElement::isInvertedDirected
bool isInvertedDirected(edge e) const
Returns true iff edge e is an inverted edge to this (directed) edge.
Definition: Graph_d.h:415
ogdf::filter_any_edge
bool filter_any_edge(edge e)
std::function<bool(edge)> that returns true for any edge e
ogdf::GraphCopy
Copies of graphs supporting edge splitting.
Definition: GraphCopy.h:384
ogdf::GlueMap::m_mapEloser
const EdgeArray< edge > * m_mapEloser
A map from the edges of the loser graph to the original graph, to denote the original of each node.
Definition: NonPlanarCore.h:415
ogdf::QueueEntry::m_parent
node m_parent
Definition: NonPlanarCore.h:675
ogdf::isPlanar
bool isPlanar(const Graph &G)
Returns true, if G is planar, false otherwise.
Definition: extended_graph_alg.h:274
Queue.h
Declaration and implementation of list-based queues (classes QueuePure<E> and Queue<E>).
ogdf::NonPlanarCore::CutEdge::CutEdge
CutEdge(edge paramEdge, bool directed)
Definition: NonPlanarCore.h:78
ogdf::NonPlanarCore::m_real
EdgeArray< edge > m_real
Corresp. original edge (0 if virtual)
Definition: NonPlanarCore.h:317
ogdf::GlueMap::m_gLoser
const Graph * m_gLoser
The graph that eLoser represents.
Definition: NonPlanarCore.h:411
ogdf::Direction::before
@ before
ogdf::NonPlanarCore::tNode
node tNode(edge e) const
Returns the t node of the skeleton of the st-component represented by the core edge e = (s,...
Definition: NonPlanarCore.h:152
ogdf::parallelFreeSortUndirected
void parallelFreeSortUndirected(const Graph &G, SListPure< edge > &edges, EdgeArray< int > &minIndex, EdgeArray< int > &maxIndex)
Sorts the edges of G such that undirected parallel edges come after each other in the list.
ogdf::Skeleton::treeNode
node treeNode() const
Returns the corresponding node in the owner tree T to which S belongs.
Definition: Skeleton.h:79
ogdf::SListIteratorBase::valid
bool valid() const
Returns true iff the iterator points to an element.
Definition: SList.h:122
ogdf::GlueMap::mapLoserToWinnerNode
void mapLoserToWinnerNode(node vInLoser, node vInWinner)
A mapping from the vInLoser to the vInWinner is created.
Definition: NonPlanarCore.h:1249
ogdf::GlueMap::GlueMap
GlueMap(edge eWinner, edge eLoser, NonPlanarCore< TCost > &npc)
A GlueMap is created from an NonPlanarCore and two core edges that ought to be glued together.
Definition: NonPlanarCore.h:1207
ogdf::GlueMap
This is a helper class to make the glueing of two edges simpler.
Definition: NonPlanarCore.h:348
ogdf::List::insertAfter
iterator insertAfter(const E &x, iterator it)
Inserts element x after it.
Definition: List.h:1562
ogdf::GlueMap::mapLoserToNewWinnerEdge
void mapLoserToNewWinnerEdge(edge eInLoser)
A mapping from the eInLoser graph to a new edge in the winner graph is created.
Definition: NonPlanarCore.h:1242
ogdf::NonPlanarCore::isVirtual
bool isVirtual(edge e) const
True iff the edge e in the core represents more than one orginal edge and therefore is virtual.
Definition: NonPlanarCore.h:137
ogdf::GlueMap::m_gWinner
Graph * m_gWinner
The graph that eWinner represents.
Definition: NonPlanarCore.h:409
ogdf::GlueMap::getWinnerNodeOfLoserNode
node getWinnerNodeOfLoserNode(node v) const
Getter for m_mapV_l2w.
Definition: NonPlanarCore.h:393
ogdf::SListPure::begin
iterator begin()
Returns an iterator to the first element of the list.
Definition: SList.h:332
ogdf::List::concFront
void concFront(List< E > &L2)
Prepends L2 to this list and makes L2 empty.
Definition: List.h:1664
ogdf::AdjElement
Class for adjacency list elements.
Definition: Graph_d.h:135
ogdf::NonPlanarCore::retransform
void retransform(const GraphCopy &planarCore, GraphCopy &planarGraph, bool pCisPlanar=true)
Inserts the crossings from a copy of the core into a copy of the original graph.
Definition: NonPlanarCore.h:932
ogdf::MinSTCutModule::call
virtual bool call(const Graph &graph, const EdgeArray< TCost > &weight, node s, node t, List< edge > &edgeList, edge e_st=nullptr)=0
The actual algorithm call.
ogdf::AdjElement::theEdge
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition: Graph_d.h:153
ogdf::EdgeElement::graphOf
const Graph * graphOf() const
Returns the graph containing this node (debug only).
Definition: Graph_d.h:433
ogdf::NodeElement::degree
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition: Graph_d.h:276
ogdf::NonPlanarCore::m_pOriginal
const Graph * m_pOriginal
The original graph.
Definition: NonPlanarCore.h:299
ogdf::List::pushFront
iterator pushFront(const E &x)
Adds element x at the beginning of the list.
Definition: List.h:1524
ogdf::GlueMap::m_mapE_l2w
EdgeArray< edge > m_mapE_l2w
A map from the edges of the loser graph to their new home in the winner graph.
Definition: NonPlanarCore.h:423
ogdf::NonPlanarCore::getAllMultiedges
void getAllMultiedges(List< edge > &winningEdges, List< edge > &losingEdges)
Checks for multiedges in the core.
Definition: NonPlanarCore.h:822
ogdf::GlueMap::m_npc
NonPlanarCore< TCost > & m_npc
The NonPlanarCore on which this instance operates.
Definition: NonPlanarCore.h:403
ogdf::Graph::numberOfNodes
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition: Graph_d.h:974
ogdf::NonPlanarCore::m_sNode
EdgeArray< node > m_sNode
The s node of the st-component of a core edge.
Definition: NonPlanarCore.h:338
ogdf::GlueMap::m_eLoser
const edge m_eLoser
The core edge that will be deleted.
Definition: NonPlanarCore.h:407
ogdf::Queue::pop
E pop()
Removes front element and returns it.
Definition: Queue.h:331
ogdf::NonPlanarCore::cost
const EdgeArray< TCost > & cost() const
Returns the costs of the edges in the core, which is the number of original edges crossed,...
Definition: NonPlanarCore.h:146
ogdf::AdjElement::succ
adjEntry succ() const
Returns the successor in the adjacency list.
Definition: Graph_d.h:211
ogdf::NodeElement::adjEntries
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition: Graph_d.h:264
ogdf::QueueEntry
Definition: NonPlanarCore.h:672
ogdf::MinSTCutModule
Definition: MinSTCutModule.h:40
ogdf::NonPlanarCore::m_T
StaticSPQRTree m_T
The SPQRTree that represents the original graph.
Definition: NonPlanarCore.h:326
ogdf::NonPlanarCore::mapE
EdgeArray< edge > * mapE(edge e) const
Returns a map from the edges of the st-component represented by the core edge e to the original graph...
Definition: NonPlanarCore.h:163
ogdf::SListPure
Singly linked lists.
Definition: SList.h:39
ogdf::GlueMap::m_mapV_l2w
NodeArray< node > m_mapV_l2w
A map from the nodes of the loser graph to their new home in the winner graph.
Definition: NonPlanarCore.h:421
ogdf::NonPlanarCore::m_endGraph
GraphCopy * m_endGraph
A pointer to a copy of the original graph, in which crossings are replaced by dummy nodes.
Definition: NonPlanarCore.h:311
ogdf::planarEmbed
bool planarEmbed(Graph &G)
Returns true, if G is planar, false otherwise. If true is returned, G will be planarly embedded.
Definition: extended_graph_alg.h:308
ogdf::EdgeElement::source
node source() const
Returns the source node of the edge.
Definition: Graph_d.h:391
ogdf::NonPlanarCore::mincut
const List< CutEdge > & mincut(edge e) const
Returns the mincut of the st-component represented by e.
Definition: NonPlanarCore.h:172
ogdf::GlueMap::m_mapVwinner
NodeArray< node > * m_mapVwinner
A map from the nodes of the winner graph to the original graph, to denote the original of each edge.
Definition: NonPlanarCore.h:417
ogdf::List< edge >
ogdf::internal::GraphRegisteredArray
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition: Graph_d.h:651
ogdf::Queue
The parameterized class Queue<E> implements list-based queues.
Definition: Queue.h:200
ogdf::EdgeElement::adjSource
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition: Graph_d.h:400
ogdf::Graph
Data type for general directed graphs (adjacency list representation).
Definition: Graph_d.h:862
ogdf::NonPlanarCore::m_underlyingGraphs
EdgeArray< Graph * > m_underlyingGraphs
The graph for the underlying skeleton of a virtual edge in the core.
Definition: NonPlanarCore.h:335
ogdf::NonPlanarCore::m_orig
NodeArray< node > m_orig
Corresp. original node.
Definition: NonPlanarCore.h:314
ogdf::Skeleton::twinTreeNode
virtual node twinTreeNode(edge e) const =0
Returns the tree node in T containing the twin edge of skeleton edge e.
ogdf::Skeleton::getGraph
const Graph & getGraph() const
Returns a reference to the skeleton graph M.
Definition: Skeleton.h:89
ogdf::AdjElement::twinNode
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition: Graph_d.h:168
ogdf::AdjElement::cyclicSucc
adjEntry cyclicSucc() const
Returns the cyclic successor in the adjacency list.
Definition: Graph_d.h:347
ogdf::NonPlanarCore::removeSplitdummies
void removeSplitdummies(List< node > &splitdummies)
After inserting the crossings, the end graph edges don't need to be partitioned anymore so the splitd...
Definition: NonPlanarCore.h:1032
ogdf::EdgeStandardType::tree
@ tree
for every hyperedge e a minimal subcubic tree connecting all hypernodes incident with e together is a...
ogdf::Queue::empty
bool empty() const
Returns true iff the queue is empty.
Definition: Queue.h:238
ogdf::MinSTCutDijkstra
Min-st-cut algorithm, that calculates the cut by calculating the shortest path between the faces adja...
Definition: MinSTCutDijkstra.h:52
ogdf::EdgeElement::adjTarget
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition: Graph_d.h:403
ogdf::NodeElement::allAdjEntries
void allAdjEntries(ADJLIST &adjList) const
Returns a list with all adjacency entries of this node.
Definition: Graph_d.h:296
ogdf::NonPlanarCore::m_mapV
EdgeArray< NodeArray< node > * > m_mapV
The mapping between the nodes of each embedding and their original.
Definition: NonPlanarCore.h:329
MinSTCutBFS.h
Declaration of min-st-cut algorithm which calculates the min-st-cut of an st-planar graph by doing a ...
ogdf::NonPlanarCore::m_tNode
EdgeArray< node > m_tNode
The t node of the st-component of a core edge.
Definition: NonPlanarCore.h:341
ogdf::Graph::edges
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition: Graph_d.h:927
ogdf::NonPlanarCore::original
node original(node v) const
Returns the node of the original graph, which is represented by v in the core.
Definition: NonPlanarCore.h:118
ogdf::NonPlanarCore::CutEdge
Struct to represent an edge that needs to be crossed in order to cross an st-component.
Definition: NonPlanarCore.h:74
ogdf::NonPlanarCore::splitEdgeIntoSections
void splitEdgeIntoSections(edge e, List< node > &splitdummies)
To be able to insert crossings correctly, an end graph edge ought to be split into n-1 sections if n ...
Definition: NonPlanarCore.h:1045
ogdf::List::del
void del(iterator it)
Removes it from the list.
Definition: List.h:1601
ogdf::NonPlanarCore::m_mincut
EdgeArray< List< CutEdge > > m_mincut
Traversing path for an edge in the core.
Definition: NonPlanarCore.h:320
ogdf::CombinatorialEmbedding
Combinatorial embeddings of planar graphs with modification functionality.
Definition: CombinatorialEmbedding.h:397
ogdf::NonPlanarCore::inflateCrossing
void inflateCrossing(node v)
The crossing denoted by dummy node v from the planarized copy of the core get inserted into the end g...
Definition: NonPlanarCore.h:1102
ogdf::NodeElement::firstAdj
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition: Graph_d.h:279
ogdf::isBiconnected
bool isBiconnected(const Graph &G, node &cutVertex)
Returns true iff G is biconnected.
ogdf::GlueMap::mapLoserToNewWinnerNode
void mapLoserToNewWinnerNode(node vInLoser)
A mapping from the vInLoser to a new node in the winner graph is created.
Definition: NonPlanarCore.h:1255
ogdf::QueueEntry::QueueEntry
QueueEntry(node p, node v)
Definition: NonPlanarCore.h:673
ogdf::NonPlanarCore::originalGraph
const Graph & originalGraph() const
Returns the original graph.
Definition: NonPlanarCore.h:115
ogdf::EdgeElement
Class for the representation of edges.
Definition: Graph_d.h:356
ogdf::NonPlanarCore::core
const Graph & core() const
Returns the non-planar core.
Definition: NonPlanarCore.h:112
ogdf::NonPlanarCore::~NonPlanarCore
virtual ~NonPlanarCore()
Definition: NonPlanarCore.h:479
ogdf::Skeleton
Skeleton graphs of nodes in an SPQR-tree.
Definition: Skeleton.h:59
ogdf::RegisteredArray< GraphRegistry< Key >, Value, WithDefault, Graph >::init
void init(const Graph *base=nullptr)
Reinitializes the array. Associates the array with the matching registry of base.
Definition: RegisteredArray.h:849
ogdf::Skeleton::original
virtual node original(node v) const =0
Returns the vertex in the original graph G that corresponds to v.
ogdf::SPQRTree::NodeType::RNode
@ RNode
ogdf::List::size
int size() const
Returns the number of elements in the list.
Definition: List.h:1478
ogdf::SListPure::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: SList.h:469
ogdf::NonPlanarCore::m_cost
EdgeArray< TCost > m_cost
TCosts to cross each edge of the core.
Definition: NonPlanarCore.h:323
ogdf::NonPlanarCore::traversingPath
void traversingPath(const Skeleton &Sv, edge eS, List< CutEdge > &path, NodeArray< node > &mapV, edge coreEdge, const EdgeArray< TCost > *weight_src, MinSTCutModule< TCost > *minSTCutModule)
Computes the traversing path for a given edge and the unmarked tree rooted in the node of eS and save...
Definition: NonPlanarCore.h:680
ogdf::NonPlanarCore::m_mapE
EdgeArray< EdgeArray< edge > * > m_mapE
The mapping between the edges of each embedding and their original.
Definition: NonPlanarCore.h:332
ogdf::NonPlanarCore::NonPlanarCore
NonPlanarCore(const Graph &G, bool nonPlanarityGuaranteed=false)
The unweighted version of the Algorithm call and constructor.
Definition: NonPlanarCore.h:427
ogdf::NonPlanarCore::CutEdge::e
const edge e
the edge
Definition: NonPlanarCore.h:75
ogdf::NonPlanarCore::sNode
node sNode(edge e) const
Returns the s node of the skeleton of the st-component represented by the core edge e = (s,...
Definition: NonPlanarCore.h:158
ogdf::EdgeElement::target
node target() const
Returns the target node of the edge.
Definition: Graph_d.h:394
ogdf::GraphCopy::removePseudoCrossings
void removePseudoCrossings()
Removes all crossing nodes which are actually only two "touching" edges.
ogdf::GlueMap::m_mapVloser
const NodeArray< node > * m_mapVloser
A map from the nodes of the loser graph to the original graph, to denote the original of each node.
Definition: NonPlanarCore.h:419
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:233
ogdf::List::removeFirst
bool removeFirst(const E &x)
Removes the first occurrence of x (if any) from the list.
Definition: List.h:1607
MinSTCutDijkstra.h
MinSTCutDijkstra class template.
simple_graph_alg.h
Declaration of simple graph algorithms.
ogdf::QueueEntry::m_current
node m_current
Definition: NonPlanarCore.h:676
ogdf::NonPlanarCore::normalizeCutEdgeDirection
void normalizeCutEdgeDirection(edge coreEdge)
Every edge of coreEdge's cut that doesn't go the same direction as coreEdge gets reversed.
Definition: NonPlanarCore.h:1021
ogdf::List::pushBack
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition: List.h:1537
ogdf::internal::EdgeArrayBase2
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition: Graph_d.h:709
ogdf::List::clear
void clear()
Removes all elements from the list.
Definition: List.h:1616