MUQ  0.4.3
RandomGenerator.cpp
Go to the documentation of this file.
1 
3 
4 #include <fstream>
5 #include <iostream>
6 #include <vector>
7 #include <array>
8 
9 
10 using namespace muq::Utilities;
11 using namespace std;
12 
13 array<seed_seq::result_type, RandomGenerator::GeneratorType::state_size> UrandomRead()
14 {
15  // use a random device instead of /dev/urandom (may result in same behavior if not on windows)
16  random_device rd;
17 
18  //how much data the generator needs
19  array<seed_seq::result_type, RandomGenerator::GeneratorType::state_size> seed_data;
20 
21  //generate all the randomness
22  for (int i = 0; i < seed_data.size(); ++i) {
23  seed_data.at(i) = rd();
24  }
25 
26  return seed_data;
27 }
28 
29 SeedGenerator::SeedGenerator(const array<seed_seq::result_type,
30  RandomGenerator::GeneratorType::state_size>& seed_data) : seed_seq(begin(seed_data),
31  end(seed_data))
32 {}
33 
34 SeedGenerator::SeedGenerator() : SeedGenerator(UrandomRead())
35 {}
36 
38 {
39  static std::normal_distribution<> Gauss_RNG(0, 1);
40 
41  Gauss_RNG.reset();
42  return Gauss_RNG(GetGenerator());
43 }
44 
46 {
47  static std::uniform_real_distribution<> Uniform_RNG(0, 1);
48 
49  return Uniform_RNG(GetGenerator());
50 }
51 
52 double RandomGenerator::GetGamma(double const alpha, double const beta)
53 {
54  std::gamma_distribution<> Gamma_RNG(alpha, beta);
55  return Gamma_RNG(GetGenerator());
56 }
57 
58 Eigen::MatrixXd RandomGenerator::GetGamma(double const alpha, double const beta, int rows, int cols)
59 {
60 
61  Eigen::MatrixXd output(rows,cols);
62 
63  for(int j=0; j<cols; ++j)
64  {
65  for(int i=0; i<rows; ++i)
66  {
67  output(i,j) = GetGamma(alpha,beta);
68  }
69  }
70 
71  return output;
72 }
73 
74 
75 
76 int RandomGenerator::GetUniformInt(int lb, int ub)
77 {
78  assert(ub >= lb);
79 
80  static std::uniform_real_distribution<> Uniform_RNG(0, 1);
81  return round(Uniform_RNG(GetGenerator()) * (ub - lb) + lb);
82 }
83 
85 Eigen::MatrixXi RandomGenerator::GetUniformInt(int lb, int ub, int rows, int cols, bool unique)
86 {
87  const int N = rows*cols;
88 
89  assert(ub >= lb);
90 
91  const int maxN = ub - lb + 1;
92  if(unique){
93  assert(N <= maxN);
94  }
95 
96  if(unique)
97  {
98  // fill a set with all numbers between lb and ub
99  vector<int> allInts;
100  allInts.reserve(ub - lb + 1);
101  for (int i = lb; i <= ub; ++i) {
102  allInts.push_back(i);
103  }
104 
105  // create the output vector and fill it
106  Eigen::VectorXi output(N);
107  for (int i = 0; i < N; ++i) {
108  // generate a random index into allInts
109  int ind = GetUniformInt(i, maxN - 1);
110  std::swap(allInts[i], allInts[ind]);
111  }
112 
113  return Eigen::Map<Eigen::MatrixXi>(&allInts[0], rows, cols);
114  }
115  else
116  {
117  Eigen::MatrixXi output(rows,cols);
118  for(int j=0; j<cols; ++j){
119  for(int i=0; i<rows; ++i)
120  output(i,j) = GetUniformInt(lb,ub);
121  }
122 
123  return output;
124  }
125 }
126 
127 Eigen::MatrixXd RandomGenerator::GetUniform(int rows, int cols)
128 {
129  Eigen::MatrixXd result(rows,cols);
130 
131  for(int j=0; j<cols; ++j){
132  for (int i = 0; i < rows; ++i) {
133  result(i,j) = GetUniform();
134  }
135  }
136 
137  return result;
138 }
139 
140 
141 Eigen::MatrixXd RandomGenerator::GetNormal(int const m, int const n)
142 {
143  Eigen::MatrixXd result(m, n);
144 
145  for (int j = 0; j < n; ++j) {
146  for (int i = 0; i < m; ++i) {
147  result(i, j) = GetNormal();
148  }
149  }
150  return result;
151 }
152 
153 void RandomGenerator::SetSeed(int seedval)
154 {
155  GetGenerator().seed(seedval);
156 }
157 
159 {
160  return GetGenerator();
161 }
162 
164 {
165  GetGenerator() = state;
166 }
167 
168 int RandomGenerator::GetDiscrete(std::vector<double> const& discProbs)
169 {
170  return GetDiscrete(Eigen::Map<const Eigen::VectorXd>(discProbs.data(), discProbs.size()));
171 }
172 
173 int RandomGenerator::GetDiscrete(Eigen::Ref<const Eigen::VectorXd> const& discProbs)
174 {
175  double u = RandomGenerator::GetUniform();
176  double cumSum = 0.0;
177 
178  for(int i=0; i<discProbs.size(); ++i){
179  cumSum += discProbs(i);
180  if(u<cumSum)
181  return i;
182  }
183 
184  return 0;
185 }
186 
187 Eigen::MatrixXi RandomGenerator::GetDiscrete(std::vector<double> const& discProbs, int rows, int cols)
188 {
189  return GetDiscrete(Eigen::Map<const Eigen::VectorXd>(discProbs.data(), discProbs.size()), rows, cols);
190 }
191 
192 Eigen::MatrixXi RandomGenerator::GetDiscrete(Eigen::Ref<const Eigen::VectorXd> const& discProbs, int rows, int cols)
193 {
194  std::vector<int> indices(discProbs.size());
195  for(int i=0; i<discProbs.size(); ++i)
196  indices[i] = i;
197 
198  // Sort in descending order so that we're more likely to terminate early in the cumulative sum loop below
199  std::sort(indices.begin(), indices.end(), [discProbs](int const& a, int const& b) -> bool{ return discProbs(a) > discProbs(b); });
200 
201  Eigen::MatrixXi output(rows,cols);
202  for(int j=0; j<cols; ++j){
203  for(int i=0; i<rows; ++i){
204 
205  double cumSum = 0;
206  double u = RandomGenerator::GetUniform();
207 
208  for(int k=0; k<discProbs.size(); ++k){
209  cumSum += discProbs(indices.at(k));
210  if(u<cumSum){
211  output(i,j) = indices.at(k);
212  break;
213  }
214  }
215  }
216  }
217 
218  return output;
219 }
220 
221 
223 {
224 
225 #if defined(__has_feature) && __has_feature(cxx_thread_local)
226 # define MUQ_NATIVE_TLS thread_local
227 #endif
228 
229 #if defined(MUQ_NATIVE_TLS)
230  static MUQ_NATIVE_TLS SeedGenerator seedGen;
231  static MUQ_NATIVE_TLS RandomGenerator::GeneratorType BaseGenerator(seedGen.seed_seq);
232 #else
233  static SeedGenerator seedGen;
234  static RandomGenerator::GeneratorType BaseGenerator(seedGen.seed_seq);
235 #endif
236 
237  return BaseGenerator;
238 }
239 
240 
242 {
245 }
246 
248 {
250 }
array< seed_seq::result_type, RandomGenerator::GeneratorType::state_size > UrandomRead()
static int GetDiscrete(std::vector< double > const &discProbs)
static void SetGenerator(GeneratorType)
Set the state of the generator, designed for use with CopyGenerator. Be very careful in using this,...
static GeneratorType & GetGenerator()
static GeneratorType CopyGenerator()
Store a copy of the generator, designed for use with SetGenerator. Be very careful in using this,...
static void SetSeed(int seedval)
Set the seed for the random number generator. This is a fairly low quality way to do this,...
static double GetGamma(double const alpha, double const beta)
static int GetUniformInt(int lb, int ub)