From f09fd41964405784006cd5571740767a4719c31c Mon Sep 17 00:00:00 2001 From: jnke2016 Date: Sun, 22 Sep 2024 19:00:03 -0700 Subject: [PATCH] update API to symmetrize the edgelist and update docstring --- cpp/CMakeLists.txt | 1 - cpp/include/cugraph_c/graph.h | 8 + cpp/src/c_api/graph_mg.cpp | 2 +- cpp/src/c_api/graph_sg.cpp | 41 ++-- cpp/src/c_api/symmetrize_edgelist.cpp | 182 ------------------ .../cugraph/structure/graph_classes.py | 20 +- .../simpleDistributedGraph.py | 39 ++-- .../graph_implementation/simpleGraph.py | 116 ++++------- .../pylibcugraph/_cugraph_c/graph.pxd | 3 + .../_cugraph_c/graph_functions.pxd | 13 ++ python/pylibcugraph/pylibcugraph/graphs.pyx | 21 +- 11 files changed, 145 insertions(+), 301 deletions(-) delete mode 100644 cpp/src/c_api/symmetrize_edgelist.cpp diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index f2eec1786b4..b8eaba9d575 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -666,7 +666,6 @@ add_library(cugraph_c src/c_api/weakly_connected_components.cpp src/c_api/strongly_connected_components.cpp src/c_api/allgather.cpp - src/c_api/symmetrize_edgelist.cpp ) add_library(cugraph::cugraph_c ALIAS cugraph_c) diff --git a/cpp/include/cugraph_c/graph.h b/cpp/include/cugraph_c/graph.h index bbf368b68e2..c47a1a2cd3f 100644 --- a/cpp/include/cugraph_c/graph.h +++ b/cpp/include/cugraph_c/graph.h @@ -152,6 +152,9 @@ cugraph_error_code_t cugraph_graph_create_sg( * If false, do not renumber. Renumbering enables some significant optimizations within * the graph primitives library, so it is strongly encouraged. Renumbering is required if * the vertices are not sequential integer values from 0 to num_vertices. + * @param [in] symmetrize If true, symmetrize the edgelist. + * or take the maximum weight), the caller should remove specific edges themselves and not rely + * on this flag. * @param [in] do_expensive_check If true, do expensive checks to validate the input data * is consistent with software assumptions. If false bypass these checks. * @param [out] graph A pointer to the graph object @@ -170,6 +173,7 @@ cugraph_error_code_t cugraph_sg_graph_create_from_csr( const cugraph_type_erased_device_array_view_t* edge_type_ids, bool_t store_transposed, bool_t renumber, + bool_t symmetrize, bool_t do_expensive_check, cugraph_graph_t** graph, cugraph_error_t** error); @@ -192,6 +196,9 @@ cugraph_error_code_t cugraph_sg_graph_create_from_csr( * If false, do not renumber. Renumbering enables some significant optimizations within * the graph primitives library, so it is strongly encouraged. Renumbering is required if * the vertices are not sequential integer values from 0 to num_vertices. + * @param [in] symmetrize If true, symmetrize the edgelist. + * or take the maximum weight), the caller should remove specific edges themselves and not rely + * on this flag. * @param [in] do_expensive_check If true, do expensive checks to validate the input data * is consistent with software assumptions. If false bypass these checks. * @param [out] graph A pointer to the graph object @@ -210,6 +217,7 @@ cugraph_error_code_t cugraph_graph_create_sg_from_csr( const cugraph_type_erased_device_array_view_t* edge_type_ids, bool_t store_transposed, bool_t renumber, + bool_t symmetrize, bool_t do_expensive_check, cugraph_graph_t** graph, cugraph_error_t** error); diff --git a/cpp/src/c_api/graph_mg.cpp b/cpp/src/c_api/graph_mg.cpp index d2f121e5ec1..18406a1a2cc 100644 --- a/cpp/src/c_api/graph_mg.cpp +++ b/cpp/src/c_api/graph_mg.cpp @@ -230,7 +230,7 @@ struct create_graph_functor : public cugraph::c_api::abstract_functor { if (symmetrize_) { if (edgelist_edge_ids || edgelist_edge_types) { - // Currently doesn't support the symmetrization with edge_ids and edge_types + // Currently doesn't support the symmetrization of edgelist with edge_ids and edge_types unsupported(); } diff --git a/cpp/src/c_api/graph_sg.cpp b/cpp/src/c_api/graph_sg.cpp index c3181695093..2a6070c9e86 100644 --- a/cpp/src/c_api/graph_sg.cpp +++ b/cpp/src/c_api/graph_sg.cpp @@ -167,23 +167,6 @@ struct create_graph_functor : public cugraph::c_api::abstract_functor { edge_type_ids_->size_, handle_.get_stream()); } - - if (symmetrize_) { - if (edgelist_edge_ids || edgelist_edge_types) { - // Currently doesn't support the symmetrization with edge_ids and edge_types - unsupported(); - } - - // Symmetrize the edgelist - std::tie( - edgelist_srcs, edgelist_dsts, edgelist_weights) = - cugraph::symmetrize_edgelist(handle_, - std::move(edgelist_srcs), - std::move(edgelist_dsts), - std::move(edgelist_weights), - false); - } - auto graph = new cugraph::graph_t(handle_); @@ -227,7 +210,6 @@ struct create_graph_functor : public cugraph::c_api::abstract_functor { : false); } - if (symmetrize_) { if (edgelist_edge_ids || edgelist_edge_types) { // Currently doesn't support the symmetrization with edge_ids and edge_types @@ -305,6 +287,7 @@ struct create_graph_csr_functor : public cugraph::c_api::abstract_functor { cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_ids_; cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_type_ids_; bool_t renumber_; + bool_t symmetrize_; bool_t do_expensive_check_; cugraph::c_api::cugraph_graph_t* result_{}; @@ -317,6 +300,7 @@ struct create_graph_csr_functor : public cugraph::c_api::abstract_functor { cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_ids, cugraph::c_api::cugraph_type_erased_device_array_view_t const* edge_type_ids, bool_t renumber, + bool_t symmetrize, bool_t do_expensive_check) : abstract_functor(), properties_(properties), @@ -327,6 +311,7 @@ struct create_graph_csr_functor : public cugraph::c_api::abstract_functor { edge_ids_(edge_ids), edge_type_ids_(edge_type_ids), renumber_(renumber), + symmetrize_(symmetrize), do_expensive_check_(do_expensive_check) { } @@ -434,6 +419,22 @@ struct create_graph_csr_functor : public cugraph::c_api::abstract_functor { auto edge_types = new cugraph::edge_property_t< cugraph::graph_view_t, edge_type_id_t>(handle_); + + if (symmetrize_) { + if (edgelist_edge_ids || edgelist_edge_types) { + // Currently doesn't support the symmetrization with edge_ids and edge_types + unsupported(); + } + + // Symmetrize the edgelist + std::tie( + edgelist_srcs, edgelist_dsts, edgelist_weights) = + cugraph::symmetrize_edgelist(handle_, + std::move(edgelist_srcs), + std::move(edgelist_dsts), + std::move(edgelist_weights), + false); + } std::tie(*graph, new_edge_weights, new_edge_ids, new_edge_types, new_number_map) = cugraph::create_graph_from_edgelist -//#include - -#include -//#include -//#include -#include -#include - -namespace { - -struct create_allgather_functor : public cugraph::c_api::abstract_functor { - raft::handle_t const& handle_; - cugraph::c_api::cugraph_type_erased_device_array_view_t const* src_; - cugraph::c_api::cugraph_type_erased_device_array_view_t const* dst_; - cugraph::c_api::cugraph_type_erased_device_array_view_t const* weights_; - bool_t reciprocal_; - cugraph::c_api::cugraph_induced_subgraph_result_t* result_{}; - - create_allgather_functor( - raft::handle_t const& handle, - cugraph::c_api::cugraph_type_erased_device_array_view_t const* src, - cugraph::c_api::cugraph_type_erased_device_array_view_t const* dst, - cugraph::c_api::cugraph_type_erased_device_array_view_t const* weights, - bool_t reciprocal) - : abstract_functor(), - handle_(handle), - src_(src), - dst_(dst), - weights_(weights), - reciprocal_(reciprocal) - { - } - - template - void operator()() - { - - rmm::device_uvector edgelist_srcs(src_->size_, handle_.get_stream()); - rmm::device_uvector edgelist_dsts(dst_->size_, handle_.get_stream()); - - raft::copy( - edgelist_srcs.data(), src_->as_type(), src_->size_, handle_.get_stream()); - raft::copy( - edgelist_dsts.data(), dst_->as_type(), dst_->size_, handle_.get_stream()); - - std::optional> edgelist_weights = - weights_ - ? std::make_optional(rmm::device_uvector(weights_->size_, handle_.get_stream())) - : std::nullopt; - - if (edgelist_weights) { - raft::copy(edgelist_weights->data(), - weights_->as_type(), - weights_->size_, - handle_.get_stream()); - } - - cugraph::detail::symmetrize_edgelist( - edgelist_srcs, - edgelist_dsts, - edgelist_weights, - reciprocal - ); - - - - - - - - - } -}; - -} // namespace - - -extern "C" cugraph_error_code_t symmetrize_edgelist( - const cugraph_resource_handle_t* handle, - const cugraph_type_erased_device_array_view_t* src, - const cugraph_type_erased_device_array_view_t* dst, - const cugraph_type_erased_device_array_view_t* weights, - bool_t reciprocal, - cugraph_induced_subgraph_result_t** edgelist, - cugraph_error_t** error) -{ - *edgelist = nullptr; - *error = nullptr; - - auto p_handle = reinterpret_cast(handle); - auto p_src = - reinterpret_cast(src); - auto p_dst = - reinterpret_cast(dst); - auto p_weights = - reinterpret_cast(weights); - - CAPI_EXPECTS((dst == nullptr) || (src == nullptr) || p_src->size_ == p_dst->size_, - CUGRAPH_INVALID_INPUT, - "Invalid input arguments: src size != dst size.", - *error); - CAPI_EXPECTS((dst == nullptr) || (src == nullptr) || p_src->type_ == p_dst->type_, - CUGRAPH_INVALID_INPUT, - "Invalid input arguments: src type != dst type.", - *error); - - CAPI_EXPECTS((weights == nullptr) || (src == nullptr) || (p_weights->size_ == p_src->size_), - CUGRAPH_INVALID_INPUT, - "Invalid input arguments: src size != weights size.", - *error); - - cugraph_data_type_id_t vertex_type; - cugraph_data_type_id_t weight_type; - - cugraph_data_type_id_t edge_type = cugraph_data_type_id_t::INT32; - cugraph_data_type_id_t edge_type_id_type = cugraph_data_type_id_t::INT32; - - if (src != nullptr) { - vertex_type = p_src->type_; - } else { - vertex_type = cugraph_data_type_id_t::INT32; - } - - if (weights != nullptr) { - weight_type = p_weights->type_; - } else { - weight_type = cugraph_data_type_id_t::FLOAT32; - } - - constexpr bool multi_gpu = false; - constexpr bool store_transposed = false; - - ::symmetrize_edgelist_functor functor( - *p_handle->handle_, p_src, p_dst, p_weights); - - - try { - cugraph::c_api::vertex_dispatcher( - vertex_type, edge_type, weight_type, edge_type_id_type, store_transposed, multi_gpu, functor); - - if (functor.error_code_ != CUGRAPH_SUCCESS) { - *error = reinterpret_cast(functor.error_.release()); - return functor.error_code_; - } - - *edgelist = reinterpret_cast(functor.result_); - } catch (std::exception const& ex) { - *error = reinterpret_cast(new cugraph::c_api::cugraph_error_t{ex.what()}); - return CUGRAPH_UNKNOWN_ERROR; - } - - - -} \ No newline at end of file diff --git a/python/cugraph/cugraph/structure/graph_classes.py b/python/cugraph/cugraph/structure/graph_classes.py index 82a4be5976c..046888a6619 100644 --- a/python/cugraph/cugraph/structure/graph_classes.py +++ b/python/cugraph/cugraph/structure/graph_classes.py @@ -116,6 +116,7 @@ def from_cudf_edgelist( renumber=True, store_transposed=False, legacy_renum_only=False, + symmetrize=None ): """ Initialize a graph from the edge list. It is an error to call this @@ -174,9 +175,11 @@ def from_cudf_edgelist( This parameter is deprecated and will be removed. - symmetrize: bool, optional (default=True) + symmetrize: bool, optional (default=None) If True, symmetrize the edge list for an undirected graph. Setting - this flag to True for a directed graph returns an error. + this flag to True for a directed graph returns an error. The default + behavior symmetrizes the edges if the graph is undirected. If the edges + are already symmetric, set this flag to False. Examples -------- @@ -205,6 +208,7 @@ def from_cudf_edgelist( renumber=renumber, store_transposed=store_transposed, legacy_renum_only=legacy_renum_only, + symmetrize=symmetrize ) def from_cudf_adjlist( @@ -214,6 +218,7 @@ def from_cudf_adjlist( value_col=None, renumber=True, store_transposed=False, + symmetrize=None ): """ Initialize a graph from the adjacency list. It is an error to call this @@ -251,6 +256,11 @@ def from_cudf_adjlist( store_transposed : bool, optional (default=False) If True, stores the transpose of the adjacency matrix. Required for certain algorithms. + symmetrize: bool, optional (default=None) + If True, symmetrize the edge list for an undirected graph. Setting + this flag to True for a directed graph returns an error. The default + behavior symmetrizes the edges if the graph is undirected. If the edges + are already symmetric, set this flag to False. Examples -------- @@ -272,7 +282,11 @@ def from_cudf_adjlist( raise RuntimeError("Graph is already initialized") elif self._Impl.edgelist is not None or self._Impl.adjlist is not None: raise RuntimeError("Graph already has values") - self._Impl._simpleGraphImpl__from_adjlist(offset_col, index_col, value_col) + self._Impl._simpleGraphImpl__from_adjlist( + offset_col=offset_col, + index_col=index_col, + value_col=value_col, + symmetrize=symmetrize) def from_dask_cudf_edgelist( self, diff --git a/python/cugraph/cugraph/structure/graph_implementation/simpleDistributedGraph.py b/python/cugraph/cugraph/structure/graph_implementation/simpleDistributedGraph.py index 5fa02e738ce..e95a91527ee 100644 --- a/python/cugraph/cugraph/structure/graph_implementation/simpleDistributedGraph.py +++ b/python/cugraph/cugraph/structure/graph_implementation/simpleDistributedGraph.py @@ -174,6 +174,7 @@ def __from_edgelist( renumber=True, store_transposed=False, legacy_renum_only=False, + symmetrize=None ): if not isinstance(input_ddf, dask_cudf.DataFrame): raise TypeError("input should be a dask_cudf dataFrame") @@ -190,6 +191,22 @@ def __from_edgelist( raise ValueError( "The edgelist can only be symmetrized for undirected graphs." ) + + if (symmetrize or symmetrize == None): + unsupported = False + if edge_id is not None or edge_type is not None: + unsupported = True + if isinstance(edge_attr, list): + if len(edge_attr) > 1: + unsupported = True + if unsupported: + raise ValueError( + "Edge list containing Edge Ids or Types can't be symmetrized. " + "If the edges are already symmetric, set the 'symmetrize' " + "flag to False") + if symmetrize == None: + # default behavior + symmetrize = not self.properties.directed s_col = source d_col = destination @@ -273,27 +290,11 @@ def __from_edgelist( ddf_columns += value_col_names input_ddf = input_ddf[ddf_columns] - if len(value_col_names) == 0: - source_col, dest_col = symmetrize( - input_ddf, - source, - destination, - multi=True, # Deprecated parameter - symmetrize=not self.properties.directed, - ) - value_col = None - else: - source_col, dest_col, value_col = symmetrize( - input_ddf, - source, - destination, - value_col_names, - multi=True, # Deprecated parameter - symmetrize=not self.properties.directed, - ) - # Create a dask_cudf dataframe from the cudf series # or dataframe objects obtained from symmetrization + source_col = input_ddf[source] + dest_col = input_ddf[destination] + value_col = input_ddf[value_col_names] if isinstance(source_col, dask_cudf.Series): frames = [ source_col.to_frame(name=source), diff --git a/python/cugraph/cugraph/structure/graph_implementation/simpleGraph.py b/python/cugraph/cugraph/structure/graph_implementation/simpleGraph.py index 87be03bebc5..43fd1640890 100644 --- a/python/cugraph/cugraph/structure/graph_implementation/simpleGraph.py +++ b/python/cugraph/cugraph/structure/graph_implementation/simpleGraph.py @@ -13,7 +13,7 @@ #from cugraph.structure import graph_primtypes_wrapper ********* from cugraph.structure.replicate_edgelist import replicate_cudf_dataframe -from cugraph.structure.symmetrize import symmetrize as symmetrize_ +from cugraph.structure.symmetrize import symmetrize as symmetrize from cugraph.structure.number_map import NumberMap import cugraph.dask.common.mg_utils as mg_utils import cudf @@ -134,7 +134,7 @@ def __from_edgelist( renumber=True, legacy_renum_only=False, store_transposed=False, - symmetrize=False + symmetrize=None ): if legacy_renum_only: warning_msg = ( @@ -148,7 +148,23 @@ def __from_edgelist( raise ValueError( "The edgelist can only be symmetrized for undirected graphs." ) - + + if (symmetrize or symmetrize == None): + unsupported = False + if edge_id is not None or edge_type is not None: + unsupported = True + if isinstance(edge_attr, list): + if len(edge_attr) > 1: + unsupported = True + if unsupported: + raise ValueError( + "Edge list containing Edge Ids or Types can't be symmetrized. " + "If the edges are already symmetric, set the 'symmetrize' " + "flag to False") + if symmetrize == None: + # default behavior + symmetrize = not self.properties.directed + # Verify column names present in input DataFrame s_col = source d_col = destination @@ -209,6 +225,7 @@ def __from_edgelist( edge_attr.append(edge_id) if edge_type is not None: edge_attr.append(edge_type) + df_columns += edge_attr input_df = input_df[df_columns] @@ -270,55 +287,12 @@ def __from_edgelist( ) raise ValueError("set renumber to True for non integer columns ids") - # The dataframe will be symmetrized iff the graph is undirected - # otherwise the inital dataframe will be returned. Duplicated edges - # will be dropped unless the graph is a MultiGraph(Not Implemented yet) - # TODO: Update Symmetrize to work on Graph and/or DataFrame - """ - if edge_attr is not None: - source_col, dest_col, value_col = symmetrize_( - elist, - source, - destination, - edge_attr, - multi=self.properties.multi_edge, # Deprecated parameter - symmetrize=not self.properties.directed, - ) - - if isinstance(value_col, cudf.DataFrame): - value_dict = {} - for i in value_col.columns: - value_dict[i] = value_col[i] - value_col = value_dict - else: - value_col = None - source_col, dest_col = symmetrize_( - elist, - source, - destination, - multi=self.properties.multi_edge, # Deprecated parameter - symmetrize=not self.properties.directed, - ) - - if isinstance(value_col, dict): - value_col = { - self.edgeWeightCol: value_col[weight] if weight in value_col else None, - self.edgeIdCol: value_col[edge_id] if edge_id in value_col else None, - self.edgeTypeCol: value_col[edge_type] - if edge_type in value_col - else None, - } - - self.edgelist = simpleGraphImpl.EdgeList(source_col, dest_col, value_col) - - print("original edgelist = ", len(elist[source]), " symmetrize edgelist = ", len(source_col)) - print("value_col = \n", value_col) - """ - - #self.edgelist = simpleGraphImpl.EdgeList(elist[source], elist[destination], elist[weight]) - print("\nelist = \n", elist.head()) - - #""" + # The dataframe will be symmetrized iff the graph is undirected with the + # symmetrize flag set to None or True otherwise, the inital dataframe will + # be returned. If set to False, the API will assume that the edges are already + # symmetric. Duplicated edges will be dropped unless the graph is a + # MultiGraph(Not Implemented yet) + if edge_attr is not None: value_col = { self.edgeWeightCol: elist[weight] if weight in edge_attr else None, @@ -327,27 +301,13 @@ def __from_edgelist( if edge_type in edge_attr else None, } - print("value_col = \n", value_col) else: value_col = None - # unsymmetrize edgelist - # FIXME: if the user calls self.edgelist after creating the graph, returns the symmetrized - # edgelist if the graph is undirected or symmetrize = True (decompress) + # FIXME: if the user calls self.edgelist.edgelist_df after creating a symmetric graph, + # return the symmetric edgelist? self.edgelist = simpleGraphImpl.EdgeList(elist[source], elist[destination], value_col) - #print("value_col_df = \n", elist[weight]) - #""" - - - - - - - - - - if self.batch_enabled: self._replicate_edgelist() @@ -356,7 +316,7 @@ def __from_edgelist( store_transposed=store_transposed, renumber=renumber, drop_multi_edges=not self.properties.multi_edge, - symmetrize=not self.properties.directed + symmetrize=symmetrize ) def to_pandas_edgelist( @@ -594,16 +554,23 @@ def __from_adjlist( value_col=None, renumber=True, store_transposed=False, + symmetrize=None ): self.adjlist = simpleGraphImpl.AdjList(offset_col, index_col, value_col) + + if (self.properties.directed and symmetrize): + raise ValueError( + "The edges can only be symmetrized for undirected graphs." + ) + if value_col is not None: self.properties.weighted = True self._make_plc_graph( value_col=value_col, store_transposed=store_transposed, renumber=renumber, - symmetrize=not self.properties.directed + symmetrize=not self.properties.directed if symmetrize is None else symmetrize ) if self.batch_enabled: @@ -1265,12 +1232,7 @@ def _make_plc_graph( "This may cause extra memory usage. Consider passing" " a int64 list of edge ids instead." ) - df = cudf.DataFrame() - df["srcs"] = src_or_offset_array - df["dsts"] = dst_or_index_array - df["wgts"] = weight_col - print("df = \n", df) self._plc_graph = SGGraph( resource_handle=ResourceHandle(), graph_properties=graph_props, @@ -1310,12 +1272,16 @@ def to_directed(self, DiG, store_transposed=False): DiG._make_plc_graph(value_col, store_transposed) def to_undirected(self, G, store_transposed=False): + """ Return an undirected copy of the graph. Note: This will discard any edge ids or edge types but will preserve edge weights if present. """ + # FIXME: Update this function to not call the deprecated + # symmetrize function. + # 1) Import the C++ function that symmetrize a graph G.properties.renumbered = self.properties.renumbered G.renumber_map = self.renumber_map if self.properties.directed is False: diff --git a/python/pylibcugraph/pylibcugraph/_cugraph_c/graph.pxd b/python/pylibcugraph/pylibcugraph/_cugraph_c/graph.pxd index 4247bcc1b2a..497607860bd 100644 --- a/python/pylibcugraph/pylibcugraph/_cugraph_c/graph.pxd +++ b/python/pylibcugraph/pylibcugraph/_cugraph_c/graph.pxd @@ -67,6 +67,7 @@ cdef extern from "cugraph_c/graph.h": bool_t renumber, bool_t drop_self_loops, bool_t drop_multi_edges, + bool_t symmetrize, bool_t check, cugraph_graph_t** graph, cugraph_error_t** error) @@ -117,6 +118,7 @@ cdef extern from "cugraph_c/graph.h": const cugraph_type_erased_device_array_view_t* edge_type_ids, bool_t store_transposed, bool_t renumber, + bool_t symmetrize, bool_t check, cugraph_graph_t** graph, cugraph_error_t** error @@ -173,6 +175,7 @@ cdef extern from "cugraph_c/graph.h": size_t num_arrays, bool_t drop_self_loops, bool_t drop_multi_edges, + bool_t symmetrize, bool_t do_expensive_check, cugraph_graph_t** graph, cugraph_error_t** error) diff --git a/python/pylibcugraph/pylibcugraph/_cugraph_c/graph_functions.pxd b/python/pylibcugraph/pylibcugraph/_cugraph_c/graph_functions.pxd index 315c9bd7503..4daf2130e93 100644 --- a/python/pylibcugraph/pylibcugraph/_cugraph_c/graph_functions.pxd +++ b/python/pylibcugraph/pylibcugraph/_cugraph_c/graph_functions.pxd @@ -248,3 +248,16 @@ cdef extern from "cugraph_c/graph_functions.h": cugraph_degrees_result_free( cugraph_degrees_result_t* degrees_result ) + + ########################################################################### + # symmetrize + cdef cugraph_error_code_t \ + symmetrize_edgelist( + const cugraph_resource_handle_t* handle, + const cugraph_type_erased_device_array_view_t* src, + const cugraph_type_erased_device_array_view_t* dst, + const cugraph_type_erased_device_array_view_t* weights, + bool_t reciprocal, + cugraph_induced_subgraph_result_t** result, + cugraph_error_t** error + ) diff --git a/python/pylibcugraph/pylibcugraph/graphs.pyx b/python/pylibcugraph/pylibcugraph/graphs.pyx index def47390ce5..b65852d8d8e 100644 --- a/python/pylibcugraph/pylibcugraph/graphs.pyx +++ b/python/pylibcugraph/pylibcugraph/graphs.pyx @@ -122,10 +122,18 @@ cdef class SGGraph(_GPUGraph): drop_self_loops : bool, optional (default='False') If true, drop any self loops that exist in the provided edge list. + + Not supported for CSR graph. drop_multi_edges: bool, optional (default='False') If true, drop any multi edges that exist in the provided edge list + Not supported for CSR graph. + + symmetrize: bool, optional (default='False') + If true, symmetrize the edge list + + Examples --------- >>> import pylibcugraph, cupy, numpy @@ -155,7 +163,8 @@ cdef class SGGraph(_GPUGraph): input_array_format="COO", vertices_array=None, drop_self_loops=False, - drop_multi_edges=False): + drop_multi_edges=False, + symmetrize=False): # FIXME: add tests for these if not(isinstance(store_transposed, (int, bool))): @@ -217,6 +226,7 @@ cdef class SGGraph(_GPUGraph): renumber, drop_self_loops, drop_multi_edges, + symmetrize, do_expensive_check, &(self.c_graph_ptr), &error_ptr) @@ -233,6 +243,7 @@ cdef class SGGraph(_GPUGraph): self.edge_id_view_ptr, edge_type_view_ptr, store_transposed, + symmetrize, renumber, # drop_self_loops, #FIXME: Not supported yet # drop_multi_edges, #FIXME: Not supported yet @@ -325,6 +336,10 @@ cdef class MGGraph(_GPUGraph): drop_multi_edges: bool, optional (default='False') If true, drop any multi edges that exist in the provided edge list + + symmetrize: bool, optional (default='False') + If true, symmetrize the edge list + """ def __cinit__(self, ResourceHandle resource_handle, @@ -339,7 +354,8 @@ cdef class MGGraph(_GPUGraph): vertices_array=None, size_t num_arrays=1, # default value to not break users drop_self_loops=False, - drop_multi_edges=False): + drop_multi_edges=False, + symmetrize=False,): if not(isinstance(store_transposed, (int, bool))): raise TypeError("expected int or bool for store_transposed, got " @@ -465,6 +481,7 @@ cdef class MGGraph(_GPUGraph): num_arrays, drop_self_loops, drop_multi_edges, + symmetrize, do_expensive_check, &(self.c_graph_ptr), &error_ptr)