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