簡體   English   中英

如何隨機洗牌具有比PRNG時期更多排列的列表?

[英]How to randomly shuffle a list that has more permutations than the PRNG's period?

我有一個包含大約3900個元素的列表,我需要隨機置換以生成統計分布。 我環顧四周, 用Python random.shuffle找到了這個最大長度列表,它解釋了Python中PRNG的周期是2**19937-1 ,這導致一個列表的最大長度為2080然后才變得不可能生成所有可能的排列。 我只生成300-1000個列表的排列,因此我不太可能產生重復的排列,但是,由於這產生了統計分布,我希望將所有可能的排列作為潛在樣本。

PR的期限比MT長,但很難找到。

獲得所有3090! 組合,你需要40,905位的熵。 那大概是5kb。 你應該能夠從random.org這樣的地方抓取一大塊字節,沒有任何問題。 要獲得精確平衡,您必須添加一些並進行拒絕采樣。 即,一次抓取12位(0..4095),並拒絕高於當前循環索引的數字。 這可能會增加所需的位數,但可能不會超過8kb。

我同意@ user2357112它不太可能是一個真正的問題 - 但似乎你應該能夠以這樣的方式使用標准random模塊,使得所有排列至少是可能的。

你可以做一個分而治之的方法。 使用初始種子將列表分成2個列表,每個列表大約2000個。 這種分區的數量大致為C(4000,2000) ,大約為1.66 x 10^1202 這比周期少,這表明至少可以使用random.sample()生成所有這樣的分區。 然后 - 重新設置隨機數發生器並置換上半部分。 然后 - 第二次重新訓練並將下半場置換。 也許在重新設定之前幾乎沒有時間延遲,因此您不會遇到涉及系統時鍾分辨率的問題。 您還可以嘗試將初始列表隨機分區為更大數量的較小列表。

在數學上,很容易看出,如果您將列表隨機分區為子列表,以便每個分區具有相同的可能性,然后以這樣的方式置換每個子列表,使得所有子列表排列同樣可能,並將這些子列表排列粘合在一起以獲得整個列表排列,然后所有整列排列都是同樣可能的。

這是一個實現:

import random, time

def permuted(items, pieces = 2):
    sublists = [[] for i in range(pieces)]
    for x in items:
        sublists[random.randint(0,pieces-1)].append(x)
    permutedList = []
    for i in range(pieces):
        time.sleep(0.01)
        random.seed()
        random.shuffle(sublists[i])
        permutedList.extend(sublists[i])
    return permutedList

我不確定time.sleep(0.01)是否真的需要。 我擔心的是,如果種植在一毫秒內發生,那么在某些系統上可能會使用相同的種子。

作為最后的評論,僅僅因為上述函數(具有合適的pieces選擇)不能通過簡單的計數參數(比較排列的數量與初始狀態的數量)來顯示錯過某些排列,這不在本身就構成了所有排列實際上都是可能的證明。 這將需要對隨機數生成器,播種它的散列函數以及混洗算法進行更詳細的分析。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM