Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
NonPlanarCore.h
Go to the documentation of this file.
1
33#pragma once
34
36#include <ogdf/basic/Graph.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
53namespace ogdf {
54template<typename TCost>
55class MinSTCutModule;
56
58
78template<typename TCost = int>
80 template<typename T>
81 friend class GlueMap;
82
83public:
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
200protected:
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
258
267
275
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
361template<typename TCost>
362class GlueMap {
363public:
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
415protected:
438};
439
440template<typename TCost>
441NonPlanarCore<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
457template<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
474template<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
492template<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
505template<typename TCost>
507 MinSTCutModule<TCost>* minSTCutModule, bool nonPlanarityGuaranteed) {
508 if (!nonPlanarityGuaranteed && isPlanar(G)) {
509 return;
510 }
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
643template<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
692
693template<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
835template<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
854template<typename TCost>
855void 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
945template<typename TCost>
946void 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
1034template<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
1045template<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
1058template<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
1080template<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
1115template<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
1164template<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
1192template<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
1220template<typename TCost>
1222 : m_npc(npc), m_eWinner(eWinner), m_eLoser(eLoser) {
1224
1227
1230
1232
1233 OGDF_ASSERT(m_npc.m_mapV[m_eWinner] != nullptr);
1234 OGDF_ASSERT(m_npc.m_mapV[m_eLoser] != nullptr);
1235
1238
1239 OGDF_ASSERT(m_npc.m_mapE[m_eWinner] != nullptr);
1240 OGDF_ASSERT(m_npc.m_mapE[m_eLoser] != nullptr);
1241
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
1255template<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
1262template<typename TCost>
1264 m_mapV_l2w[loser] = winner;
1265 (*m_mapVwinner)[winner] = (*m_mapVloser)[loser];
1266}
1267
1268template<typename TCost>
1270 node newNode = m_gWinner->newNode();
1271 m_mapV_l2w[loser] = newNode;
1272 (*m_mapVwinner)[newNode] = (*m_mapVloser)[loser];
1273}
1274
1275template<typename TCost>
1276void 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}
Declaration of CombinatorialEmbedding and face.
Includes declaration of graph class.
Declaration of graph copy classes.
Decralation of GraphElement and GraphList classes.
Declaration of doubly linked lists and iterators.
Declaration of min-st-cut algorithm which calculates the min-st-cut of an st-planar graph by doing a ...
MinSTCutDijkstra class template.
Declaration of singly linked lists and iterators.
Declaration of class SPQRTree.
Declaration of class Skeleton.
Declaration of class StaticSPQRTree.
Declaration and implementation of list-based queues (classes QueuePure<E> and Queue<E>).
Basic declarations, included by all source files.
Class for adjacency list elements.
Definition Graph_d.h:143
adjEntry cyclicSucc() const
Returns the cyclic successor in the adjacency list.
Definition Graph_d.h:355
adjEntry succ() const
Returns the successor in the adjacency list.
Definition Graph_d.h:219
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition Graph_d.h:161
node theNode() const
Returns the node whose adjacency list contains this element.
Definition Graph_d.h:167
Combinatorial embeddings of planar graphs with modification functionality.
Class for the representation of edges.
Definition Graph_d.h:364
adjEntry adjSource() const
Returns the corresponding adjacancy entry at source node.
Definition Graph_d.h:408
const Graph * graphOf() const
Returns the graph containing this node (debug only).
Definition Graph_d.h:441
adjEntry adjTarget() const
Returns the corresponding adjacancy entry at target node.
Definition Graph_d.h:411
bool isInvertedDirected(edge e) const
Returns true iff edge e is an inverted edge to this (directed) edge.
Definition Graph_d.h:423
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:429
node target() const
Returns the target node of the edge.
Definition Graph_d.h:402
node source() const
Returns the source node of the edge.
Definition Graph_d.h:399
This is a helper class to make the glueing of two edges simpler.
void mapLoserToNewWinnerEdge(edge eInLoser)
A mapping from the eInLoser graph to a new edge in the winner graph is created.
node getWinnerNodeOfLoserNode(node v) const
Getter for m_mapV_l2w.
const edge m_eWinner
The core edge that will survive.
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.
void mapLoserToWinnerNode(node vInLoser, node vInWinner)
A mapping from the vInLoser to the vInWinner is created.
NodeArray< node > m_mapV_l2w
A map from the nodes of the loser graph to their new home in the winner graph.
EdgeArray< edge > m_mapE_l2w
A map from the edges of the loser graph to their new home in the winner graph.
const Graph * m_gLoser
The graph that eLoser represents.
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...
const edge m_eLoser
The core edge that will be deleted.
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.
Graph * m_gWinner
The graph that eWinner represents.
NodeArray< node > * m_mapVwinner
A map from the nodes of the winner graph to the original graph, to denote the original of each edge.
EdgeArray< edge > * m_mapEwinner
A map from the edges of the winner graph to the original graph, to denote the original of each edge.
void mapLoserToNewWinnerNode(node vInLoser)
A mapping from the vInLoser to a new node in the winner graph is created.
NonPlanarCore< TCost > & m_npc
The NonPlanarCore on which this instance operates.
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.
const Graph & getLoserGraph() const
Getter for m_gLoser.
Copies of graphs supporting edge splitting.
Definition GraphCopy.h:390
void removePseudoCrossings()
Removes all crossing nodes which are actually only two "touching" edges.
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:866
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition Graph_d.h:979
void allNodes(CONTAINER &nodeContainer) const
Returns a container with all nodes of the graph.
Definition Graph_d.h:1033
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition Graph_d.h:932
Doubly linked lists (maintaining the length of the list).
Definition List.h:1451
int size() const
Returns the number of elements in the list.
Definition List.h:1488
void clear()
Removes all elements from the list.
Definition List.h:1626
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition List.h:1547
bool removeFirst(const E &x)
Removes the first occurrence of x (if any) from the list.
Definition List.h:1617
void del(iterator it)
Removes it from the list.
Definition List.h:1611
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
iterator pushFront(const E &x)
Adds element x at the beginning of the list.
Definition List.h:1534
iterator insertAfter(const E &x, iterator it)
Inserts element x after it.
Definition List.h:1572
E popFrontRet()
Removes the first element from the list and returns it.
Definition List.h:1591
void concFront(List< E > &L2)
Prepends L2 to this list and makes L2 empty.
Definition List.h:1674
void conc(List< E > &L2)
Appends L2 to this list and makes L2 empty.
Definition List.h:1667
iterator begin()
Returns an iterator to the first element of the list.
Definition List.h:391
void reverse()
Reverses the order of the list elements.
Definition List.h:1260
int pos(const_iterator it) const
Returns the position (starting with 0) of iterator it in the list.
Definition List.h:369
const_reference front() const
Returns a const reference to the first element.
Definition List.h:305
const_iterator get(int pos) const
Returns a const iterator pointing to the element at position pos.
Definition List.h:341
bool empty() const
Returns true iff the list is empty.
Definition List.h:286
ListConstIterator< E > search(const E &e) const
Scans the list for the specified element and returns an iterator to the first occurrence in the list,...
Definition List.h:1280
iterator end()
Returns an iterator to one-past-last element of the list.
Definition List.h:409
Min-st-cut algorithm, that calculates the cut by doing a depth first search over the dual graph of of...
Definition MinSTCutBFS.h:59
Min-st-cut algorithm, that calculates the cut by calculating the shortest path between the faces adja...
virtual bool direction(edge e)
Returns the direction of e in the cut.
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.
Class for the representation of nodes.
Definition Graph_d.h:241
void allAdjEntries(ADJLIST &adjList) const
Returns a list with all adjacency entries of this node.
Definition Graph_d.h:304
int degree() const
Returns the degree of the node (indegree + outdegree).
Definition Graph_d.h:284
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition Graph_d.h:272
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition Graph_d.h:287
Non-planar core reduction.
EdgeArray< List< CutEdge > > m_mincut
Traversing path for an edge in the core.
const Graph & originalGraph() const
Returns the original graph.
void glue(edge eWinner, edge eLoser)
Glues together the skeletons of eWinner and eLoser for pruned P- and S-nodes.
Graph m_graph
The core.
List< edge > original(edge e) const
Returns the edges of the original graph, which are represented by e in the core.
NodeArray< node > m_orig
Corresp. original node.
const EdgeArray< TCost > & cost() const
Returns the costs of the edges in the core, which is the number of original edges crossed,...
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...
node tNode(edge e) const
Returns the t node of the skeleton of the st-component represented by the core edge e = (s,...
void inflateCrossing(node v)
The crossing denoted by dummy node v from the planarized copy of the core get inserted into the end g...
bool isVirtual(edge e) const
True iff the edge e in the core represents more than one orginal edge and therefore is virtual.
const GraphCopy * m_planarCore
A pointer to a copy of the core, in which crossings are replaced by dummy nodes.
const List< CutEdge > & mincut(edge e) const
Returns the mincut of the st-component represented by e.
void getAllMultiedges(List< edge > &winningEdges, List< edge > &losingEdges)
Checks for multiedges in the core.
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.
const Graph * m_pOriginal
The original graph.
void markCore(NodeArray< bool > &mark)
Marks all nodes of the underlying SPQRTree and prunes planar leaves until the marked nodes span a tre...
node original(node v) const
Returns the node of the original graph, which is represented by v in the core.
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...
void importEmbedding(edge e)
This method asserts that all parts of the end graph that are represented by edge e internally have th...
EdgeArray< node > m_tNode
The t node of the st-component of a core edge.
StaticSPQRTree m_T
The SPQRTree that represents the original graph.
NonPlanarCore(const Graph &G, const EdgeArray< TCost > &weight, MinSTCutModule< TCost > *minSTCutModule, bool nonPlanarityGuaranteed=false)
Algorithm call and constructor.
EdgeArray< node > m_sNode
The s node of the st-component of a core edge.
void call(const Graph &G, const EdgeArray< TCost > *weight, MinSTCutModule< TCost > *minSTCutModule, bool nonPlanarityGuaranteed)
The private method behind the constructors.
node sNode(edge e) const
Returns the s node of the skeleton of the st-component represented by the core edge e = (s,...
void normalizeCutEdgeDirection(edge coreEdge)
Every edge of coreEdge's cut that doesn't go the same direction as coreEdge gets reversed.
void glueMincuts(edge eWinner, edge eLoser)
Glues together the mincuts of the winner and the loser edge.
GraphCopy * m_endGraph
A pointer to a copy of the original graph, in which crossings are replaced by dummy nodes.
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 ...
NonPlanarCore(const Graph &G, bool nonPlanarityGuaranteed=false)
The unweighted version of the Algorithm call and constructor.
EdgeArray< NodeArray< node > * > m_mapV
The mapping between the nodes of each embedding and their original.
EdgeArray< TCost > m_cost
TCosts to cross each edge of the core.
const Graph & core() const
Returns the non-planar core.
void getMincut(edge e, List< edge > &cut)
Get the mincut of e with respect to its position in the chain of its original edge.
TCost cost(edge e) const
Returns the cost of e, which is the number of original edges crossed, if e is crossed,...
NonPlanarCore(const Graph &G, const EdgeArray< TCost > &weight, bool nonPlanarityGuaranteed=false)
An slimmed version of the Algorithm call and constructor.
EdgeArray< EdgeArray< edge > * > m_mapE
The mapping between the edges of each embedding and their original.
EdgeArray< Graph * > m_underlyingGraphs
The graph for the underlying skeleton of a virtual edge in the core.
edge realEdge(edge e) const
Returns the edge of the orginal graph, which is represented by e or nullptr iff e is virtual.
void removeSplitdummies(List< node > &splitdummies)
After inserting the crossings, the end graph edges don't need to be partitioned anymore so the splitd...
EdgeArray< edge > m_real
Corresp. original edge (0 if virtual)
The parameterized class Queue<E> implements list-based queues.
Definition Queue.h:205
E pop()
Removes front element and returns it.
Definition Queue.h:336
bool empty() const
Returns true iff the queue is empty.
Definition Queue.h:243
iterator append(const E &x)
Adds x at the end of queue.
Definition Queue.h:324
void init(const Base *base=nullptr)
Reinitializes the array. Associates the array with the matching registry of base.
Encapsulates a pointer to an ogdf::SList element.
Definition SList.h:104
bool valid() const
Returns true iff the iterator points to an element.
Definition SList.h:134
Singly linked lists.
Definition SList.h:191
iterator begin()
Returns an iterator to the first element of the list.
Definition SList.h:344
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition SList.h:481
Skeleton graphs of nodes in an SPQR-tree.
Definition Skeleton.h:60
virtual node original(node v) const =0
Returns the vertex in the original graph G that corresponds to v.
virtual edge realEdge(edge e) const =0
Returns the real edge that corresponds to skeleton edge e.
virtual node twinTreeNode(edge e) const =0
Returns the tree node in T containing the twin edge of skeleton edge e.
const Graph & getGraph() const
Returns a reference to the skeleton graph M.
Definition Skeleton.h:90
virtual bool isVirtual(edge e) const =0
Returns true iff e is a virtual edge.
node treeNode() const
Returns the corresponding node in the owner tree T to which S belongs.
Definition Skeleton.h:80
Linear-time implementation of static SPQR-trees.
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition Graph_d.h:717
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
Graph * graphOf() const
Returns a pointer to the associated graph.
Definition Graph_d.h:666
Declaration of extended graph algorithms.
bool isBiconnected(const Graph &G, node &cutVertex)
Returns true iff G is biconnected.
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.
bool planarEmbed(Graph &G)
Returns true, if G is planar, false otherwise. If true is returned, G will be planarly embedded.
bool isPlanar(const Graph &G)
Returns true, if G is planar, false otherwise.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
The namespace for all OGDF objects.
@ tree
for every hyperedge e a minimal subcubic tree connecting all hypernodes incident with e together is a...
bool filter_any_edge(edge e)
std::function<bool(edge)> that returns true for any edge e
Declaration of simple graph algorithms.
Struct to represent an edge that needs to be crossed in order to cross an st-component.
const bool dir
true, iff the edge is directed from the s partition to the t partion
CutEdge(edge paramEdge, bool directed)
QueueEntry(node p, node v)
node m_parent
node m_current