Skip to content

Commit

Permalink
Add core number to the C API (rapidsai#2338)
Browse files Browse the repository at this point in the history
This addresses parts of rapidsai#2169, notably the libcugraph_c API for core number, implemented in `src/c_api/core_number.cpp`, with relevant header updates. Testing had been started for the sg variant in `tests/c_api/core_number_test.c`, though results are currently not matching up with what's expected. Testing for the mg variant in `tests/c_api/mg_core_number_test.c` has not been started.

Also, the pylibcugraph wrapper for core number is included (not tested yet), so this PR can include both APIs or be split into 2 separate PRs, one for each level.

Authors:
  - Dylan Chima-Sanchez (https://github.com/betochimas)
  - Chuck Hastings (https://github.com/ChuckHastings)

Approvers:
  - Seunghwa Kang (https://github.com/seunghwak)
  - Joseph Nke (https://github.com/jnke2016)
  - Chuck Hastings (https://github.com/ChuckHastings)
  - Rick Ratzel (https://github.com/rlratzel)

URL: rapidsai#2338
  • Loading branch information
betochimas authored Jul 18, 2022
1 parent 8b2aaee commit 23f9444
Show file tree
Hide file tree
Showing 13 changed files with 733 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ add_library(cugraph_c
src/c_api/katz.cpp
src/c_api/centrality_result.cpp
src/c_api/eigenvector_centrality.cpp
src/c_api/core_number.cpp
src/c_api/core_result.cpp
src/c_api/hits.cpp
src/c_api/bfs.cpp
src/c_api/sssp.cpp
Expand Down
6 changes: 5 additions & 1 deletion cpp/include/cugraph/algorithms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1438,7 +1438,11 @@ void weakly_connected_components(
vertex_t* components,
bool do_expensive_check = false);

enum class k_core_degree_type_t { IN, OUT, INOUT };
/**
* @brief Identify whether the core number computation should be based off incoming edges,
* outgoing edges or both.
*/
enum class k_core_degree_type_t { IN = 0, OUT = 1, INOUT = 2 };

/**
* @brief Compute core numbers of individual vertices from K-core decomposition.
Expand Down
1 change: 1 addition & 0 deletions cpp/include/cugraph_c/algorithms.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <cugraph_c/centrality_algorithms.h>
#include <cugraph_c/community_algorithms.h>
#include <cugraph_c/core_algorithms.h>
#include <cugraph_c/labeling_algorithms.h>
#include <cugraph_c/sampling_algorithms.h>
#include <cugraph_c/traversal_algorithms.h>
Expand Down
91 changes: 91 additions & 0 deletions cpp/include/cugraph_c/core_algorithms.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <cugraph_c/array.h>
#include <cugraph_c/error.h>
#include <cugraph_c/graph.h>
#include <cugraph_c/resource_handle.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Opaque core number result type
*/
typedef struct {
int32_t align_;
} cugraph_core_result_t;

/**
* @brief Get the vertex ids from the core result
*
* @param [in] result The result from core number
* @return type erased array of vertex ids
*/
cugraph_type_erased_device_array_view_t* cugraph_core_result_get_vertices(
cugraph_core_result_t* result);

/**
* @brief Get the core numbers from the core result
*
* @param [in] result The result from core number
* @return type erased array of core numbers
*/
cugraph_type_erased_device_array_view_t* cugraph_core_result_get_core_numbers(
cugraph_core_result_t* result);

/**
* @brief Free core result
*
* @param [in] result The result from core number
*/
void cugraph_core_result_free(cugraph_core_result_t* result);

/**
* @brief Enumeration for computing core number
*/
typedef enum {
K_CORE_DEGREE_TYPE_IN = 0, /** Compute core_number using incoming edges */
K_CORE_DEGREE_TYPE_OUT = 1, /** Compute core_number using outgoing edges */
K_CORE_DEGREE_TYPE_INOUT = 2 /** Compute core_number using both incoming and outgoing edges */
} cugraph_k_core_degree_type_t;

/**
* @brief Perform core number.
*
* @param [in] handle Handle for accessing resources
* @param [in] graph Pointer to graph
* @param [in] degree_type Compute core_number using in, out or both in and out edges
* @param [in] do_expensive_check A flag to run expensive checks for input arguments (if set to
* `true`).
* @param [out] result Opaque pointer to paths 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_core_number(const cugraph_resource_handle_t* handle,
cugraph_graph_t* graph,
cugraph_k_core_degree_type_t degree_type,
bool_t do_expensive_check,
cugraph_core_result_t** result,
cugraph_error_t** error);

#ifdef __cplusplus
}
#endif
116 changes: 116 additions & 0 deletions cpp/src/c_api/core_number.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <cugraph_c/algorithms.h>

#include <c_api/abstract_functor.hpp>
#include <c_api/core_result.hpp>
#include <c_api/graph.hpp>
#include <c_api/resource_handle.hpp>
#include <c_api/utils.hpp>

#include <cugraph/algorithms.hpp>
#include <cugraph/detail/utility_wrappers.hpp>
#include <cugraph/graph_functions.hpp>

#include <optional>

namespace {

struct core_number_functor : public cugraph::c_api::abstract_functor {
raft::handle_t const& handle_;
cugraph::c_api::cugraph_graph_t* graph_{};
cugraph::k_core_degree_type_t degree_type_{};
bool do_expensive_check_{};
cugraph::c_api::cugraph_core_result_t* result_{};

core_number_functor(cugraph_resource_handle_t const* handle,
cugraph_graph_t* graph,
cugraph_k_core_degree_type_t degree_type,
bool do_expensive_check)
: abstract_functor(),
handle_(*reinterpret_cast<cugraph::c_api::cugraph_resource_handle_t const*>(handle)->handle_),
graph_(reinterpret_cast<cugraph::c_api::cugraph_graph_t*>(graph)),
degree_type_(static_cast<cugraph::k_core_degree_type_t>(degree_type)),
do_expensive_check_(do_expensive_check)
{
}

template <typename vertex_t,
typename edge_t,
typename weight_t,
bool store_transposed,
bool multi_gpu>
void operator()()
{
if constexpr (!cugraph::is_candidate<vertex_t, edge_t, weight_t>::value) {
unsupported();
} else {
if constexpr (store_transposed) {
error_code_ = cugraph::c_api::
transpose_storage<vertex_t, edge_t, weight_t, store_transposed, multi_gpu>(
handle_, graph_, error_.get());
if (error_code_ != CUGRAPH_SUCCESS)
;
}
// FIXME: Transpose_storage may have a bug, since if store_transposed is True it can reverse
// the bool value of is_symmetric
auto graph =
reinterpret_cast<cugraph::graph_t<vertex_t, edge_t, weight_t, false, multi_gpu>*>(
graph_->graph_);

auto graph_view = graph->view();

auto number_map = reinterpret_cast<rmm::device_uvector<vertex_t>*>(graph_->number_map_);

rmm::device_uvector<edge_t> core_numbers(graph_view.local_vertex_partition_range_size(),
handle_.get_stream());

auto degree_type = reinterpret_cast<cugraph::k_core_degree_type_t>(degree_type);

cugraph::core_number<vertex_t, edge_t, weight_t, multi_gpu>(
handle_,
graph_view,
core_numbers.data(),
degree_type,
size_t{0},
std::numeric_limits<size_t>::max(),
do_expensive_check_);

rmm::device_uvector<vertex_t> vertex_ids(graph_view.local_vertex_partition_range_size(),
handle_.get_stream());
raft::copy(vertex_ids.data(), number_map->data(), vertex_ids.size(), handle_.get_stream());

result_ = new cugraph::c_api::cugraph_core_result_t{
new cugraph::c_api::cugraph_type_erased_device_array_t(vertex_ids, graph_->vertex_type_),
new cugraph::c_api::cugraph_type_erased_device_array_t(core_numbers, graph_->edge_type_)};
}
}
};

} // namespace

extern "C" cugraph_error_code_t cugraph_core_number(const cugraph_resource_handle_t* handle,
cugraph_graph_t* graph,
cugraph_k_core_degree_type_t degree_type,
bool_t do_expensive_check,
cugraph_core_result_t** result,
cugraph_error_t** error)
{
core_number_functor functor(handle, graph, degree_type, do_expensive_check);

return cugraph::c_api::run_algorithm(graph, functor, result, error);
}
43 changes: 43 additions & 0 deletions cpp/src/c_api/core_result.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <cugraph_c/algorithms.h>

#include <c_api/core_result.hpp>

extern "C" cugraph_type_erased_device_array_view_t* cugraph_core_result_get_vertices(
cugraph_core_result_t* result)
{
auto internal_pointer = reinterpret_cast<cugraph::c_api::cugraph_core_result_t*>(result);
return reinterpret_cast<cugraph_type_erased_device_array_view_t*>(
internal_pointer->vertex_ids_->view());
}

extern "C" cugraph_type_erased_device_array_view_t* cugraph_core_result_get_core_numbers(
cugraph_core_result_t* result)
{
auto internal_pointer = reinterpret_cast<cugraph::c_api::cugraph_core_result_t*>(result);
return reinterpret_cast<cugraph_type_erased_device_array_view_t*>(
internal_pointer->core_numbers_->view());
}

extern "C" void cugraph_core_result_free(cugraph_core_result_t* result)
{
auto internal_pointer = reinterpret_cast<cugraph::c_api::cugraph_core_result_t*>(result);
delete internal_pointer->vertex_ids_;
delete internal_pointer->core_numbers_;
delete internal_pointer;
}
30 changes: 30 additions & 0 deletions cpp/src/c_api/core_result.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <c_api/array.hpp>

namespace cugraph {
namespace c_api {

struct cugraph_core_result_t {
cugraph_type_erased_device_array_t* vertex_ids_{};
cugraph_type_erased_device_array_t* core_numbers_{};
};

} // namespace c_api
} // namespace cugraph
2 changes: 2 additions & 0 deletions cpp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ if(BUILD_CUGRAPH_MG_TESTS)
ConfigureCTestMG(MG_CAPI_UNIFORM_NEIGHBOR_SAMPLE c_api/mg_uniform_neighbor_sample_test.c c_api/mg_test_utils.cpp)
ConfigureCTestMG(MG_CAPI_TRIANGLE_COUNT c_api/mg_triangle_count_test.c c_api/mg_test_utils.cpp)
ConfigureCTestMG(MG_CAPI_LOUVAIN c_api/mg_louvain_test.c c_api/mg_test_utils.cpp)
ConfigureCTestMG(MG_CAPI_CORE_NUMBER c_api/mg_core_number_test.c c_api/mg_test_utils.cpp)
else()
message(FATAL_ERROR "OpenMPI NOT found, cannot build MG tests.")
endif()
Expand Down Expand Up @@ -685,6 +686,7 @@ ConfigureCTest(CAPI_STRONGLY_CONNECTED_COMPONENTS c_api/strongly_connected_compo
ConfigureCTest(CAPI_UNIFORM_NEIGHBOR_SAMPLE c_api/uniform_neighbor_sample_test.c)
ConfigureCTest(CAPI_TRIANGLE_COUNT c_api/triangle_count_test.c)
ConfigureCTest(CAPI_LOUVAIN c_api/louvain_test.c)
ConfigureCTest(CAPI_CORE_NUMBER c_api/core_number_test.c)

###################################################################################################
### enable testing ################################################################################
Expand Down
Loading

0 comments on commit 23f9444

Please sign in to comment.