python 最短路径算法_Python:如何计算通过一个节点的最短路径数?

1586010002-jmsa.png

Say that I have a regular network of NxN nodes. The shortest path between two nodes is the minimum number of hops required to reach one target node from a source node. Now, each shortest path passes through a number of nodes along the way.

My goal: for each node in the network, I want to count the number of shortest paths that pass through a specific node, and save that number in a dict.

In this little example, node B has 4 shortest paths passing through it:

A -> B, A -> C, C -> B, C -> A. I want to be able to compute this number for each node in a generic graph.

huEjm.png

I know I could use the nx.betweenness_centrality(), but this will give me a numerator (which is, for each node, what I want) divided by a denominator which stores all the possible shortest paths between two nodes. I have even accessed the source code but I wasn't able to figure out where the division is performed.

I know this is a wordy question but I had no other means to explain my problem. Thank you to anyone who will help.

EDIT

This is the source code for nx.betweenness_centrality(). My graph is undirected. It is unclear which line hosts the division I introduced above:

def betweenness_centrality(G, k=None, normalized=True, weight=None,

endpoints=False,

seed=None): #G is the graph

betweenness = dict.fromkeys(G, 0.0)

if k is None:

nodes = G

else:

random.seed(seed)

nodes = random.sample(G.nodes(), k)

for s in nodes:

# single source shortest paths

if weight is None: # use BFS

S, P, sigma = _single_source_shortest_path_basic(G, s)

else: # use Dijkstra's algorithm

S, P, sigma = _single_source_dijkstra_path_basic(G, s, weight)

# accumulation

if endpoints:

betweenness = _accumulate_endpoints(betweenness, S, P, sigma, s)

else:

betweenness = _accumulate_basic(betweenness, S, P, sigma, s)

# rescaling

betweenness = _rescale(betweenness, len(G),

normalized=normalized,

directed=G.is_directed(),

k=k)

return betweenness #Returns a dict with the node ID as a key and the value

解决方案

You could just use nx.all_pairs_shortest_path(G):

>>> G = nx.Graph()

>>> G.add_path([0,1,2])

>>> spaths = nx.all_pairs_shortest_path(G)

>>> spaths

{0: {0: [0], 1: [0, 1], 2: [0, 1, 2]},

1: {0: [1, 0], 1: [1], 2: [1, 2]},

2: {0: [2, 1, 0], 1: [2, 1], 2: [2]}}

Which finds you all the shortest paths between all pair of nodes in a graph (which is very expensive for large graphs). Then, the following code gives you the desired result:

def num_spaths(G):

n_spaths = dict.fromkeys(G, 0.0)

spaths = nx.all_pairs_shortest_path(G)

for source in G:

for path in spaths[source].values():

for node in path[1:]: # ignore firs element (source == node)

n_spaths[node] += 1 # this path passes through `node`

return n_spaths

In your example:

>>> num_spaths(G)

{0: 2.0, 1: 4.0, 2: 2.0}

Additionally, if you could go inside the all_pairs_shortest_path code and sightly edit it to add a counter for shortest paths and

for node in path[1:]:

n_spaths[node] += 1

this way, you would update the number of paths online at the same time you find one, rather than having to iterate over all them (as my code does) after all them are calculated.

EDIT: in networkx (github), line 251 says:

paths[w]=paths[v]+[w]

You could potentially modify that function to update the number of shortest paths online (at the same time they are found) by passing n_spath as an argument to the modified function and updating it inside. Then calling the function would be as:

def num_spaths(G):

n_spaths = dict.fromkeys(G, 0.0)

for n in G:

my_single_source_shortest_path(G, n, n_spaths)

return n_spaths

and n_spaths would have the number of shortest path updated.

EDIT: The above only works if there is only 1 shortest path between A and B, as nx.all_pairs_shortest_path only returns one shortest paths per each node pair. Find bellow the brute force search for all posible shortest paths. I wouldn't recommend runing this in a large graph:

def bf_num_spaths(G):

n_spaths = dict.fromkeys(G, 0.0)

for source in G:

for target in G:

if source == target:

continue

for path in nx.all_shortest_paths(G, source, target):

for node in path[1:]: # ignore firs element (source == node)

n_spaths[node] += 1 # this path passes through `node`

return n_spaths

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值