使用用户定义的随机生成器运行std :: normal_distribution

时间:2013-10-04 10:10:26

标签: c++ visual-c++ c++11 random

我即将生成一组正态分布的伪随机数。据我所知,std库提供了以下代码:

std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<> d(mean,std);
...
double number = d(gen);

问题在于我想使用Sobol'的准随机序列而不是Mersenne Twister伪随机生成器。所以,我的问题是: 是否可以使用用户定义的随机生成器运行std :: normal_distribution(在我的情况下使用Sobol'准随机序列生成器)?


更多细节:我有一个名为RandomGenerators的类,用于生成Sobol'的准随机数:

RandomGenerator randgen;
double number = randgen.sobol(0,1);

3 个答案:

答案 0 :(得分:5)

是的,有可能。只要使其符合统一随机数发生器的要求(第26.5.1.3段第2和第3段):

  

2类G满足统一随机数的要求   如果表116中显示的表达式有效且具有   表示语义,如果G也满足所有其他要求   这部分。在该表和整个部分中:

     

a)TG’s associated result_type`命名的类型,

     

b)g的值为G

     

表116 - 统一随机数发生器要求

Expression     | Return type | Pre/post-condition         | Complexity
----------------------------------------------------------------------
G::result_type |    T        | T is an unsigned integer   | compile-time
               |             | type (§3.9.1).             |
----------------------------------------------------------------------
g()            |    T        | Returns a value in the     | amortized constant
               |             | closed interval            |
               |             | [G::min(), G::max()].      |
----------------------------------------------------------------------
G::min()       |    T        | Denotes the least value    | compile-time
               |             | potentially returned by    |
               |             | operator().                |
----------------------------------------------------------------------
G::max()       |    T        | Denotes the greatest value | compile-time
               |             | potentially returned by    |
               |             | operator().                |
     

3以下关系应成立:G::min() < G::max()

答案 1 :(得分:1)

这里要谨慎一点 - 当我实施这个时,我遇到了一个大问题。似乎如果max()/ min()/ operator()的返回类型不是64位,那么分布将重新取样。我的(无符号)32位Sobol实现每个偏差都被采样两次,从而破坏了数字的属性。此代码重现:

#include <random>
#include <limits>
#include <iostream>
#include <cstdint>

typedef uint32_t rng_int_t;

int requested = 0;
int sampled = 0;

struct Quasi
{
  rng_int_t operator()()
  {
    ++sampled;
    return 0;
  }

  rng_int_t min() const 
  {
    return 0;
  }

  rng_int_t max() const
  {
    return std::numeric_limits<rng_int_t>::max();
  }
};

int main()
{
  std::uniform_real_distribution<double> dist(0.0,1.0);

  Quasi q;

  double total = 0.0;
  for (size_t i = 0; i < 10; ++i)
  {
    dist(q);
    ++requested;
  }
  std::cout << "requested: " << requested << std::endl;
  std::cout << "sampled: " << sampled << std::endl;
}

输出(使用g ++ 5.4):

requested: 10
sampled: 20

甚至在使用-m32编译时。如果将rng_int_t更改为64位,问题就会消失。我的解决方法是将32位值粘贴到返回值的最高位,例如

return uint64_t(val) << 32;

答案 2 :(得分:0)

您现在可以直接使用Boost生成Sobol序列。参见boost / random / sobol.hpp。