From c2e42281d15fbb03b73f9dbfa8f23bcebc53c70d Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch <12932279+MoKob@users.noreply.github.com> Date: Thu, 28 Dec 2017 22:54:12 +0100 Subject: [PATCH 1/3] Union Find Algorithm --- include/algorithm/union_find.hpp | 27 ++++++++++++++++++++ src/algorithm/CMakeLists.txt | 3 ++- src/algorithm/union_find.cpp | 43 ++++++++++++++++++++++++++++++++ test/algorithm/CMakeLists.txt | 1 + test/algorithm/union_find.cpp | 34 +++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 include/algorithm/union_find.hpp create mode 100644 src/algorithm/union_find.cpp create mode 100644 test/algorithm/union_find.cpp diff --git a/include/algorithm/union_find.hpp b/include/algorithm/union_find.hpp new file mode 100644 index 0000000..889ce14 --- /dev/null +++ b/include/algorithm/union_find.hpp @@ -0,0 +1,27 @@ +#ifndef PROJECT_X_ALGORITHM_UNION_FIND_HPP_ +#define PROJECT_X_ALGORITHM_UNION_FIND_HPP_ + +#include +#include + +namespace project_x { +namespace algorithm { +// implementaiton of the classic union-find algorithm, allowing combination of +// entries into groups and finding representatives of these groups +class UnionFind { +public: + UnionFind(std::uint64_t const universe_size); + + // combine two groups into a single one + void unite(std::uint64_t const lhs, std::uint64_t const rhs); + + // find the representative of a group + std::uint64_t find(std::uint64_t rep); + +private: + std::vector reps; +}; +} // namespace algorithm +} // namespace project_x + +#endif // PROJECT_X_ALGORITHM_UNION_FIND_HPP_ diff --git a/src/algorithm/CMakeLists.txt b/src/algorithm/CMakeLists.txt index 2897304..573759b 100644 --- a/src/algorithm/CMakeLists.txt +++ b/src/algorithm/CMakeLists.txt @@ -1,5 +1,6 @@ set (algorithm_SOURCES - "scc.cpp") + "scc.cpp" + "union_find.cpp") add_library(Xalgorithm STATIC ${algorithm_SOURCES}) diff --git a/src/algorithm/union_find.cpp b/src/algorithm/union_find.cpp new file mode 100644 index 0000000..a4a7407 --- /dev/null +++ b/src/algorithm/union_find.cpp @@ -0,0 +1,43 @@ +#include "algorithm/union_find.hpp" + +#include + +namespace project_x { +namespace algorithm { + +UnionFind::UnionFind(std::uint64_t const universe_size) + : reps(universe_size, -1) {} + +void UnionFind::unite(std::uint64_t const lhs, std::uint64_t const rhs) { + // union by size + auto const lhs_rep = find(lhs); + auto const rhs_rep = find(rhs); + + if (lhs_rep == rhs_rep) + return; + + auto const lhs_size = std::abs(reps[lhs_rep]); + auto const rhs_size = std::abs(reps[rhs_rep]); + + if (lhs_size < rhs_size) { + reps[lhs_rep] -= rhs_size; + reps[rhs_rep] = lhs_rep; + } else { + reps[rhs_rep] -= lhs_size; + reps[lhs_rep] = rhs_rep; + } +} + +// find the representative of a group +std::uint64_t UnionFind::find(std::uint64_t rep) { + if (reps[rep] < 0) + return rep; + else { + // path compression + reps[rep] = find(reps[rep]); + return reps[rep]; + } +} + +} // namespace algorithm +} // namespace project_x diff --git a/test/algorithm/CMakeLists.txt b/test/algorithm/CMakeLists.txt index 443f1ca..720e314 100644 --- a/test/algorithm/CMakeLists.txt +++ b/test/algorithm/CMakeLists.txt @@ -10,3 +10,4 @@ set(testINCLUDES add_unit_test(scc scc.cpp "${testLIBS}" "${testINCLUDES}") add_unit_test(dijkstra dijkstra.cpp "${testLIBS}" "${testINCLUDES}") +add_unit_test(union_find union_find.cpp "${testLIBS}" "${testINCLUDES}") diff --git a/test/algorithm/union_find.cpp b/test/algorithm/union_find.cpp new file mode 100644 index 0000000..6a08567 --- /dev/null +++ b/test/algorithm/union_find.cpp @@ -0,0 +1,34 @@ +#include "algorithm/union_find.hpp" + +// make sure we get a new main function here +#define BOOST_TEST_MODULE UnionFind +#define BOOST_TEST_MAIN +#include + +using namespace project_x; + +// test a construction of an undirected graph from a set of edges +BOOST_AUTO_TEST_CASE(uf_algo) { + algorithm::UnionFind uf(10); + BOOST_CHECK_EQUAL(uf.find(0), 0); + BOOST_CHECK_EQUAL(uf.find(1), 1); + BOOST_CHECK_EQUAL(uf.find(2), 2); + BOOST_CHECK_EQUAL(uf.find(3), 3); + BOOST_CHECK_EQUAL(uf.find(4), 4); + BOOST_CHECK_EQUAL(uf.find(5), 5); + BOOST_CHECK_EQUAL(uf.find(6), 6); + BOOST_CHECK_EQUAL(uf.find(7), 7); + BOOST_CHECK_EQUAL(uf.find(8), 8); + BOOST_CHECK_EQUAL(uf.find(9), 9); + + uf.unite(0, 1); + uf.unite(0, 2); + + BOOST_CHECK_EQUAL(uf.find(1), uf.find(2)); + + uf.unite(4, 4); + BOOST_CHECK(uf.find(4) != uf.find(0)); + uf.unite(uf.find(0), uf.find(5)); + BOOST_CHECK(uf.find(4) != uf.find(5)); + BOOST_CHECK_EQUAL(uf.find(0), uf.find(5)); +} From 6d17d99da80dc65d60fcddccde281c16a0546e22 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch <12932279+MoKob@users.noreply.github.com> Date: Thu, 28 Dec 2017 23:11:16 +0100 Subject: [PATCH 2/3] full coverage uf --- test/algorithm/union_find.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/algorithm/union_find.cpp b/test/algorithm/union_find.cpp index 6a08567..b2a93c5 100644 --- a/test/algorithm/union_find.cpp +++ b/test/algorithm/union_find.cpp @@ -31,4 +31,6 @@ BOOST_AUTO_TEST_CASE(uf_algo) { uf.unite(uf.find(0), uf.find(5)); BOOST_CHECK(uf.find(4) != uf.find(5)); BOOST_CHECK_EQUAL(uf.find(0), uf.find(5)); + uf.unite(uf.find(6), uf.find(0)); + BOOST_CHECK_EQUAL(uf.find(6), uf.find(5)); } From be9c43a42435a5824b84786ecb5d54ff0eb33976 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch <12932279+MoKob@users.noreply.github.com> Date: Thu, 28 Dec 2017 23:34:40 +0100 Subject: [PATCH 3/3] start partitioning --- include/algorithm/partition.hpp | 30 ++++++++++++++++++++++++++++++ src/algorithm/partition.cpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 include/algorithm/partition.hpp create mode 100644 src/algorithm/partition.cpp diff --git a/include/algorithm/partition.hpp b/include/algorithm/partition.hpp new file mode 100644 index 0000000..bf5be89 --- /dev/null +++ b/include/algorithm/partition.hpp @@ -0,0 +1,30 @@ +#ifndef PROJECT_X_ALGORITHM_PARTITION_HPP_ +#define PROJECT_X_ALGORITHM_PARTITION_HPP_ + +#include "graph/forward_star.hpp" + +#include +#include + +namespace project_x { +namespace algorithm { + +// recursive bisection of a forward star graph, following a fixed balance +// constraint for cells +class Partition { +public: + using PartitionID = std::uint64_t; + + Partition(ForwardStar const &graph, std::uint32_t const max_cell_size); + +private: + // compute a set of base-cells + std::vector compute_cells(std::uint32_t const max_cell_size); + + graph::ForwardStar const &graph; +}; + +} // namespace algorithm +} // namespace project_x + +#endif // PROJECT_X_ALGORITHM_PARTITION_HPP_ diff --git a/src/algorithm/partition.cpp b/src/algorithm/partition.cpp new file mode 100644 index 0000000..2da3cd7 --- /dev/null +++ b/src/algorithm/partition.cpp @@ -0,0 +1,33 @@ +#include "algorithm/partition.hpp" +#include "algorithm/union_find.hpp" +#include "graph/id.hpp" + +#include + +namespace project_x { +namespace algorithm { + +namespace { +std::vector close_nodes(graph::ForwardStar const &graph, + NodeID const to_node, + std::uint32_t node_count) { + std::vector nodes; + nodes.push_back(to_node); + + return nodes; +} +} // namespace + +Partition::Partition(graph::ForwardStar const &graph, + std::uint32_t const max_cell_size) + : graph(graph) { + auto cells = compute_cells(max_cell_size); +} + +std::vector +Partition::compute_cells(std::uint32_t max_cell_size) { + algorithm::UnionFind uf(graph.number_of_nodes()); +} + +} // namespace algorithm +} // namespace project_x