Skip to content

Commit

Permalink
Removed NetworkX requirement for type checks, fixed docstring, added …
Browse files Browse the repository at this point in the history
…new docstrings, import cleanups (#1853)

* Changed type check code to no longer require NetworkX and instead only check Nx types if installed. #1851
* Cleaned up imports, removed unused imports.
* Changed `import_optional` to use `importlib` instead, and return `MissingModule` instances for easier error reporting.
* Fixed format of example in `rmat` docstring #1807
* Added docstrings for `pylibcugraph` `*_connected_components` APIs. #1782 

Tested changes to optional import and type checking code by uninstalling `NetworkX`, observing the failure shown in #1851, applying change, then testing to observe the same script runs to completion without Nx installed.

closes #1851 
closes #1807 
closes #1782

Authors:
  - Rick Ratzel (https://github.com/rlratzel)

Approvers:
  - Brad Rees (https://github.com/BradReesWork)
  - Joseph Nke (https://github.com/jnke2016)

URL: #1853
  • Loading branch information
rlratzel authored Sep 28, 2021
1 parent 177e9ad commit 1397f6c
Show file tree
Hide file tree
Showing 30 changed files with 391 additions and 251 deletions.
10 changes: 6 additions & 4 deletions python/cugraph/cugraph/centrality/betweenness_centrality.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
import cudf
from cugraph.centrality import betweenness_centrality_wrapper
from cugraph.centrality import edge_betweenness_centrality_wrapper
from cugraph.utilities import df_edge_score_to_dictionary
from cugraph.utilities import df_score_to_dictionary
from cugraph.utilities import (df_edge_score_to_dictionary,
df_score_to_dictionary,
ensure_cugraph_obj_for_nx,
)
import cugraph


Expand Down Expand Up @@ -127,7 +129,7 @@ def betweenness_centrality(
if result_dtype not in [np.float32, np.float64]:
raise TypeError("result type can only be np.float32 or np.float64")

G, isNx = cugraph.utilities.check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

vertices = _initialize_vertices(G, k, seed)

Expand Down Expand Up @@ -249,7 +251,7 @@ def edge_betweenness_centrality(
if result_dtype not in [np.float32, np.float64]:
raise TypeError("result type can only be np.float32 or np.float64")

G, isNx = cugraph.utilities.check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)
vertices = _initialize_vertices(G, k, seed)

df = edge_betweenness_centrality_wrapper.edge_betweenness_centrality(
Expand Down
8 changes: 5 additions & 3 deletions python/cugraph/cugraph/centrality/katz_centrality.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
# limitations under the License.

from cugraph.centrality import katz_centrality_wrapper
import cugraph
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
df_score_to_dictionary,
)


def katz_centrality(
Expand Down Expand Up @@ -112,7 +114,7 @@ def katz_centrality(
"currently not supported"
)

G, isNx = cugraph.utilities.check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

if nstart is not None:
if G.renumbered is True:
Expand All @@ -130,7 +132,7 @@ def katz_centrality(
df = G.unrenumber(df, "vertex")

if isNx is True:
dict = cugraph.utilities.df_score_to_dictionary(df, 'katz_centrality')
dict = df_score_to_dictionary(df, 'katz_centrality')
return dict
else:
return df
7 changes: 4 additions & 3 deletions python/cugraph/cugraph/community/ecg.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
# limitations under the License.

from cugraph.community import ecg_wrapper
from cugraph.utilities import check_nx_graph
from cugraph.utilities import df_score_to_dictionary
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
df_score_to_dictionary,
)


def ecg(input_graph, min_weight=0.05, ensemble_size=16, weight=None):
Expand Down Expand Up @@ -70,7 +71,7 @@ def ecg(input_graph, min_weight=0.05, ensemble_size=16, weight=None):
"""

input_graph, isNx = check_nx_graph(input_graph, weight)
input_graph, isNx = ensure_cugraph_obj_for_nx(input_graph, weight)

parts = ecg_wrapper.ecg(input_graph, min_weight, ensemble_size)

Expand Down
9 changes: 3 additions & 6 deletions python/cugraph/cugraph/community/egonet.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,17 @@
import cudf
from cugraph.utilities import (
ensure_cugraph_obj,
import_optional,
is_nx_graph_type,
)
from cugraph.utilities import cugraph_to_nx

# optional dependencies used for handling different input types
nx = import_optional("networkx")


def _convert_graph_to_output_type(G, input_type):
"""
Given a cugraph.Graph, convert it to a new type appropriate for the
graph algos in this module, based on input_type.
"""
if (nx is not None) and (input_type in [nx.Graph, nx.DiGraph]):
if is_nx_graph_type(input_type):
return cugraph_to_nx(G)

else:
Expand All @@ -40,7 +37,7 @@ def _convert_df_series_to_output_type(df, offsets, input_type):
Given a cudf.DataFrame df, convert it to a new type appropriate for the
graph algos in this module, based on input_type.
"""
if (nx is not None) and (input_type in [nx.Graph, nx.DiGraph]):
if is_nx_graph_type(input_type):
return df.to_pandas(), offsets.values_host.tolist()

else:
Expand Down
7 changes: 4 additions & 3 deletions python/cugraph/cugraph/community/ktruss_subgraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

from cugraph.community import ktruss_subgraph_wrapper
from cugraph.structure.graph_classes import Graph
from cugraph.utilities import check_nx_graph
from cugraph.utilities import cugraph_to_nx
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
cugraph_to_nx,
)

from numba import cuda

Expand Down Expand Up @@ -67,7 +68,7 @@ def k_truss(G, k):

_ensure_compatible_cuda_version()

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

if isNx is True:
k_sub = ktruss_subgraph(G, k)
Expand Down
7 changes: 4 additions & 3 deletions python/cugraph/cugraph/community/leiden.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

from cugraph.community import leiden_wrapper
from cugraph.structure.graph_classes import Graph
from cugraph.utilities import check_nx_graph
from cugraph.utilities import df_score_to_dictionary
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
df_score_to_dictionary,
)


def leiden(G, max_iter=100, resolution=1.):
Expand Down Expand Up @@ -72,7 +73,7 @@ def leiden(G, max_iter=100, resolution=1.):
>>> G.from_cudf_edgelist(M, source='0', destination='1')
>>> parts, modularity_score = cugraph.leiden(G)
"""
G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

if type(G) is not Graph:
raise Exception(f"input graph must be undirected was {type(G)}")
Expand Down
7 changes: 4 additions & 3 deletions python/cugraph/cugraph/community/louvain.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

from cugraph.community import louvain_wrapper
from cugraph.structure.graph_classes import Graph
from cugraph.utilities import check_nx_graph
from cugraph.utilities import df_score_to_dictionary
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
df_score_to_dictionary,
)


def louvain(G, max_iter=100, resolution=1.):
Expand Down Expand Up @@ -73,7 +74,7 @@ def louvain(G, max_iter=100, resolution=1.):
>>> parts, modularity_score = cugraph.louvain(G)
"""

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

if type(G) is not Graph:
raise Exception("input graph must be undirected")
Expand Down
13 changes: 7 additions & 6 deletions python/cugraph/cugraph/community/spectral_clustering.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
# limitations under the License.

from cugraph.community import spectral_clustering_wrapper
from cugraph.utilities import check_nx_graph
from cugraph.utilities import df_score_to_dictionary
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
df_score_to_dictionary,
)


def spectralBalancedCutClustering(
Expand Down Expand Up @@ -75,7 +76,7 @@ def spectralBalancedCutClustering(

# Error checking in C++ code

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

df = spectral_clustering_wrapper.spectralBalancedCutClustering(
G,
Expand Down Expand Up @@ -152,7 +153,7 @@ def spectralModularityMaximizationClustering(

# Error checking in C++ code

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

df = spectral_clustering_wrapper.spectralModularityMaximizationClustering(
G,
Expand Down Expand Up @@ -222,7 +223,7 @@ def analyzeClustering_modularity(G, n_clusters, clustering,
if type(cluster_col_name) is not str:
raise Exception("cluster_col_name must be a string")

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

if G.renumbered:
clustering = G.add_internal_vertex_id(clustering,
Expand Down Expand Up @@ -288,7 +289,7 @@ def analyzeClustering_edge_cut(G, n_clusters, clustering,
if type(cluster_col_name) is not str:
raise Exception("cluster_col_name must be a string")

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

if G.renumbered:
clustering = G.add_internal_vertex_id(clustering,
Expand Down
8 changes: 5 additions & 3 deletions python/cugraph/cugraph/community/subgraph_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
# limitations under the License.

from cugraph.community import subgraph_extraction_wrapper
from cugraph.utilities import check_nx_graph
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
cugraph_to_nx,
)

import cudf
from cugraph.utilities import cugraph_to_nx


def subgraph(G, vertices):
Expand Down Expand Up @@ -53,7 +55,7 @@ def subgraph(G, vertices):
>>> Sg = cugraph.subgraph(G, sverts)
"""

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

if G.renumbered:
if isinstance(vertices, cudf.DataFrame):
Expand Down
4 changes: 2 additions & 2 deletions python/cugraph/cugraph/community/triangle_count.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from cugraph.community import triangle_count_wrapper
from cugraph.structure.graph_classes import Graph
from cugraph.utilities import check_nx_graph
from cugraph.utilities import ensure_cugraph_obj_for_nx


def triangles(G):
Expand Down Expand Up @@ -47,7 +47,7 @@ def triangles(G):
>>> count = cugraph.triangles(G)
"""

G, _ = check_nx_graph(G)
G, _ = ensure_cugraph_obj_for_nx(G)

if type(G) is not Graph:
raise Exception("input graph must be undirected")
Expand Down
27 changes: 4 additions & 23 deletions python/cugraph/cugraph/components/connectivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,12 @@
ensure_cugraph_obj,
is_matrix_type,
is_cp_matrix_type,
import_optional,
is_nx_graph_type,
cupy_package as cp,
)
from cugraph.structure import Graph, DiGraph
from cugraph.components import connectivity_wrapper

# optional dependencies used for handling different input types
nx = import_optional("networkx")

cp = import_optional("cupy")
cp_coo_matrix = import_optional("coo_matrix",
import_from="cupyx.scipy.sparse.coo")
cp_csr_matrix = import_optional("csr_matrix",
import_from="cupyx.scipy.sparse.csr")
cp_csc_matrix = import_optional("csc_matrix",
import_from="cupyx.scipy.sparse.csc")

sp = import_optional("scipy")
sp_coo_matrix = import_optional("coo_matrix",
import_from="scipy.sparse.coo")
sp_csr_matrix = import_optional("csr_matrix",
import_from="scipy.sparse.csr")
sp_csc_matrix = import_optional("csc_matrix",
import_from="scipy.sparse.csc")


def _ensure_args(api_name, G, directed, connection, return_labels):
"""
Expand All @@ -49,8 +31,7 @@ def _ensure_args(api_name, G, directed, connection, return_labels):
"""
G_type = type(G)
# Check for Graph-type inputs and set defaults if unset
if (G_type in [Graph, DiGraph]) or \
((nx is not None) and (G_type in [nx.Graph, nx.DiGraph])):
if (G_type in [Graph, DiGraph]) or is_nx_graph_type(G_type):
exc_value = "'%s' cannot be specified for a Graph-type input"
if directed is not None:
raise TypeError(exc_value % "directed")
Expand Down Expand Up @@ -92,7 +73,7 @@ def _convert_df_to_output_type(df, input_type, return_labels):
if input_type in [Graph, DiGraph]:
return df

elif (nx is not None) and (input_type in [nx.Graph, nx.DiGraph]):
elif is_nx_graph_type(input_type):
return df_score_to_dictionary(df, "labels", "vertex")

elif is_matrix_type(input_type):
Expand Down
7 changes: 4 additions & 3 deletions python/cugraph/cugraph/cores/core_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
# limitations under the License.

from cugraph.cores import core_number_wrapper
from cugraph.utilities import check_nx_graph
from cugraph.utilities import df_score_to_dictionary
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
df_score_to_dictionary,
)


def core_number(G):
Expand Down Expand Up @@ -52,7 +53,7 @@ def core_number(G):
>>> cn = cugraph.core_number(G)
"""

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

df = core_number_wrapper.core_number(G)

Expand Down
7 changes: 4 additions & 3 deletions python/cugraph/cugraph/cores/k_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
# limitations under the License.

from cugraph.cores import k_core_wrapper, core_number_wrapper
from cugraph.utilities import cugraph_to_nx
from cugraph.utilities import check_nx_graph
from cugraph.utilities import (ensure_cugraph_obj_for_nx,
cugraph_to_nx,
)
from cugraph.structure.graph_classes import Graph


Expand Down Expand Up @@ -59,7 +60,7 @@ def k_core(G, k=None, core_number=None):
>>> KCoreGraph = cugraph.k_core(G)
"""

G, isNx = check_nx_graph(G)
G, isNx = ensure_cugraph_obj_for_nx(G)

mytype = type(G)
KCoreGraph = mytype()
Expand Down
30 changes: 15 additions & 15 deletions python/cugraph/cugraph/generators/rmat.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,21 +290,21 @@ def rmat(
Examples
--------
import cugraph
from cugraph.generators import rmat
df = rmat(
scale,
(2**scale)*edgefactor,
0.1,
0.2,
0.3,
seed or 42,
clip_and_flip=False,
scramble_vertex_ids=True,
create_using=None, # return edgelist instead of Graph instance
mg=False
)
>>> import cugraph
>>> from cugraph.generators import rmat
>>>
>>> df = rmat(
... scale,
... (2**scale)*edgefactor,
... 0.1,
... 0.2,
... 0.3,
... seed or 42,
... clip_and_flip=False,
... scramble_vertex_ids=True,
... create_using=None, # return edgelist instead of Graph instance
... mg=False
... )
"""

_ensure_args_rmat(scale, num_edges, a, b, c, seed, clip_and_flip,
Expand Down
Loading

0 comments on commit 1397f6c

Please sign in to comment.