Networkx图:查找给定节点集中的任何节点与另一组节点之间是否存在路径

时间:2013-05-02 09:51:06

标签: python graph nodes networkx edges

我有一个大的无向图,有数十万个节点和数万个边。我有两个不同的问题:

1)对于一组节点N =(节点[1],节点[2],节点[3],节点[4],节点[5]),例如,M =(节点[1001],节点[1002],节点[1003],节点[1004],节点[1005])在N中的任何节点与M中的任何节点之间是否存在路径?

我知道存在nx.path.bidirectional_dijkstra()函数,但要使用它我必须测试所有N * M组合是多余的(因为许多节点会被多次查询),并且因为在实践中N / M的长度可能是数千,这是不实际的。

2)一个稍微独立的问题,但有没有办法获得从N到M的所有路径列表?

我对如何“推出自己的”解决方案有一个粗略的想法,但我想它会比有人已经这样做慢很多倍,但没有图论的背景我不知道甚至知道我需要搜索什么!感谢。

2 个答案:

答案 0 :(得分:2)

  1. 这样的事情应该有效:

    def is_there_a_path(_from, _to):
        visited = set() # remember what you visited
        while _from:
            from_node = _from.pop(0) # get a new unvisited node
            if from_node in _to:
                # went the path
                return True
            # you need to implement get_nodes_referenced_by(node)
            for neighbor_node in get_nodes_referenced_by(from_node): 
                # iterate over all the nodes the from_node points to
                if neighbor_node not in visited:
                    # expand only unvisited nodes to avoid circles
                    visited.add(neighbor_node)
                    _from.append(neighbor_node)
        return False
    
  2. 您可以通过附加路径而不是neighbor_node从1.中的函数构建此函数,但需要花费更多时间并且可能出现圆圈。在执行yield

  3. 时,使用return代替for path in is_there_a_path(_from, _to):获取无穷无尽的路径

    这是上面的算法,它遍历ruby中的对象图,并找到从self到另一个对象的路径,返回路径:

    class Object
      #
      # breadth first search for references from the given object to self
      #
      def reference_path_to(to_object, length, trace = false)
        paths = [[to_object]]
        traversed = IdentitySet.new
        traversed.add(to_object)
        start_size = 1 if trace
        while not paths.empty? and paths.first.size <= length
          references = paths[0][0].find_references_in_memory
          # if we print here a SecurityError mey occur
          references.each{ |reference| 
            return [reference] + paths[0] if reference.equal?(self)
            unless traversed.include?(reference) or paths.any?{ |path| reference.equal?(path)}
              paths.push([reference] + paths[0])
              traversed.add(reference)
            end
          }
          if trace and start_size != paths[0].size
            puts "reference_path_length: #{paths[0].size}"
            start_size = paths[0].size
          end
          paths.delete_at(0)
        end
        return nil
      end
    end # from https://github.com/knub/maglevrecord/blob/60082fd8c16fa7974166b96e5243fc0a176d172e/lib/maglev_record/tools/object_reference.rb
    

    Python算法应该与我认为的ruby算法大致相同。

答案 1 :(得分:0)

1)将一个带有边缘的节点x添加到N中的每个节点,将一个节点y添加到M中的每个节点。然后检查是否有x - y路径。注意 - 确保xy不是节点。

G.add_edges_from([('x',node) for node in N])
G.add_edges_from([(node,'y') for node in M])
nx.has_path(N,M) #true if there was an M to N path

2)

augmented_paths = nx.all_simple_paths(G,source=x,target=y)

(这会产生一个发电机)。

for augmentedpath in nx.all_simple_paths(G, source=x, target=y):
    path = augmentedpath[1:-1] #don't want the x and y included
    print path