【问题标题】:How to create random graph where each node has at least 1 edge using Networkx如何使用 Networkx 创建每个节点至少有 1 条边的随机图
【发布时间】:2020-05-22 15:23:40
【问题描述】:

我已经设法创建了一个随机无向加权图,用于使用 Dijkstra 算法进行测试,但是如何才能使每个节点至少有一条边将它们连接到图?

我正在使用 Networkx,我的图形生成器如下:

import networkx as nx
import random

random.seed()
nodes = random.randint(5,10)
seed = random.randint(1,10)
probability = random.random()
G = nx.gnp_random_graph(nodes,probability,seed, False)
for (u, v) in G.edges():
    G.edges[u,v]['weight'] = random.randint(0,10)

这很好地创建了图表,我设法绘制它,所以我可以实际看到它,我的问题是边缘创建的概率。我不希望它太高以至于所有节点都具有最大数量的边,但是设置一个低值可能会导致节点的边数为 0。有没有办法确保每个节点至少有一条边?

【问题讨论】:

    标签: python networkx graph-theory weighted-graph


    【解决方案1】:

    似乎没有NetworkX graph generator 可以直接生成满足此类要求的图表。

    但是,您可以调整一点点 nx.gnp_random_graph 中使用的方法,这样我们就不会在所有可能的边组合中以随机概率设置一条边,而是为每个节点添加一条边随机,然后然后p的概率添加剩余边。

    以下方法不仅会生成每个节点至少有一条边的图,还会生成connected graph。这在 进一步说明 -

    中解释如下
    def gnp_random_connected_graph(n, p):
        """
        Generates a random undirected graph, similarly to an Erdős-Rényi 
        graph, but enforcing that the resulting graph is conneted
        """
        edges = combinations(range(n), 2)
        G = nx.Graph()
        G.add_nodes_from(range(n))
        if p <= 0:
            return G
        if p >= 1:
            return nx.complete_graph(n, create_using=G)
        for _, node_edges in groupby(edges, key=lambda x: x[0]):
            node_edges = list(node_edges)
            random_edge = random.choice(node_edges)
            G.add_edge(*random_edge)
            for e in node_edges:
                if random.random() < p:
                    G.add_edge(*e)
        return G
    

    样本运行 -

    如下例所示,即使分配一个非常低的概率,得到的图是connected

    from itertools import combinations, groupby
    import networkx as nx
    import random
    
    nodes = random.randint(5,10)
    seed = random.randint(1,10)
    probability = 0.1
    G = gnp_random_connected_graph(nodes,probability)
    
    plt.figure(figsize=(8,5))
    nx.draw(G, node_color='lightblue', 
            with_labels=True, 
            node_size=500)
    

    nodes = 40
    seed = random.randint(1,10)
    probability = 0.001
    G = gnp_random_connected_graph(nodes,probability)
    
    plt.figure(figsize=(10,6))
    
    nx.draw(G, node_color='lightblue', 
            with_labels=True, 
            node_size=500)
    


    补充说明 -

    上述方法,不仅保证了每个节点至少有一条边,而且如前所述,结果图是连通的。这是因为我们使用itertools.combinations(range(n_nodes), 2) 的结果为每个节点设置了至少一条边。举个例子可能会更清楚:

    edges = combinations(range(5), 2)
    for _, node_edges in groupby(edges, key=lambda x: x[0]):
        print(list(node_edges))
    
    #[(0, 1), (0, 2), (0, 3), (0, 4)]
    #[(1, 2), (1, 3), (1, 4)]
    #[(2, 3), (2, 4)]
    #[(3, 4)]
    

    在这种情况下,我们在每种情况下设置至少一个边,每次迭代时从可用边中获取random.choice,这些边是尚未设置的边。这是使用itertools.combinations 的结果设置边缘的结果。对于无向图,如果这些边之前已经以概率p 添加,那么在每次迭代中迭代所有现有边是没有意义的。

    这不是采用permutations 的情况(请参阅directed graph case 的源代码)。在有向图的情况下,按照这种方法无法保证连通性,因为可能有两个节点通过相反方向的两条边连接,并且与图的其余部分隔离。所以应该采用另一种方法(也许扩展上述想法)。

    【讨论】:

    • 非常感谢!!我也感谢您的解释!
    • 谢谢你,有什么方法可以在networkx文档中宣传这个吗?
    • seed = random.randint(1,10) 是否以某种方式被使用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 2015-06-04
    • 2015-01-02
    • 2014-09-06
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    相关资源
    最近更新 更多