我们在启发式乃至计算机模拟中都要产生大量的随机数,而随机数的产生并非像大家想想的那样的简单,
以下就是一个简单的随机数产生问题,相信做过启发式算法以及模拟的同学都可能遇到:
例如我们求解一个优化问题,而问题的变量要求其和等于1,即:
X1+X2+X3+...+X10 = 1;
要求X1...X10符合均匀分布。
这个随机数产生问题解法并不唯一,但产生的结果却大相径庭,其中可能包含一定的统计学知识。
下面我们说一说我所知道的两种策略:
策略一:
产生10个0到1间的均匀分布随机数,接着我们求这10个数的和;并将每个数除以总和,即可巧妙的保证
除的结果的和为1。
当我第一次看到这种方法时,觉得很巧妙;在感叹方法巧妙的同时感觉这种方法并不能保证所得的10个随机数满足均匀分布,而且结果的差别很大,随机数大量的分布在0.1附近(似乎这也合常理),下面是经过1000次模拟所得的结果,见直方图:
今天,也是在某博客上看到这个问题,在有人提到这个方法后博主回应并不能满足均匀的条件;回想一下学过的统计知识,我发现对于等式:
X1+X2+...X10=1;
其隐隐的包含着一个信息:
产生的随机数并非10个自由度,进一步说,如果我们确定了其中的9个,那么第10个变量实质上已经确定了。继而会想到以前曾有过的一个更为直觉的想法:
我们将0-1这个区间看成一个线段,我们不如考虑怎样将这条线段分成10份作为问题的转化,于是接下来的事情就简单多了,我们产生9个点,并以这9个点做一个对线段的剖分,得到的结果将是我们的10个随机数,而且这10个小的线段加和必然是1.
好,说完即做,我满怀信心的编程,结果似乎很让人满意,各个变量的分布几乎相同,而且分布的很广,见下图:
顿时成就感十足以为解决了这个问题,但是问题并不是那么的简单,这10个数的分布经过上述的处理之后其分布不再是均匀的,然而让人觉的好像是正态分布的另一半,殊不知C语言产生正态分布的方法就是取若干均匀分布数的和,其和近似满足正态分布。
到底是方法的问题还是问题本身的问题,我百思不得其解;在直觉上,似乎完美的方案在实际应用中并非像想象的那样。
我隐隐觉得取均匀分布并满足其和为1这种苛刻的条件实在是存在某种矛盾,而这种矛盾的结果意味着,产生的分布已经不再是原来的均匀分布。
问题没有得到圆满的解释,不过通过这个问题我们也能看出直觉与实际往往相差很大,通过实验往往能够看出其中的差异。
RONGE KUTA
代码:
%策略1:
n = 10;
S = 1000;% 测试次数
X = rand(S ,n);
SumX = sum(X,2);
x = zeros(S,10);
for i = 1:n
x(:,i) = X(:,i)./SumX;
end
hist(x)
m = mean(x);
%策略2:
n = 10;
S = 1000;% 测试次数
X = rand(S ,n-1);
X = [zeros(S,1),X];
X = sort(X,2);
x = zeros(S,10);
x(:,1:end-1) = X(:,2:end)-X(:,1:end-1);
x(:,10) = 1-X(:,end);
hist(x)
m = mean(x);