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/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/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 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..b2a93c5 --- /dev/null +++ b/test/algorithm/union_find.cpp @@ -0,0 +1,36 @@ +#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)); + uf.unite(uf.find(6), uf.find(0)); + BOOST_CHECK_EQUAL(uf.find(6), uf.find(5)); +}