你的问题的问题
我不认为您的解决方案可以按照您尝试的方式工作。我首先说明原因,然后我在下面提出一个替代解决方案。
考虑这段代码:
import networkx as nx
import matplotlib.pyplot as plt
import random
# Set up a graph with random edges and weights
G = nx.barabasi_albert_graph(6, 2, seed= 3214562)
for u,v in G.edges_iter():
G[u][v]['weight'] = int(random.random() * 10)
pos = nx.spring_layout(G)
nx.draw(G, pos)
nx.draw_networkx_edge_labels(G,pos)
plt.show()
它产生这个数字:
考虑节点 1。它有两条边,权重分别为 2 和 9。我们应该将权重分别调整为 2/11 和 9/11。
接下来考虑节点 4。它现在有两条边,权重分别为 2/11 和 8。第一个权重是从之前的计算中固定的,所以我们基本上将第二个权重调整为 8/(8+2/11)。
我们现在有三个边,它们的权重被调整和固定。我们现在对节点 0、3 和 5 重复此操作。到该过程结束时,节点 2 周围的所有边都已重新调整和固定,但它们的总和不会等于 1,除非非常巧合。当然,在更大的图中,这个问题会出现得更快。
解决方案
我建议您为每个节点附加一个包含重新加权边缘字典的新数据属性,而不是重新加权边缘本身。这是演示的相关代码:
for n in G.nodes_iter():
total = sum([ attr['weight']
for u,v,attr in G.edges(n, data=True) ])
total = float(total)
weights = dict([(nb, G[n][nb]['weight']/total)
for nb in G.neighbors(n)])
G[n]['adj_weights'] = weights
# Print out the adjusted weights
for n in G.nodes_iter():
for nb,w in G[n]['adj_weights'].iteritems():
w = int(w*1000)/1000.
print '{} to {}: {}'.format(n, nb, w)
这会产生:
0 to 2: 0.272
0 to 3: 0.727
1 to 2: 0.818
1 to 4: 0.181
2 to 0: 0.081
2 to 1: 0.243
2 to 3: 0.243
2 to 4: 0.216
2 to 5: 0.216
3 to 0: 0.363
3 to 2: 0.409
3 to 5: 0.227
4 to 1: 0.2
4 to 2: 0.8
5 to 2: 0.615
5 to 3: 0.384
因此,节点 0 的边总和为 1,例如,连接到节点 3 的边也是如此。但是从节点 0 看边 (0,3) 的权重为 0.727,从节点 3 看时为 0.363。
我希望这能让你继续前进。