Main Content

本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。

创建和控制随机数流

通过 RandStream 类,可以创建随机数流。在很多情况下,这是很有用的。例如,要生成随机值,而不影响全局流的状态。可能希望在仿真时使用不同的随机性源。或者,可能需要使用与 MATLAB® 软件在启动时所用不同的生成器算法。使用 RandStream 构造函数,可以创建自己的流、设置可写属性以及生成随机数。可以采用控制全局流的相同方式来控制所创建的流,甚至可将全局流替换为所创建的流。

要创建流,请使用 RandStream 构造函数。

myStream=RandStream('mlfg6331_64');
rand(myStream,1,5)

ans =

    0.6530    0.8147    0.7167    0.8615    0.0764

随机流 myStream 的行为与全局流的行为不同。函数 randrandnrandi 将继续从全局流中获取,并且不会影响应用于 myStreamRandStream 方法 randrandnrandi 的结果。

可以使用 RandStream.setGlobalStream 方法使 myStream 成为全局流。

RandStream.setGlobalStream(myStream)
RandStream.getGlobalStream

ans = 

mlfg6331_64 random stream (current global stream)
             Seed: 0
  NormalTransform: Ziggurat

RandStream.getGlobalStream==myStream

ans =

     1

子流

也许需要返回到模拟的前一部分。可以通过使随机流跳转到称为子流的固定检查点来控制随机流。Substream 属性允许您在多个子流之间来回跳转。要使用 Substream 属性,请使用支持子流的生成器创建流。(有关生成器算法及其属性的列表,请参阅选择随机数生成器。)

stream=RandStream('mlfg6331_64');
RandStream.setGlobalStream(stream)

Substream 的初始值为 1。

stream.Substream

ans =

     1

子流在序列计算中很有用。子流可以通过返回到流中的特定检查点来重新创建所有或部分仿真。例如,可以在循环中使用子流。

for i=1:5
    stream.Substream=i;
    rand(1,i)
end

ans =
    0.6530

ans =
    0.3364    0.8265

ans =
    0.9539    0.6446    0.4913

ans =
    0.0244    0.5134    0.6305    0.6534

ans =
    0.3323    0.9296    0.5767    0.1233    0.6934

其中每个子流都可以重新生成其循环迭代。例如,可以返回到第 5 个子流。结果将返回与上面的第 5 个输出相同的值。

stream.Substream=5;
rand(1,5)

ans =

    0.3323    0.9296    0.5767    0.1233    0.6934

选择随机数生成器

MATLAB 提供了多个生成器算法选项。下表概述了可用的生成器算法的关键属性以及用于创建这些算法的关键字。要返回所有可用生成器算法的列表,请使用 RandStream.list 方法。

关键字生成器多流和子流支持全精度的近期周期
mt19937ar梅森旋转(MATLAB 启动时默认流使用的算法)219937-1
dsfmt19937面向 SIMD 的快速梅森旋转算法 219937-1
mcg16807乘法同余生成器231-2
mlfg6331_64乘法滞后 Fibonacci 生成器2124(251 个流,长度为 272
mrg32k3a组合多递归生成器2191(263 个流,长度为 2127
philox4x32_10执行 10 轮的 Philox 4×32 生成器2193(264 个流,长度为 2129
threefry4x64_20执行 20 轮的 Threefry 4×64 生成器2514(2256 个流,长度为 2258
shr3cong移位寄存器生成器与线性同余生成器求和264
swb2712修正的借位减法生成器21492

生成器 mcg16807shr3congswb2712 可与以前的 MATLAB 版本向后兼容。mt19937ardsfmt19937 主要是为序列应用程序设计的。其余的生成器明确支持并行随机数生成。

根据应用程序情况,某些生成器可能会更快或者返回精度更高的值。所有伪随机数生成器均基于确定性算法,并且均无法通过足够具体的随机性统计学测试。检查蒙特卡罗仿真结果的一种方法是使用两种或更多种不同的生成器算法重新运行该仿真,MATLAB 软件的生成器选项提供了执行该操作的方式。使用不同的生成器时,尽管结果不可能因多个蒙特卡罗采样误差而异,但资料中存在此类验证在特定的生成器算法中出现缺陷的示例(请参阅[13]了解示例)。

生成器算法

mt19937ar

梅森旋转算法(如 [11] 中所述)的周期为 2199371,并且每个 U(0,1) 值都是使用两个 32 位整数生成的。可能的值为 (0,1) 区间内 253 的倍数。此生成器不支持多个流或子流。默认情况下用于 mt19937ar 流的 randn 算法为 ziggurat 算法 [7],但基于 mt19937ar 生成器。注意:此生成器与 rand 函数从 MATLAB 版本 7 开始使用的生成器相同,通过 rand('twister',s) 激活。

dsfmt19937

面向 SIMD 的双精度快速梅森旋转算法(如 [12] 中所述)是速度更快的梅森旋转算法实现。周期为 2199371,可能的值为 (0,1) 区间内 252 的倍数。生成器本身会生成 [1,2) 内的双精度值,这些值经过变换生成 U(0,1) 值。此生成器不支持多个流或子流。

mcg16807

32 位乘法同余生成器,如 [14] 中所述,其中乘数为 a=75,模为 m=2311。此生成器的周期为 2312,不支持多个流或子流。每个 U(0,1) 值都是使用单个 32 位整数通过该生成器创建的;可能的值为 (2311)1 的所有倍数(严格位于区间 (0,1) 内)。mcg16807 流默认情况下使用的 randn 算法是极坐标算法(如[1]中所述)。注意:此生成器与 randrandn 函数从 MATLAB 版本 4 开始使用的生成器相同,通过 rand('seed',s)randn('seed',s) 进行激活。

mlfg6331_64

64 位的乘法滞后 Fibonacci 生成器,如 [10] 中所述,其中滞后值为 l=63k=31。此生成器与 SPRNG 包中实现的 MLFG 类似。其周期约为 2124。通过参数化,它最多支持 261 个并行流以及 251 个长度均为 272 的子流。每个 U(0,1) 值都是使用一个 64 位整数通过该生成器创建的;可能的值全部为 264 的倍数(严格位于区间 (0,1) 内)。默认情况下用于 mlfg6331_64 流的 randn 算法为 ziggurat 算法 [7],但基于 mlfg6331_64 生成器。

mrg32k3a

32 位组合多递归生成器,如[2]中所述。此生成器与 RngStreams 包中实现的 CMRG 类似。其周期为 2191,通过序列拆分最多支持 263 个长度均为 2127 的并行流。它还支持 251 个长度均为 276 的子流。每个 U(0,1) 值都是使用两个 32 位整数通过该生成器创建的;可能的值为 253 的倍数(严格位于区间 (0,1) 内)。默认情况下用于 mrg32k3a 流的 randn 算法为 ziggurat 算法 [7],但基于 mrg32k3a 生成器。

philox4x32_10

执行 10 轮的 4×32 生成器,如 [15] 中所述。此生成器使用 Feistel 网络和整数乘法,专为在高度并行系统(如 GPU)中实现高性能而设计。它的周期为 2193(264 个流,长度为 2129)。

threefry4x64_20

执行 20 轮的 4×64 生成器,如 [15] 中所述。此生成器是 Skein 散列函数中的 Threefish 块加密的非加密改编。它的周期为 2514(2256 个流,长度为 2258)。

shr3cong

Marsaglia 的 SHR3 移位寄存器生成器与线性同余生成器求和,其中乘数为 a=69069,加数为 b=1234567,模为 232。SHR3 是一个定义为 u=u(I+L13)(I+R17)(I+L5) 的 3 移位寄存器生成器,其中 I 为单位运算符,L 为向左移位运算符,R 为向右移位运算符。此组合生成器(SHR3 部分在 [7] 中有述)的周期约为 264。此生成器不支持多个流或子流。每个 U(0,1) 值都是使用一个 32 位整数通过该生成器创建的;可能的值为 232 的所有倍数(严格位于区间 (0,1) 内)。默认情况下用于 shr3cong 流的 randn 算法为早期形式的 ziggurat 算法 [9],但基于 shr3cong 生成器。此生成器与 randn 函数从 MATLAB 版本 5 开始使用的生成器相同,通过 randn('state',s) 进行激活。

注意

[6] (1999) 中用到的 SHR3 生成器与 [7] (2000) 中不同。MATLAB 使用 [7] 中提供的最新版生成器。

swb2712

修正的借位减法生成器,如[8]中所述。此生成器与加法滞后 Fibonacci 生成器(其滞后值为 27 和 12)类似,但修改后具有约为 21492 的更长周期。此生成器本身会使用双精度类型来创建 U(0,1) 值,并且开区间 (0,1) 中的所有值都是可能的。默认情况下用于 swb2712 流的 randn 算法为 ziggurat 算法 [7],但基于 swb2712 生成器。注意:此生成器与 MATLAB 版本 5 开始的版本中的 rand 函数所用生成器相同,通过 rand('state',s) 进行激活。

转换算法

Inversion

通过对均匀的随机变量应用标准正态逆累积分布函数来计算正态随机变量。每个正态值恰好使用一个均匀值。

Polar

极坐标抑制算法,如[1]中所述。每个正态值平均约使用 1.27 个均匀值。

Ziggurat

ziggurat 算法,如[7]中所述。每个正态值平均约使用 2.02 个均匀值。

参考

[1] Devroye, L. Non-Uniform Random Variate Generation, Springer-Verlag, 1986.

[2] L’Ecuyer, P. “Good Parameter Sets for Combined Multiple Recursive Random Number Generators”, Operations Research, 47(1): 159–164. 1999.

[3] L'Ecuyer, P. and S. Côté. “Implementing A Random Number Package with Splitting Facilities”, ACM Transactions on Mathematical Software, 17: 98–111. 1991.

[4] L'Ecuyer, P. and R. Simard. “TestU01: A C Library for Empirical Testing of Random Number Generators,” ACM Transactions on Mathematical Software, 33(4): Article 22. 2007.

[5] L'Ecuyer, P., R. Simard, E. J. Chen, and W. D. Kelton. “An Objected-Oriented Random-Number Package with Many Long Streams and Substreams.” Operations Research, 50(6):1073–1075. 2002.

[6] Marsaglia, G. “Random numbers for C: The END?” Usenet posting to sci.stat.math. 1999. Available online at https://groups.google.com/group/sci.crypt/browse_thread/
thread/ca8682a4658a124d/
.

[7] Marsaglia G., and W. W. Tsang. “The ziggurat method for generating random variables.” Journal of Statistical Software, 5:1–7. 2000. Available online at https://www.jstatsoft.org/v05/i08.

[8] Marsaglia, G., and A. Zaman. “A new class of random number generators.” Annals of Applied Probability 1(3):462–480. 1991.

[9] Marsaglia, G., and W. W. Tsang. “A fast, easily implemented method for sampling from decreasing or symmetric unimodal density functions.” SIAM J.Sci.Stat.Comput. 5(2):349–359. 1984.

[10] Mascagni, M., and A. Srinivasan. “Parameterizing Parallel Multiplicative Lagged-Fibonacci Generators.” Parallel Computing, 30: 899–916. 2004.

[11] Matsumoto, M., and T. Nishimura.“Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudorandom Number Generator.” ACM Transactions on Modeling and Computer Simulation, 8(1):3–30. 1998.

[12] Matsumoto, M., and M. Saito.“A PRNG Specialized in Double Precision Floating Point Numbers Using an Affine Transition.” Monte Carlo and Quasi-Monte Carlo Methods 2008, 10.1007/978-3-642-04107-5_38. 2009.

[13] Moler, C.B. Numerical Computing with MATLAB. SIAM, 2004. Available online at https://www.mathworks.com/moler

[14] Park, S.K., and K.W. Miller. “Random Number Generators: Good Ones Are Hard to Find.” Communications of the ACM, 31(10):1192–1201. 1998.

[15] Salmon, J. K., M. A. Moraes, R. O. Dror, and D. E. Shaw. "Parallel Random Numbers: As Easy as 1, 2, 3." In Proceedings of the International Conference for High Performance Computing, Networking, Storage and Analysis (SC11). New York, NY: ACM, 2011.

另请参阅

相关主题