基于节点的对交互加速边缘的创建

时间:2016-09-08 22:31:39

标签: networkx

我的意思是创建一个有向图,如果符合某个标准,就会创建节点之间的边,即

if (crit(i,j)) :
    G.add_edge(i,j)

为此,我写了一个循环

nnd = len( ndlist )
for ind in range( nnd ) :
    ndi = ndlist[ ind ] 
    for jnd in range( nnd ) :
        if ( jnd != ind ) :  # no self interaction
            ndj = ndlist[ jnd ]
            interaction = inrange( ndi, ndj, threshold )
            if ( interaction ) :
                G.add_edge( ind, jnd )

ndlist是一个包含节点功能的列表,每个节点一个元素,此信息用于评估节点对之间的交互。节点标有与ndlist中相同的索引号,这是有利的。这也是循环整数的原因,因为边连接(ind,jnd),而不是(ndi,ndj)

事实证明这很慢。 有没有优化方法?

当然,执行时间取决于inrange,但可能有一种方法可以加速代码而不管inrange(可能将ndlist的内容作为节点属性插入并迭代不同)。 甚至改变我的非常慢的#34;代码进入"只是缓慢"代码会有所帮助。

2 个答案:

答案 0 :(得分:1)

如果我理解变量之间的关系,以下内容至少会使代码更容易阅读,并减少for循环的数量,这通常会使Python更有效率。基本上我理解它(这可能是一个错误的理解)你将更多的循环推送到C,而不是纯Python:

from intertools import permutations
for ind, jnd in permutations(ndlist, 2): #all pairs without replacemnt
    if inrange(ndi, ndj, threshold):
        G.add_edge(ndi, ndj)

使用list comprehension

可以使这更加简洁并避免使用for循环(这可能会提高效率)
from itertools import permutations
new_edges = [ (ind,jnd) for ind, jnd in permutations(ndlist, 2) if inrange(ndi, ndj, threshold)]
G.add_edges_from(new_edges)

使new_edges生成器而不是列表可以节省内存。

顺便说一句:使用更具描述性的变量名称可能有助于使代码更易于阅读。

答案 1 :(得分:0)

answer by Joel显示了一种使代码更具可读性的方法,但仍然一次添加一条边。另一种方法是在一次添加所有边缘,这可能使代码更快。 但事实证明,一次添加所有边缘并不会使代码更快(至少在我的情况下)

PS:我的代码的第一个版本一次添加一个节点(上面没有显示这部分,以减少混乱)。 后来我改为使用

一次添加所有节点
G.add_nodes_from( range( nnd ) )
nx.set_node_attributes( G, 'pos', posdict )

它使代码更快。

因此,我对边缘发生的类似事情有所期待。但瓶颈是对每个候选边缘的评估,我想这没什么可做的。我可能不得不去编译评估函数。这值得一些工作,也许还有进一步的SO问题。