Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为<;创建PRNG引擎;随机>;在C++;11匹配PRNG的结果为R_R_C++11_Random - Fatal编程技术网

为<;创建PRNG引擎;随机>;在C++;11匹配PRNG的结果为R

为<;创建PRNG引擎;随机>;在C++;11匹配PRNG的结果为R,r,c++11,random,R,C++11,Random,这个问题有两个方面。我将R脚本翻译成C++,使用L'ECu耶组合多递归发生器(CMRG)作为它的引擎(特别是MRG32 K3A),然后在间隔(0, 1)上从均匀分布返回随机数。R中的最小示例如下所示: seednum<-100 # set seed set.seed(seednum, kind="L'Ecuyer-CMRG") # set RNG engine runif(1)

这个问题有两个方面。我将R脚本翻译成C++,使用L'ECu耶组合多递归发生器(CMRG)作为它的引擎(特别是MRG32 K3A),然后在间隔(0, 1)上从均匀分布返回随机数。R中的最小示例如下所示:

seednum<-100                              # set seed
set.seed(seednum, kind="L'Ecuyer-CMRG")   # set RNG engine
runif(1)                                  # set distribution
/*
   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);
}
结果随机数为
0.671156
。我最初对这个结果感到困惑,但之前的问题为我澄清了这一点(如上链接)。看来,R中有参数传递给MRG32 K3A,我需要在C++中复制,以便生成相同的随机数。因此,第一个问题是,我在哪里可以找到在R中指定这些参数的MRG32k3a实现的文档

第二个问题涉及在C++11中实现此生成器。此生成器不出现在所列C++11的
库中预先配置的发动机类型列表中。可以找到用C实现的MRG32k3a示例,如下所示:

seednum<-100                              # set seed
set.seed(seednum, kind="L'Ecuyer-CMRG")   # set RNG engine
runif(1)                                  # set distribution
/*
   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);
}
/*
32位随机数发生器U(0,1):MRG32k3a
作者:Pierre L'Ecuyer,
来源:组合多重递归随机变量的良好参数集
数字发生器,
运筹学的较短版本,
47, 1 (1999), 159--164.
---------------------------------------------------------
*/
#包括
#定义规范2.328306549295728e-10
#定义m1 4294967087.0
#定义m2 42944443.0
#定义a12 1403580.0
#定义a13n 810728.0
#定义a21 527612.0
#定义a23n 1370589.0
/***
s10、s11、s12的种子必须是[0,m1-1]中的整数,而不是全部为0。
s20、s21、s22的种子必须是[0,m2-1]中的整数,而不是全部为0。
***/
#定义种子100
静态双s10=种子,s11=种子,s12=种子,
s20=种子,s21=种子,s22=种子;
双MRG32k3a(无效)
{
长k;
双p1,p2;
/*组成部分1*/
p1=a12*s11-a13n*s10;
k=p1/m1;
p1-=k*m1;
如果(p1<0.0)
p1+=m1;
s10=s11;
s11=s12;
s12=p1;
/*构成部分2*/
p2=a21*s22-a23n*s20;
k=p2/m2;
p2-=k*m2;
如果(p2<0.0)
p2+=m2;
s20=s21;
s21=s22;
s22=p2;
/*组合*/
如果(p1
因此,第一个问题是,我在哪里可以找到在R中指定这些参数的MRG32k3a实现的文档

我将使用以下来源:

问题是我不知道这是如何做到的,而且我似乎在任何地方都找不到任何信息(除了知道引擎是类之外)

RandomNumberEngine的要求可在此处找到: 虽然如果您想使用统一的真实分布,就足以满足以下要求:

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.  

主要问题是MRG32 K3A是返回(0,1)中的浮点数,而C++统一随机比特生成器返回整数类型。为什么要与<代码>头?< /P>集成? 您必须考虑的其他困难:

  • R,c.f.使用的播种策略
  • R将用户提供的种子c.f.置乱
替代方法包括直接使用R源代码,而不与
标题集成或链接到
libR

我发现在不同语言中具有相同种子的PRNG不一定产生相同的结果(因为它们可能有编译器可以自由指定的参数)如SO帖子和中所示。也就是说,根据PRNG的具体实现,使用相同的种子、相同的引擎和相同的分布可能会导致不同的随机数

第一个答案仅仅解释了不存在与给定的PRNG种子普遍对应的随机数序列;它可能在不同的API中以不同的方式记录和实现(不仅仅是在编译器中,也不仅仅是在语言级别).第二个答案是针对C语言中的
rand
srand
的,原因是

虽然两个答案都不涉及随机数分布,但如果需要可再现的“随机性”,它们也是重要的。在这个意义上,尽管C++保证了它提供的引擎的行为,但它使得

一般来说,如果使用一种稳定(不变)且记录在案的算法不仅用于已播种的PRNG,而且用于使用该PRNG的任何随机数方法(在R的情况下,包括
runif
rnorm
),则可以避免涉及可重复“随机性”的PRNG播种问题-在后一种情况下,因为“随机”序列的再现性取决于这些方法(不仅仅是PRNG本身)的记录方式

根据您是否编写了R代码,一个选项可以是写C++和R代码(如你似乎已经做了自己的部分),并使用自定义实现的算法来使用原来的R代码使用的每个随机数方法(例如<代码> RunIF <代码>和<代码> RAMNOR> <代码>)。此选项可能是可行的,尤其是因为统计测试通常对使用的特定PRNG的细节不敏感


根据R脚本的编写方式,另一个选项可能是预生成代码所需的随机数。

为什么不使用R源代码的实现?