В моем текущем проекте С++ 11 мне нужно выполнить M моделирования. Для каждого моделирования m = 1, ..., M
я произвольно генерирую набор данных с использованием объекта std::mt19937
, созданного следующим образом:
std::mt19937 generator(m);
DatasetFactory dsf(generator);
Согласно qaru.site/info/139891/... и qaru.site/info/274776/..., Merrenne Twister PRNG выигрывает от разогрева фазы, которая в настоящее время отсутствует в моем коде. Я сообщаю для удобства предлагаемый фрагмент кода:
#include <random>
std::mt19937 get_prng() {
std::uint_least32_t seed_data[std::mt19937::state_size];
std::random_device r;
std::generate_n(seed_data, std::mt19937::state_size, std::ref(r));
std::seed_seq q(std::begin(seed_data), std::end(seed_data));
return std::mt19937{q};
}
В моем случае проблема заключается в том, что мне нужна воспроизводимость результатов, т.е. среди разных исполнений, для каждого моделирования набор данных должен быть одинаковым. Это причина, почему в моем текущем решении я использую текущую симуляцию, чтобы засеять Merrenne Twister PRNG. Мне кажется, что использование std::random_device
не позволяет данным быть одинаковыми (AFAIK, это точная цель std::random_device
).
EDIT: с помощью разных исполнений. Я имею в виду перезапуск исполняемого файла.
Как я могу представить вышеупомянутую фазу прогрева в моем коде, не влияя на воспроизводимость? Спасибо.
Возможное решение # 1
Здесь предварительная реализация, основанная на втором предложении @SteveJessop
#include <random>
std::mt19937 get_generator(unsigned int seed) {
std::minstd_rand0 lc_generator(seed);
std::uint_least32_t seed_data[std::mt19937::state_size];
std::generate_n(seed_data, std::mt19937::state_size, std::ref(lc_generator));
std::seed_seq q(std::begin(seed_data), std::end(seed_data));
return std::mt19937{q};
}
Возможное решение # 2
Здесь предварительная реализация, основанная на совместном вкладе @SteveJassop и @AndréNeve. Функция sha256
адаптирована из qaru.site/info/111326/...
#include <openssl/sha.h>
#include <sstream>
#include <iomanip>
#include <random>
std::string sha256(const std::string str) {
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, str.c_str(), str.size());
SHA256_Final(hash, &sha256);
std::stringstream ss;
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
return ss.str();
}
std::mt19937 get_generator(unsigned int seed) {
std::string seed_str = sha256(std::to_string(seed));
std::seed_seq q(seed_str.begin(), seed_str.end());
return std::mt19937{q};
}
Скомпилировать с помощью: -I/opt/ssl/include/ -L/opt/ssl/lib/ -lcrypto