使用python中的networkx以高效的方式生成所有路径

时间:2016-11-08 04:03:39

标签: python python-2.7 pandas graph networkx

我正在尝试生成所有路径,从一个相当大的网络(20,000+弧)中,每个原点到每个目的地最多有6个节点。我正在使用networkx和python 2.7。对于小型网络,它运行良好但我需要为整个网络运行它。我想知道是否有更有效的方法在python中执行此操作。我的代码包含一个递归函数(见下文)。我正在考虑在记忆中保留一些路径,以便我不会再为其他路径创建它们,但我不确定如何快速完成它。现在它甚至不会在几天内完成。对我的项目来说,3-4个小时应该没问题。

以下是我创建的示例。我可以随意忽略打印功能,因为我为了说明目的而添加了它们。这里还有示例输入文件。 input

import networkx as nx
import pandas as pd
import copy
import os

class ODPath(object):    
    def __init__(self,pathID='',transittime=0,path=[],vol=0,OD='',air=False,sortstrat=[],arctransit=[]):
        self.pathID = pathID
        self.transittime = transittime
        self.path = path
        self.vol = vol
        self.OD = OD
        self.air = air
        self.sortstrat = sortstrat # a list of sort strategies
        self.arctransit = arctransit # keep the transit time of each arc as a list
    def setpath(self,newpath):
        self.path = newpath
    def setarctransitpath(self,newarctransit):
        self.arctransit = newarctransit
    def settranstime(self,newtranstime):
        self.transittime = newtranstime
    def setpathID(self,newID):
        self.pathID = newID
    def setvol(self,newvol):
        self.vol = newvol
    def setOD(self,newOD):
        self.OD = newOD
    def setAIR(self,newairTF):
        self.air = newairTF
    def setsortstrat(self,newsortstrat):
        self.sortstrat = newsortstrat

def find_allpaths(graph, start, end, pathx=ODPath(None,0,[],0,None,False)):
    path = copy.deepcopy(pathx) #to make sure the original has not been revised
    newpath = path.path +[start]    
    path.setpath(newpath)
    if len(path.path) >6:
        return []
    if start == end: 
    return [path]
    if (start) not in graph:    #check if node:start exists in the graph
        return []
    paths = []
    for node in graph[start]:   #loop over all outbound nodes of starting point  
        if node not in path.path:    #makes sure there are no cycles
            newpaths = find_allpaths(graph,node,end,path)
            for newpath in newpaths:
                if len(newpath.path) < 7: #generate only the paths that are with at most 6 hops      
                    paths.append(newpath)
    return paths
def printallpaths(path_temp):
map(printapath,path_temp)
def printapath(path):
print path.path

filename='transit_sample1.csv'
df_t= pd.read_csv(filename,delimiter=',')
df_t = df_t.reset_index()
G=nx.from_pandas_dataframe(df_t, 'node1', 'node2', ['Transit Time'],nx.DiGraph())
allpaths=find_allpaths(G,'A','S')  
printallpaths(allpaths)

我真的很感激任何帮助。

2 个答案:

答案 0 :(得分:1)

我实际上问了这个问题previously关于优化我之前使用networkx编写的算法。基本上你要做的就是摆脱递归函数,转向像我一样使用记忆的解决方案。

从这里开始,您可以进行进一步的优化,例如使用multiple cores,或者根据度数等标准选择下一个要遍历的节点。

答案 1 :(得分:1)

NetworkX已经具有此功能。除非您有特殊情况,否则通常最好使用已建立的库功能,因为它将经过测试且高效。

这是一个简单的示例:

from itertools import combinations
from networkx.algorithms.simple_paths import all_simple_paths
import networkx as nx

G = nx.DiGraph()
node_names = ['A', 'B', 'C', 'S']
G.add_edges_from(combinations(node_names, 2))
print (G)

for path in all_simple_paths(G, 'A', 'S'):
    print (path)

(我跳过了csv文件,因为它对这个问题并不重要,并且我不希望该dropbox消失时该答案也会失败。它应该适用于所有图形。)

在不涉及内部细节的情况下,我注意到您的实现生成了所有答案的列表,然后将其返回。您会注意到networkx.algorithms.simple_paths.all_simple_paths返回一个生成器。生成器在内存(分配,缓存,交换)上友好得多,因此性能更好。 https://stackoverflow.com/a/102632/1766544或……几乎到处都有关于该主题的讨论。