Инициализация последовательности семян в списке инициализации

В настоящее время я пытаюсь реализовать генератор случайных чисел (класс), который использует метод отклонения принятия. Поэтому мне нужны разные C ++ 11 распределения случайных чисел (в моем случае нормальное распределение и равномерное распределение). Я хочу, чтобы случайные числа были как можно лучше, и поэтому я хотел использовать следующее для построения функций:

 [...]
#include <random>
#include <vector>
[...]
std::vector<int> seeds(16);
std::mt19937 mt;
std::minstd_rand seed_rng(101); // random seed
for(size_t i=0;i<16;++i) seeds[i]=seed_rng();
std::seed_seq seq(seeds.begin(), seeds.end());
mt.seed(seq);
rng_normal = std::bind(ndist, std::ref(mt));
[...]

Это работает отлично. Но когда я пытаюсь поместить все это сейчас в конструктор, я больше не могу использовать инициализацию начальной последовательности. Я проверил ссылку на c ++, но наткнулся только на std :: seed_seq :: generate, что не является правильным решением.
Есть ли способ создать seed_seq в моем списке инициализации после заполнения вектора?
Ссылку на seed_seq смотрите здесь:
http://en.cppreference.com/w/cpp/numeric/random/seed_seq
Заранее спасибо за любые предложения!

0

Решение

Предполагая, что вы не заинтересованы в сохранении seed_seq экземпляр, используемый для построения mt19937Вы могли бы сделать что-то вроде этого:

 struct foo
{
std::mt19937 mt;
std::normal_distribution<> ndist;
std::function<decltype(mt)::result_type()> rng_normal;

foo()
: mt{make_mersenne_twister()}
, rng_normal{std::bind(ndist, std::ref(mt))}
{}

static std::mt19937 make_mersenne_twister()
{
std::minstd_rand seed_rng(std::random_device{}()); // random seed
std::vector<int> seeds(16);

std::generate(seeds.begin(), seeds.end(), seed_rng);

std::seed_seq seq(seeds.begin(), seeds.end());
return std::mt19937{seq};
}
};

Я заменил ваше семя (101) с std::random_device.

Проблема с сохранением seed_seq в том, что он не является ни копируемым, ни перемещаемым, поэтому делегировать его конструкцию функции, подобной I, с Mersenne Twister невозможно.

Живая демо

0

Другие решения

Я серьезно сомневаюсь, что ваше улучшение стоит очень дорого. Конструктор с одним значением (и значением по умолчанию) для std :: mt19937 указан в Стандарте C ++. Это что-то вроде

static constexpr size_t WS = 32;
static constexpr result_type IM = 1812433253;
static constexpr result_type default_seed = 5489u;

explicit mt19937(result_type value = default_seed)
{
state[0] = value;
for (int i = 1; i != state_size; ++i)
{
state[i] = i + IM * (state[i - 1] ^ (state[i - 1] >> (WS - 2)));
}
}

Таким образом, он использует генератор случайных чисел XOR-SHIFT для заполнения массива состояний. Учитывая людей, которые участвовали в разработке этого алгоритма посева, и людей, которые работали над получением <random> в стандарт, я думаю, что было бы безопасно предположить, что они знали о std :: minstd_ran, но нашли вышеупомянутое превосходство для посева Twister Mersenne.

0

По вопросам рекламы [email protected]