简体   繁体   English

如何使用Python NetworkX找到最长的路径?

[英]How to find the longest path with Python NetworkX?

I have a directed graph from S to T. 我有一个从S到T的有向图。

And I would like to find the route (S, A, C, E, T) and the sum of its capacities (1 + 2 + 3 + 1 = 7) so the sum is the largest. 我想找到路线(S,A,C,E,T)及其容量的总和(1 + 2 + 3 + 1 = 7),所以总和最大。

I tried networkx.algorithms.flow.ford_fulkerson, but I don't know how to get the one-way direction from S to T. 我尝试使用networkx.algorithms.flow.ford_fulkerson,但我不知道如何获得从S到T的单向方向。

My environment: 我的环境:

  • Ubuntu 12.04 Ubuntu 12.04
  • Python 2.7.8 Python 2.7.8
  • NetworkX 1.9 NetworkX 1.9
  • Matplotlib 1.4.0 Matplotlib 1.4.0

example.py example.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import matplotlib.pylab as p
import networkx as nx

if __name__ == '__main__':
    DG = nx.DiGraph()
    DG.add_edge('S', 'a', capacity=1)
    DG.add_edge('a', 'b', capacity=1)
    DG.add_edge('a', 'c', capacity=2)
    DG.add_edge('b', 'd', capacity=1)
    DG.add_edge('b', 'e', capacity=2)
    DG.add_edge('c', 'e', capacity=3)
    DG.add_edge('c', 'f', capacity=2)
    DG.add_edge('d', 'T', capacity=1)
    DG.add_edge('e', 'T', capacity=1)
    DG.add_edge('f', 'T', capacity=1)

    result = nx.algorithms.flow.ford_fulkerson(DG, 'S', 'T')
    print(result.size(weight='capacity')) # 15.0, but I want 7.

    pos = nx.spectral_layout(DG)
    nx.draw(DG, pos)
    nx.draw_networkx_labels(DG, pos)
    nx.draw_networkx_edge_labels(DG, pos)
    p.show()

    # This shows a partly bidirectional graph, which is not what I want.
    pos = nx.spectral_layout(result)
    nx.draw(result, pos)
    nx.draw_networkx_labels(result, pos)
    nx.draw_networkx_edge_labels(result, pos)
    p.show()

Using negative weight often doesn't work for Dijkstra algorithm. 负权重通常不适用于Dijkstra算法。 This error ValueError: ('Contradictory paths found:', 'negative weights?') will show up. 将显示此错误ValueError: ('Contradictory paths found:', 'negative weights?')

It should distinguish the problem of "Longest Path" and the "Maximum Sum Path". 它应该区分“最长路径”和“最大和路径”的问题。

The answer here: How to find path with highest sum in a weighted networkx graph? 答案在这里: 如何在加权的networkx图中找到具有最高总和的路径? , that uses all_simple_paths . ,它使用all_simple_paths

Note that in the function all_simple_paths(G, source, target, cutoff=None) , using cutoff param (integer number) can help to limit the depth of search from source to target . 请注意,在函数all_simple_paths(G, source, target, cutoff=None) ,使用cutoff参数(整数)可以帮助限制从sourcetarget的搜索深度。 It also controls the length of the path that we want to find. 它还控制我们要查找的路径的长度。

The negative weights works for johnson. 负权重适用于约翰逊。 In your case, modified as: 就您而言,修改为:

DG = nx.DiGraph()
DG.add_edge('S', 'a', weight=-1)
DG.add_edge('a', 'b', weight=-1)
DG.add_edge('a', 'c', weight=-2)
DG.add_edge('b', 'd', weight=-1)
DG.add_edge('b', 'e', weight=-2)
DG.add_edge('c', 'e', weight=-3)
DG.add_edge('c', 'f', weight=-2)
DG.add_edge('d', 'T', weight=-1)
DG.add_edge('e', 'T', weight=-1)
DG.add_edge('f', 'T', weight=-1)

To find longest path, get the one-way direction from S to T with 要找到最长的路径,请使用来确定从S到T的单向方向

p2 = nx.johnson (DG, weight='weight')
print('johnson: {0}'.format(p2['S']['T']))

result as: johnson: ['S', 'a', 'c', 'e', 'T'] 结果为: johnson: ['S', 'a', 'c', 'e', 'T']

My environment: 我的环境:

  • Software Version 软件版本
  • Python 3.4.5 64bit [MSC v.1600 64 bit (AMD64)] Python 3.4.5 64位[MSC v.1600 64位(AMD64)]
  • IPython 5.1.0 OS Windows 10 10.0.14393 IPython 5.1.0操作系统Windows 10 10.0.14393
  • networkx 1.11 网络x 1.11

Networkx 1.11 docs for johnson 约翰逊的Networkx 1.11文档

I think I found a solution. 我想我找到了解决方案。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import networkx as nx

def inverse_weight(graph, weight='weight'):
    copy_graph = graph.copy()
    for n, eds in copy_graph.adjacency_iter():
        for ed, eattr in eds.items():
            copy_graph[n][ed][weight] = eattr[weight] * -1
    return copy_graph

def longest_path_and_length(graph, s, t, weight='weight'):
    i_w_graph = inverse_weight(graph, weight)
    path = nx.dijkstra_path(i_w_graph, s, t)
    length = nx.dijkstra_path_length(i_w_graph, s, t) * -1
    return path, length

if __name__ == '__main__':
    DG = nx.DiGraph()
    DG.add_edge('S', 'a', weight=1)
    DG.add_edge('a', 'b', weight=1)
    DG.add_edge('a', 'c', weight=2)
    DG.add_edge('b', 'd', weight=1)
    DG.add_edge('b', 'e', weight=2)
    DG.add_edge('c', 'e', weight=3)
    DG.add_edge('c', 'f', weight=2)
    DG.add_edge('d', 'T', weight=1)
    DG.add_edge('e', 'T', weight=1)
    DG.add_edge('f', 'T', weight=1)

    print(longest_path_and_length(DG, 'S', 'T')) # (['S', 'a', 'c', 'e', 'T'], 7)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM