Add templates to RngEngine class (#690)

* Add templates to RngEngine class

* Use 64-bit mersenne twister rng engine
This commit is contained in:
Christopher J. Wood 2020-04-17 18:25:28 -04:00 committed by GitHub
parent 5828c51d91
commit 7816fa0102
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 95 deletions

View File

@ -0,0 +1,5 @@
---
upgrade:
- |
Change the RNG engine for simulators from 32-bit Mersenne twister to
64-bit Mersenne twister engine.

View File

@ -18,117 +18,85 @@
#include <cstdint>
#include <random>
#include "framework/types.hpp"
namespace AER {
/***************************************************************************/ /**
*
* RngEngine Class
*
* Objects of this class are used to generate random numbers for backends.
*These
* are used to decide outcomes of measurements and resets, and for implementing
* noise.
*
******************************************************************************/
//============================================================================
// RngEngine Class
//
// Objects of this class are used to generate random numbers for backends.
// These are used to decide outcomes of measurements and resets, and for
// implementing noise.
//
//============================================================================
class RngEngine {
public:
/**
* Generate a uniformly distributed pseudo random real in the half-open
* interval [a,b)
* @param a closed lower bound on interval
* @param b open upper bound on interval
* @return the generated double
*/
double rand(double a, double b);
/**
* Generate a uniformly distributed pseudo random real in the half-open
* interval [0,b)
* @param b open upper bound on interval
* @return the generated double
*/
inline double rand(double b) { return rand(0, b); };
//-----------------------------------------------------------------------
// Constructors
//-----------------------------------------------------------------------
/**
* Generate a uniformly distributed pseudo random real in the half-open
* interval [0,1)
* @return the generated double
*/
inline double rand() { return rand(0, 1); };
// Default constructor initialize RNG engine with a random seed
RngEngine() { set_random_seed(); }
/**
* Generate a uniformly distributed pseudo random integer in the closed
* interval [a,b]
* @param a lower bound on interval
* @param b upper bound on interval
* @return the generated integer
*/
int_t rand_int(int_t a, int_t b);
uint_t rand_int(uint_t a, uint_t b);
// Seeded constructor initialize RNG engine with a fixed seed
explicit RngEngine(size_t seed) { set_seed(seed); }
/**
* Generate a pseudo random integer from a a discrete distribution
* constructed from an input vector of probabilities for [0,..,n-1]
* where n is the lenght of the vector. If this vector is not normalized
* it will be scaled when it is converted to a discrete_distribution
* @param probs the vector of probabilities
* @return the generated integer
*/
uint_t rand_int(const std::vector<double> &probs);
//-----------------------------------------------------------------------
// Set fixed or random seed for RNG
//-----------------------------------------------------------------------
/**
* Default constructor initialize RNG engine with a random seed
*/
RngEngine() {
// Set random seed for the RNG engine
void set_random_seed() {
std::random_device rd;
rng.seed(rd());
};
/**
* Seeded constructor initialize RNG engine with a fixed seed
* @param seed integer to use as seed for mt19937 engine
*/
explicit RngEngine(uint_t seed) { rng.seed(seed); };
set_seed(rd());
}
// Set a fixed seed for the RNG engine
void set_seed(uint_t seed) { rng.seed(seed); };
void set_seed(size_t seed) { rng.seed(seed); }
private:
std::mt19937 rng; // Mersenne twister rng engine
//-----------------------------------------------------------------------
// Sampling methods
//-----------------------------------------------------------------------
// Generate a uniformly distributed pseudo random real in the half-open
// interval [a,b)
double rand(double a, double b) {
return std::uniform_real_distribution<double>(a, b)(rng);
}
// Generate a uniformly distributed pseudo random real in the half-open
// interval [0,b)
double rand(double b) {
return rand(double(0), b);
};
/*******************************************************************************
*
* RngEngine Methods
*
******************************************************************************/
// Generate a uniformly distributed pseudo random real in the half-open
// interval [0,1)
double rand() {return rand(0, 1); };
double RngEngine::rand(double a, double b) {
double p = std::uniform_real_distribution<double>(a, b)(rng);
return p;
// Generate a uniformly distributed pseudo random integer in the closed
// interval [a,b]
template <typename Integer,
typename = std::enable_if_t<std::is_integral<Integer>::value>>
Integer rand_int(Integer a, Integer b) {
return std::uniform_int_distribution<Integer>(a, b)(rng);
}
// randomly distributed integers in [a,b]
int_t RngEngine::rand_int(int_t a, int_t b) {
int_t n = std::uniform_int_distribution<int_t>(a, b)(rng);
return n;
// Generate a pseudo random integer from a a discrete distribution
// constructed from an input vector of probabilities for [0,..,n-1]
// where n is the lenght of the vector. If this vector is not normalized
// it will be scaled when it is converted to a discrete_distribution
template <typename Float,
typename = std::enable_if_t<std::is_floating_point<Float>::value>>
size_t rand_int(const std::vector<Float> &probs) {
return std::discrete_distribution<size_t>(probs.begin(), probs.end())(rng);
}
uint_t RngEngine::rand_int(uint_t a, uint_t b) {
int_t n = std::uniform_int_distribution<uint_t>(a, b)(rng);
return n;
}
// randomly distributed integers from vector
uint_t RngEngine::rand_int(const std::vector<double> &probs) {
uint_t n = std::discrete_distribution<uint_t>(probs.begin(), probs.end())(rng);
return n;
}
private:
std::mt19937_64 rng; // Mersenne twister rng engine
};
//------------------------------------------------------------------------------
} // End namespace QISKIT
} // End namespace AER
#endif