【问题标题】:Add and delete a random edge in networkx在networkx中添加和删除随机边
【发布时间】:2017-12-13 12:24:30
【问题描述】:

我在 python 中使用 NetworkX。给定任何无向和未加权的图,我想遍历所有节点。对于每个节点,我想添加一个随机边和/或删除该节点的现有随机边,概率为 p。有没有一种简单的方法可以做到这一点?非常感谢!

【问题讨论】:

  • 删除随机现有边更容易,我可以将节点的现有邻居放入列表并使用 random.choice 从中选择一个节点并删除该边。但是,添加一个随机的不存在的边缘我仍然没有一个好的方法。
  • 要在节点之间随机添加边,您可以遍历图以获取节点 i 并从图中随机选择另一个节点 j ij之间没有边,则以概率p添加边

标签: python random graph networkx


【解决方案1】:

在networkx中创建一个新的随机边

让我们建立一个测试图:

import networkx as nx
import random
import matplotlib.pyplot as plt

graph = nx.Graph()
graph.add_edges_from([(1,3), (3,5), (2,4)])
nx.draw(graph, with_labels=True)
plt.show()

现在我们可以从图中的非边列表中选择一条随机边。目前还不完全清楚你提到的概率是多少。既然你添加了一条评论说你想使用random.choice,我会坚持下去。

def random_edge(graph, del_orig=True):
    '''
    Create a new random edge and delete one of its current edge if del_orig is True.
    :param graph: networkx graph
    :param del_orig: bool
    :return: networkx graph
    '''
    edges = list(graph.edges)
    nonedges = list(nx.non_edges(graph))

    # random edge choice
    chosen_edge = random.choice(edges)
    chosen_nonedge = random.choice([x for x in nonedges if chosen_edge[0] == x[0]])

    if del_orig:
        # delete chosen edge
        graph.remove_edge(chosen_edge[0], chosen_edge[1])
    # add new edge
    graph.add_edge(chosen_nonedge[0], chosen_nonedge[1])

    return graph

使用示例:

new_graph = random_edge(graph, del_orig=True)

nx.draw(new_graph, with_labels=True)
plt.show()

如果您需要,我们仍然可以在 random.choice 的边缘上添加概率分布(例如使用 numpy.random.choice())。

【讨论】:

    【解决方案2】:

    给定一个节点 i,要添加不重复的边,您需要知道 (1) i 中的哪些边已经存在,然后计算 (2) i 中不存在的候选边集.对于删除,您已经在注释中定义了一个方法 - 它仅基于 (1)。 这是一个基于列表理解提供一轮随机添加和删除的函数

    def add_and_remove_edges(G, p_new_connection, p_remove_connection):    
        '''    
        for each node,    
          add a new connection to random other node, with prob p_new_connection,    
          remove a connection, with prob p_remove_connection    
    
        operates on G in-place    
        '''                
        new_edges = []    
        rem_edges = []    
    
        for node in G.nodes():    
            # find the other nodes this one is connected to    
            connected = [to for (fr, to) in G.edges(node)]    
            # and find the remainder of nodes, which are candidates for new edges   
            unconnected = [n for n in G.nodes() if not n in connected]    
    
            # probabilistically add a random edge    
            if len(unconnected): # only try if new edge is possible    
                if random.random() < p_new_connection:    
                    new = random.choice(unconnected)    
                    G.add_edge(node, new)    
                    print "\tnew edge:\t {} -- {}".format(node, new)    
                    new_edges.append( (node, new) )    
                    # book-keeping, in case both add and remove done in same cycle  
                    unconnected.remove(new)    
                    connected.append(new)    
    
            # probabilistically remove a random edge    
            if len(connected): # only try if an edge exists to remove    
                if random.random() < p_remove_connection:    
                    remove = random.choice(connected)    
                    G.remove_edge(node, remove)    
                    print "\tedge removed:\t {} -- {}".format(node, remove)    
                    rem_edges.append( (node, remove) )    
                    # book-keeping, in case lists are important later?    
                    connected.remove(remove)    
                    unconnected.append(remove)    
        return rem_edges, new_edges    
    

    要查看此功能的实际效果:

    import networkx as nx
    import random
    import matplotlib.pyplot as plt
    
    p_new_connection = 0.1
    p_remove_connection = 0.1
    
    G = nx.karate_club_graph() # sample graph (undirected, unweighted)
    # show original
    plt.figure(1); plt.clf()
    fig, ax = plt.subplots(2,1, num=1, sharex=True, sharey=True)
    pos = nx.spring_layout(G)
    nx.draw_networkx(G, pos=pos, ax=ax[0])
    
    # now apply one round of changes
    rem_edges, new_edges = add_and_remove_edges(G, p_new_connection, p_remove_connection)
    
    # and draw new version and highlight changes
    nx.draw_networkx(G, pos=pos, ax=ax[1])
    nx.draw_networkx_edges(G, pos=pos, ax=ax[1], edgelist=new_edges,
                           edge_color='b', width=4)
    # note: to highlight edges that were removed, add them back in;
    # This is obviously just for display!
    G.add_edges_from(rem_edges)
    nx.draw_networkx_edges(G, pos=pos, ax=ax[1], edgelist=rem_edges,
                           edge_color='r', style='dashed', width=4)
    G.remove_edges_from(rem_edges)
    
    plt.show() 
    

    您应该会看到类似这样的内容。

    请注意,您也可以对邻接矩阵做类似的事情, A = nx.adjacency_matrix(G).todense()(它是一个 numpy 矩阵,因此像 A[i,:].nonzero() 这样的操作是相关的)。如果您有非常大的网络,这可能会更有效。

    【讨论】:

      猜你喜欢
      • 2023-02-25
      • 1970-01-01
      • 2019-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 2021-05-05
      • 2012-10-10
      相关资源
      最近更新 更多