Algorithm 你从这个坏的随机洗牌中得到了什么分布?

Algorithm 你从这个坏的随机洗牌中得到了什么分布?,algorithm,language-agnostic,math,random,shuffle,Algorithm,Language Agnostic,Math,Random,Shuffle,著名的Fisher-Yates shuffle算法可用于随机排列长度为N的数组: For k = 1 to N Pick a random integer j from k to N Swap A[k] and A[j] 我被一再告知不要犯的一个常见错误是: For k = 1 to N Pick a random integer j from 1 to N Swap A[k] and A[j] 也就是说,不是从k到N选取一个随机整数,而是从1到N选取一个随机

著名的Fisher-Yates shuffle算法可用于随机排列长度为N的数组:

For k = 1 to N
    Pick a random integer j from k to N
    Swap A[k] and A[j]
我被一再告知不要犯的一个常见错误是:

For k = 1 to N
    Pick a random integer j from 1 to N
    Swap A[k] and A[j]
也就是说,不是从k到N选取一个随机整数,而是从1到N选取一个随机整数


如果你犯了这个错误怎么办?我知道结果的排列不是均匀分布的,但我不知道对结果的分布有什么保证。特别是,有人对元素最终位置的概率分布有一个表达式吗?

有一个描述和示例,说明在这种情况下会发生什么。

一种经验方法。

让我们在Mathematica中实现错误的算法:

p = 10; (* Range *)
s = {}
For[l = 1, l <= 30000, l++, (*Iterations*)
   a = Range[p];
   For[k = 1, k <= p, k++, 
     i = RandomInteger[{1, p}];
     temp = a[[k]];
     a[[k]] = a[[i]];
     a[[i]] = temp
   ];
   AppendTo[s, a];
]  
让我们在结果数组中取三个位置,并绘制该位置每个整数的频率分布:

r = SortBy[#, #[[1]] &] & /@ Tally /@ Transpose[s]  
对于位置1,频率分布为:

位置5(中间)

第10位(最后一位):

这里是所有位置的分布图:

在这里,您可以更好地统计8个职位:

一些观察结果:

  • 对于所有位置 “1”是相同的(1/n)
  • 概率矩阵是对称的 关于大反对角线
  • 所以,最后一个数的概率 位置也是一致的(1/n)
您可以从同一点(第一个特性)和最后一条水平线(第三个特性)的所有直线的起点处查看这些特性

第二个属性可以从以下矩阵表示示例中看到,其中行表示位置,列表示占用人数,颜色表示实验概率:

对于100x100矩阵:

{{  1/n,    1/n      , ...},
 {... .., A007318, ....},
 {... .., ... ..., ..},
 ... ....,
 {A129687, ... ... ... ... ... ... ..},
 {A131084, A028326 ... ... ... ... ..},
 {A028326, A131084 , A129687 ... ....}}

编辑

为了好玩,我计算了第二个对角线元素的精确公式(第一个是1/n)。其余的都可以做,但工作量很大

h[n_] := (n-1)/n^2 + (n-1)^(n-2) n^(-n)
从n=3到6验证的值({8/27、57/256、564/312517105/46656})

编辑

在@wnoise answer中计算出一点一般的显式计算,我们可以得到更多的信息

将1/n替换为p[n],因此计算保持未计算,例如,对于矩阵的第一部分,我们得到n=7(单击以查看更大的图像):

在与其他n值的结果进行比较后,让我们确定矩阵中的一些已知整数序列:

{{  1/n,    1/n      , ...},
 {... .., A007318, ....},
 {... .., ... ..., ..},
 ... ....,
 {A129687, ... ... ... ... ... ... ..},
 {A131084, A028326 ... ... ... ... ..},
 {A028326, A131084 , A129687 ... ....}}
你可以在精彩的视频中找到这些序列(在某些情况下有不同的符号)


解决一般问题更难,但我希望这是一个开始

多么可爱的问题!我希望我有一个完整的答案

费舍尔·耶茨(Fisher Yates)善于分析,因为一旦它决定了第一个元素,它就不去管它了。有偏见的人可以在任何地方反复交换一个元素

我们可以用马尔可夫链的方法来分析这个问题,通过将行为描述为线性作用于概率分布的随机转移矩阵。大多数元素被单独保留,对角线通常为(n-1)/n。在过程k中,当它们没有被单独留下时,它们会被元素k交换(如果它们是元素k,则是一个随机元素)。这在k行或k列中都是1/(n-1)。行和列k中的元素也是1/(n-1)。对于从1到n的k,将这些矩阵相乘很容易

我们确实知道,最后一位的元素最初出现在任何地方的可能性都是相同的,因为最后一位的元素与其他元素交换最后一位的可能性是相同的。类似地,第一个元素同样可能被放置在任何位置。这种对称性是因为转置颠倒了矩阵乘法的顺序。事实上,矩阵是对称的,因为行i与列(n+1-i)相同。除此之外,这些数字并没有显示出多少明显的规律。这些精确解确实与belisarius运行的模拟结果一致:在插槽i中,获得j的概率随着j上升到i而降低,在i-1处达到其最低值,然后在i处跳到其最高值,直到j达到n为止

在Mathematica中,我用

 step[k_, n_] := Normal[SparseArray[{{k, i_} -> 1/n, 
                      {j_, k} -> 1/n, {i_, i_} -> (n - 1)/n} , {n, n}]]
(我没有在任何地方找到它的文档,但使用了第一个匹配规则。) 最终过渡矩阵可通过以下公式计算:

Fold[Dot, IdentityMatrix[n], Table[step[m, n], {m, s}]]
ListDensityPlot
是一个有用的可视化工具

编辑(贝里萨里乌斯)

只是确认一下。以下代码给出了与@Eelvex答案中相同的矩阵:

step[k_, n_] := Normal[SparseArray[{{k, i_} -> (1/n), 
                      {j_, k} -> (1/n), {i_, i_} -> ((n - 1)/n)}, {n, n}]];
r[n_, s_] := Fold[Dot, IdentityMatrix[n], Table[step[m, n], {m, s}]];
Last@Table[r[4, i], {i, 1, 4}] // MatrixForm

我知道我以前见过这个问题

“”答案中有很多好东西,尤其是链接到

正如您可能已经猜到的,根据@belisarius的答案,确切的分布高度依赖于要洗牌的元素数量。以下是阿特伍德的6元素甲板图:

您提到的“常见错误”是通过随机换位进行洗牌。Diaconis和Shahani在年对这个问题进行了详细研究。他们对停止时间和收敛到一致性进行了完整的分析。如果你找不到报纸的链接,请给我发一封电子邮件,我可以给你转发一份。这实际上是一本有趣的读物(就像大多数波斯·迪亚科尼斯的论文一样)


如果数组有重复的条目,则问题略有不同。作为一个无耻的插件,我、Diaconis和Soundarararajan在的附录B中解决了这个更普遍的问题。

您可以使用。让矩阵A(i,j)描述卡最初在位置i结束在位置j的概率。然后,如果
i==k
function FisherYatesDurstenfeldKnuthshuffle( array ) {
    var pickIndex, arrayPosition = array.length;
    while( --arrayPosition ) {
        pickIndex = Math.floor( Math.random() * ( arrayPosition + 1 ) );
        array[ pickIndex ] = [ array[ arrayPosition ], array[ arrayPosition ] = array[ pickIndex ] ][ 0 ];
    }
}