Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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