From 6e14ede580f8d745656bd49d2f0c41e56661dcb7 Mon Sep 17 00:00:00 2001 From: Andrey Prokopenko Date: Thu, 6 Feb 2025 13:11:52 -0500 Subject: [PATCH] Move MinimumSpanningTree and WeightedEdge to Experimenal namespace --- benchmarks/dbscan/dbscan_timpl.hpp | 2 +- src/cluster/ArborX_Dendrogram.hpp | 4 +- src/cluster/ArborX_MinimumSpanningTree.hpp | 62 ++++++++++---------- src/cluster/detail/ArborX_BoruvkaHelpers.hpp | 4 +- src/cluster/detail/ArborX_WeightedEdge.hpp | 4 +- test/tstCompileOnlyWeightedEdges.cpp | 2 +- test/tstDendrogram.cpp | 11 ++-- test/tstMinimumSpanningTree.cpp | 36 ++++++------ test/tstMinimumSpanningTreeGoldenTest.cpp | 6 +- 9 files changed, 68 insertions(+), 63 deletions(-) diff --git a/benchmarks/dbscan/dbscan_timpl.hpp b/benchmarks/dbscan/dbscan_timpl.hpp index 3c109ae3e..58921c37b 100644 --- a/benchmarks/dbscan/dbscan_timpl.hpp +++ b/benchmarks/dbscan/dbscan_timpl.hpp @@ -317,7 +317,7 @@ bool ArborXBenchmark::run(ArborXBenchmark::Parameters const ¶ms) { Kokkos::Profiling::pushRegion("ArborX::MST::total"); - ArborX::Details::MinimumSpanningTree mst( + ArborX::Experimental::MinimumSpanningTree mst( exec_space, primitives, params.core_min_size); Kokkos::Profiling::popRegion(); diff --git a/src/cluster/ArborX_Dendrogram.hpp b/src/cluster/ArborX_Dendrogram.hpp index a6337b6fe..890d73f19 100644 --- a/src/cluster/ArborX_Dendrogram.hpp +++ b/src/cluster/ArborX_Dendrogram.hpp @@ -44,7 +44,7 @@ struct Dendrogram template Dendrogram(ExecutionSpace const &exec_space, - Kokkos::View edges) + Kokkos::View edges) : _parents("ArborX::Dendrogram::parents", 0) , _parent_heights("ArborX::Dendrogram::parent_heights", 0) { @@ -81,7 +81,7 @@ struct Dendrogram template void splitEdges( ExecutionSpace const &exec_space, - Kokkos::View edges, + Kokkos::View edges, Kokkos::View unweighted_edges, Kokkos::View weights) { diff --git a/src/cluster/ArborX_MinimumSpanningTree.hpp b/src/cluster/ArborX_MinimumSpanningTree.hpp index 161a3decd..9d7da218a 100644 --- a/src/cluster/ArborX_MinimumSpanningTree.hpp +++ b/src/cluster/ArborX_MinimumSpanningTree.hpp @@ -25,10 +25,11 @@ #include #include -namespace ArborX::Details +namespace ArborX::Experimental { -template +template struct MinimumSpanningTree { using memory_space = MemorySpace; @@ -69,11 +70,11 @@ struct MinimumSpanningTree bvh.query( space, Experimental::attach_indices(Experimental::make_nearest(points, k)), - MaxDistance{points, - core_distances}); + Details::MaxDistance{ + points, core_distances}); Kokkos::Profiling::popRegion(); - MutualReachability mutual_reachability{ + Details::MutualReachability mutual_reachability{ core_distances}; Kokkos::Profiling::pushRegion("ArborX::MST::boruvka"); doBoruvka(space, bvh, mutual_reachability); @@ -82,11 +83,11 @@ struct MinimumSpanningTree else { Kokkos::Profiling::pushRegion("ArborX::MST::boruvka"); - doBoruvka(space, bvh, Euclidean{}); + doBoruvka(space, bvh, Details::Euclidean{}); Kokkos::Profiling::popRegion(); } - finalizeEdges(space, bvh, edges); + Details::finalizeEdges(space, bvh, edges); Kokkos::Profiling::popRegion(); } @@ -107,7 +108,7 @@ struct MinimumSpanningTree Kokkos::view_alloc(space, Kokkos::WithoutInitializing, "ArborX::MST::tree_parents"), 2 * n - 1); - findParents(space, bvh, tree_parents); + Details::findParents(space, bvh, tree_parents); Kokkos::Profiling::pushRegion("ArborX::MST::initialize_node_labels"); Kokkos::View labels( @@ -118,7 +119,7 @@ struct MinimumSpanningTree Kokkos::subview(labels, std::make_pair((decltype(n))0, n))); Kokkos::Profiling::popRegion(); - Kokkos::View component_out_edges( + Kokkos::View component_out_edges( Kokkos::view_alloc(space, Kokkos::WithoutInitializing, "ArborX::MST::component_out_edges"), n); @@ -169,7 +170,7 @@ struct MinimumSpanningTree Kokkos::View sided_parents("ArborX::MST::sided_parents", 0); - if constexpr (Mode == BoruvkaMode::HDBSCAN) + if constexpr (Mode == Details::BoruvkaMode::HDBSCAN) { KokkosExt::reallocWithoutInitializing(space, edges_mapping, n - 1); KokkosExt::reallocWithoutInitializing(space, sided_parents, n - 1); @@ -189,16 +190,16 @@ struct MinimumSpanningTree std::to_string(num_components)); // Propagate leaf node labels to internal nodes - reduceLabels(space, tree_parents, labels); + Details::reduceLabels(space, tree_parents, labels); constexpr auto inf = KokkosExt::ArithmeticTraits::infinity::value; - constexpr DirectedEdge uninitialized_edge; + constexpr Details::DirectedEdge uninitialized_edge; Kokkos::deep_copy(space, component_out_edges, uninitialized_edge); Kokkos::deep_copy(space, weights, inf); Kokkos::deep_copy(space, radii, inf); resetSharedRadii(space, bvh, labels, metric, radii); - FindComponentNearestNeighbors( + Details::FindComponentNearestNeighbors( space, bvh, labels, weights, component_out_edges, metric, radii, lower_bounds, std::bool_constant()); retrieveEdges(space, labels, weights, component_out_edges); @@ -207,40 +208,40 @@ struct MinimumSpanningTree updateLowerBounds(space, labels, component_out_edges, lower_bounds); } - UpdateComponentsAndEdges + Details::UpdateComponentsAndEdges< + decltype(labels), decltype(component_out_edges), decltype(edges), + decltype(edges_mapping), decltype(num_edges), Mode> f{labels, component_out_edges, edges, edges_mapping, num_edges}; // For every component C and a found shortest edge `(u, w)`, add the // edge to the list of MST edges. Kokkos::parallel_for( "ArborX::MST::update_unidirectional_edges", - Kokkos::RangePolicy(space, 0, - n), + Kokkos::RangePolicy( + space, 0, n), f); int num_edges_host; Kokkos::deep_copy(space, num_edges_host, num_edges); space.fence(); - if constexpr (Mode == BoruvkaMode::HDBSCAN) + if constexpr (Mode == Details::BoruvkaMode::HDBSCAN) { Kokkos::parallel_for( "ArborX::MST::update_bidirectional_edges", - Kokkos::RangePolicy(space, 0, - n), + Kokkos::RangePolicy( + space, 0, n), f); if (iterations > 1) - updateSidedParents(space, labels, edges, edges_mapping, sided_parents, - edges_start, edges_end); + Details::updateSidedParents(space, labels, edges, edges_mapping, + sided_parents, edges_start, edges_end); else { Kokkos::Profiling::ScopedRegion guard( "ArborX::MST::compute_vertex_parents"); - assignVertexParents(space, labels, component_out_edges, edges_mapping, - bvh, dendrogram_parents); + Details::assignVertexParents(space, labels, component_out_edges, + edges_mapping, bvh, dendrogram_parents); } } @@ -248,7 +249,8 @@ struct MinimumSpanningTree // with the component that w belongs to by updating the labels Kokkos::parallel_for( "ArborX::MST::update_labels", - Kokkos::RangePolicy(space, 0, n), f); + Kokkos::RangePolicy(space, 0, n), + f); num_components = static_cast(n) - num_edges_host; @@ -267,7 +269,7 @@ struct MinimumSpanningTree Kokkos::resize(component_out_edges, 0); Kokkos::resize(tree_parents, 0); - if constexpr (Mode == BoruvkaMode::HDBSCAN) + if constexpr (Mode == Details::BoruvkaMode::HDBSCAN) { // Done with the recursion as there are no more alpha edges. Assign @@ -275,9 +277,9 @@ struct MinimumSpanningTree Kokkos::deep_copy(space, Kokkos::subview(sided_parents, std::make_pair(edges_start, edges_end)), - ROOT_CHAIN_VALUE); + Details::ROOT_CHAIN_VALUE); - computeParents(space, edges, sided_parents, dendrogram_parents); + Details::computeParents(space, edges, sided_parents, dendrogram_parents); KokkosExt::reallocWithoutInitializing(space, dendrogram_parent_heights, n - 1); @@ -293,6 +295,6 @@ struct MinimumSpanningTree } }; -} // namespace ArborX::Details +} // namespace ArborX::Experimental #endif diff --git a/src/cluster/detail/ArborX_BoruvkaHelpers.hpp b/src/cluster/detail/ArborX_BoruvkaHelpers.hpp index 1af447221..93b3a7395 100644 --- a/src/cluster/detail/ArborX_BoruvkaHelpers.hpp +++ b/src/cluster/detail/ArborX_BoruvkaHelpers.hpp @@ -97,7 +97,7 @@ class DirectedEdge , weight{weight} {} KOKKOS_DEFAULTED_FUNCTION constexpr DirectedEdge() = default; - KOKKOS_FUNCTION explicit constexpr operator WeightedEdge() + KOKKOS_FUNCTION explicit constexpr operator Experimental::WeightedEdge() { return {source(), target(), weight}; } @@ -453,7 +453,7 @@ struct UpdateComponentsAndEdges // append new edge at the "end" of the array (akin to // std::vector::push_back) - auto const edge = static_cast(_out_edges(i)); + auto const edge = static_cast(_out_edges(i)); auto const back = Kokkos::atomic_fetch_inc(&_num_edges()); // atomic post-increment _edges(back) = edge; diff --git a/src/cluster/detail/ArborX_WeightedEdge.hpp b/src/cluster/detail/ArborX_WeightedEdge.hpp index 3a3bc515e..671e40bd3 100644 --- a/src/cluster/detail/ArborX_WeightedEdge.hpp +++ b/src/cluster/detail/ArborX_WeightedEdge.hpp @@ -15,7 +15,7 @@ #include #include -namespace ArborX::Details +namespace ArborX::Experimental { struct WeightedEdge @@ -48,6 +48,6 @@ struct WeightedEdge } }; -} // namespace ArborX::Details +} // namespace ArborX::Experimental #endif diff --git a/test/tstCompileOnlyWeightedEdges.cpp b/test/tstCompileOnlyWeightedEdges.cpp index 4c20eb70b..f7791993d 100644 --- a/test/tstCompileOnlyWeightedEdges.cpp +++ b/test/tstCompileOnlyWeightedEdges.cpp @@ -46,7 +46,7 @@ static_assert(test_directed_edges()); // avoid warning unused function KOKKOS_FUNCTION constexpr bool test_weighted_edges() { - using ArborX::Details::WeightedEdge; + using ArborX::Experimental::WeightedEdge; static_assert(WeightedEdge{1, 2, 3} < WeightedEdge{1, 2, 4}); diff --git a/test/tstDendrogram.cpp b/test/tstDendrogram.cpp index f2f7b5bfb..bf2de6003 100644 --- a/test/tstDendrogram.cpp +++ b/test/tstDendrogram.cpp @@ -25,7 +25,7 @@ BOOST_AUTO_TEST_SUITE(Dendrogram) -using ArborX::Details::WeightedEdge; +using ArborX::Experimental::WeightedEdge; namespace tt = boost::test_tools; namespace @@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(dendrogram_union_find, DeviceType, ARBORX_DEVICE_TYPES) { using ExecutionSpace = typename DeviceType::execution_space; - using ArborX::Details::WeightedEdge; + using ArborX::Experimental::WeightedEdge; ExecutionSpace space; @@ -121,7 +121,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(dendrogram_boruvka, DeviceType, int const n = 3000; auto points = ArborXTest::make_random_cloud>(space, n); - MinimumSpanningTree mst(space, points); + ArborX::Experimental::MinimumSpanningTree + mst(space, points); ArborX::Experimental::Dendrogram dendrogram(space, mst.edges); // Because the dendrogram in the MST is permuted, we need to reorder it in the @@ -209,8 +210,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(dendrogram_boruvka_same_weights, DeviceType, // minpts = 5 is the first value that leads to the test failure with N = 4 int const minpts = 5; - MinimumSpanningTree mst(space, points, - minpts); + ArborX::Experimental::MinimumSpanningTree + mst(space, points, minpts); ArborX::Experimental::Dendrogram dendrogram(space, mst.edges); // Check that the dendrogram is binary diff --git a/test/tstMinimumSpanningTree.cpp b/test/tstMinimumSpanningTree.cpp index f54bcd192..11746898c 100644 --- a/test/tstMinimumSpanningTree.cpp +++ b/test/tstMinimumSpanningTree.cpp @@ -19,7 +19,7 @@ namespace ArborX { -namespace Details +namespace Experimental { // NOTE not sure why but wasn't detected when defined in the global namespace inline constexpr bool operator==(WeightedEdge const &lhs, @@ -27,21 +27,21 @@ inline constexpr bool operator==(WeightedEdge const &lhs, { return !(lhs < rhs) && !(rhs < lhs); } -} // namespace Details +} // namespace Experimental } // namespace ArborX void test_weighted_edges_comparison_compile_only() { - using ArborX::Details::WeightedEdge; + using ArborX::Experimental::WeightedEdge; static_assert(WeightedEdge{1, 2, 3} == WeightedEdge{1, 2, 3}); static_assert(WeightedEdge{1, 2, 3} == WeightedEdge{2, 1, 3}); } template <> struct boost::test_tools::tt_detail::print_log_value< - ArborX::Details::WeightedEdge> + ArborX::Experimental::WeightedEdge> { - void operator()(std::ostream &os, ArborX::Details::WeightedEdge const &e) + void operator()(std::ostream &os, ArborX::Experimental::WeightedEdge const &e) { os << e.source << " -> " << e.target << " [weight=" << e.weight << "]"; } @@ -58,7 +58,8 @@ auto build_minimum_spanning_tree(ExecutionSpace const &exec_space, auto points = toView(points_host, "Test::points"); using MemorySpace = typename ExecutionSpace::memory_space; - ArborX::Details::MinimumSpanningTree mst{exec_space, points, k}; + ArborX::Experimental::MinimumSpanningTree mst{exec_space, points, + k}; auto edges_host = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, mst.edges); @@ -87,6 +88,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(minimum_spanning_tree, DeviceType, ExecutionSpace exec_space; using Point = ArborX::Point<3>; + using WeightedEdge = ArborX::Experimental::WeightedEdge; { // equidistant points // 0 1 2 3 4 @@ -97,27 +99,27 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(minimum_spanning_tree, DeviceType, ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, points, 1, - (std::vector{ + (std::vector{ {0, 1, 1}, {1, 2, 1}, {2, 3, 1}, {3, 4, 1}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, points, 2, - (std::vector{ + (std::vector{ {0, 1, 1}, {1, 2, 1}, {2, 3, 1}, {3, 4, 1}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, points, 3, - (std::vector{ + (std::vector{ {0, 1, 2}, {1, 2, 1}, {2, 3, 1}, {2, 4, 2}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, points, 4, - (std::vector{ + (std::vector{ {0, 1, 3}, {1, 2, 2}, {1, 3, 2}, {1, 4, 3}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, points, 5, - (std::vector{ + (std::vector{ {0, 1, 4}, {1, 2, 3}, {1, 3, 3}, {0, 4, 4}})); } { // non-equidistant points @@ -129,32 +131,32 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(minimum_spanning_tree, DeviceType, ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, non_equidistant_points, 1, - (std::vector{ + (std::vector{ {0, 1, 1}, {1, 2, 1}, {2, 3, 1}, {3, 4, 3}, {4, 5, 4}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, non_equidistant_points, 2, - (std::vector{ + (std::vector{ {0, 1, 1}, {1, 2, 1}, {2, 3, 1}, {3, 4, 3}, {4, 5, 4}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, non_equidistant_points, 3, - (std::vector{ + (std::vector{ {0, 1, 2}, {1, 2, 1}, {1, 3, 2}, {2, 4, 4}, {3, 5, 7}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, non_equidistant_points, 4, - (std::vector{ + (std::vector{ {0, 1, 3}, {1, 2, 2}, {0, 3, 3}, {2, 4, 4}, {2, 5, 8}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, non_equidistant_points, 5, - (std::vector{ + (std::vector{ {0, 1, 6}, {1, 2, 5}, {2, 3, 4}, {1, 4, 5}, {1, 5, 9}})); ARBORX_TEST_MINIMUM_SPANNING_TREE( exec_space, non_equidistant_points, 6, - (std::vector{ + (std::vector{ {0, 1, 10}, {1, 2, 9}, {2, 3, 8}, {3, 4, 7}, {0, 5, 10}})); } } diff --git a/test/tstMinimumSpanningTreeGoldenTest.cpp b/test/tstMinimumSpanningTreeGoldenTest.cpp index 537fcd38c..5394c58be 100644 --- a/test/tstMinimumSpanningTreeGoldenTest.cpp +++ b/test/tstMinimumSpanningTreeGoldenTest.cpp @@ -24,7 +24,7 @@ namespace Test { -struct UndirectedEdge : ArborX::Details::WeightedEdge +struct UndirectedEdge : ArborX::Experimental::WeightedEdge { private: friend bool operator==(UndirectedEdge const &lhs, UndirectedEdge const &rhs) @@ -33,7 +33,7 @@ struct UndirectedEdge : ArborX::Details::WeightedEdge (lhs.source == rhs.target && lhs.target == rhs.source)); } friend std::ostream &operator<<(std::ostream &os, - ArborX::Details::WeightedEdge const &e) + ArborX::Experimental::WeightedEdge const &e) { os << e.source << " -> " << e.target << " [weight=" << e.weight << "]"; return os; @@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(minimum_spanning_tree_golden_test, DeviceType, auto edges_ref = Test::parseEdgesFromCSVFile("mst_golden_test_edges.csv"); std::sort(edges_ref.data(), edges_ref.data() + edges_ref.size()); - using ArborX::Details::MinimumSpanningTree; + using ArborX::Experimental::MinimumSpanningTree; auto edges = Kokkos::create_mirror_view_and_copy( Kokkos::HostSpace{}, MinimumSpanningTree(exec_space, points).edges);