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 <cstdint>
#include <random> #include <random>
#include "framework/types.hpp"
namespace AER { namespace AER {
/***************************************************************************/ /** //============================================================================
* // RngEngine Class
* RngEngine Class //
* // Objects of this class are used to generate random numbers for backends.
* Objects of this class are used to generate random numbers for backends. // These are used to decide outcomes of measurements and resets, and for
*These // implementing noise.
* are used to decide outcomes of measurements and resets, and for implementing //
* noise. //============================================================================
*
******************************************************************************/
class RngEngine { class RngEngine {
public: 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 // Constructors
* interval [0,b) //-----------------------------------------------------------------------
* @param b open upper bound on interval
* @return the generated double
*/
inline double rand(double b) { return rand(0, b); };
/** // Default constructor initialize RNG engine with a random seed
* Generate a uniformly distributed pseudo random real in the half-open RngEngine() { set_random_seed(); }
* interval [0,1)
* @return the generated double
*/
inline double rand() { return rand(0, 1); };
/** // Seeded constructor initialize RNG engine with a fixed seed
* Generate a uniformly distributed pseudo random integer in the closed explicit RngEngine(size_t seed) { set_seed(seed); }
* 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);
/** //-----------------------------------------------------------------------
* Generate a pseudo random integer from a a discrete distribution // Set fixed or random seed for RNG
* 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 random seed for the RNG engine
* Default constructor initialize RNG engine with a random seed void set_random_seed() {
*/
RngEngine() {
std::random_device rd; std::random_device rd;
rng.seed(rd()); set_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 a fixed seed for the RNG engine // 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); }
//-----------------------------------------------------------------------
// 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);
};
// Generate a uniformly distributed pseudo random real in the half-open
// interval [0,1)
double rand() {return rand(0, 1); };
// 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);
}
// 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);
}
private: private:
std::mt19937 rng; // Mersenne twister rng engine std::mt19937_64 rng; // Mersenne twister rng engine
}; };
/*******************************************************************************
*
* RngEngine Methods
*
******************************************************************************/
double RngEngine::rand(double a, double b) {
double p = std::uniform_real_distribution<double>(a, b)(rng);
return p;
}
// 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;
}
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;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
} // End namespace QISKIT } // End namespace AER
#endif #endif