Skip to content

Commit

Permalink
Add support in C API for handling unweighted graphs in algorithms tha…
Browse files Browse the repository at this point in the history
…t expect weights (#3513)

Closes #3499 

Some of our C++ algorithms require a graph to be weighted.  The python layer will add "fake" edge weights of 1 to every edge in order to call these algorithms.  This adds a persisted constant value for every edge that will continue to exist for the life span of the python graph object, even though it is only necessary for a handful of algorithms.

This PR addresses these concerns.

Many of the C++ algorithms already actually support the graph not having weights.  A few should support it and had bugs that were corrected (induced subgraph, k-core, egonet).  A few can easily support it but did not (legacy spectral algorithms).

The Louvain and Leiden algorithms need to have a weighted graph because they will coarsen the weights as the graph is coarsened, and the weights will eventually not be one while the algorithm is running.  These require a slightly different approach.

This PR also added C API tests for unweighted graphs for these algorithms.

Authors:
  - Chuck Hastings (https://github.com/ChuckHastings)
  - Brad Rees (https://github.com/BradReesWork)

Approvers:
  - Seunghwa Kang (https://github.com/seunghwak)

URL: #3513
  • Loading branch information
ChuckHastings authored May 4, 2023
1 parent c69de18 commit 0fd72f9
Show file tree
Hide file tree
Showing 18 changed files with 657 additions and 194 deletions.
3 changes: 2 additions & 1 deletion cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ add_library(cugraph_c
src/c_api/capi_helper.cu
src/c_api/legacy_spectral.cpp
src/c_api/legacy_ecg.cpp
src/c_api/graph_helper.cu
src/c_api/graph_helper_sg.cu
src/c_api/graph_helper_mg.cu
src/c_api/graph_generators.cpp
src/c_api/induced_subgraph_result.cpp
src/c_api/hits.cpp
Expand Down
8 changes: 5 additions & 3 deletions cpp/src/c_api/core_result.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
* Copyright (c) 2022-2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -95,8 +95,10 @@ cugraph_type_erased_device_array_view_t* cugraph_k_core_result_get_weights(
cugraph_k_core_result_t* result)
{
auto internal_pointer = reinterpret_cast<cugraph::c_api::cugraph_k_core_result_t*>(result);
return reinterpret_cast<cugraph_type_erased_device_array_view_t*>(
internal_pointer->weights_->view());
return (internal_pointer->weights_ == nullptr)
? NULL
: reinterpret_cast<cugraph_type_erased_device_array_view_t*>(
internal_pointer->weights_->view());
}

void cugraph_k_core_result_free(cugraph_k_core_result_t* result)
Expand Down
54 changes: 0 additions & 54 deletions cpp/src/c_api/graph_helper.cu

This file was deleted.

7 changes: 6 additions & 1 deletion cpp/src/c_api/graph_helper.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
* Copyright (c) 2022-2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -26,5 +26,10 @@ rmm::device_uvector<vertex_t> expand_sparse_offsets(raft::device_span<edge_t con
vertex_t base_vertex_id,
rmm::cuda_stream_view const& stream);

template <typename GraphViewType, typename T>
edge_property_t<GraphViewType, T> create_constant_edge_property(raft::handle_t const& handle,
GraphViewType const& graph_view,
T constant_value);

} // namespace c_api
} // namespace cugraph
45 changes: 45 additions & 0 deletions cpp/src/c_api/graph_helper_impl.cuh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2022-2023, 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 <prims/fill_edge_property.cuh>
#include <structure/detail/structure_utils.cuh>

namespace cugraph {
namespace c_api {

template <typename vertex_t, typename edge_t>
rmm::device_uvector<vertex_t> expand_sparse_offsets(raft::device_span<edge_t const> offsets,
vertex_t base_vertex_id,
rmm::cuda_stream_view const& stream)
{
return cugraph::detail::expand_sparse_offsets(offsets, base_vertex_id, stream);
}

template <typename GraphViewType, typename T>
edge_property_t<GraphViewType, T> create_constant_edge_property(raft::handle_t const& handle,
GraphViewType const& graph_view,
T constant_value)
{
edge_property_t<GraphViewType, T> edge_property(handle, graph_view);

cugraph::fill_edge_property(handle, graph_view, constant_value, edge_property);

return edge_property;
}

} // namespace c_api
} // namespace cugraph
89 changes: 89 additions & 0 deletions cpp/src/c_api/graph_helper_mg.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2023, 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 <c_api/graph_helper_impl.cuh>

namespace cugraph {
namespace c_api {

template edge_property_t<cugraph::graph_view_t<int32_t, int32_t, false, true>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int32_t, false, true> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int64_t, false, true>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int64_t, false, true> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int64_t, int64_t, false, true>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int64_t, int64_t, false, true> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int32_t, true, true>, float>
create_constant_edge_property(raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int32_t, true, true> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int64_t, true, true>, float>
create_constant_edge_property(raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int64_t, true, true> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int64_t, int64_t, true, true>, float>
create_constant_edge_property(raft::handle_t const& handle,
cugraph::graph_view_t<int64_t, int64_t, true, true> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int32_t, false, true>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int32_t, false, true> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int64_t, false, true>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int64_t, false, true> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int64_t, int64_t, false, true>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int64_t, int64_t, false, true> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int32_t, true, true>, double>
create_constant_edge_property(raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int32_t, true, true> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int64_t, true, true>, double>
create_constant_edge_property(raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int64_t, true, true> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int64_t, int64_t, true, true>, double>
create_constant_edge_property(raft::handle_t const& handle,
cugraph::graph_view_t<int64_t, int64_t, true, true> const& graph_view,
double constant_value);

} // namespace c_api
} // namespace cugraph
118 changes: 118 additions & 0 deletions cpp/src/c_api/graph_helper_sg.cu
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2022-2023, 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 <c_api/graph_helper_impl.cuh>

namespace cugraph {
namespace c_api {

template rmm::device_uvector<int32_t> expand_sparse_offsets(
raft::device_span<int32_t const> offsets,
int32_t base_vertex_id,
rmm::cuda_stream_view const& stream);

template rmm::device_uvector<int32_t> expand_sparse_offsets(
raft::device_span<int64_t const> offsets,
int32_t base_vertex_id,
rmm::cuda_stream_view const& stream);

template rmm::device_uvector<int64_t> expand_sparse_offsets(
raft::device_span<int64_t const> offsets,
int64_t base_vertex_id,
rmm::cuda_stream_view const& stream);

template rmm::device_uvector<int32_t> expand_sparse_offsets(raft::device_span<size_t const> offsets,
int32_t base_vertex_id,
rmm::cuda_stream_view const& stream);

template rmm::device_uvector<int64_t> expand_sparse_offsets(raft::device_span<size_t const> offsets,
int64_t base_vertex_id,
rmm::cuda_stream_view const& stream);

template edge_property_t<cugraph::graph_view_t<int32_t, int32_t, false, false>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int32_t, false, false> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int64_t, false, false>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int64_t, false, false> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int64_t, int64_t, false, false>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int64_t, int64_t, false, false> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int32_t, true, false>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int32_t, true, false> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int64_t, true, false>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int64_t, true, false> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int64_t, int64_t, true, false>, float>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int64_t, int64_t, true, false> const& graph_view,
float constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int32_t, false, false>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int32_t, false, false> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int64_t, false, false>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int64_t, false, false> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int64_t, int64_t, false, false>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int64_t, int64_t, false, false> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int32_t, true, false>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int32_t, true, false> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int32_t, int64_t, true, false>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int32_t, int64_t, true, false> const& graph_view,
double constant_value);

template edge_property_t<cugraph::graph_view_t<int64_t, int64_t, true, false>, double>
create_constant_edge_property(
raft::handle_t const& handle,
cugraph::graph_view_t<int64_t, int64_t, true, false> const& graph_view,
double constant_value);

} // namespace c_api
} // namespace cugraph
7 changes: 5 additions & 2 deletions cpp/src/c_api/induced_subgraph_result.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, NVIDIA CORPORATION.
* Copyright (c) 2022-2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -39,7 +39,10 @@ extern "C" cugraph_type_erased_device_array_view_t* cugraph_induced_subgraph_get
{
auto internal_pointer =
reinterpret_cast<cugraph::c_api::cugraph_induced_subgraph_result_t*>(induced_subgraph);
return reinterpret_cast<cugraph_type_erased_device_array_view_t*>(internal_pointer->wgt_->view());
return (internal_pointer->wgt_ == nullptr)
? NULL
: reinterpret_cast<cugraph_type_erased_device_array_view_t*>(
internal_pointer->wgt_->view());
}

extern "C" cugraph_type_erased_device_array_view_t* cugraph_induced_subgraph_get_subgraph_offsets(
Expand Down
Loading

0 comments on commit 0fd72f9

Please sign in to comment.