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

New graph generator for the Kneser graph #7146

Merged
merged 13 commits into from
Jan 29, 2024
1 change: 1 addition & 0 deletions doc/reference/generators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Classic
dorogovtsev_goltsev_mendes_graph
empty_graph
full_rary_tree
kneser_graph
ladder_graph
lollipop_graph
null_graph
Expand Down
47 changes: 47 additions & 0 deletions networkx/generators/classic.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"dorogovtsev_goltsev_mendes_graph",
"empty_graph",
"full_rary_tree",
"kneser_graph",
"ladder_graph",
"lollipop_graph",
"null_graph",
Expand Down Expand Up @@ -103,6 +104,52 @@ def full_rary_tree(r, n, create_using=None):
return G


@nx._dispatchable(graphs=None)
def kneser_graph(n, k):
"""Returns the Kneser Graph with parameters $n$ and $k$.

The Kneser Graph has nodes that are k-tuples (subsets) of the integers
between 0 and n-1. Nodes are adjacent if their corresponding sets are disjoint.

Parameters
----------
n: int
Total number of elements.
rossbar marked this conversation as resolved.
Show resolved Hide resolved
k: int
Size of the subsets.

Returns
-------
G : NetworkX Graph

Examples
--------
>>> G = nx.kneser_graph(5, 2)
>>> G.number_of_nodes()
10
>>> G.number_of_edges()
15
>>> nx.is_isomorphic(G, nx.petersen_graph())
True
"""
if n <= 0:
raise NetworkXError("n should be greater than zero")
if k <= 0 or k > n:
raise NetworkXError("k should be greater than zero and smaller than n")

G = nx.Graph()
# Create all k-subsets of [0, 1, ..., n-1]
subsets = list(itertools.combinations(range(n), k))

if 2 * k > n:
G.add_nodes_from(subsets)

universe = set(range(n))
comb = itertools.combinations # only to make it all fit on one line
G.add_edges_from((s, t) for s in subsets for t in comb(universe - set(s), k))
return G


@nx._dispatchable(graphs=None)
def balanced_tree(r, h, create_using=None):
"""Returns the perfectly balanced `r`-ary tree of height `h`.
Expand Down
16 changes: 16 additions & 0 deletions networkx/generators/tests/test_classic.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,3 +617,19 @@ def test_complete_multipartite_graph(self):
assert G.nodes[u] != G.nodes[v]
with pytest.raises(nx.NetworkXError, match="Negative number of nodes"):
nx.complete_multipartite_graph(2, -3, 4)

def test_kneser_graph(self):
# the petersen graph is a special case of the kneser graph when n=5 and k=2
assert is_isomorphic(nx.kneser_graph(5, 2), nx.petersen_graph())

# when k is 1, the kneser graph returns a complete graph with n vertices
for i in range(1, 7):
assert is_isomorphic(nx.kneser_graph(i, 1), nx.complete_graph(i))

# the kneser graph of n and n-1 is the empty graph with n vertices
for j in range(3, 7):
assert is_isomorphic(nx.kneser_graph(j, j - 1), nx.empty_graph(j))

# in general the number of edges of the kneser graph is equal to
# (n choose k) times (n-k choose k) divided by 2
assert nx.number_of_edges(nx.kneser_graph(8, 3)) == 280