Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define API for Betweenness Centrality #2823

Merged
3 changes: 3 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ set(CUGRAPH_SOURCES
src/centrality/katz_centrality_mg.cu
src/centrality/eigenvector_centrality_sg.cu
src/centrality/eigenvector_centrality_mg.cu
src/centrality/betweenness_centrality_sg.cu
src/centrality/betweenness_centrality_mg.cu
src/tree/legacy/mst.cu
src/components/weakly_connected_components_sg.cu
src/components/weakly_connected_components_mg.cu
Expand Down Expand Up @@ -347,6 +349,7 @@ add_library(cugraph_c
src/c_api/katz.cpp
src/c_api/centrality_result.cpp
src/c_api/eigenvector_centrality.cpp
src/c_api/betweenness_centrality.cpp
src/c_api/core_number.cpp
src/c_api/core_result.cpp
src/c_api/k_core.cpp
Expand Down
86 changes: 86 additions & 0 deletions cpp/include/cugraph/algorithms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,92 @@ void edge_betweenness_centrality(const raft::handle_t& handle,
vertex_t k = 0,
vertex_t const* vertices = nullptr);

/**
* @brief Compute betweenness centrality for a graph
*
* Betweenness centrality for a vertex is the sum of the fraction of
* all pairs shortest paths that pass through the vertex.
*
* The current implementation does not support a weighted graph.
*
* If @p num_vertices and @p vertices are not specified then this function will compute
* exact betweenness (compute betweenness using a traversal from all vertices).
*
* If @p num_vertices or @p vertices are specified then we will compute approximate
* betweenness either by random sampling @p num_vertices as the seeds of the traversal, or
* by using the provided @p vertices as the seeds of the traversal.
*
* If both @p and @num_vertices are specified we will throw an error.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we better use std::optional<std::variant>>? Then, the code self documents the expected behavior and this comment is unnecessary.

*
* @throws cugraph::logic_error when an error occurs.
*
* @tparam vertex_t Type of vertex identifiers. Needs to be an integral type.
* @tparam edge_t Type of edge identifiers. Needs to be an integral type.
* @tparam weight_t Type of edge weights. Needs to be a floating point type.
* @tparam multi_gpu Flag indicating whether template instantiation should target single-GPU (false)
*
* @param handle RAFT handle object to encapsulate resources (e.g. CUDA stream, communicator, and
* handles to various CUDA libraries) to run graph algorithms.
* @param graph_view Graph view object.
* @param num_vertices Optional, if specified, how many vertices to randomly select
* @param vertices Optional, if specified this provides the list of vertices to app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like some texts after to app got deleted.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed missing text, cleaned up documentation based on using std::variant

* @param normalized A flag indicating results should be normalized
* @param include_endpoints A flag indicating whether endpoints of a path should be counted
* @param do_expensive_check A flag to run expensive checks for input arguments (if set to `true`).
*
* @return device vector containing the centralities.
*/
template <typename vertex_t, typename edge_t, typename weight_t, bool multi_gpu>
rmm::device_uvector<weight_t> betweenness_centrality(
const raft::handle_t& handle,
graph_view_t<vertex_t, edge_t, weight_t, false, multi_gpu> const& graph_view,
std::optional<vertex_t> num_vertices,
std::optional<raft::device_span<vertex_t const>> vertices,
bool const normalized = true,
bool const include_endpoints = false,
bool const do_expensive_check = false);

/**
* @brief Compute edge betweenness centrality for a graph
*
* Betweenness centrality of an edge is the sum of the fraction of all-pairs shortest paths that
* pass through this edge. The weight parameter is currenlty not supported
*
* If @p num_vertices and @p vertices are not specified then this function will compute
* exact betweenness (compute betweenness using a traversal from all vertices).
*
* If @p num_vertices or @p vertices are specified then we will compute approximate
* betweenness either by random sampling @p num_vertices as the seeds of the traversal, or
* by using the provided @p vertices as the seeds of the traversal.
*
* If both @p and @num_vertices are specified we will throw an error.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we better use std::optional<std::variant>>? Then, the code self documents the expected behavior and this comment is unnecessary.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't think of that. Updated in next push.

*
* @throws cugraph::logic_error when an error occurs.
*
* @tparam vertex_t Type of vertex identifiers. Needs to be an integral type.
* @tparam edge_t Type of edge identifiers. Needs to be an integral type.
* @tparam weight_t Type of edge weights. Needs to be a floating point type.
* @tparam multi_gpu Flag indicating whether template instantiation should target single-GPU (false)
*
* @param handle RAFT handle object to encapsulate resources (e.g. CUDA stream, communicator, and
* handles to various CUDA libraries) to run graph algorithms.
* @param graph_view Graph view object.
* @param num_vertices Optional, if specified, how many vertices to randomly select
* @param vertices Optional, if specified this provides the list of vertices to app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like some texts after to app got deleted.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in next push

* @param normalized A flag indicating whether or not to normalize the result
* @param do_expensive_check A flag to run expensive checks for input arguments (if set to `true`).
*
* @return device vector containing the centralities.
*/
template <typename vertex_t, typename edge_t, typename weight_t, bool multi_gpu>
rmm::device_uvector<weight_t> edge_betweenness_centrality(
const raft::handle_t& handle,
graph_view_t<vertex_t, edge_t, weight_t, false, multi_gpu> const& graph_view,
std::optional<vertex_t> num_vertices,
std::optional<raft::device_span<vertex_t const>> vertices,
bool normalized = true,
bool do_expensive_check = false);

enum class cugraph_cc_t {
CUGRAPH_WEAK = 0, ///> Weakly Connected Components
CUGRAPH_STRONG, ///> Strongly Connected Components
Expand Down
122 changes: 122 additions & 0 deletions cpp/include/cugraph_c/centrality_algorithms.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,128 @@ cugraph_error_code_t cugraph_katz_centrality(const cugraph_resource_handle_t* ha
cugraph_centrality_result_t** result,
cugraph_error_t** error);

/**
* @brief Compute betweenness centrality
*
* Betweenness can be computed exactly by specifying num_vertices as 0 and
* vertex_list as NULL. This will compute betweenness centrality by doing a
* traversal from every vertex and counting the frequency that a vertex appears on
* a shortest path.
*
* Approximate betweenness can be computed either by specifying num_vertices > 0,
* which will randomly pick the specified number of seeds; or by specifying a
* list of vertices that should be used as seeds for the BFS.
*
* Specifying both num_vertices > 0 and vertex_list as non-null will result in an
* error as the request is ambiguous.
*
* @param [in] handle Handle for accessing resources
* @param [in] graph Pointer to graph
* @param [in] num_vertices Number of vertices to randomly sample
* @param [in] vertex_list Optionally specify a device array containing a list of vertices
* to use as seeds for BFS
* @param [in] normalized Normalize
* @param [in] include_endpoints The traditional formulation of betweenness centrality does not
* include endpoints when considering a vertex to be on a shortest
* path. Setting this to true will consider the endpoints of a
* path to be part of the path.
* @param [in] do_expensive_check A flag to run expensive checks for input arguments (if set to
* `true`).
* @param [out] result Opaque pointer to betweenness centrality results
* @param [out] error Pointer to an error object storing details of any error. Will
* be populated if error code is not CUGRAPH_SUCCESS
* @return error code
*/
cugraph_error_code_t cugraph_betweenness_centrality(
const cugraph_resource_handle_t* handle,
cugraph_graph_t* graph,
size_t num_vertices,
const cugraph_type_erased_device_array_view_t* vertex_list,
bool_t normalized,
bool_t include_endpoints,
bool_t do_expensive_check,
cugraph_centrality_result_t** result,
cugraph_error_t** error);

/**
* @brief Opaque edge centrality result type
*/
typedef struct {
int32_t align_;
} cugraph_edge_centrality_result_t;

/**
* @brief Get the src vertex ids from an edge centrality result
*
* @param [in] result The result from an edge centrality algorithm
* @return type erased array of src vertex ids
*/
cugraph_type_erased_device_array_view_t* cugraph_edge_centrality_result_get_src_vertices(
cugraph_edge_centrality_result_t* result);

/**
* @brief Get the dst vertex ids from an edge centrality result
*
* @param [in] result The result from an edge centrality algorithm
* @return type erased array of dst vertex ids
*/
cugraph_type_erased_device_array_view_t* cugraph_edge_centrality_result_get_dst_vertices(
cugraph_edge_centrality_result_t* result);

/**
* @brief Get the centrality values from an edge centrality algorithm result
*
* @param [in] result The result from an edge centrality algorithm
* @return type erased array view of centrality values
*/
cugraph_type_erased_device_array_view_t* cugraph_edge_centrality_result_get_values(
cugraph_edge_centrality_result_t* result);

/**
* @brief Free centrality result
*
* @param [in] result The result from a centrality algorithm
*/
void cugraph_edge_centrality_result_free(cugraph_edge_centrality_result_t* result);

/**
* @brief Compute edge betweenness centrality
*
* Edge betweenness can be computed exactly by specifying num_vertices as 0 and
* vertex_list as NULL. This will compute betweenness centrality by doing a
* traversal from every vertex and counting the frequency that a edge appears on
* a shortest path.
*
* Approximate betweenness can be computed either by specifying num_vertices > 0,
* which will randomly pick the specified number of seeds; or by specifying a
* list of vertices that should be used as seeds for the BFS.
*
* Specifying both num_vertices > 0 and vertex_list as non-null will result in an
* error as the request is ambiguous.
*
* @param [in] handle Handle for accessing resources
* @param [in] graph Pointer to graph
* @param [in] num_vertices Number of vertices to randomly sample
* @param [in] vertex_list Optionally specify a device array containing a list of vertices
* to use as seeds for BFS
* @param [in] normalized Normalize
* @param [in] do_expensive_check A flag to run expensive checks for input arguments (if set to
* `true`).
* @param [out] result Opaque pointer to edge betweenness centrality results
* @param [out] error Pointer to an error object storing details of any error. Will
* be populated if error code is not CUGRAPH_SUCCESS
* @return error code
*/
cugraph_error_code_t cugraph_edge_betweenness_centrality(
const cugraph_resource_handle_t* handle,
cugraph_graph_t* graph,
size_t num_vertices,
const cugraph_type_erased_device_array_view_t* vertex_list,
bool_t normalized,
bool_t do_expensive_check,
cugraph_edge_centrality_result_t** result,
cugraph_error_t** error);

/**
* @brief Opaque hits result type
*/
Expand Down
Loading