获取有向图中的并行路径列表

时间:2016-06-04 19:02:08

标签: python algorithm networkx directed-graph

我需要一种算法来查找有向图中所有并行路径的集合。以下是我用于测试的示例的直观表示。

visual representation of example directed graph with a set of parallel paths

以下是我在Python中使用networkx的示例代码:

import networkx as nx

G = nx.MultiDiGraph()
# relevant part of graph to my question
G.add_edges_from([(1,2),(2,3),(3,4),(2,5),(5,6),(6,4),(4,7)])
# subordinate part of graph to my question
G.add_edges_from([(7,8),(8,9),(7,10),(10,11),(11,13),(11,12),(12,14)])

pp = get_parallel_paths(G)  # -> the function I'm looking for

# pp should contain:
# pp = [[[(2,3),(3,4)],[(2,5),(5,6),(6,4)]],[...]]
# the procedure should list all sets of parallel paths
# hence the [...] indicates a possible other set of parallel paths (not in example)

我正在寻找的功能是“get_parallel_paths”。它不一定是在Python中:非常欢迎指向任何可以帮助我实现的算法的指针。

2 个答案:

答案 0 :(得分:2)

如果考虑带分支的并行路径,则此问题将是NP完全的(参见vertex-disjoint paths problem)。

但是,由于不考虑分支,问题很简单:

  1. 遍历所有顶点。
  2. 如果顶点有多个外边,请跟随它们直到它们收敛。
  3. 如果它们汇聚到同一节点,则它们是并行路径。
  4. 伪码:

    allParallelPaths = []
    
    #loop over all vertices to find ones that split
    foreach(vertices as v)
      if(out-degree(v) > 1) 
    
        #store every eventual target and the paths that got there
        destinations = new Map()
        foreach(v.out as e)
          path = [e]
    
          #stop at any vertex that has non-one in- or out-degree
          while(in-degree(e.target) == 1 && out-degree(e.target) == 1)
            e = e.target.out[0]
            path.push(e)
    
          #make a list of paths that reached the destination
          if(empty(destinations[e.target]))
            destinations[e.target] = []
          destinations[e.target].push(path)
    
        foreach(destinations as dest)
          if(dest.size > 1)
            allParallelPaths.push(dest)
    

答案 1 :(得分:2)

有一个内置函数可列出两个顶点之间的所有简单路径。这用它来列出任意两个顶点之间的所有路径集:

def get_parallel_paths(G):
    return [list(nx.all_simple_paths(G, i, j)) for i in G.nodes_iter() for j in G.nodes_iter() if i != j and nx.has_path(G, i, j)]

要过滤出内部顶点大于2的任何路径,我们可以这样做:

def get_parallel_paths(G):
    colpaths = []
    for i in G.nodes_iter():
        for j in G.nodes_iter():
            if i == j:
                continue
            nbp = nobranchpaths(G, i, j)
            if len(nbp) > 1:
                colpaths += [nbp]
    return colpaths

def nobranchpaths(G, u, v):
    paths = []
    for p in nx.all_simple_paths(G, u, v):
        if len(p) == 2 or max(G.degree(i) for i in p[1:-1]) == 2:
            paths += [p]
    return paths

这仅包括存在多个路径的顶点对;要包含具有唯一路径的对,请将if len(nbp) > 1:更改为if len(nbp):