僞隨機數對大列表的完全性洗牌

對一個列表(一維數組)的完全性洗牌(shuffle)操作,是要讓其元素每種排列模式等概率出現。

列表元素個數爲n,那麼其全排列的數目就是n的階乘“n!”。

僞隨機數是有周期的,設週期爲m。那基於僞隨機數映射的元素排列模式也只會有m種。

當列表元素很多,n! 會是個天文數字,大於僞隨機數週期,那樣永遠有一部分排列模式無法出現。

python標準庫函數random.shuffle(x)就說明了——“請注意,即使對於小的len(x),x的排列總數也可以快速增長,大於大多數隨機數生成器的週期。 這意味着長序列的大多數排列永遠不會產生。 例如,長度爲2080的序列是可以在 Mersenne Twister 隨機數生成器的週期內擬合的最大序列。”

要對大於僞隨機數週期的大列表完全性shuffle,怎麼辦呢

我採用的辦法是多輪洗牌,每輪用不同質數週期的僞隨機數序列。這些週期的乘積大於列表元素全排列數目“n!”,就保證了完全性shuffle的完成。

我寫了這個算法的實現python包,源碼放在GitHub上,complete_shuffle

已經發布到了PyPI上,可以很方便的安裝分發:

pip install complete-shuffle

此包還包括了Sattolo算法實現的對列表隨機循環排列。算法介紹見Sattolo算法

等概率生成列表的“全錯位排列”函數,功能實現了可以用於含重複元素的列表。我使用的是優化的接受-拒絕採樣算法,時間複雜度爲O(n)。生成均勻分佈“全錯位排列”還有一種優化算法,見Generating Random Derangements。此算法時間複雜度也是O(n),但聲稱其時間複雜度的常數項較低。我看意義不大。

順便說python 3.9版已聲明 random.shuffle() 的 random 形參將被棄用

我寫這個包中函數就有等同於 random.shuffle() 的 random 的形參。可以替代標準庫random.shuffle()函數了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章