From 8ed2e17d44911f90eea94de05710590472649446 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Tue, 2 Jan 2024 20:25:40 +0100 Subject: [PATCH] Also add `is_incomplete` and `is_different` --- .../algorithms/centrality/betweenness.py | 14 +++++++++-- .../algorithms/centrality/eigenvector.py | 5 +++- .../nx_cugraph/algorithms/centrality/katz.py | 5 +++- .../algorithms/community/louvain.py | 2 ++ .../nx-cugraph/nx_cugraph/algorithms/core.py | 2 +- .../algorithms/link_analysis/pagerank_alg.py | 1 + .../traversal/breadth_first_search.py | 10 ++++---- .../nx-cugraph/nx_cugraph/convert_matrix.py | 3 ++- .../nx_cugraph/scripts/print_table.py | 13 +++++++--- .../nx_cugraph/scripts/print_tree.py | 24 +++++++++++++++++++ .../nx-cugraph/nx_cugraph/utils/decorators.py | 8 +++++++ 11 files changed, 73 insertions(+), 14 deletions(-) diff --git a/python/nx-cugraph/nx_cugraph/algorithms/centrality/betweenness.py b/python/nx-cugraph/nx_cugraph/algorithms/centrality/betweenness.py index 642b2d0ac88..1d05eb36d97 100644 --- a/python/nx-cugraph/nx_cugraph/algorithms/centrality/betweenness.py +++ b/python/nx-cugraph/nx_cugraph/algorithms/centrality/betweenness.py @@ -18,7 +18,12 @@ __all__ = ["betweenness_centrality", "edge_betweenness_centrality"] -@networkx_algorithm(plc="betweenness_centrality", version_added="23.10") +@networkx_algorithm( + is_incomplete=True, # weight not supported + is_different=True, # RNG with seed is different + plc="betweenness_centrality", + version_added="23.10", +) def betweenness_centrality( G, k=None, normalized=True, weight=None, endpoints=False, seed=None ): @@ -46,7 +51,12 @@ def _(G, k=None, normalized=True, weight=None, endpoints=False, seed=None): return weight is None -@networkx_algorithm(plc="edge_betweenness_centrality", version_added="23.10") +@networkx_algorithm( + is_incomplete=True, # weight not supported + is_different=True, # RNG with seed is different + plc="edge_betweenness_centrality", + version_added="23.10", +) def edge_betweenness_centrality(G, k=None, normalized=True, weight=None, seed=None): """`weight` parameter is not yet supported.""" if weight is not None: diff --git a/python/nx-cugraph/nx_cugraph/algorithms/centrality/eigenvector.py b/python/nx-cugraph/nx_cugraph/algorithms/centrality/eigenvector.py index 6d541dcfe14..7c354d4991b 100644 --- a/python/nx-cugraph/nx_cugraph/algorithms/centrality/eigenvector.py +++ b/python/nx-cugraph/nx_cugraph/algorithms/centrality/eigenvector.py @@ -27,7 +27,10 @@ @not_implemented_for("multigraph") @networkx_algorithm( - extra_params=_dtype_param, plc="eigenvector_centrality", version_added="23.12" + is_incomplete=True, # nstart not supported + extra_params=_dtype_param, + plc="eigenvector_centrality", + version_added="23.12", ) def eigenvector_centrality( G, max_iter=100, tol=1.0e-6, nstart=None, weight=None, *, dtype=None diff --git a/python/nx-cugraph/nx_cugraph/algorithms/centrality/katz.py b/python/nx-cugraph/nx_cugraph/algorithms/centrality/katz.py index 3d8a09f421f..f064904eb6d 100644 --- a/python/nx-cugraph/nx_cugraph/algorithms/centrality/katz.py +++ b/python/nx-cugraph/nx_cugraph/algorithms/centrality/katz.py @@ -27,7 +27,10 @@ @not_implemented_for("multigraph") @networkx_algorithm( - extra_params=_dtype_param, plc="katz_centrality", version_added="23.12" + is_incomplete=True, # nstart and normalized=False not supported + extra_params=_dtype_param, + plc="katz_centrality", + version_added="23.12", ) def katz_centrality( G, diff --git a/python/nx-cugraph/nx_cugraph/algorithms/community/louvain.py b/python/nx-cugraph/nx_cugraph/algorithms/community/louvain.py index 7f4f8d52749..0776f829f35 100644 --- a/python/nx-cugraph/nx_cugraph/algorithms/community/louvain.py +++ b/python/nx-cugraph/nx_cugraph/algorithms/community/louvain.py @@ -30,6 +30,8 @@ @not_implemented_for("directed") @networkx_algorithm( + is_incomplete=True, # seed not supported; self-loops not supported + is_different=True, # RNG different extra_params={ "max_level : int, optional": ( "Upper limit of the number of macro-iterations (max: 500)." diff --git a/python/nx-cugraph/nx_cugraph/algorithms/core.py b/python/nx-cugraph/nx_cugraph/algorithms/core.py index cf112bbafdd..ddb43a5fc13 100644 --- a/python/nx-cugraph/nx_cugraph/algorithms/core.py +++ b/python/nx-cugraph/nx_cugraph/algorithms/core.py @@ -27,7 +27,7 @@ @not_implemented_for("directed") @not_implemented_for("multigraph") -@networkx_algorithm(plc="k_truss_subgraph", version_added="23.12") +@networkx_algorithm(is_incomplete=True, plc="k_truss_subgraph", version_added="23.12") def k_truss(G, k): """ Currently raises `NotImplementedError` for graphs with more than one connected diff --git a/python/nx-cugraph/nx_cugraph/algorithms/link_analysis/pagerank_alg.py b/python/nx-cugraph/nx_cugraph/algorithms/link_analysis/pagerank_alg.py index 6cf7b37a685..5bcd4479b33 100644 --- a/python/nx-cugraph/nx_cugraph/algorithms/link_analysis/pagerank_alg.py +++ b/python/nx-cugraph/nx_cugraph/algorithms/link_analysis/pagerank_alg.py @@ -27,6 +27,7 @@ @networkx_algorithm( + is_incomplete=True, # dangling not supported extra_params=_dtype_param, plc={"pagerank", "personalized_pagerank"}, version_added="23.12", diff --git a/python/nx-cugraph/nx_cugraph/algorithms/traversal/breadth_first_search.py b/python/nx-cugraph/nx_cugraph/algorithms/traversal/breadth_first_search.py index 04eb04baa2e..66f9138f6da 100644 --- a/python/nx-cugraph/nx_cugraph/algorithms/traversal/breadth_first_search.py +++ b/python/nx-cugraph/nx_cugraph/algorithms/traversal/breadth_first_search.py @@ -57,7 +57,7 @@ def _bfs(G, source, *, depth_limit=None, reverse=False): return distances[mask], predecessors[mask], node_ids[mask] -@networkx_algorithm(plc="bfs", version_added="24.02") +@networkx_algorithm(is_incomplete=True, plc="bfs", version_added="24.02") def generic_bfs_edges(G, source, neighbors=None, depth_limit=None, sort_neighbors=None): """`neighbors` and `sort_neighbors` parameters are not yet supported.""" return bfs_edges(source, depth_limit=depth_limit) @@ -68,7 +68,7 @@ def _(G, source, neighbors=None, depth_limit=None, sort_neighbors=None): return neighbors is None and sort_neighbors is None -@networkx_algorithm(plc="bfs", version_added="24.02") +@networkx_algorithm(is_incomplete=True, plc="bfs", version_added="24.02") def bfs_edges(G, source, reverse=False, depth_limit=None, sort_neighbors=None): """`sort_neighbors` parameter is not yet supported.""" G = _check_G_and_source(G, source) @@ -95,7 +95,7 @@ def _(G, source, reverse=False, depth_limit=None, sort_neighbors=None): return sort_neighbors is None -@networkx_algorithm(plc="bfs", version_added="24.02") +@networkx_algorithm(is_incomplete=True, plc="bfs", version_added="24.02") def bfs_tree(G, source, reverse=False, depth_limit=None, sort_neighbors=None): """`sort_neighbors` parameter is not yet supported.""" G = _check_G_and_source(G, source) @@ -149,7 +149,7 @@ def _(G, source, reverse=False, depth_limit=None, sort_neighbors=None): return sort_neighbors is None -@networkx_algorithm(plc="bfs", version_added="24.02") +@networkx_algorithm(is_incomplete=True, plc="bfs", version_added="24.02") def bfs_successors(G, source, depth_limit=None, sort_neighbors=None): """`sort_neighbors` parameter is not yet supported.""" G = _check_G_and_source(G, source) @@ -201,7 +201,7 @@ def bfs_layers(G, sources): return (G._nodearray_to_list(groups[key]) for key in range(len(groups))) -@networkx_algorithm(plc="bfs", version_added="24.02") +@networkx_algorithm(is_incomplete=True, plc="bfs", version_added="24.02") def bfs_predecessors(G, source, depth_limit=None, sort_neighbors=None): """`sort_neighbors` parameter is not yet supported.""" G = _check_G_and_source(G, source) diff --git a/python/nx-cugraph/nx_cugraph/convert_matrix.py b/python/nx-cugraph/nx_cugraph/convert_matrix.py index f6e57ffe4f5..ff06d78b070 100644 --- a/python/nx-cugraph/nx_cugraph/convert_matrix.py +++ b/python/nx-cugraph/nx_cugraph/convert_matrix.py @@ -23,7 +23,8 @@ ] -@networkx_algorithm(version_added="23.12") +# Value columns with string dtype is not supported +@networkx_algorithm(is_incomplete=True, version_added="23.12") def from_pandas_edgelist( df, source="source", diff --git a/python/nx-cugraph/nx_cugraph/scripts/print_table.py b/python/nx-cugraph/nx_cugraph/scripts/print_table.py index 79cb0370a9e..c06d8bc8402 100755 --- a/python/nx-cugraph/nx_cugraph/scripts/print_table.py +++ b/python/nx-cugraph/nx_cugraph/scripts/print_table.py @@ -32,7 +32,10 @@ def get_path_to_name(): } -Info = namedtuple("Info", "networkx_path, dispatch_name, version_added, plc") +Info = namedtuple( + "Info", + "networkx_path, dispatch_name, version_added, plc, is_incomplete, is_different", +) def get_path_to_info(path_to_name=None, version_added_sep=".", plc_sep="/"): @@ -44,14 +47,18 @@ def get_path_to_info(path_to_name=None, version_added_sep=".", plc_sep="/"): cufunc = getattr(BackendInterface, funcname) plc = plc_sep.join(sorted(cufunc._plc_names)) if cufunc._plc_names else "" version_added = cufunc.version_added.replace(".", version_added_sep) - rv[funcpath] = Info(funcpath, funcname, version_added, plc) + is_incomplete = cufunc.is_incomplete + is_different = cufunc.is_different + rv[funcpath] = Info( + funcpath, funcname, version_added, plc, is_incomplete, is_different + ) return rv def main(path_to_info=None, *, file=sys.stdout): if path_to_info is None: path_to_info = get_path_to_info(version_added_sep=".") - lines = ["networkx_path,dispatch_name,version_added,plc"] + lines = ["networkx_path,dispatch_name,version_added,plc,is_incomplete,is_different"] lines.extend(",".join(info) for info in path_to_info.values()) text = "\n".join(lines) print(text, file=file) diff --git a/python/nx-cugraph/nx_cugraph/scripts/print_tree.py b/python/nx-cugraph/nx_cugraph/scripts/print_tree.py index 3a1cc1488e2..aa384f4900d 100755 --- a/python/nx-cugraph/nx_cugraph/scripts/print_tree.py +++ b/python/nx-cugraph/nx_cugraph/scripts/print_tree.py @@ -42,6 +42,8 @@ def get_extra( version_added=False, plc=False, dispatch_name_if_different=False, + incomplete=False, + different=False, ): extra = [] if networkx_path: @@ -58,6 +60,10 @@ def get_extra( extra.append(v[:2] + "." + v[-2:]) if plc and info.plc: extra.append(info.plc) + if incomplete and info.is_incomplete: + extra.append("is-incomplete") + if different and info.is_different: + extra.append("is-different") return extra @@ -71,6 +77,8 @@ def create_tree( version_added=False, plc=False, dispatch_name_if_different=False, + incomplete=False, + different=False, prefix="", ): if path_to_info is None: @@ -106,6 +114,8 @@ def main( version_added=False, plc=False, dispatch_name_if_different=True, + incomplete=False, + different=False, file=sys.stdout, ): if path_to_info is None: @@ -116,6 +126,8 @@ def main( "version_added": version_added, "plc": plc, "dispatch_name_if_different": dispatch_name_if_different, + "incomplete": incomplete, + "different": different, } if by == "networkx_path": G = create_tree(path_to_info, by="networkx_path", **kwargs) @@ -199,6 +211,16 @@ def get_argumentparser(add_help=True): action="store_true", help="Show the full networkx path in parentheses", ) + parser.add_argument( + "--incomplete", + action="store_true", + help="Show which functions are incomplete", + ) + parser.add_argument( + "--different", + action="store_true", + help="Show which functions are different", + ) return parser @@ -212,4 +234,6 @@ def get_argumentparser(add_help=True): version_added=args.version_added, plc=args.plc, dispatch_name_if_different=not args.dispatch_name_always, + incomplete=args.incomplete, + different=args.different, ) diff --git a/python/nx-cugraph/nx_cugraph/utils/decorators.py b/python/nx-cugraph/nx_cugraph/utils/decorators.py index a6ef329ef60..c4a0383f04a 100644 --- a/python/nx-cugraph/nx_cugraph/utils/decorators.py +++ b/python/nx-cugraph/nx_cugraph/utils/decorators.py @@ -42,6 +42,8 @@ class networkx_algorithm: extra_doc: str | None extra_params: dict[str, str] | None version_added: str + is_incomplete: bool + is_different: bool _plc_names: set[str] | None def __new__( @@ -53,6 +55,8 @@ def __new__( nodes_or_number: list[int] | int | None = None, plc: str | set[str] | None = None, version_added: str, + is_incomplete: bool = False, + is_different: bool = False, ): if func is None: return partial( @@ -62,6 +66,8 @@ def __new__( nodes_or_number=nodes_or_number, plc=plc, version_added=version_added, + is_incomplete=is_incomplete, + is_different=is_different, ) instance = object.__new__(cls) if nodes_or_number is not None and nx.__version__[:3] > "3.2": @@ -87,6 +93,8 @@ def __new__( else: raise TypeError(f"plc argument must be str, set, or None; got {type(plc)}") instance.version_added = version_added + instance.is_incomplete = is_incomplete + instance.is_different = is_different # The docstring on our function is added to the NetworkX docstring. instance.extra_doc = ( dedent(func.__doc__.lstrip("\n").rstrip()) if func.__doc__ else None