在 NetworkX 中检查子图是不是为集团的最快方法

Posted

技术标签:

【中文标题】在 NetworkX 中检查子图是不是为集团的最快方法【英文标题】:Fastest way of checking if a subgraph is a clique in NetworkX在 NetworkX 中检查子图是否为集团的最快方法 【发布时间】:2020-03-19 10:32:19 【问题描述】:

我想知道 G 的给定子图是否是完整图。我期待找到一个内置函数,比如is_complete_graph(G),但我看不到这样的东西。

我目前的解决方案是创建一个新的辅助函数:

def is_complete(G):
    n = G.order()
    return n*(n-1)/2 == G.size()

我想这可能很快,但我觉得自己实现这种事情是错误的,我觉得在 NetworkX 中必须有一种“正确”的方式来做到这一点。

我只需要简单无向图的解决方案。

【问题讨论】:

不要使用/进行整数除法,而是使用//。如果您使用/,Python 3 会将整数转换为浮点数,而// 在 Python 2 和 3 中都有效,为整数操作数生成整数结果。 看起来使用这个函数需要你建立一个新的图,它是你原来的子图。除非您无论如何都需要构建该新图表,否则会有更快的方法不需要您创建单独的新图表。您能否告诉我们您是否需要为其他目的构建新图表? @Joel 不,我实际上不需要子图来做其他事情。所以像G.has_clique(t) 这样的东西会很棒 @TomKarzes 有趣的汤姆,我不知道。我对使用 // 运算符犹豫不决,因为对我而言,它向读者暗示正在发生某种舍入,但事实并非如此(因为 n 是一个 int n*(n-1) 保证是偶数)。虽然我不知道这是一个很酷的优化。 @bubsy_revelations 不,这只是意味着它正在执行整数除法而不是浮点。事实上,这与您的说法相反:浮点除法意味着结果是 not 整数,否则您肯定会使用整数除法。使用浮点运算是不合适的。请注意,如果您使用 Python 2,它进行整数除法。只是在 Python 3 中它被改变了,所以你的代码在两个版本之间也是不兼容的。使用// 也可以解决这个问题。 【参考方案1】:

编辑

底部的答案比较干净。但是,似乎以下方法更快:

def is_subclique(G,nodelist):
    H = G.subgraph(nodelist)
    n = len(nodelist)
    return H.size() == n*(n-1)/2

我不得不承认,我并不完全明白。但显然创建子图比检查每条边是否存在要快。


较慢的替代方案我预计会更快:

我们将检查是否所有边缘都在那里。我们将使用combinations 来生成我们检查的对。请注意,如果combinations 返回(1,2),则不会返回(2,1)

from itertools import combinations
import networkx as nx

def is_subclique(G, nodelist):
    r'''For each pair of nodes in nodelist whether there is an edge
        if any edge is missing, we know that it's not a subclique.
        if all edges are there, it is a subclique
    '''
    for (u,v) in combinations(nodelist,2):  #check each possible pair
        if not G.has_edge(u,v):
            return False #if any edge is missing we're done
    return True  #if we get to here, then every edge was there.  It's True.

G = nx.Graph()
G.add_edges_from([(1,2), (2,3), (3,1), (4,1)])

is_subclique(G, [1,2,3])
> True
is_subclique(G, [1,4])
> True
is_subclique(G, [2,3,4])
> False

【讨论】:

嗨乔尔。谢谢回答我的问题!我在这个函数和我原来的函数之间做了一些比较。 See my code here。我发现对于大约 200 个节点的图,由于组合的爆炸式增长,这种实现速度要慢许多数量级。 即使对于大约有 10 个节点的图,这个实现也会慢一个数量级左右。我认为以这种方式迭代边缘的成本超过了创建新图的成本。如果在内存受限时处理非常小的图形,这可能会更好?但是对于我的用例来说,问题中的实现仍然是最好的。 这让我很吃惊。我假设您在 networkx 中使用subgraph 命令?我原以为它使用类似于我所做的循环的东西生成子图,但现在我查看源代码它正在做其他事情,我想这要快得多。鉴于你所说的,我认为你的实现可能是最好的。 好的,感谢您的帮助。希望得到一个内置于networkx的解决方案,但如果它不可用,那么我怀疑我会得到这个问题的合适答案。【参考方案2】:

实际上,您需要检查的不仅仅是边的数量,因为 complete_graph 不允许自循环。此外,它们可能会改变预期的边数。

这是一个非常快速的函数——尤其是当它不是一个完整的图表时。请注意,它甚至避免计算边缘。它只是确保每个节点都有正确的邻居。

def is_complete_graph(G):
    N = len(G) - 1
    return not any(n in nbrdict or len(nbrdict)!=N for n, nbrdict in G.adj.items())

【讨论】:

以上是关于在 NetworkX 中检查子图是不是为集团的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 python 的 networkx 模块从节点列表生成完全连接的子图

python—networkx:在一张图中画出多个子图

networkx里哪个函数是提取网络最大连通子图的?

NetworkX:有效地诱导给定顶点的集团

从 networkx 绘制以底图位置为中心的图形

检查字符是不是为数字的最快方法?