【问题标题】:Finding the n-degree neighborhood of a node查找节点的 n 度邻域
【发布时间】:2014-05-09 16:20:53
【问题描述】:

我是 networkx 的新手,实际上对如何有效地找到节点的 n 度邻域有点困惑。节点 v_i 的 n 度邻域是距离 v_i 正好 n 跳的节点集合。给定一个指定的 n,我需要找到图/网络中每个节点的 n 度邻域。

假设我有下图,我想找到节点 v1 的 n=1 邻域。那将是v2和v3。接下来假设我想找到节点 v1 的 n=2 邻域,那么就是 v4。

【问题讨论】:

    标签: python algorithm graph-algorithm networkx


    【解决方案1】:

    使用 adj 矩阵找到 n 跳邻居

    import networkx as nx
     
    G = nx.Graph()
    G.add_edges_from([('v1','v2'),('v2','v4'),('v1','v3')])
    
    def n_neighbor(G, id, n_hop):
        node = [id]
        node_visited = set()
        neighbors= []
        
        while n_hop !=0:
            neighbors= []
            for node_id in node:
                node_visited.add(node_id)
                neighbors +=  [id for id in G.neighbors(node_id) if id not in node_visited]
            node = neighbors
            n_hop -=1
            
            if len(node) == 0 :
                return neighbors 
            
        return list(set(neighbors))
    
    print(n_neighbor(G, 'v2', 1))
    

    功能:

    G: Networkx Graph
    id : Root node Id to find neighbors
    n_hop : hop length
    

    返回:

    Neighbor list
    

    输出:

    print(n_neighbor(G, 'v2', 1)) 
    ['v1', 'v4']
    

    【讨论】:

    • 在某些情况下,n_neighbor() 返回不应该出现的重复邻居节点。经过测试和使用,在函数中将return neighbors 替换为return list(set(neighbors)) 会产生一个唯一列表。
    【解决方案2】:

    nx.descendants_at_distance() 可以解决问题(尽管是为有向图设计的):

    G = nx.Graph()
    G.add_edges_from([('v1', 'v2'), ('v2', 'v4'), ('v2', 'v4'), ('v1', 'v3')])
    nx.descendants_at_distance(G, 'v1', distance=2) # returns {'v4'}
    

    来自source code comment

    这基本上是 BFS,除了队列只存储 每次迭代时距源的“current_distance”处的节点。

    【讨论】:

      【解决方案3】:

      当您在图上执行广度优先搜索时,从根节点 r 开始 - 节点被认为与 r 的距离越来越大。

      因此,您只需要在执行 BFS 时跟踪节点的级别,请参阅http://en.wikipedia.org/wiki/Level_structure 以获得更全面的讨论。

      【讨论】:

        【解决方案4】:
        import networkx as nx
        G = nx.Graph()
        G.add_edges_from([('v1','v2'),('v2','v4'),('v1','v3')])
        
        def neighborhood(G, node, n):
            path_lengths = nx.single_source_dijkstra_path_length(G, node)
            return [node for node, length in path_lengths.iteritems()
                            if length == n]
        
        print(neighborhood(G, 'v1', 1))
        # ['v2', 'v3']
        print(neighborhood(G, 'v1', 2))
        # ['v4']
        

        【讨论】:

        • 你在python中做的return [trick]中的代码技巧叫什么名字?我是 python 新手,我想了解这意味着什么。我想了解更多。
        • 返回的表达式称为list comprehension
        【解决方案5】:

        查找给定节点的 n 个邻居的最有效方法是使用深度优先搜索: http://en.wikipedia.org/wiki/Depth-first_search。下面的函数返回 start 的所有距离的邻居。但是,如果您需要找到所有节点的 n 个邻居,则对所有节点使用此函数并不是最有效的解决方案。相反,可以将此函数仅用于每个连接组件中的起始节点,并计算其他节点相对于起始节点的 n 邻居,但这会更加复杂。

        import networkx as nx
        
        def n_neighbor(G, start):
        
            #  {distance : [list of nodes at that distance]}
            distance_nodes = {}
        
            # nodes at distance 1 from the currently visited ones
            next_shell = G.neighbors(start)
        
            # set of all visited nodes
            visited=set()
            visited.add(start)
        
            # how fare we are from start
            distance = 0
        
            # until we run out of nodes
            while len(next_shell) > 0:
        
                # this will be the next shell
                shell_after_this = []
        
                # update distance
                distance += 1
                distance_nodes[distance] = []
        
                # update visited and distance_nodes
                for node in next_shell:
                    visited.add(node)
                    distance_nodes[distance].append(node)
        
        
                # compute shell_after_this
                for node in next_shell:
                    # add neighbors to shell_after_this
                    # if they have not been visited already
                    for neighbor in G.neighbors(node):
                        if neighbor not in visited:
                            shell_after_this.append(neighbor)
        
                # we repeat with the new_shell
                next_shell = set(shell_after_this)
        
            return distance_nodes
        
        
        # example 
        G=nx.Graph()
        
        G.add_edge(1,2)
        G.add_edge(1,3)
        G.add_edge(2,3)
        G.add_edge(2,4)
        G.add_edge(3,5)
        G.add_edge(5,17)
        G.add_edge(2,6)
        
        print n_neighbor(G, 1)    
        

        【讨论】:

        • 所以我不应该使用你建议的,而是使用深度优先搜索?!!
        • 我提出的是深度优先搜索的实现,我还记录了与源的距离。
        • 另外,深度优先搜索并不是查找起始节点 k 跳内所有节点的好工具
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-03
        • 1970-01-01
        相关资源
        最近更新 更多