algo_test.cpp (6316B)
1 #include <catch2/catch_test_macros.hpp> 2 #include <cstddef> 3 4 #include "../include/prim.hpp" 5 6 TEST_CASE("Small Prim algorithm", "[small prim algo]") { 7 std::size_t edgeCount = 1; 8 std::size_t vertCount = 2; 9 10 float xMax = 5120; 11 float yMax = 1440; 12 13 Graph g = Graph(edgeCount, vertCount, xMax, yMax); 14 std::unordered_set<std::size_t> visitedIndices{}; 15 std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> toVisit{}; 16 std::vector<Edge> edges = g.getEdgesOfVertexIdx(0); 17 std::vector<double> minEdgeToVertex(vertCount, -1); 18 19 for (auto edge : edges) { 20 toVisit.push(edge); 21 } 22 23 g.traverseVertexIdx(0); 24 visitedIndices.insert(0); 25 26 while (toVisit.size() != 0) { 27 oneStepPrim(toVisit, visitedIndices, g, minEdgeToVertex); 28 } 29 // this will be true bc 2 vertices 1 edge... 30 // our graph may have multi-edges. 31 REQUIRE(visitedIndices.size() == 2); 32 } 33 34 bool isConnected(Graph g) { 35 std::unordered_set<std::size_t> verticesFound{0}; 36 37 std::vector<std::size_t> current{}; 38 39 while (true) { 40 for (auto key : verticesFound) { 41 auto edges = g.getEdgesOfVertexIdx(key); 42 for (auto edge : edges) { 43 current.push_back(edge.v1Index); 44 current.push_back(edge.v2Index); 45 } 46 } 47 std::size_t len = verticesFound.size(); 48 for (auto idx : current) { 49 verticesFound.insert(idx); 50 } 51 if (len == verticesFound.size()) { 52 break; 53 } 54 } 55 56 return verticesFound.size() == g.getVertexCount(); 57 } 58 59 TEST_CASE("Large Prim algorithm", "[Large prim algo]") { 60 std::size_t edgeCount = 3000; 61 std::size_t vertCount = 1000; 62 63 float xMax = 5120; 64 float yMax = 1440; 65 66 Graph g = Graph(edgeCount, vertCount, xMax, yMax); 67 std::unordered_set<std::size_t> visitedIndices{}; 68 std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> toVisit{}; 69 std::vector<double> minEdgeToVertex(vertCount, -1); 70 71 do { 72 g = Graph(edgeCount, vertCount, xMax, yMax); 73 } while (!isConnected(g)); 74 75 g.traverseVertexIdx(0); 76 visitedIndices.insert(0); 77 78 std::vector<Edge> edges = g.getEdgesOfVertexIdx(0); 79 80 for (auto edge : edges) { 81 toVisit.push(edge); 82 } 83 84 while (toVisit.size() != 0) { 85 oneStepPrim(toVisit, visitedIndices, g, minEdgeToVertex); 86 } 87 88 REQUIRE(visitedIndices.size() == vertCount); 89 } 90 91 TEST_CASE("Medium Prim algorithm", "[Medium prim algo]") { 92 std::size_t edgeCount = 70; 93 std::size_t vertCount = 51; 94 95 float xMax = 5120; 96 float yMax = 1440; 97 98 Graph g = Graph(edgeCount, vertCount, xMax, yMax); 99 std::unordered_set<std::size_t> visitedIndices{}; 100 std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> toVisit{}; 101 std::vector<double> minEdgeToVertex(vertCount, -1); 102 103 do { 104 g = Graph(edgeCount, vertCount, xMax, yMax); 105 } while (!isConnected(g)); 106 107 g.traverseVertexIdx(0); 108 visitedIndices.insert(0); 109 110 std::vector<Edge> edges = g.getEdgesOfVertexIdx(0); 111 112 for (auto edge : edges) { 113 toVisit.push(edge); 114 } 115 116 while (toVisit.size() != 0) { 117 oneStepPrim(toVisit, visitedIndices, g, minEdgeToVertex); 118 } 119 120 REQUIRE(visitedIndices.size() == vertCount); 121 } 122 123 TEST_CASE("Staircase Prim algorithm", "[Staircase prim algo]") { 124 for (int i = 2; i < 30; ++i) { 125 for (int x = i - 1; x < 60; ++x) { 126 std::size_t edgeCount = x; 127 std::size_t vertCount = i; 128 129 float xMax = 5120; 130 float yMax = 1440; 131 132 std::vector<double> minEdgeToVertex(vertCount, -1); 133 Graph g = Graph(edgeCount, vertCount, xMax, yMax); 134 std::unordered_set<std::size_t> visitedIndices{}; 135 std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> 136 toVisit{}; 137 138 do { 139 g = Graph(edgeCount, vertCount, xMax, yMax); 140 } while (!isConnected(g)); 141 142 std::vector<Edge> edges = g.getEdgesOfVertexIdx(0); 143 for (auto edge : edges) { 144 toVisit.push(edge); 145 } 146 g.traverseVertexIdx(0); 147 visitedIndices.insert(0); 148 149 while (toVisit.size() != 0) { 150 oneStepPrim(toVisit, visitedIndices, g, minEdgeToVertex); 151 } 152 153 REQUIRE(visitedIndices.size() == vertCount); 154 } 155 } 156 } 157 158 TEST_CASE("Small Prim Test", "[Small full validation]") { 159 for (int i = 0; i < 100; ++i) { 160 std::size_t edgeCount = 10; 161 std::size_t vertCount = 5; 162 163 float xMax = 5120; 164 float yMax = 1440; 165 166 Graph g = Graph(edgeCount, vertCount, xMax, yMax); 167 do { 168 g = Graph(edgeCount, vertCount, xMax, yMax); 169 } while (!isConnected(g)); 170 171 std::unordered_set<std::size_t> visitedIndices{}; 172 std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> 173 toVisit{}; 174 175 for (auto edge : g.getEdgesOfVertexIdx(0)) toVisit.push(edge); 176 g.traverseVertexIdx(0); 177 visitedIndices.insert(0); 178 179 std::unordered_set<std::size_t> vBefore = visitedIndices; 180 181 bool havePrior = false; 182 Edge prior = toVisit.top(); 183 std::unordered_set<std::size_t> visibleAtPrior; 184 std::vector<double> minEdgeToVertex(vertCount, -1); 185 186 while (toVisit.size() != 0) { 187 auto current = toVisit.top(); 188 if (havePrior) { 189 bool wasPresent = visibleAtPrior.count(current.v1Index) > 0 || 190 visibleAtPrior.count(current.v2Index) > 0; 191 // anytime we use the same source node two steps in a row, the 192 // second weight must be smaller. 193 if (wasPresent) { 194 REQUIRE(current.length2 >= prior.length2); 195 } 196 } 197 198 prior = current; 199 visibleAtPrior = visitedIndices; 200 havePrior = true; 201 oneStepPrim(toVisit, visitedIndices, g, minEdgeToVertex); 202 bool valid = vBefore.size() + 1 == visitedIndices.size() || 203 vBefore.size() == vertCount; 204 REQUIRE(valid); 205 vBefore = visitedIndices; 206 } 207 REQUIRE(visitedIndices.size() == vertCount); 208 } 209 }