以下LINQPad代码生成从0到N的唯一整数的随机序列,并计算从0开始的每个整数的循环长度。为了计算给定整数的循环长度,它从{读取值{1}}索引处的数组等于该整数,而不是取值并从索引读取等于该值,依此类推。当从数组读取的值等于我们开始使用的原始整数时,该过程停止。计算每个周期长度所花费的迭代次数将保存到boxes
。
Dictionary
典型结果如下:
我得到的结果对我来说似乎很奇怪:
我尝试过几种不同的随机函数,比如.NET的const int count = 100;
var random = new Random();
var boxes = Enumerable.Range(0, count).OrderBy(x => random.Next(0, count - 1)).ToArray();
string.Join(", ", boxes.Select(x => x.ToString())).Dump("Boxes");
var stats = Enumerable.Range(0, count).ToDictionary(x => x, x => {
var iterations = 0;
var ind = x;
while(boxes[ind] != x)
{
ind = boxes[ind];
iterations++;
}
return iterations;
});
stats.GroupBy(x => x.Value).Select(x => new {x.Key, Count = x.Count()}).OrderBy(x => x.Key).Dump("Stats");
stats.Sum(x => x.Value).Dump("Total Iterations");
和Random
类,以及从random.org生成的随机数据。所有这些似乎都会产生类似的结果。
我做错了吗?这些结果是从数学角度预期的吗?或者,也许,我使用的随机函数的伪性质有副作用?
答案 0 :(得分:1)
您正在做的是生成大小为count
的随机排列。然后检查排列的属性。如果你的随机数生成器是好的,那么你应该观察random permutations的统计数据。
对于k<count
,长度k的平均周期数为1 / k。平均而言,有1个固定点,1/2个长度为2个周期,1个长度为3个周期,等等。因此,任何长度的平均周期数为1 + 1/2 + 1/3 + ...... + 1 / count~ln count + gamma。 distribution of the number of cycles有很多简洁的属性。偶尔会有很多周期,但2 ^#周期的平均值是count + 1。
您的水桶对应于不同周期长度的数量,最多是周期数,但由于重复周期长度可能会更低。平均而言,重复几个循环长度。即使计数增加到无穷大,并且平均周期数增加到无穷大,重复周期长度的平均数也保持有限。
在统计信息中的排列测试(通常是bootstrapping的示例)中,为了分析某些类型的数据,您将其视为排列的示例。例如,您可能会观察到两个数量,x_i和y_i。通过对xs和ys进行排序,并查看y的索引与第k个x值配对,可以获得排列。然后,将此排列的统计信息与随机排列的属性进行比较。这并没有对底层分布做太多假设,但它仍然可以检测x和y何时相关。因此,知道随机排列会有什么期望是有用的。