diff --git a/cpp/src/community/detail/common_methods.cuh b/cpp/src/community/detail/common_methods.cuh index 4e250ff6c4..53313359f1 100644 --- a/cpp/src/community/detail/common_methods.cuh +++ b/cpp/src/community/detail/common_methods.cuh @@ -30,6 +30,10 @@ #include #include +#include +#include +#include + CUCO_DECLARE_BITWISE_COMPARABLE(float) CUCO_DECLARE_BITWISE_COMPARABLE(double) // FIXME: a temporary workaround for a compiler error, should be deleted once cuco gets patched. @@ -41,6 +45,24 @@ struct is_bitwise_comparable> : std::true_type {}; namespace cugraph { namespace detail { +template +constexpr weight_t louvain_delta_modularity_noise_floor() +{ + if constexpr (std::is_same_v) { + return weight_t{1e-12}; + } else { + return weight_t{1e-15}; + } +} + +template +weight_t compute_louvain_min_vertex_move_gain(weight_t threshold, vertex_t number_of_vertices) +{ + auto const vertex_count = std::max(number_of_vertices, vertex_t{1}); + auto const scaled_threshold = threshold / static_cast(vertex_count); + return std::max(scaled_threshold, louvain_delta_modularity_noise_floor()); +} + // FIXME: a workaround for cudaErrorInvalidDeviceFunction error when device lambda is used template struct key_aggregated_edge_op_t { @@ -111,6 +133,7 @@ struct count_updown_moves_op_t { : false; } }; + // FIXME: a workaround for cudaErrorInvalidDeviceFunction error when device lambda is used template struct cluster_update_op_t { @@ -394,13 +417,16 @@ rmm::device_uvector update_clustering_by_delta_modularity( detail::reduce_op_t{}, cugraph::get_dataframe_buffer_begin(output_buffer)); - int nr_moves = - thrust::count_if(handle.get_thrust_policy(), - thrust::make_zip_iterator(next_clusters_v.begin(), - cugraph::get_dataframe_buffer_begin(output_buffer)), - thrust::make_zip_iterator(next_clusters_v.end(), - cugraph::get_dataframe_buffer_end(output_buffer)), - detail::count_updown_moves_op_t{up_down, threshold}); + auto const min_vertex_move_gain = + compute_louvain_min_vertex_move_gain(threshold, graph_view.number_of_vertices()); + + int nr_moves = thrust::count_if( + handle.get_thrust_policy(), + thrust::make_zip_iterator(next_clusters_v.begin(), + cugraph::get_dataframe_buffer_begin(output_buffer)), + thrust::make_zip_iterator(next_clusters_v.end(), + cugraph::get_dataframe_buffer_end(output_buffer)), + detail::count_updown_moves_op_t{up_down, min_vertex_move_gain}); if constexpr (multi_gpu) { nr_moves = host_scalar_allreduce( @@ -414,7 +440,7 @@ rmm::device_uvector update_clustering_by_delta_modularity( next_clusters_v.end(), cugraph::get_dataframe_buffer_begin(output_buffer), next_clusters_v.begin(), - detail::cluster_update_op_t{up_down, threshold}); + detail::cluster_update_op_t{up_down, min_vertex_move_gain}); return std::move(next_clusters_v); } diff --git a/cpp/tests/community/louvain_test.cpp b/cpp/tests/community/louvain_test.cpp index 1db519b8f2..486e5a1b2f 100644 --- a/cpp/tests/community/louvain_test.cpp +++ b/cpp/tests/community/louvain_test.cpp @@ -232,7 +232,7 @@ INSTANTIATE_TEST_SUITE_P( ::testing::Combine(::testing::Values( Louvain_Usecase{ std::nullopt, std::nullopt, std::nullopt, true, 3, 0.39907956}, - Louvain_Usecase{20, double{1e-3}, std::nullopt, true, 3, 0.41978961}, + Louvain_Usecase{20, double{1e-3}, std::nullopt, true, 3, 0.39907956}, Louvain_Usecase{100, double{1e-3}, double{0.8}, true, 3, 0.48573306}), ::testing::Values(cugraph::test::File_Usecase("test/datasets/karate.mtx"))));