r - 在 C++11 中为 <random> 创建一个与 R 中的 PRNG 结果相匹配的 PRNG 引擎

标签 r c++11 random

这个问题是双重的。我正在将 R 脚本翻译成 C++,它使用 L'Ecuyer 组合多重递归生成器 (CMRG) 作为引擎(特别是 MRG32k3a),然后从区间 (0, 1) 上的均匀分布返回一个随机数。 R 中的一个最小示例如下所示:

seednum<-100                              # set seed
set.seed(seednum, kind="L'Ecuyer-CMRG")   # set RNG engine
runif(1)                                  # set distribution

我希望能够在 R 脚本和 C++ 代码之间验证我的结果(因为生成的随机数只是开始)。我发现 PRNG 在不同语言中具有相同的种子不一定会产生相同的结果(因为它们可能具有编译器可以自由指定的参数),如 SO 帖子中所示 herehere .也就是说,使用相同的种子、相同的引擎和相同的分布可能会根据 PRNG 的特定实现而产生不同的随机数。下面是 R 和 C++11 之间的相关示例。在 R 中使用无处不在的 Mersenne-Twister PRNG:

seednum<-100
set.seed(seednum, kind="Mersenne-Twister")
runif(1)

产生随机数 0.3077661 .在 C++11 中做同样的事情:

#include <iostream>
#include <random>

int main()
{
  unsigned seed = 100;

  std::mt19937 generator (seed);

  std::uniform_real_distribution<double> distribution (0.0, 1.0);

  std::cout << distribution(generator) << std::endl;

  return 0;
}

产生随机数 0.671156 .我最初对这个结果感到困惑,但之前的 SO 问题为我澄清了这一点(如上链接)。似乎有一些参数被传递给 R 中的 MRG32k3a,我需要在 C++ 中复制这些参数以生成相同的随机数。因此,第一个问题是,我在哪里可以找到有关 R 中指定这些参数的 MRG32k3a 实现的文档?

第二个问题是关于在 C++11 中实现这个生成器的。此生成器未出现在 <random> 中的预配置引擎类型列表中C++11 库已列出 here .可以找到用 C 实现的 MRG32k3a 示例 here如下所示:

/*
   32-bits Random number generator U(0,1): MRG32k3a
   Author: Pierre L'Ecuyer,
   Source: Good Parameter Sets for Combined Multiple Recursive Random
           Number Generators,
           Shorter version in Operations Research,
           47, 1 (1999), 159--164.
   ---------------------------------------------------------
*/
#include <stdio.h>

#define norm 2.328306549295728e-10
#define m1   4294967087.0
#define m2   4294944443.0
#define a12     1403580.0
#define a13n     810728.0
#define a21      527612.0
#define a23n    1370589.0

/***
The seeds for s10, s11, s12 must be integers in [0, m1 - 1] and not all 0. 
The seeds for s20, s21, s22 must be integers in [0, m2 - 1] and not all 0. 
***/

#define SEED 100

static double s10 = SEED, s11 = SEED, s12 = SEED,
              s20 = SEED, s21 = SEED, s22 = SEED;


double MRG32k3a (void)
{
   long k;
   double p1, p2;
   /* Component 1 */
   p1 = a12 * s11 - a13n * s10;
   k = p1 / m1;
   p1 -= k * m1;
   if (p1 < 0.0)
      p1 += m1;
   s10 = s11;
   s11 = s12;
   s12 = p1;

   /* Component 2 */
   p2 = a21 * s22 - a23n * s20;
   k = p2 / m2;
   p2 -= k * m2;
   if (p2 < 0.0)
      p2 += m2;
   s20 = s21;
   s21 = s22;
   s22 = p2;

   /* Combination */
   if (p1 <= p2)
      return ((p1 - p2 + m1) * norm);
   else
      return ((p1 - p2) * norm);
}

int main()
{
   double result = MRG32k3a();

   printf("Result with seed 100 is: %f\n", result);

   return (0);
}

如前所述,我需要使用此生成器来创建一个可以馈送到统一真实分布中的引擎。问题是我不知道这是如何完成的,而且我似乎无法在任何地方找到任何信息(除了知道引擎是类之外)。有没有可用的 C++11 资源可以帮助我完成这样的任务?我不是在寻求问题的解决方案,而是可以帮助我自己实现的建议。

最佳答案

The first question is thus, where can I find the documentation on the MRG32k3a implementation in R that specifies these parameters?

我会使用来源: https://github.com/wch/r-source/blob/5a156a0865362bb8381dcd69ac335f5174a4f60c/src/main/RNG.c#L143

The problem is I have no idea how this is done and I can't seem to find any information anywhere (aside from knowing that engines are classes).

可以在此处找到对 RandomNumberEngine 的要求: https://en.cppreference.com/w/cpp/named_req/RandomNumberEngine 虽然足以满足 UniformRandomBitGenerator如果你想使用 uniform_real_distribution :

Expression      Return type     Requirements
G::result_type  T               T is an unsigned integer type
G::min()        T               Returns the smallest value that G's operator()
                                may return. The value is strictly less than
                                G::max().
G::max()        T               Returns the largest value that G's operator() may
                                return. The value is strictly greater than
                                G::min()
g()             T               Returns a value in the closed interval [G::min(),
                                G::max()]. Has amortized constant complexity.  

主要问题是 MRG32k3a 旨在返回 (0,1) 中的 float ,而 C++ UniformRandomBitGenerator 返回整数类型。为什么要与 <random> 集成标题?

您必须考虑的其他困难:

备选方案包括直接使用 R 源代码而不与 <random> 集成 header 或链接到 libR .

关于r - 在 C++11 中为 <random> 创建一个与 R 中的 PRNG 结果相匹配的 PRNG 引擎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53201392/

相关文章:

r - 将 kable 导出到镜像时的 XDG_RUNTIME_DIR (Rstudio + Ubuntu 20.04)

c++ - 我们是否应该从派生类调用基类移动复制/赋值构造函数

scala - 在 Scala 中随机拆分数组

c - 如何让 "rand()"生成实际的随机数?

java - 如何避免覆盖java中的按钮文本?

r - 如何强制分派(dispatch)到 R 中的内部泛型?

r - 如何从MODISTools中的超时错误中恢复

r - 插入符 - 使用 train()、predict() 和 resamples() 的不同结果

c++ - vector::clear 在 libc++ 中用于简单可破坏的类型

c++ - 在 C++ 高效存储上,刷新文件策略