VPTissue Reference Manual
RandomEngine.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Universiteit Antwerpen
3  *
4  * Licensed under the EUPL, Version 1.1 or as soon they will be approved by
5  * the European Commission - subsequent versions of the EUPL (the "Licence");
6  * You may not use this work except in compliance with the Licence.
7  * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl5
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the Licence is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the Licence for the specific language governing
13  * permissions and limitations under the Licence.
14  */
20 #include "RandomEngine.h"
21 
23 
24 using namespace std;
25 using namespace SimPT_Sim::ClockMan;
26 using namespace SimPT_Sim::RandomEngineType;
27 using namespace boost::property_tree;
28 using boost::optional;
29 
30 namespace SimPT_Sim {
31 
32 RandomEngine::RandomEngine()
33  : m_seed(1U), m_type_id(TypeId::mrg2)
34 {
35  // Create as many random number generators of each type as the number of
36  // threads; or 1 if no OpenMP support.
37  const size_t nthreads = 1;
38 
39  this->m_lcg64.resize(nthreads);
40  this->m_lcg64_shift.resize(nthreads);
41  this->m_mrg2.resize(nthreads);
42  this->m_mrg3.resize(nthreads);
43  this->m_yarn2.resize(nthreads);
44  this->m_yarn3.resize(nthreads);
45 
46  SetState(m_seed);
47 }
48 
50 {
51  Info info;
52  stringstream ss;
53 
54  switch (m_type_id) {
55  case TypeId::lcg64 :
56  ss << m_lcg64[0]; break;
57  case TypeId::lcg64_shift :
58  ss << m_lcg64_shift[0]; break;
59  case TypeId::mrg2 :
60  ss << m_mrg2[0]; break;
61  case TypeId::mrg3 :
62  ss << m_mrg3[0]; break;
63  case TypeId::yarn2 :
64  ss << m_yarn2[0]; break;
65  case TypeId::yarn3 :
66  ss << m_yarn3[0]; break;
67  }
68 
69  info.seed = m_seed;
70  info.state = ss.str();
71  info.type = ToString(m_type_id);
72  return info;
73 }
74 
76 {
77  m_type_id = TypeId::mrg2;
78  m_seed = 1U;
79  SetState(m_seed);
80  return true;
81 }
82 
83 bool RandomEngine::Reinitialize(const ptree& pt)
84 {
85  bool status = false;
86  const string type = pt.get<string>("type");
87  if(IsExisting(type)) {
88  m_type_id = FromString(type);
89  optional<unsigned long> seed = pt.get_optional<unsigned long>("seed");
90  if (seed) {
91  m_seed = seed.get();
92  } else {
93  // Apparently std::random_device not non-deterministic on
94  // some platforms, so we use a reading of the wall-clock.
95  m_seed = static_cast<unsigned long>(TimeStamp().ToTimeT());
96  }
97  optional<const ptree&> re_pt = pt.get_child_optional("state");
98  if (re_pt) {
99  SetState(re_pt.get().get_value<string>());
100  } else {
101  SetState(m_seed);
102  }
103  status = true;
104  }
105  return status;
106 }
107 
114 template <typename T>
115 void para_seed(std::vector<T>& rngs, const unsigned long seed)
116 {
117  // n is equal to the number of OpenMP worker threads, i.e: the number
118  // of parallel RNG streams we require
119  const size_t n = rngs.size();
120  // Seed all RNGs with 'seed' & divide in 'n' streams
121  for (size_t i = 0; i < n; ++i) {
122  rngs[i].seed(seed);
123  rngs[i].split(n, i);
124  }
125 }
126 
127 void RandomEngine::SetState(unsigned long seed)
128 {
129  switch (m_type_id) {
130  case TypeId::lcg64 :
131  para_seed(m_lcg64, seed); break;
132  case TypeId::lcg64_shift :
133  para_seed(m_lcg64_shift, seed); break;
134  case TypeId::mrg2 :
135  para_seed(m_mrg2, seed); break;
136  case TypeId::mrg3 :
137  para_seed(m_mrg3, seed); break;
138  case TypeId::yarn2 :
139  para_seed(m_yarn2, seed); break;
140  case TypeId::yarn3 :
141  para_seed(m_yarn3, seed); break;
142  }
143 }
144 
151 template <typename T>
152 void para_seed(std::vector<T>& rngs, const std::string& state)
153 {
154  stringstream ss(state);
155  // n is equal to the number of OpenMP worker threads, i.e: the number
156  // of parallel RNG streams we require
157  const size_t n = rngs.size();
158  // Seed all RNGs with 'seed' & divide in 'n' streams
159  for (size_t i = 0; i < n; ++i) {
160  ss >> rngs[i];
161  rngs[i].split(n, i);
162  }
163 }
164 
165 void RandomEngine::SetState(const string& state)
166 {
167  switch (m_type_id) {
168  case TypeId::lcg64 :
169  para_seed(m_lcg64, state); break;
170  case TypeId::lcg64_shift :
171  para_seed(m_lcg64_shift, state); break;
172  case TypeId::mrg2 :
173  para_seed(m_mrg2, state); break;
174  case TypeId::mrg3 :
175  para_seed(m_mrg3, state); break;
176  case TypeId::yarn2 :
177  para_seed(m_yarn2, state); break;
178  case TypeId::yarn3 :
179  para_seed(m_yarn3, state); break;
180  }
181 }
182 
183 } // namespace
184 
185 
186 
187 
Type FromString(string s)
Converts a string with name to WallType::Type value.
Definition: WallType.cpp:59
STL namespace.
string ToString(Type w)
Converts a WallType::Type value to corresponding name.
Definition: WallType.cpp:49
Interface of RandomEngine.
Namespace for the core simulator.
bool Reinitialize()
Reset to the default engine (trng::mrg2 with seed 1).
Namespace for Types of random engines.
TypeId
Enumerates type ids.
std::time_t ToTimeT() const
Returns time stamp as a time_t.
Definition: TimeStamp.h:53
TimeStamp class.
Provides wall-clock time stamp using the time call.
Definition: TimeStamp.h:37
RandomEngineType::Info GetInfo() const
Return the state of the random engine.
void para_seed(std::vector< T > &rngs, const unsigned long seed)
Seed a vector of random number generators and splits in 'n' parallel streams using the leapfrog schem...
Namespace for clock and timekeeping related classes.
Definition: ClockCLib.h:27
bool IsExisting(std::string s)
Check whether type with name s exists.