【问题标题】:NetworkX / Python_igraph: All paths between two nodes, limited by list of nodesNetworkX / Python_igraph:两个节点之间的所有路径,受节点列表限制
【发布时间】:2015-09-15 22:57:29
【问题描述】:

我正在使用here的函数:

def find_all_paths(graph, start, end, mode = 'OUT', maxlen = None):
def find_all_paths_aux(adjlist, start, end, path, maxlen = None):
    path = path + [start]
    if start == end:
        return [path]
    paths = []
    if maxlen is None or len(path) <= maxlen:
        for node in adjlist[start] - set(path):
            paths.extend(find_all_paths_aux(adjlist, node, end, path, maxlen))
    return paths
adjlist = [set(graph.neighbors(node, mode = mode)) \
    for node in xrange(graph.vcount())]
all_paths = []
start = start if type(start) is list else [start]
end = end if type(end) is list else [end]
for s in start:
    for e in end:
        all_paths.extend(find_all_paths_aux(adjlist, s, e, [], maxlen))
return all_paths

查找两个节点之间的所有路径。

另一种功能是here

def find_all_paths(graph, start, end):
path  = []
paths = []
queue = [(start, end, path)]
while queue:
    start, end, path = queue.pop()
    print 'PATH', path

    path = path + [start]
    if start == end:
        paths.append(path)
    for node in set(graph[start]).difference(path):
        queue.append((node, end, path))
return paths

我想扩展其中一个函数以获取另一个参数,即“via_nodes”列表。

如果路径在其结束和开始节点之间有这些 via_nodes 之一,则不应返回。

首先使用函数计算所有路径很容易,然后排除满足上述条件的路径,但为了提高性能,我希望它在遇到路径搜索时停止via_node 在早期阶段。

有什么想法吗?

【问题讨论】:

    标签: python graph igraph networkx network-analysis


    【解决方案1】:

    您可以创建一个仅包含您希望在路径中看到的节点的子图 在 Networkx 2.5 中:

    sub_graph = nx.subgraph_view(graph, filter_node:lambda n: n in [start, end] or n not in vn)
    return all_simple_paths(sub_graph, start, end)
    

    这将找到所有简单路径并排除 vn 中的任何节点,因为它们不在子图中

    【讨论】:

      【解决方案2】:

      好的,我会回答自己,但会很高兴测试和 cmets:从上面的第二个函数(适用于 python-igraph 和 networkx),我添加了 vn 参数,所以路径搜索停止如果 a到达 vn 节点:

      import igraph as ig
      
      def find_all_paths2(graph, start, end, vn = []):
              """ 
              Finds all paths between nodes start and end in graph.
              If any node on such a path is within vn, the path is not         
              returned.
              !! start and end node can't be in the vn list !!
      
              Params:
              --------
      
              G : igraph graph
      
              start: start node index
      
              end : end node index
      
              vn : list of via- or stop-nodes indices
      
              Returns:
              --------
      
              A list of paths (node index lists) between start and end node
              """
      
          vn = vn if type(vn) is list else [vn]
          path  = []
          paths = []
          queue = [(start, end, path)]
          while queue:
              start, end, path = queue.pop()
              #print 'PATH', path
              path = path + [start]
              #print 'PATH after adding start ', path
      
              if start in vn:
                  print start,' is in vianodes ',str(vn)
                  pass#paths.append(path)
      
              if start == end:
                  print 'end'
                  paths.append(path)
              #print graph.neighbors(start)
              if start not in vn:
                  print start,' not in vianodes ',str(vn)
                  for node in set(graph.neighbors(start)).difference(path):
                      queue.append((node, end, path))
          return paths
      
      G = ig.Graph()
      G.add_vertices(14)
      G.add_edges([(13,10),(12,13),(11,12),(10,11),(9,10),(2,9),(0,1), (1,2),(2,3),(3,0),(0,4),(4,5),(5,6),(6,7),(7,8),(8,6)])#,(0,0)])
      #G = G.as_directed()
      
      
      for p in find_all_paths2(G,0,12,[]):
          print 'path: ',p
      
      path:  [0, 3, 2, 9, 10, 13, 12]
      path:  [0, 3, 2, 9, 10, 11, 12]
      path:  [0, 1, 2, 9, 10, 13, 12]
      path:  [0, 1, 2, 9, 10, 11, 12]
      
      for p in find_all_paths2(G,0,12,[13]):
              print 'path: ',p
      
      
      path:  [0, 3, 2, 9, 10, 11, 12]
      path:  [0, 1, 2, 9, 10, 11, 12]
      

      【讨论】:

        【解决方案3】:

        在长路径递归之前从图中删除节点。

        完成后将它们放回去。

        这在高度连接的图中占用更少的内存。

        import networkx
        G = networkx.Graph()
        G.add_node(14)
        G.add_edges_from([(13,10),(12,13),(11,12),(10,11),(9,10),(2,9),(0,1),(1,2),(2,3),(3,0),(0,4),(4,5),(5,6),(6,7),(7,8),(8,6)])
        
        
        def simple_paths_with_node_exclusion(G, source, target, exclude_nodes):
                edge_list = []
                edge_list.extend(G.edges_iter(exclude_nodes))
                G.remove_nodes_from(exclude_nodes)
                value = networkx.all_simple_paths(G, source, target)
                G.add_nodes_from(edge_list)
                return value
        
        print(list(simple_paths_with_node_exclusion(G,0,12,[13])))
        
        • 如果您要进行时间或记忆力测试,我会很高兴听到下面 cmets 中真实数据的结果。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-21
          • 2021-11-30
          • 1970-01-01
          • 2015-05-17
          • 2017-08-21
          • 1970-01-01
          相关资源
          最近更新 更多