繁体   English   中英

如何使用 Networkx 创建每个节点至少有 1 条边的随机图

[英]How to create random graph where each node has at least 1 edge using Networkx

我已经设法创建了一个随机无向加权图,用于使用 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)

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

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

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

下面的方法不仅生成了一个图,其中每个节点至少有一条边,而且还生成了一个连通图 这在下面的进一步说明中进行了解释-

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

样品运行-

如以下示例所示,即使分配非常低的概率,结果图也是连接的:

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的情况(参见有向图案例的源代码)。 在有向图的情况下,这种方法无法保证连通性,因为可能有两个节点通过相反方向的两条边连接,并且与图的 rest 隔离。 所以应该遵循另一种方法(也许扩展上述想法)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM