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

DEP : adding not_implemented_for("multigraph”) to k_core, k_shell, k_crust and k_corona #7121

Merged
merged 3 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/developer/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ Version 3.5
~~~~~~~~~~~
* Remove ``all_triplets`` from ``algorithms/triads.py``
* Remove ``random_triad`` from ``algorithms/triad.py``.
* Add `not_implemented_for("multigraph”)` decorator to ``k_core``, ``k_shell``, ``k_crust`` and ``k_corona`` functions.
65 changes: 65 additions & 0 deletions networkx/algorithms/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ def k_core(G, k=None, core_number=None):

A k-core is a maximal subgraph that contains nodes of degree `k` or more.

.. deprecated:: 3.3
`k_core` will not accept `MultiGraph` objects in version 3.5.

Parameters
----------
G : NetworkX graph
Expand Down Expand Up @@ -202,6 +205,19 @@ def k_core(G, k=None, core_number=None):
https://arxiv.org/abs/cs.DS/0310049
"""

import warnings

if G.is_multigraph():
warnings.warn(
(
"\n\n`k_core` will not accept `MultiGraph` objects in version 3.5.\n"
"Convert it to an undirected graph instead, using::\n\n"
"\tG = nx.Graph(G)\n"
),
category=DeprecationWarning,
stacklevel=5,
)

def k_filter(v, k, c):
return c[v] >= k

Expand All @@ -215,6 +231,9 @@ def k_shell(G, k=None, core_number=None):
The k-shell is the subgraph induced by nodes with core number k.
That is, nodes in the k-core that are not in the (k+1)-core.

.. deprecated:: 3.3
`k_shell` will not accept `MultiGraph` objects in version 3.5.

Parameters
----------
G : NetworkX graph
Expand Down Expand Up @@ -268,6 +287,19 @@ def k_shell(G, k=None, core_number=None):
http://www.pnas.org/content/104/27/11150.full
"""

import warnings

if G.is_multigraph():
warnings.warn(
(
"\n\n`k_shell` will not accept `MultiGraph` objects in version 3.5.\n"
"Convert it to an undirected graph instead, using::\n\n"
"\tG = nx.Graph(G)\n"
),
category=DeprecationWarning,
stacklevel=5,
)

def k_filter(v, k, c):
return c[v] == k

Expand All @@ -281,6 +313,9 @@ def k_crust(G, k=None, core_number=None):
The k-crust is the graph G with the edges of the k-core removed
and isolated nodes found after the removal of edges are also removed.

.. deprecated:: 3.3
`k_crust` will not accept `MultiGraph` objects in version 3.5.

Parameters
----------
G : NetworkX graph
Expand Down Expand Up @@ -330,6 +365,20 @@ def k_crust(G, k=None, core_number=None):
and Eran Shir, PNAS July 3, 2007 vol. 104 no. 27 11150-11154
http://www.pnas.org/content/104/27/11150.full
"""

import warnings

if G.is_multigraph():
warnings.warn(
(
"\n\n`k_crust` will not accept `MultiGraph` objects in version 3.5.\n"
"Convert it to an undirected graph instead, using::\n\n"
"\tG = nx.Graph(G)\n"
),
category=DeprecationWarning,
stacklevel=5,
)

# Default for k is one less than in _core_subgraph, so just inline.
# Filter is c[v] <= k
if core_number is None:
Expand All @@ -347,6 +396,9 @@ def k_corona(G, k, core_number=None):
The k-corona is the subgraph of nodes in the k-core which have
exactly k neighbours in the k-core.

.. deprecated:: 3.3
`k_corona` will not accept `MultiGraph` objects in version 3.5.

Parameters
----------
G : NetworkX graph
Expand Down Expand Up @@ -395,6 +447,19 @@ def k_corona(G, k, core_number=None):
http://link.aps.org/doi/10.1103/PhysRevE.73.056101
"""

import warnings

if G.is_multigraph():
warnings.warn(
(
"\n\n`k_corona` will not accept `MultiGraph` objects in version 3.5.\n"
"Convert it to an undirected graph instead, using::\n\n"
"\tG = nx.Graph(G)\n"
),
category=DeprecationWarning,
stacklevel=5,
)

def func(v, k, c):
return c[v] == k and k == sum(1 for w in G[v] if c[w] >= k)

Expand Down
69 changes: 69 additions & 0 deletions networkx/algorithms/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ def test_core_number2(self):
assert nodes_equal(nodes_by_core[1], [1, 3])
assert nodes_equal(nodes_by_core[2], [2, 4, 5, 6])

def test_core_number_multigraph(self):
G = nx.complete_graph(3)
G = nx.MultiGraph(G)
G.add_edge(1, 2)
with pytest.raises(
nx.NetworkXNotImplemented, match="not implemented for multigraph type"
):
nx.core_number(G)

def test_core_number_self_loop(self):
G = nx.cycle_graph(3)
G.add_edge(0, 0)
Expand Down Expand Up @@ -104,6 +113,12 @@ def test_k_core(self):
k_core_subgraph = nx.k_core(self.H, k=2)
assert sorted(k_core_subgraph.nodes()) == [2, 4, 5, 6]

def test_k_core_multigraph(self):
core_number = nx.core_number(self.H)
H = nx.MultiGraph(self.H)
with pytest.deprecated_call():
nx.k_core(H, k=0, core_number=core_number)

def test_main_crust(self):
main_crust_subgraph = nx.k_crust(self.H)
assert sorted(main_crust_subgraph.nodes()) == [0, 1, 3]
Expand All @@ -119,6 +134,12 @@ def test_k_crust(self):
k_crust_subgraph = nx.k_crust(self.H, k=0)
assert sorted(k_crust_subgraph.nodes()) == [0]

def test_k_crust_multigraph(self):
core_number = nx.core_number(self.H)
H = nx.MultiGraph(self.H)
with pytest.deprecated_call():
nx.k_crust(H, k=0, core_number=core_number)

def test_main_shell(self):
main_shell_subgraph = nx.k_shell(self.H)
assert sorted(main_shell_subgraph.nodes()) == [2, 4, 5, 6]
Expand All @@ -134,6 +155,12 @@ def test_k_shell(self):
k_shell_subgraph = nx.k_shell(self.H, k=0)
assert sorted(k_shell_subgraph.nodes()) == [0]

def test_k_shell_multigraph(self):
core_number = nx.core_number(self.H)
H = nx.MultiGraph(self.H)
with pytest.deprecated_call():
nx.k_shell(H, k=0, core_number=core_number)

def test_k_corona(self):
# k=0
k_corona_subgraph = nx.k_corona(self.H, k=2)
Expand All @@ -145,6 +172,12 @@ def test_k_corona(self):
k_corona_subgraph = nx.k_corona(self.H, k=0)
assert sorted(k_corona_subgraph.nodes()) == [0]

def test_k_corona_multigraph(self):
core_number = nx.core_number(self.H)
H = nx.MultiGraph(self.H)
with pytest.deprecated_call():
nx.k_corona(H, k=0, core_number=core_number)

def test_k_truss(self):
# k=-1
k_truss_subgraph = nx.k_truss(self.G, -1)
Expand All @@ -168,6 +201,24 @@ def test_k_truss(self):
k_truss_subgraph = nx.k_truss(self.G, 5)
assert sorted(k_truss_subgraph.nodes()) == []

def test_k_truss_digraph(self):
G = nx.complete_graph(3)
G = nx.DiGraph(G)
G.add_edge(2, 1)
with pytest.raises(
nx.NetworkXNotImplemented, match="not implemented for directed type"
):
nx.k_truss(G, k=1)

def test_k_truss_multigraph(self):
G = nx.complete_graph(3)
G = nx.MultiGraph(G)
G.add_edge(1, 2)
with pytest.raises(
nx.NetworkXNotImplemented, match="not implemented for multigraph type"
):
nx.k_truss(G, k=1)

def test_k_truss_self_loop(self):
G = nx.cycle_graph(3)
G.add_edge(0, 0)
Expand All @@ -188,6 +239,24 @@ def test_onion_layers(self):
assert nodes_equal(nodes_by_layer[4], [1, 2, 4, 5, 6, 8])
assert nodes_equal(nodes_by_layer[5], [3, 7])

def test_onion_digraph(self):
G = nx.complete_graph(3)
G = nx.DiGraph(G)
G.add_edge(2, 1)
with pytest.raises(
nx.NetworkXNotImplemented, match="not implemented for directed type"
):
nx.onion_layers(G)

def test_onion_multigraph(self):
G = nx.complete_graph(3)
G = nx.MultiGraph(G)
G.add_edge(1, 2)
with pytest.raises(
nx.NetworkXNotImplemented, match="not implemented for multigraph type"
):
nx.onion_layers(G)

def test_onion_self_loop(self):
G = nx.cycle_graph(3)
G.add_edge(0, 0)
Expand Down
10 changes: 10 additions & 0 deletions networkx/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ def set_warnings():
warnings.filterwarnings(
"ignore", category=DeprecationWarning, message="\n\nrandom_triad"
)
warnings.filterwarnings("ignore", category=DeprecationWarning, message="\n\nk_core")
warnings.filterwarnings(
"ignore", category=DeprecationWarning, message="\n\nk_shell"
)
warnings.filterwarnings(
"ignore", category=DeprecationWarning, message="\n\nk_crust"
)
warnings.filterwarnings(
"ignore", category=DeprecationWarning, message="\n\nk_corona"
)


@pytest.fixture(autouse=True)
Expand Down