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

Nx compatibility based on making Graph subclass and calling Cugraph algos #2099

Merged
merged 61 commits into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
c02bfde
Created initial list of simple Graph creation tests for nx compatibility
acostadon Jan 25, 2022
35c2878
Merge remote-tracking branch 'upstream/branch-22.04' into nxCompat
acostadon Feb 4, 2022
58beab4
cleaned up flake8, copywrite and removed important warning
acostadon Feb 4, 2022
33f83b8
Added call to bfs in test case
acostadon Feb 6, 2022
9d39bb7
adding initial nx code to development branch
acostadon Feb 7, 2022
2012edd
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Feb 7, 2022
f52c560
Adding more Graph code
acostadon Feb 11, 2022
57d214d
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Feb 11, 2022
0ea4ee9
Added some adjacency code to Graph and started testing it
acostadon Feb 11, 2022
fa15f29
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Feb 14, 2022
6092bc1
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Feb 15, 2022
b306981
adding more nx methods to graph
acostadon Feb 15, 2022
56f0ff8
Adding tests as Graph gets implemented
acostadon Feb 15, 2022
aef4d9a
Added changes for new Property Graph parameter names
acostadon Feb 15, 2022
8257f8c
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Feb 15, 2022
f20e536
making weights work in Graph testing with algorithms
acostadon Feb 15, 2022
f61d615
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Feb 17, 2022
29c892d
Added weighted load and ran bfs
acostadon Feb 17, 2022
6511f84
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Feb 18, 2022
3ddeb91
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Feb 22, 2022
0ed3f7b
Added subscripting code and NotImplementedError
acostadon Feb 22, 2022
6d7dc2f
inheriting everything from networkx graph and calling cugraph bfs
acostadon Mar 1, 2022
45ef5d1
more files to call cugraph bfs from networkx graph
acostadon Mar 1, 2022
6825ec0
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 1, 2022
f2eea9f
Corrected a cut paste error and added comment in bfg caller
acostadon Mar 1, 2022
719c9ef
removed files from other branch that were accidentally added to this …
acostadon Mar 1, 2022
60e9a11
Cleaned up flake8 style issues. Still looking into unused library mes…
acostadon Mar 1, 2022
48291ae
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 7, 2022
a70a140
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 11, 2022
51a1c0c
Adding pagerank with simple test
acostadon Mar 16, 2022
9ee2a5a
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 16, 2022
4618923
cleaning up style
acostadon Mar 17, 2022
5d555f1
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 17, 2022
1468d80
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 21, 2022
8ec418a
added arguments for pagerank testing
acostadon Mar 21, 2022
6702dc2
fixed cut paste error
acostadon Mar 21, 2022
484caf6
corrected DataFrame call
acostadon Mar 21, 2022
b938353
fixed dataframe conversion
acostadon Mar 21, 2022
a5584ef
fixing with style checker
acostadon Mar 21, 2022
87e2f0c
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 22, 2022
c2e47ea
personalization is working and tests are run against networkx and compat
acostadon Mar 22, 2022
8e8e71f
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 23, 2022
2768396
added parameter tests and conversion for nstart
acostadon Mar 23, 2022
de15f94
added check for a dictionary to the cudify function
acostadon Mar 23, 2022
4253ee4
moved compat to experimental
acostadon Mar 23, 2022
e0e69c8
added comment to explain print
acostadon Mar 24, 2022
233cd43
added test for nstart
acostadon Mar 24, 2022
2c5d49d
removing an old test that accidentally got in this branch but broke w…
acostadon Mar 24, 2022
d3dfe25
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 26, 2022
de43915
added data passing fixture used in one test.
acostadon Mar 26, 2022
c47785e
added fixture and tests for parameters in pagerank
acostadon Mar 27, 2022
e6772f4
removed developmental files that were accidentally included in branch
acostadon Mar 28, 2022
9718ea1
Merge remote-tracking branch 'upstream/branch-22.04' into branch-22.0…
acostadon Mar 29, 2022
dd5694e
removed duplicate comment
acostadon Mar 29, 2022
57b1fb7
Changed Tolerance in pagerank to match existing test_pagerank case si…
acostadon Mar 29, 2022
742b095
fixed a style check problem
acostadon Mar 29, 2022
b5113e6
responded to review comments but cleaning up dictionary to cudf code …
acostadon Mar 29, 2022
4cef0d4
removed some prints and responed to other review comments
acostadon Mar 29, 2022
d8d97fe
Removed more prints
acostadon Mar 29, 2022
6e759f9
fixed a redundant cast to list in a test
acostadon Mar 29, 2022
0afb1f1
fixed typos and replaced a type check with an instanceof call per rev…
acostadon Mar 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
23 changes: 23 additions & 0 deletions python/cugraph/cugraph/experimental/compat/nx/DiGraph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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.

import networkx as nx


class DiGraph(nx.DiGraph):
"""
Class which extends NetworkX DiGraph class. It provides original
NetworkX functionality and will be overridden as this compatibility
layer moves functionality to gpus in future releases.
"""
pass
23 changes: 23 additions & 0 deletions python/cugraph/cugraph/experimental/compat/nx/Graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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.

import networkx as nx


class Graph(nx.Graph):
"""
Class which extends NetworkX Graph class. It provides original
NetworkX functionality and will be overridden as this compatibility
layer moves functionality to gpus in future releases.
"""
pass
97 changes: 97 additions & 0 deletions python/cugraph/cugraph/experimental/compat/nx/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# 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.

import importlib
from types import ModuleType
import sys

# FIXME: only perform the NetworkX imports below if NetworkX is installed. If
# it's determined that NetworkX is required to use nx compat, then the contents
# of this entire namespace may have to be optional, or packaged separately with
# a hard dependency on NetworkX.

# Start by populating this namespace with the same contents as
# networkx/__init__.py
from networkx import *

# Override the individual NetworkX objects loaded above with the cugraph.nx
# compat equivalents. This means if an equivalent compat obj is not available,
# the standard NetworkX obj will be used.
#
# Each cugraph obj should have the same module path as the
# NetworkX obj it isoverriding, and the submodules along the hierarchy should
# each import the same sub objects/modules as NetworkX does. For example,
# in NetworkX, "pagerank" is a function in
# "networkx/algorithms/link_analysis/pagerank_alg.py", and is
# directly imported in the namespaces "networkx.algorithms.link_analysis",
# "networkx.algorithms", and "networkx". Therefore, the cugraph
# compat pagerank should be defined in a module of the same name and
# also be present in the same namespaces.
# Refer to the networkx __init__.py files when adding new overriding
# modules to ensure the same paths and used and namespaces are populated.
from cugraph.experimental.compat.nx import algorithms
from cugraph.experimental.compat.nx.algorithms import *

from cugraph.experimental.compat.nx.algorithms import link_analysis
from cugraph.experimental.compat.nx.algorithms.link_analysis import *

# Recursively import all of the NetworkX modules into equivalent submodules
# under this package. The above "from networkx import *" handles names in this
# namespace, but it will not create the equivalent networkx submodule
# hierarchy. For example, a user could expect to "import cugraph.nx.drawing",
# which should simply redirect to "networkx.drawing".
#
# This can be accomplished by updating sys.modules with the import path and
# module object of each NetworkX submodule in the NetworkX package hierarchy,
# but only for module paths that have not been added yet (otherwise this would
# overwrite the overides above).
_visited = set()


def _import_submodules_recursively(obj, mod_path):
# Since modules can freely import any other modules, immediately mark this
# obj as visited so submodules that import it are not re-examined
# infinitely.
_visited.add(obj)
for name in dir(obj):
sub_obj = getattr(obj, name)

if type(sub_obj) is ModuleType:
sub_mod_path = f"{mod_path}.{name}"
# Do not overwrite modules that are already present, such as those
# intended to override which were imported separately above.
if sub_mod_path not in sys.modules:
sys.modules[sub_mod_path] = sub_obj
if sub_obj not in _visited:
_import_submodules_recursively(sub_obj, sub_mod_path)


_import_submodules_recursively(


importlib.import_module("networkx"), __name__)

del _visited
del _import_submodules_recursively

# At this point, individual types that cugraph.nx are overriding
# could be used to override the corresponding types *inside* the
# networkx modules imported above. For example, the networkx graph generators
# will still return networkx.Graph objects instead of cugraph.nx.Graph
# objects (unless the user knows to pass a "create_using" arg, if available).
# For specific overrides, assignments could be made in the imported
acostadon marked this conversation as resolved.
Show resolved Hide resolved
# a networkx modules so cugraph.nx types are used by default.
# NOTE: this has the side-effect of causing all networkx
# imports in this python process/interpreter to use the override (ie. the user
# won't be able to use the original networkx types,
# even from a networkx import)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 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.
from networkx.algorithms import *
from cugraph.experimental.compat.nx.algorithms.link_analysis import *
from cugraph.experimental.compat.nx.algorithms import link_analysis
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 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.
from networkx.algorithms.link_analysis import *
from cugraph.experimental.compat.nx.algorithms.link_analysis.pagerank_alg import *
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# 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.

import cugraph
import cugraph.utilities
import cudf
import numpy as np


def create_cudf_from_dict(dict_in):
"""
converts python dictionary to a cudf.Dataframe as needed by this
cugraph pagerank call.

Parameters
----------
dictionary with node ids(key) and values

Returns
-------
a cudf DataFrame of (vertex)ids and values.
"""
if not(isinstance(dict_in, dict)):
raise TypeError("type_name must be a dict, got: "
f"{type(dict_in)}")
# FIXME: Looking to replacing fromiter with rename and
# compare performance
k = np.fromiter(dict_in.keys(), dtype="int32")
v = np.fromiter(dict_in.values(), dtype="float32")
df = cudf.DataFrame({"vertex": k, "values": v})
return df


def pagerank(
G,
alpha=0.85,
personalization=None,
max_iter=100,
tol=1.0e-6,
nstart=None,
weight="weight",
dangling=None):

"""
Calls the cugraph pagerank algorithm taking in a networkX object.
In future releases it will maintain compatibility but will migrate more
of the workflow to the GPU.

Parameters
----------
G : networkx.Graph

alpha : float, optional (default=0.85)
The damping factor alpha represents the probability to follow an
outgoing edge, standard value is 0.85.
Thus, 1.0-alpha is the probability to “teleport” to a random vertex.
Alpha should be greater than 0.0 and strictly lower than 1.0.

personalization : dictionary, optional (default=None)
dictionary comes from networkx is converted to a dataframe
containing the personalization information.

max_iter : int, optional (default=100)
The maximum number of iterations before an answer is returned. This can
be used to limit the execution time and do an early exit before the
solver reaches the convergence tolerance.
If this value is lower or equal to 0 cuGraph will use the default
value, which is 100.

tol : float, optional (default=1e-05)
Set the tolerance the approximation, this parameter should be a small
magnitude value.
The lower the tolerance the better the approximation. If this value is
0.0f, cuGraph will use the default value which is 1.0E-5.
Setting too small a tolerance can lead to non-convergence due to
numerical roundoff. Usually values between 0.01 and 0.00001 are
acceptable.

nstart : dictionary, optional (default=None)
dictionary containing the initial guess vertex and value for pagerank.
Will be converted to a Dataframe before calling the cugraph algorithm
nstart['vertex'] : cudf.Series
Subset of vertices of graph for initial guess for pagerank values
nstart['values'] : cudf.Series
Pagerank values for vertices

weight: str, optional (default=None)
This parameter is here for NetworkX compatibility and not
yet supported in this algorithm

dangling : dict, optional (default=None)
This parameter is here for NetworkX compatibility and ignored

Returns
-------
PageRank : dictionary
A dictionary of nodes with the PageRank as value

"""
local_pers = None
local_nstart = None
if (personalization is not None):
local_pers = create_cudf_from_dict(personalization)
if (nstart is not None):
local_nstart = create_cudf_from_dict(nstart)
return cugraph.pagerank(
G,
alpha,
local_pers,
max_iter,
tol,
local_nstart,
weight,
dangling)
34 changes: 34 additions & 0 deletions python/cugraph/cugraph/tests/test_compat_algo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 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.

import cugraph.experimental.compat.nx as nx


def test_connectivity():
expected = [{1, 2, 3, 4, 5}, {8, 9, 7}]
G = nx.Graph()
G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 5)])
G.add_edges_from([(7, 8), (8, 9), (7, 9)])
assert list(nx.connected_components(G)) == expected


def test_pagerank_result_type():
acostadon marked this conversation as resolved.
Show resolved Hide resolved
G = nx.DiGraph()
[G.add_node(k) for k in ["A", "B", "C", "D", "E", "F", "G"]]
G.add_edges_from([('G', 'A'), ('A', 'G'), ('B', 'A'),
('C', 'A'), ('A', 'C'), ('A', 'D'),
('E', 'A'), ('F', 'A'), ('D', 'B'),
('D', 'F')])
ppr1 = nx.pagerank(G)
# This just tests that the right type is returned.
assert type(ppr1) == dict
acostadon marked this conversation as resolved.
Show resolved Hide resolved
Loading