【问题标题】:How to generate a list with couples of random integers?如何生成包含一对随机整数的列表?
【发布时间】:2023-03-08 04:48:01
【问题描述】:

我对 Python 和 NetworkX 比较陌生。我需要创建一个类似于Edgelist=[(0,1),(0,3),(1,0),(1,2),(1,4),(2,1),(2,5)] 的列表,其中的元素表示边缘的开始和结束节点(链接),而边缘又是网络的一部分。

我希望 Python 通过从指定的值范围(即0, 999)中随机选择整数值 (start,end) 来创建您在列表中看到的对,而不是手动设置它们,这些值代表节点 ID .然后,我想确保每个节点 ID 在一系列 (start,end) 值中至少包含一次(这意味着我的所有节点都将连接到至少一个其他节点) .

我知道我可以使用random.randint(0, 999),但我不知道如何将它“嵌套”到列表的创建中(也许是 for 循环?)。我希望我有一些代码可以给你看,但这是我第一次尝试使用 NetworkX!

编辑

为了让您直观地了解我的意思,这里有两张图片。第一个是常规网络(又名 lattice),第二个是随机网络。第一个的边缘列表是手动创建的,以便重现一个国际象棋桌,而第二个显示一个边缘列表,它是第一个的(手动)洗牌对应物。 如您所见,节点保存在完全相同的位置。希望这会有所帮助。谢谢!

【问题讨论】:

  • Networkx 有许多用于生成随机网络的算法。使用其中一种可能比您描述的方法更好,特别是因为有许多非常不同种类的随机图具有您所描述的属性。您能告诉我们更多关于您想要的属性的信息吗适合您的网络?
  • 感谢乔尔的提问。我已经建立了一个格子(例如,一个长度分布是恒定值的常规网络 - 所有节点彼此等距)。现在我想通过简单地保持每个节点的坐标并随机选择要连接的节点对来从同一组节点中构建一个随机网络。我知道许多算法,但据我所知,它们似乎都不适合我的需求。
  • 什么度数分布?配置模型似乎是最有可能的选择。 nx.configuration_model([1]*1000) 会得到你所说的你需要的东西,但它可能没有你想要的所有属性。
  • 我认为我在理解您的问题时遇到的挑战是不清楚您想要什么输出。假设 start = 0 end = 2。你能给出一个示例 full 输出吗?我感兴趣的是:有多少“边”?是否允许重复边缘?
  • 顺便说一下,在格子和随机图之间进行插值的常用算法是从格子开始,然后选择随机边对(u,v)(w,x)。然后删除它们并创建新边 (u,x)(w,v)(在检查这些边不存在并且 u!=x, w!=v 之后)。

标签: python list random neural-network networkx


【解决方案1】:

有一个类似的答案,但完整的图表在 - How to generate a fully connected subgraph from node list using python's networkx module

在你的情况下,使用zubinmehtaanswer

import networkx
import itertools

def complete_graph_from_list(L, create_using=None):
    G = networkx.empty_graph(len(L),create_using)
    if len(L)>1:
        if G.is_directed():
            edges = itertools.permutations(L,2)
        else:
            edges = itertools.combinations(L,2)
        G.add_edges_from(edges)
    return G

您可以将图表构建为:

S = complete_graph_from_list(map(lambda x: str(x), range(0,1000)))
print S.edges()

【讨论】:

  • 如果您从其他问题/答案中复制内容,您必须(通过许可)通过说明谁是作者(带有指向他的个人资料的链接)来正确地归属它并且最初的问题/答案是什么。
  • @Bakuriu - 如果我要进行推荐,我会记住还要写下作者的名字。谢谢指出
【解决方案2】:

这是一个 networkx 命令,它将创建一个图,使得每个节点都只有一条边:

import networkx as nx
G = nx.configuration_model([1]*1000)

如果您深入了解它,它会执行以下操作来回答您的问题 - 每个节点将出现在恰好一个边缘。

import random
mylist = random.suffle(range(start,end))
edgelist = []
while mylist:
    edgelist.append((mylist.pop(),mylist.pop()))

你应该保证mylist在弹出之前的长度是均匀的。

【讨论】:

  • 好吧,我也应该说清楚的。我所追求的是一个每个节点在edgelist 中至少出现一次的网络。在我的概念模型中,不允许断开连接的节点。因此,对我来说,说每个节点将恰好出现在一条边上意味着我的所有节点都只有一个链接(例如,它们的度数始终为 1,无论它们位于何处)。构建这样的网络不会产生断开的节点,但也会限制链接的数量,并且可以以某种方式被视为受约束随机性的输出。有意义吗?
  • 所以我的主要问题是 - 你想要多少个链接?某人提供的任何算法都将强制链接的数量来自某个分布。您应该考虑一下您实际需要多少链接,然后创建一个算法来提供它要容易得多。目前尚不清楚您是想要最低限度(我提供的)还是最高限度(nx.complete_graph(1000))或介于两者之间。
  • 好点乔尔。我避免在原始问题中添加所有这些细节以避免发布“圣经”。随机网络的特点是随机连接,因此每个节点的链接数必须是随机的(从 0 到 x),它所连接的节点也是如此。因此,答案介于两者之间,但根据随机过程。
  • 所以一个显而易见的网络就是小世界网络。在您的格子中,使用 nx.double_edge_swap link 随机交换边。随着您越来越多地这样做,您将获得具有相同度数的完全随机网络。这使您可以在晶格和随机网络之间进行插值。或者,使用nx.configuration_model 直接进入随机网络(但请仔细阅读文档,因为它可能有自边缘或重复边缘)。
  • 如果您想确保最终网络已连接(而不是每个节点都有边),请查看nx.connected_double_edge_swap
【解决方案3】:

Python 有一个名为 itertools 的内置库。 示例如下,以了解您如何实现您所提到的:

import itertools

list = [3, 4, 6, 7]
sublist_length = 2
comb = itertools.combinations(list, sublist_length)

这将返回 comb 作为迭代器。

您可以使用comb.next() 来获取迭代器中的下一个元素,或者遍历 for 循环以获得您想要的所有结果,如下所示。

for item in comb:
    print item

应该输出:

(3, 4),
(3, 6),
(3, 7),
(4, 6),
(4, 7),
(6, 7),

希望这能解决你的问题。

【讨论】:

    【解决方案4】:

    对于列表创建,您可以执行以下操作:

    import random
    max = 999
    min = 0
    original_values = range(min, max) # could be arbitrary list
    n_edges = # some number..
    my_edge_list = [(random.choice(original_values), random.choice(original_values)) 
                          for _ in range(n_edges)]
    

    要断言您拥有其中的所有值,您可以执行以下操作

    vals = set([v for tup in my_edge_list for v in tup])
    assert all([v in vals for v in original_values])
    

    断言将确保您的边缘具有正确的表示。尽你最大的努力确保你没有达到那个断言,你可以做几件事。

    1. 从您的整数列表中不替换地进行采样,直到它们全部消失以创建一个“基础网络”,然后随机添加更多内容以满足您的心愿
    2. 使 n_edges 足够高,以便很可能满足您的条件。如果还是不行再试...

    实际上取决于您将网络用于什么以及您希望它具有什么样的结构

    编辑:我已经更新了我的响应,使其对任意值列表更加稳健,而不是需要顺序列表

    【讨论】:

    • 因为不需要断言。这基本上意味着算法被破坏了。
    • 我不同意这一点……尤其是因为选项 1 确保不会发生这种情况。 OP 没有具体说明他们希望网络生成如何发生,如果他们想要一次尝试,是否需要一个完整的图等等。唯一的规定是每个可能的数字都是至少一条边的一部分。两种提议的算法都提供了
    • @haavee 如果我生成一个随机的数字序列,但采取一些步骤来保证它们具有先验属性,那么我可能会偏向我的结果。要在这些情况下获得无偏样本,我应该生成序列然后进行测试。
    【解决方案5】:
    random.seed(datetime.datetime.now()) 
    
    from random import randint
    # ot generate 100 tuples with randints in range 0-99
    li = [(randint(0,99),randint(0,99)) for i in range(100)]
    print(li)
    
    [(80, 55), (3, 10), (66, 65), (26, 23), (8, 72), (83, 25), (24, 99), (72, 9), (52, 76), (72, 68), (67, 25), (72, 18), (94, 62), (7, 62), (49, 94), (29, 89), (11, 38), (52, 51), (19, 32), (20, 85), (56, 61), (4, 40), (97, 58), (82, 2), (50, 82), (77, 5), (2, 9), (2, 46), (39, 4), (74, 40), (69, 15), (1, 77), (45, 58), (80, 59), (85, 80), (27, 80), (81, 4), (22, 33), (77, 60), (75, 87), (43, 36), (60, 34), (90, 54), (75, 3), (89, 84), (51, 93), (62, 64), (81, 50), (15, 60), (33, 97), (42, 62), (83, 26), (13, 33), (41, 87), (29, 63), (4, 32), (6, 14), (79, 73), (95, 4), (41, 16), (96, 64), (15, 28), (35, 13), (35, 82), (77, 16), (63, 27), (75, 37), (11, 52), (21, 35), (37, 96), (9, 86), (83, 11), (5, 42), (34, 32), (17, 8), (65, 55), (58, 19), (90, 40), (18, 75), (29, 14), (0, 11), (25, 68), (34, 52), (22, 8), (12, 53), (16, 49), (73, 54), (78, 80), (74, 60), (40, 68), (69, 20), (37, 38), (74, 60), (53, 90), (25, 48), (44, 52), (49, 27), (28, 35), (29, 94), (35, 60)]
    

    【讨论】:

    • 这是一个开始,但这并不能保证每个 ID 都存在。
    • 是的,约翰,这是一个关键点。我的最终目标是建立一个拥有 10000 个节点的网络,而对于我的目标来说,即使有几个断开连接的节点也是毫无意义的。所以我必须找到一种方法来检查完整的连通性。而且,当然,不允许自链接(列表中每个括号的起点和终点不能重合)。感谢您强调这一点!
    【解决方案6】:

    这是一种解决方案,它首先生成随机的节点群 (pop1),然后对其进行洗牌 (pop2) 并将它们组合成对列表。

    注意:此方法只产生每个节点恰好出现一次start 和恰好出现一次end 的顶点,因此可能不是您想要的。另一种方法见下文

    import random, copy
    
    random.seed() # defaults to time.time() ...
    # extract a number of samples - the number of nodes you want
    pop1 = random.sample(xrange(1000), 10)
    pop2 = copy.deepcopy( pop1 )
    random.shuffle( pop2 )
    # generate pairs from the same population - this guarantees your constraint
    pairs = zip( pop1, pop2 )
    
    print pairs
    

    输出:

    [(17, 347), (812, 688), (347, 266), (731, 342), (342, 49), (904, 17), (49, 731), (50, 904), (688, 50), (266, 812)]
    

    这是另一种方法

    这允许重复出现节点。 这个想法是从同一种群中抽取startend 节点:

    import random
    random.seed()
    population = range(10) # any population would do
    # choose randomly from the population for both ends
    # so you can have duplicates
    pairs = [(random.choice(population), random.choice(population) for _ in xrange(100)]
    print pairs[:10]
    

    输出:

    [(1, 9), (7, 1), (8, 6), (4, 7), (6, 2), (7, 3), (0, 2), (1, 0), (8, 3), (8, 3)]
    

    【讨论】:

    • 您的第一种方法存在错误。尝试使用 start=0, end = 1。你会得到 (0,0) (1,1) 一半的时间,这违反了请求的约束。更一般地,对于较大值的一小部分,您将在生成的样本的 1/e 中遇到连接到自身的节点。
    • 您的第二种方法也是一个错误。正如您在输出中看到的那样,5 没有出现,这违反了 OP 给出的约束。
    • 嗯,我的第一个方法确实满足了这些限制。 OP 没有提到节点是否应该出现不止一次 - 即在不同的边缘。
    • OP提到他们应该连接到其他节点。如果 (1,1) 边缘符合 OP 的要求,我会感到震惊。
    • 好吧,您的问题描述中缺少的另一件事是您想要多少 。节点是一回事,但如果你看一下图表(感谢那些),第一个有 12 条边,第二条有 17 条(如果我计算正确的话......)。
    猜你喜欢
    • 2016-10-08
    • 2010-09-12
    • 2023-04-11
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-06
    相关资源
    最近更新 更多