OpenGM  2.3.x
Discrete Graphical Model Library
random.hxx
Go to the documentation of this file.
1 #pragma once
2 #ifndef OPENGM_RANDOM_HXX
3 #define OPENGM_RANDOM_HXX
4 
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <time.h>
10 
11 #include "opengm/opengm.hxx"
12 
13 namespace opengm {
14 
15 template<class T>
16  class RandomUniformBase;
17 template<class T>
18  class RandomUniformFloatingPoint;
19 template<class T>
20  class RandomUniformInteger;
21 template<class T>
22  class RandomUniformUnknown;
23 template<class T>
24  class RandomUniform;
25 
26 template<class T>
27 class RandomUniformBase
28 {
29 public:
30  RandomUniformBase& operator=(const RandomUniformBase& src)
31  {
32  if(this!=&src) {
33  low_=src.low_;
34  high_=src.high_;
35  }
36  return *this;
37  }
38 
39  RandomUniformBase(const T low = 0, const T high = 1)
40  : low_(low),
41  high_(high)
42  {}
43 
44  void setLow(const T low) {
45  low_ = low;
46  }
47 
48  void setHigh(const T high) {
49  high_ = high;
50  }
51 
52 private:
53  T low_;
54  T high_;
55 
56 template<class> friend class RandomUniformInteger;
57 template<class> friend class RandomUniformFloatingPoint;
58 template<class> friend class RandomUniformUnknown;
59 template<class> friend class RandomUniform;
60 };
61 
62 template<class T>
63 class RandomUniformInteger
64 : public RandomUniformBase<T>
65 {
66 public:
67  RandomUniformInteger(const T low = 0, const T high = 1)
68  : RandomUniformBase<T>(low, high)
69  {}
70 
71  RandomUniformInteger(const T low, const T high, const size_t seed)
72  : RandomUniformBase<T>(low, high)
73  {
74  srand(time_t(seed));
75  }
76 
77  T operator()() const
78  {
79  // intended semantics: random number is drawn from [low_, high)
80  // however, not all std random number generators behave like this
81  // thus this trivial work-around:
82  T randomNumber = this->high_;
83  while(randomNumber == this->high_) {
84  randomNumber = static_cast<T>((rand() % (this->high_ - this->low_)) + this->low_);
85  }
86  return randomNumber;
87  }
88 
89 template<class> friend class RandomUniform;
90 };
91 
92 template<class T>
93 class RandomUniformFloatingPoint
94 : public RandomUniformBase<T>
95 {
96 public:
97  RandomUniformFloatingPoint(const T low = 0, const T high = 1)
98  : RandomUniformBase<T>(low, high)
99  {}
100 
101  RandomUniformFloatingPoint(const T low, const T high, const size_t seed)
102  : RandomUniformBase<T>(low, high)
103  {
104  srand(time_t(seed));
105  }
106 
107  T operator()() const
108  {
109  // intended semantics: random number is drawn from [low_, high)
110  // however, not all std random number generators behave like this
111  // thus this trivial work-around:
112  T randomNumber = this->high_;
113  while(randomNumber == this->high_) {
114  randomNumber = (static_cast<T>(rand()) / static_cast<T>(RAND_MAX)) * (this->high_ - this->low_) + this->low_;
115  }
116  return randomNumber;
117  }
118 
119 template<class> friend class RandomUniform;
120 };
121 
122 template<class T>
123 class RandomUniformUnknown : RandomUniformBase<T> {
124 template<class> friend class RandomUniform;
125 };
126 
127 template<class T>
128 class RandomUniform
129 : public
130  opengm::meta::If
131  <
132  opengm::meta::IsFundamental<T>::value,
133  typename opengm::meta::If
134  <
135  opengm::meta::IsFloatingPoint<T>::value,
136  opengm::RandomUniformFloatingPoint<T>,
137  opengm::RandomUniformInteger<T>
138  >::type,
139  RandomUniformUnknown<T>
140  >::type
141 {
142 private:
143  typedef typename opengm::meta::If
144  <
145  opengm::meta::IsFundamental<T>::value,
146  typename opengm::meta::If
147  <
148  opengm::meta::IsFloatingPoint<T>::value,
149  opengm::RandomUniformFloatingPoint<T>,
150  opengm::RandomUniformInteger<T>
151  >::type,
152  RandomUniformUnknown<T>
153  >::type BaseType;
154 
155 public:
156  RandomUniform(const T low = 0, const T high = 1)
157  : BaseType(low, high)
158  {}
159 
160  RandomUniform(const T low, const T high, const size_t seed)
161  : BaseType(low, high, seed)
162  {}
163 };
164 
165 template<class T, class U>
166 class RandomDiscreteWeighted
167 {
168 public:
169  RandomDiscreteWeighted() {}
170 
171  template<class Iterator>
172  RandomDiscreteWeighted(Iterator begin, Iterator end)
173  : probSum_(std::distance(begin, end)),
174  randomFloatingPoint_(0, 1)
175  {
176  U sum = 0;
177  // normalization
178  for(size_t i=0;i<probSum_.size();++i) {
179  probSum_[i]=static_cast<U>(*begin);
180  ++begin;
181  sum+=probSum_[i];
182  }
183  probSum_[0]/=sum;
184  for(size_t i=1;i<probSum_.size();++i) {
185  probSum_[i]/=sum;
186  probSum_[i]+=probSum_[i-1];
187  }
188  }
189 
190  template<class Iterator>
191  RandomDiscreteWeighted(Iterator begin, Iterator end, size_t seed)
192  : probSum_(std::distance(begin, end)),
193  randomFloatingPoint_(0, 1, seed)
194  {
195  U sum=0;
196  // normalization
197  for(size_t i=0;i<probSum_.size();++i) {
198  probSum_[i]=static_cast<U>(*begin);
199  ++begin;
200  sum+=probSum_[i];
201  }
202  probSum_[0]/=sum;
203  // accumulatives
204  for(size_t i=1;i<probSum_.size();++i) {
205  probSum_[i]/=sum;
206  probSum_[i]+=probSum_[i-1];
207  }
208  }
209 
210  T operator()() const
211  {
212  U rnd = randomFloatingPoint_();
213  if(rnd < probSum_[0]) {
214  return 0;
215  }
216  for(size_t i=0;i<probSum_.size()-1;++i) {
217  if(probSum_[i]<=rnd && rnd<probSum_[i+1]) {
218  return static_cast<T>(i+1);
219  }
220  }
221  return static_cast<T>(probSum_.size() - 1);
222  }
223 
224 private:
225  std::vector<U> probSum_;
226  opengm::RandomUniform<U> randomFloatingPoint_;
227 };
228 
229 } // namespace opengm
230 
232 
233 #endif // #ifndef OPENGM_RANDOM_HXX
The OpenGM namespace.
Definition: config.hxx:43