Ответ 1
Mersenne Twister представляет собой pRNG на основе сдвигового регистра (генератор псевдослучайных чисел) и поэтому подвержен плохим семенам с длинными прогонами 0s или 1s, которые приводят к относительно прогнозируемым результатам до тех пор, пока внутреннее состояние не будет достаточно перемешано.
Однако конструктор, который принимает одно значение, использует сложную функцию для этого начального значения, которая предназначена для минимизации вероятности создания таких "плохих" состояний. Существует второй способ инициализации mt19937
, где вы непосредственно устанавливаете внутреннее состояние, через объект, соответствующий концепции SeedSequence. Это второй способ инициализации, когда вам может потребоваться забота о выборе "хорошего" состояния или разминки.
Стандарт включает объект, соответствующий концепции SeedSequence, называемый seed_seq
. seed_seq
принимает произвольное количество входных значений семени и затем выполняет определенные операции над этими значениями, чтобы создать последовательность различных значений, подходящих для непосредственной установки внутреннего состояния pRNG.
Здесь приведен пример загрузки последовательности семян с достаточным количеством случайных данных для заполнения всего состояния std::mt19937
:
std::array<int, 624> seed_data;
std::random_device r;
std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
std::mt19937 eng(seq);
Это гарантирует, что все состояние будет рандомизировано. Кроме того, каждый движок указывает, сколько данных он считывает из seed_sequence, поэтому вы можете прочитать документы, чтобы найти эту информацию для любого используемого вами движка.
Хотя здесь я полностью загружаю seed_seq из std::random_device
, seed_seq
указан так, что только несколько чисел, которые не особенно случайны, должны работать хорошо. Например:
std::seed_seq seq{1, 2, 3, 4, 5};
std::mt19937 eng(seq);
В комментариях ниже Cubbi указывает, что seed_seq
работает, выполняя последовательность прогрева для вас.
Здесь должен быть ваш "по умолчанию" для посева:
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 rng(seed);