使用Networkx计算顶点所属的最短路径数的更快方法

时间:2013-06-13 16:33:26

标签: python performance graph shortest-path networkx

我正在考虑顶点 i Stress i 所属的所有顶点对之间的最短路径数。

我正在尝试使用Networkx计算它,到目前为止我已经用三种方式制作了它。 可读最脏,但它们都不快。实际上,我希望它比Networkx上的betweennesssource更快。有更好的方法来计算吗? 感谢提前获取任何建议,答案或评论。以下是我到目前为止所做的事情:

Ps。:Here是一个代号,如果你想尝试一下,代码就可以了,再次感谢。

以下是所有版本的通用部分:

import networkx as nx
from collections import defaultdict

最肮脏,支持你自己:

def stress_centrality_dirtiest(g):

  stress = defaultdict(int)

  for a in nx.nodes_iter(g):
    for b in nx.nodes_iter(g):
      if a==b:
        continue
      # pred = nx.predecessor(G,b)  # for unweighted graphs
      pred, distance = nx.dijkstra_predecessor_and_distance(g,b)  # for weighted graphs
      if not pred.has_key(a):
        return [] 
      path = [[a,0]] 
      path_length = 1
      index = 0
      while index >= 0: 
        n,i = path[index] 
        if n == b: 
          for vertex in map(lambda x:x[0], path[:index+1])[1:-1]:
            stress[vertex] += 1
        if len(pred[n]) > i: 
          index += 1 
          if index == path_length: 
            path.append([pred[n][i],0]) 
            path_length += 1 
          else: 
            path[index] = [pred[n][i],0] 
        else: 
          index -= 1 
          if index >= 0: 
            path[index][4] += 1 
  return stress

def stress_centrality_dirty(g):

  stress = defaultdict(int)

  paths = nx.all_pairs_dijkstra_path(g)
  for item in paths.values():
    for element in item.values():
      if len(element) > 2:
        for vertex in element[1:-1]:
          stress[vertex] += 1
  return stress

可读

def stress_centrality_readable(g):

  stress = defaultdict(int)

  paths = nx.all_pairs_dijkstra_path(g)
  for source in nx.nodes_iter(g):
    for end in nx.nodes_iter(g):
      if source == end:
        continue
      path = paths[source][end]
      if len(path) > 2:                                         # path must contains at least 3 vertices source - another node - end
        for vertex in path[1:-1]:                               # when counting the number of occurrencies, exclude source and end vertices
          stress[vertex] += 1
  return stress

2 个答案:

答案 0 :(得分:3)

您在NetworkX中指向的中介代码几乎可以满足您的需求,并且可以轻松调整。

在中介功能中,如果在“累积”阶段调用以下(而不是_accumulate_basic),它应该计算压力中心性(未经测试)

def _accumulate_stress(betweenness,S,P,sigma,s):
    delta = dict.fromkeys(S,0)
    while S:
        w = S.pop()
        for v in P[w]:
            delta[v] += (1.0+delta[w])
        if w != s:
            betweenness[w] += sigma[w]*delta[w]
    return betweenness

参见文章Ulrik Brandes:关于最短路径中介性的变体及其通用计算。社交网络30(2):136-145,2008。http://www.inf.uni-konstanz.de/algo/publications/b-vspbc-08.pdf

压力中心算法是算法12。

答案 1 :(得分:0)

根据我给出的答案here,我尝试做同样的事情。

我的尝试围绕着nx.all_shortest_paths(G,source,target)函数的使用,它产生了一个生成器:

counts={}
for n in G.nodes(): counts[n]=0
for n in G.nodes():
    for j in G.nodes():
        if (n!=j):
            gener=nx.all_shortest_paths(G,source=n,target=j) #A generator
            print('From node '+str(n)+' to '+str(j))
            for p in gener:
                print(p) 
                for v in p: counts[v]+=1
            print('------')

我已经使用NxN节点的100网格测试了此代码,我花了大约168秒才得到结果。现在我知道这不是最好的答案,因为这段代码没有优化,但我想你可能想知道它。希望我能就如何改进我的代码获得一些指示。