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

时间:2016-04-11 14:52:54

标签: python networkx shortest-path

假设我有一个NxN节点的常规网络。两个节点之间的最短路径是从节点到达一个目标节点所需的最小跳数。现在,每条最短路径都会沿途经过许多节点。

我的目标:对于网络中的每个节点,我想计算通过特定节点的最短路径的数量,并将该数字保存在dict中。

在这个小例子中,节点B有4条最短路径通过它: A -> BA -> CC -> BC -> A我希望能够为通用图表中的每个节点计算此数字。 enter image description here

我知道我可以使用nx.betweenness_centrality(),但这会给我一个分子(对于每个节点,我想要的东西)除以分母,该分母存储两个节点之间所有可能的最短路径。我甚至访问过源代码,但我无法确定分区的执行位置。

我知道这是一个罗嗦的问题,但我没有办法解释我的问题。感谢任何有帮助的人。

修改

这是nx.betweenness_centrality()的源代码。我的图表是无向的。目前还不清楚哪条线是我上面介绍的部门:

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

4 个答案:

答案 0 :(得分:3)

您可以使用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]}}

它可以找到图形中所有节点对之间的所有最短路径(对于大型图形来说非常昂贵)。然后,以下代码为您提供所需的结果:

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

在你的例子中:

>>> num_spaths(G)
{0: 2.0, 1: 4.0, 2: 2.0}

此外,如果您可以进入all_pairs_shortest_path代码并对其进行编辑以添加最短路径的计数器并

for node in path[1:]:
    n_spaths[node] += 1
这样,您可以在找到路径的同时更新在线路径的数量,而不必在计算完所有路径之后迭代所有路径(就像我的代码一样)。

编辑:in networkx (github),第251行说:

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

您可以通过将n_spath作为参数传递给修改后的函数并在其中进行更新来修改该函数以在线更新最短路径的数量(同时找到它们)。然后调用该函数将为:

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

n_spaths将更新最短路径的数量。

编辑:以上仅在A和B之间只有1条最短路径时有效,因为nx.all_pairs_shortest_path每个节点对只返回一条最短路径。发现蛮力搜索所有可能的最短路径。我不建议在大图中运行它:

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

答案 1 :(得分:2)

我会尝试给出纯粹的算法答案。

如果从v_1v_2有多条最短路径且其中一些路径包含v_mid怎么办?如果对于每个1对,此案例计为(v_1, v_2),则可以使用Floyd-Warshall算法。运行后,您将拥有最短路径长度的矩阵。对于每个u,迭代所有(v_1, v_2)对并计算+1 D[v_1, u] + D[u, v_2] == D[v_1, v_2]。它是O(n ^ 3),适用于密集图。

我不确定,但我认为可以调整它来计算最短路径的数量。

答案 2 :(得分:1)

如果没有进一步访问源代码,就不可能肯定地说,但我的赌注是:

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

betweenness = _rescale(betweenness, len(G),...

重新缩放声音就好像它会包含一个分区。

您是否尝试使用normalized=False调用此功能?

答案 3 :(得分:1)

我相信您可以修改didn't以在另一个矩阵中保存路径的长度。伪代码(基于维基百科):

{{1}}