我的意思是创建一个有向图,如果符合某个标准,就会创建节点之间的边,即
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;代码进入"只是缓慢"代码会有所帮助。
答案 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)
可以使这更加简洁并避免使用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问题。