Python:Networkx Dijkstra算法的问题

时间:2014-05-04 15:55:24

标签: python dijkstra networkx

我的目标是做与发布here完全相同的事情。

我有一个矩阵(DataFramedf),如下所示:

community A   B   C   D
A         0   3   4   1
B         3   0   2   0
C         4   2   0   1
D         1   0   1   0 

这是对称的df,每个权重代表每个社区之间连接的权重或强度。如链接中所述,我想生成一个矩阵,显示所有节点(或社区)之间的最短距离。我首先反转上面的矩阵并设置G图形网络:

G = nx.Graph()
commu = list(df.index)
for i in range(0,len(commu)):
    for j in range(0,len(commu)):
            if i == j:
                pass
            else:
                G.add_edge(str(i),str(j),weight=df.ix[df.index[i], df.columns[j]])

这给了我以下网络图:network边缘的不同颜色适用于不同的权重。 (我在图表中更改了数字的字母)

好的,到目前为止一切顺利。现在,我想要所有节点之间的最短距离。我正在考虑使用此nx.dijkstra_shortest_path_length(G,source,target)并循环遍历sourcetarget的所有节点,并生成一个类似上述链接的矩阵,其中包含每个单元格中所有节点的最短路径的所有值矩阵但由于某种原因nx.dijkstra_shortest_path_length(G,source,target)对我不起作用。 如果我做nx.dijkstra_shortest_path_length(G,A,B)或任何节点组合,我总是得到0值。为什么?有没有一种有效的方法来使用Networkxnx.dijkstra算法来复制链接中的矩阵?

2 个答案:

答案 0 :(得分:2)

您可以使用权重='权重的networkx.shortest_path(G)'关键词。 e.g。

In [1]: import networkx as nx

In [2]: G = nx.Graph()

In [3]: G.add_edge(1,2,weight=7)

In [4]: G.add_edge(1,4,weight=3)

In [5]: G.add_edge(2,3,weight=1)

In [6]: G.add_edge(3,4,weight=100)

In [7]: nx.adjacency_matrix(G).todense()
Out[7]: 
matrix([[  0,   7,   0,   3],
        [  7,   0,   1,   0],
        [  0,   1,   0, 100],
        [  3,   0, 100,   0]])

In [8]: nx.shortest_path_length(G)
Out[8]: 
{1: {1: 0, 2: 1, 3: 2, 4: 1},
 2: {1: 1, 2: 0, 3: 1, 4: 2},
 3: {1: 2, 2: 1, 3: 0, 4: 1},
 4: {1: 1, 2: 2, 3: 1, 4: 0}}

In [9]: nx.shortest_path_length(G,weight='weight')
Out[9]: 
{1: {1: 0, 2: 7, 3: 8, 4: 3},
 2: {1: 7, 2: 0, 3: 1, 4: 10},
 3: {1: 8, 2: 1, 3: 0, 4: 11},
 4: {1: 3, 2: 10, 3: 11, 4: 0}}

In [10]: nx.utils.dict_to_numpy_array(nx.shortest_path_length(G,weight='weight'))
Out[10]: 
array([[  0.,   7.,   8.,   3.],
       [  7.,   0.,   1.,  10.],
       [  8.,   1.,   0.,  11.],
       [  3.,  10.,  11.,   0.]])

答案 1 :(得分:1)

(不是答案,只是长篇评论)。如果

In [65]: df.values
Out[65]: 
array([[0, 3, 4, 1],
       [3, 0, 2, 0],
       [4, 2, 0, 1],
       [1, 0, 1, 0]], dtype=int64)

然后代替

G = nx.Graph()
commu = list(df.index)
for i in range(0,len(commu)):
    for j in range(0,len(commu)):
            if i == j:
                pass
            else:
                G.add_edge(str(i),str(j),weight=df.ix[df.index[i], df.columns[j]])

您可以使用

构建G
In [66]: G = nx.from_numpy_matrix(df.values)

In [67]: G.edges(data=True)
Out[67]: 
[(0, 1, {'weight': 3}),
 (0, 2, {'weight': 4}),
 (0, 3, {'weight': 1}),
 (1, 2, {'weight': 2}),
 (2, 3, {'weight': 1})]

如果您想标记节点ABCD而不是0123

In [68]: G = nx.relabel_nodes(G, dict(zip(range(4), 'ABCD')))

In [69]: G.edges(data=True)
Out[69]: 
[('A', 'C', {'weight': 4}),
 ('A', 'B', {'weight': 3}),
 ('A', 'D', {'weight': 1}),
 ('C', 'B', {'weight': 2}),
 ('C', 'D', {'weight': 1})]