2

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

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

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


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

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

3 回答 3

5

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

2 如果表 116 中所示的表达式是有效的并具有指定的语义,并且还满足本节的所有其他要求,则该类G满足统一随机数生成器的要求。G在该表和本节中:

a)是由result_type`T命名的类型,并且G’s associated

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()

于 2013-10-04T10:17:19.293 回答
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;
于 2017-01-08T16:52:22.217 回答
0

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

于 2019-05-22T07:47:27.300 回答