1 | #include <random> |
2 | |
3 | #include <ogdf/planarity/PlanarSubgraphBoyerMyrvold.h> |
4 | #include <ogdf/planarity/PlanarSubgraphFast.h> |
5 | #include <ogdf/planarity/MaximalPlanarSubgraphSimple.h> |
6 | #include <ogdf/planarity/MaximumPlanarSubgraph.h> |
7 | #include <ogdf/planarity/PlanarSubgraphCactus.h> |
8 | #include <ogdf/planarity/PlanarSubgraphTree.h> |
9 | |
10 | #include <graphs.h> |
11 | |
12 | using std::minstd_rand; |
13 | |
14 | template <typename TCost> |
15 | void testSubgraphInstance(Graph &graph, PlanarSubgraphModule<TCost> &psm, PlanarityModule &tester, bool assertMaximality, bool weighEdges, bool connects) { |
16 | makeSimpleUndirected(graph); |
17 | makeConnected(graph); |
18 | |
19 | EdgeArray<TCost> costs; |
20 | edge mustHaveEdge = nullptr; |
21 | |
22 | if(weighEdges) { |
23 | costs.init(graph); |
24 | |
25 | for(edge e : graph.edges) { |
26 | costs[e] = TCost(1); |
27 | } |
28 | |
29 | mustHaveEdge = graph.chooseEdge(); |
30 | costs[mustHaveEdge] = TCost(1 + graph.numberOfEdges()); |
31 | } |
32 | |
33 | List<edge> removedEdges; |
34 | if(weighEdges) { |
35 | psm.call(graph, costs, removedEdges); |
36 | } else { |
37 | psm.call(graph, removedEdges); |
38 | } |
39 | |
40 | std::cout << std::endl << " removed " << removedEdges.size() << " edges" << std::endl; |
41 | bool connected = isConnected(graph); |
42 | |
43 | Graph::HiddenEdgeSet set(graph); |
44 | List<edge> hiddenEdges; |
45 | for(edge e : removedEdges) { |
46 | set.hide(e); |
47 | hiddenEdges.pushBack(e); |
48 | AssertThat(e, Is().Not().EqualTo(mustHaveEdge)); |
49 | } |
50 | |
51 | if(connects) { |
52 | AssertThat(isConnected(graph), Equals(connected)); |
53 | } |
54 | |
55 | AssertThat(tester.isPlanar(graph), Equals(true)); |
56 | |
57 | if(assertMaximality) { |
58 | ListConstIterator<edge> it = removedEdges.begin(); |
59 | for(edge e : hiddenEdges) { |
60 | set.restore(e); |
61 | AssertThat(tester.isPlanar(graph), Equals(false)); |
62 | set.hide(e); |
63 | it = it.succ(); |
64 | } |
65 | } |
66 | } |
67 | |
68 | void testSubgraphInstanceForIntAndDouble(Graph &graph, PlanarSubgraphModule<int> &psmi, PlanarSubgraphModule<double> &psmd) { |
69 | makeSimpleUndirected(graph); |
70 | makeConnected(graph); |
71 | EdgeArray<int> costsInt(graph); |
72 | EdgeArray<double> costsDouble(graph); |
73 | int cnt = 0; |
74 | for(edge e : graph.edges) { |
75 | cnt++; |
76 | costsInt(e) = cnt; |
77 | costsDouble(e) = double(cnt); |
78 | } |
79 | List<edge> removedEdgesInt; |
80 | List<edge> removedEdgesDouble; |
81 | psmi.call(graph, costsInt, removedEdgesInt); |
82 | psmd.call(graph, costsDouble, removedEdgesDouble); |
83 | int sumOfRemovedInt = 0; |
84 | double sumRemovedDouble = 0; |
85 | for (edge e: removedEdgesInt) { sumOfRemovedInt += costsInt(e); } |
86 | for (edge e: removedEdgesDouble) { sumRemovedDouble += costsDouble(e); } |
87 | AssertThat( sumOfRemovedInt, Equals(int(sumRemovedDouble)) ); |
88 | } |
89 | |
90 | void performGenericTests(const string &name, bool optimal, bool respectsEdgeWeight, bool skip, std::function<void(Graph &, bool)> callFunc) { |
91 | describe(name, [&]() { |
92 | auto doTest = [&](bool weighted) { |
93 | forEachGraphItWorks({GraphProperty::sparse}, [&](Graph G) { callFunc(G, weighted); }, optimal ? GraphSizes(10) : GraphSizes()); |
94 | }; |
95 | |
96 | doTest(false); |
97 | |
98 | if(respectsEdgeWeight) { |
99 | describe("weighted" , [&] { doTest(true); }); |
100 | } |
101 | }, skip); |
102 | } |
103 | |
104 | template <typename TCost> |
105 | void testSubgraphAlgorithm(const string &name, PlanarSubgraphModule<TCost> &psm, bool optimal, bool maximal, bool respectsEdgeWeight, bool connects, bool skip = false) { |
106 | maximal |= optimal; |
107 | BoothLueker bl; |
108 | performGenericTests(name, optimal, respectsEdgeWeight, skip, [&](Graph &graph, bool weighEdges) { |
109 | testSubgraphInstance<TCost>(graph, psm, bl, maximal, weighEdges, connects); |
110 | }); |
111 | } |
112 | |
113 | void testSubgraphAlgorithmForIntAndDouble(const string &name, PlanarSubgraphModule<int> &psmi, PlanarSubgraphModule<double> &psmd) { |
114 | performGenericTests(name + " int VS double" , false, true, false, [&](Graph &graph, bool weighEdges) { |
115 | testSubgraphInstanceForIntAndDouble(graph, psmi, psmd); |
116 | }); |
117 | } |
118 | |
119 | template<template<typename> class Algorithm> |
120 | void describeAlgorithm(const string &name, bool optimal, bool maximal, bool respectsEdgeWeight, bool connects, bool skip = false) { |
121 | Algorithm<int> algoInt; |
122 | testSubgraphAlgorithm(name + "<int>" , algoInt, optimal, maximal, respectsEdgeWeight, connects, skip); |
123 | |
124 | Algorithm<double> algoDouble; |
125 | testSubgraphAlgorithm(name + "<double>" , algoDouble, optimal, maximal, respectsEdgeWeight, connects, skip); |
126 | } |
127 | |
128 | go_bandit([]() { |
129 | describe("Planar Subgraphs" , []() { |
130 | PlanarSubgraphBoyerMyrvold bms; |
131 | MaximumPlanarSubgraph mps; |
132 | |
133 | testSubgraphAlgorithm("PlanarSubgraphBoyerMyrvold" , bms, false, false, true, true, true); |
134 | describeAlgorithm<PlanarSubgraphFast>("PlanarSubgraphFast" , false, false, false, true); |
135 | describeAlgorithm<PlanarSubgraphCactus>("PlanarSubgraphCactus" , false, false, false, true); |
136 | describeAlgorithm<PlanarSubgraphTree>("PlanarSubgraphTree" , false, false, false, true); |
137 | testSubgraphAlgorithm("MaximumPlanarSubgraph" , mps, true, true, true, true); |
138 | describeAlgorithm<PlanarSubgraphEmpty>("PlanarSubgraphEmpty" , false, false, false, false); |
139 | |
140 | MaximalPlanarSubgraphSimple<int> mpss; |
141 | PlanarSubgraphCactus<int> psc; |
142 | MaximalPlanarSubgraphSimple<int> mpssPsc(psc); |
143 | PlanarSubgraphFast<int> fps; |
144 | MaximalPlanarSubgraphSimple<int> mpssFps(fps); |
145 | MaximalPlanarSubgraphSimple<int> mpssBms(bms); |
146 | |
147 | testSubgraphAlgorithm("MaximalPlanarSubgraphSimple" , mpss, false, true, false, true); |
148 | testSubgraphAlgorithm("Maximal PlanarSubgraphCactus" , mpssPsc, false, true, false, true); |
149 | testSubgraphAlgorithm("Maximal PlanarSubgraphFast" , mpssFps, false, true, false, true); |
150 | testSubgraphAlgorithm("Maximal PlanarSubgraphBoyerMyrvold" , mpssBms, false, true, false, true, true); |
151 | |
152 | PlanarSubgraphCactus<double> pscd; |
153 | MaximalPlanarSubgraphSimple<double> mpssPscd(pscd); |
154 | testSubgraphAlgorithmForIntAndDouble("Maximal PlanarSubgraphCactus" , mpssPsc, mpssPscd); |
155 | }); |
156 | }); |
157 | |