#include #include "algorithm/tarjan.h" #include "algorithm/breadth_first_search.h" #include #include #include #include constexpr int verticesNum = 10; using namespace graph; TEST_SUITE("Algorithm") { TEST_CASE("Tarjan::execute") { // 1 --> 2 --> 3 --> 1 // 3 --> 4 --> 5 --> 3 // 2 --> 6 --> 7 --> 8 --> 6 // 7 --> 9 // 6 --> 9 --> 10 --> 11 --> 12 --> 13 --> 9 // 12 --> 10 Digraph G; G.insert(1, 2); G.insert(2, 3); G.insert(3, 1); G.insert(3, 4); G.insert(4, 5); G.insert(5, 3); G.insert(2, 6); G.insert(6, 7); G.insert(7, 8); G.insert(7, 9); G.insert(8, 6); G.insert(6, 9); G.insert(9, 10); G.insert(10, 11); G.insert(11, 12); G.insert(12, 13); G.insert(13, 9); G.insert(12, 10); REQUIRE_EQ(G.V(), 13); auto SCCs = algo::Tarjan(G.adjList).execute(); std::vector> expected = { {9, 10, 11, 12, 13}, {6, 7, 8}, {1, 2, 3, 4, 5} }; for (auto i = 0; i < SCCs.size(); i++) { auto kv = SCCs[i].vertices(); CHECK_EQ(std::is_permutation(kv.begin(), kv.end(), expected[i].begin()), true); } } TEST_CASE("Tarjan::execute ~ DAG") { Digraph G; auto gen = std::bind_front(std::uniform_real_distribution<>(0, 1), std::default_random_engine()); for (int i = 0; i <= verticesNum; ++i) { for (int j = i + 1; j <= verticesNum; ++j) { if (gen() < 0.25) G.insert(i, j); } } auto SCCs = algo::Tarjan(G.adjList).execute(); // Testing whether an scc is a 1-vertex scc which after the normalization // has no edges, in this case we know tgat there exist no 2-vertex sccs for (auto& scc : SCCs) { CHECK_EQ(std::all_of(scc.adjList.begin(), scc.adjList.end(), [](const auto& p) { return p.second.size() == 0; }), true); } } TEST_CASE("BreadthFirstSearch::execute") { // 1 --> 2 --> 3 --> 1 // 3 --> 4 --> 5 --> 3 // 2 --> 6 --> 7 --> 8 --> 6 // 7 --> 9 // 6 --> 9 --> 10 --> 11 --> 12 --> 13 --> 9 // 12 --> 10 Digraph G; G.insert(1, 2); G.insert(2, 3); G.insert(3, 1); G.insert(3, 4); G.insert(4, 5); G.insert(5, 3); G.insert(2, 6); G.insert(6, 7); G.insert(7, 8); G.insert(7, 9); G.insert(8, 6); G.insert(6, 9); G.insert(9, 10); G.insert(10, 11); G.insert(11, 12); G.insert(12, 13); G.insert(13, 9); G.insert(12, 10); auto tree = algo::BreadthFirstSearch(G.adjList).execute(1); std::unordered_map> expected = { {1, {2}}, {2, {3, 6}}, {3, {4}}, {4, {5}}, {5, {}}, {6, {7, 9}}, {7, {8}}, {8, {}}, {9, {10}}, {10, {11}}, {11, {12}}, {12, {13}}, {13, {}} }; CHECK_EQ(tree, expected); } TEST_CASE("BreadthFirstSearch::query") { // 1 --> 2 --> 3 --> 1 // 3 --> 4 --> 5 --> 3 // 2 --> 6 --> 7 --> 8 --> 6 // 7 --> 9 // 6 --> 9 --> 10 --> 11 --> 12 --> 13 --> 9 // 12 --> 10 Digraph G; G.insert(1, 2); G.insert(2, 3); G.insert(3, 1); G.insert(3, 4); G.insert(4, 5); G.insert(5, 3); G.insert(2, 6); G.insert(6, 7); G.insert(7, 8); G.insert(7, 9); G.insert(8, 6); G.insert(6, 9); G.insert(9, 10); G.insert(10, 11); G.insert(11, 12); G.insert(12, 13); G.insert(13, 9); G.insert(12, 10); auto bfs = std::make_unique>(G.adjList); CHECK_EQ(bfs->query(1, 5), true); CHECK_EQ(bfs->query(1, 10), true); CHECK_EQ(bfs->query(9, 5), false); CHECK_EQ(bfs->query(8, 4), false); } }