diff --git a/algorithm/italiano.h b/algorithm/italiano.h index 662fe66..ddc8e8d 100644 --- a/algorithm/italiano.h +++ b/algorithm/italiano.h @@ -38,7 +38,6 @@ private: std::map E; }; - template void Italiano::init() { for (const auto& u : std::views::keys(G.adjMatrix)) { @@ -62,21 +61,45 @@ bool Italiano::query(const T& u, const T& v) { template void Italiano::remove(const T& u, const T& v) { - std::map> R; + std::map> R; for (const auto& w : std::views::keys(G.adjMatrix)) { - if (RT[w].contains(u, v)) { - R[w].insert(v); + if (RT[w].contains(u, v) && + std::distance(E[w].inc.begin(), E[w].inc.end()) > 1) { + if (E[v].inc.front() == u) { + E[v].inc.pop_front(); + R[w].push_front(E[v].inc.front()); + E[v].inc.push_front(u); + } else { + R[w].push_front(E[v].inc.front()); + } } - E[u].inc.remove(v); - E[u].out.remove(u); - G.remove(u, v); } + E[u].inc.remove(v); + E[u].out.remove(u); + G.remove(u, v); - //for (const auto& w : std::views::keys(G.adjMatrix)) { - // while (R[w].size() > 0) { - // auto pop = R[w]. - // } - //} + for (const auto& w : std::views::keys(G.adjMatrix)) { + bool hooked = false; + // R contains all vertices that need a hook-parent + while (!R[w].empty()) { + // z is a candidate hook-parent if it is in RT[w] + const auto& toHook = R[w].front(); + for (const auto& z : E[toHook].inc) { + if (RT[w].contains(u, z)) { + R[w].remove(toHook); + hooked = true; + break; + } + } + if (!hooked) { + TC[w][toHook] = false; + for (const auto& z : E[toHook].out) { + if (RT[w].contains(toHook, z)) + R[w].push_front(z); + } + } + } + } } } // namespace algo diff --git a/benchmark/decremental_bench.cc b/benchmark/decremental_bench.cc index edb607f..b43f352 100644 --- a/benchmark/decremental_bench.cc +++ b/benchmark/decremental_bench.cc @@ -4,6 +4,7 @@ #include "algorithm/decremental_scc.h" #include "algorithm/italiano.h" #include "algorithm/frigioni.h" +#include "algorithm/tarjan.h" #include @@ -12,9 +13,22 @@ using namespace graph; TEST_SUITE("Decremental algorithms") { TEST_CASE("Decremental maintenance of SCCs 1") { - std::ifstream infile("resources/data.txt"); + std::ifstream infile("resources/dag.txt"); std::uint16_t u, v; + Digraph G; - //while (infile >> u >> v) {} + while (infile >> u >> v) + G.insert(u, v); + + auto SCCs = algo::Tarjan(G.adjMatrix).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.adjMatrix.begin(), scc.adjMatrix.end(), + [](const auto& p) { + return p.second.size() == 0; + }), true); + } } } \ No newline at end of file diff --git a/test/decremental_test.cc b/test/decremental_test.cc index dc741cc..7a7885b 100644 --- a/test/decremental_test.cc +++ b/test/decremental_test.cc @@ -65,48 +65,50 @@ TEST_SUITE("Decremental algorithms") { } TEST_CASE("Italiano") { - // 1 --> 2 --> 3 --> 1 - // 3 --> 4 --> 5 --> 3 - // 2 --> 6 --> 7 --> 8 --> 6 - // 7 --> 9 - // 6 --> 9 --> 10 --> 11 --> 12 --> 13 --> 9 - // 12 --> 10 + // 1 --> 2 --> 4 --> 6 --> 8 --> 9 + // 4 --> 5 --> 7 --> 8 + // 7 --> 9 + // 1 --> 3 --> 9 + // 3 --> 5 --> 6 Digraph G; G.insert(1, 2); - G.insert(2, 3); - G.insert(3, 1); - G.insert(3, 4); + G.insert(1, 3); + G.insert(2, 4); + G.insert(3, 5); + G.insert(3, 9); G.insert(4, 5); - G.insert(5, 3); - G.insert(2, 6); - G.insert(6, 7); + G.insert(4, 6); + G.insert(5, 6); + G.insert(5, 7); + G.insert(6, 8); 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); + G.insert(8, 9); - REQUIRE_EQ(G.adjMatrix.size(), 13); + REQUIRE_EQ(G.adjMatrix.size(), 9); algo::Italiano italiano(G); italiano.init(); SUBCASE("Italiano::query") { - CHECK_EQ(italiano.query(1, 13), true); - CHECK_EQ(italiano.query(6, 10), true); - CHECK_EQ(italiano.query(9, 11), true); - CHECK_EQ(italiano.query(8, 2), false); - CHECK_EQ(italiano.query(9, 3), false); - CHECK_EQ(italiano.query(9, 8), false); + CHECK_EQ(italiano.query(1, 9), true); + CHECK_EQ(italiano.query(2, 8), true); + CHECK_EQ(italiano.query(3, 7), true); + CHECK_EQ(italiano.query(4, 3), false); + CHECK_EQ(italiano.query(5, 4), false); + CHECK_EQ(italiano.query(6, 1), false); } SUBCASE("Italiano::remove") { + italiano.remove(4, 6); + CHECK_EQ(italiano.query(1, 8), true); + CHECK_EQ(italiano.query(3, 6), true); + + italiano.remove(5, 6); + + CHECK_EQ(italiano.query(1, 9), true); + CHECK_EQ(italiano.query(1, 6), false); } }