KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
prob_sample.h
Go to the documentation of this file.
1 /* ======================================================================== *
2  | |
3  | Copyright (c) 2007-2010, by members of University of Arizona Computer |
4  | Vision group (the authors) including |
5  | Kobus Barnard, Kyle Simek, Ernesto Brau. |
6  | |
7  | For use outside the University of Arizona Computer Vision group please |
8  | contact Kobus Barnard. |
9  | |
10  * ======================================================================== */
11 
12 /* $Id: prob_sample.h 18761 2015-04-04 00:47:45Z cdawson $ */
13 
14 #ifndef PROB_SAMPLE_H_INCLUDED
15 #define PROB_SAMPLE_H_INCLUDED
16 
29 #include <prob_cpp/prob_pdf.h>
30 #include <m_cpp/m_vector.h>
31 #include <m_cpp/m_vector_d.h>
32 #include <m_cpp/m_matrix_d.h>
33 #include <g_cpp/g_util.h>
34 #include <l_cpp/l_util.h>
35 #include <boost/random.hpp>
36 #include <algorithm>
37 #include <vector>
38 
39 namespace kjb {
40 
42 extern const unsigned int DEFAULT_SEED;
43 
44 // Basic random generator -- used for sampling -- belongs to the cpp file
45 //typedef boost::minstd_rand Base_generator_type;
46 typedef boost::mt19937 Base_generator_type;
48 //extern boost::uniform_01<Base_generator_type> uni01;
49 
50 /* /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ */
51 
55 inline void seed_sampling_rand(unsigned int x0)
56 {
57  basic_rnd_gen.seed(x0);
58 // uni01 = boost::uniform_01<Base_generator_type>(basic_rnd_gen);
59 }
60 
64 inline double sample(const Uniform_distribution& dist)
65 {
66  typedef boost::uniform_real<> Distribution_type;
67  typedef boost::variate_generator<Base_generator_type&, Distribution_type> Rng;
68  Rng rng(basic_rnd_gen, Distribution_type(dist.lower(), dist.upper()));
69  return rng();
70 }
71 
84 template<class Distro>
85 inline double sample(const Distro& dist)
86 {
87  // this sometimes results in infinite recursion inside of boost. No ideas :-(
88  double u = sample(Uniform_distribution());
89  return quantile(dist, u);
90 }
91 
95 inline double sample(const Bernoulli_distribution& dist)
96 {
97  typedef boost::bernoulli_distribution<> Distribution_type;
98  typedef boost::variate_generator<Base_generator_type&, Distribution_type> Rng;
99 
100  Rng rng(basic_rnd_gen, Distribution_type(dist.success_fraction()));
101  return rng();
102 }
103 
107 inline double sample(const Binomial_distribution& dist)
108 {
109  typedef boost::binomial_distribution<> Distribution_type;
110  typedef boost::variate_generator<Base_generator_type&, Distribution_type> Rng;
111 
112  Rng rng(basic_rnd_gen, Distribution_type(dist.trials(), dist.success_fraction()));
113  return rng();
114 }
115 
119 inline double sample(const Exponential_distribution& dist)
120 {
121  typedef boost::exponential_distribution<> Distribution_type;
122  typedef boost::variate_generator<Base_generator_type&, Distribution_type> Rng;
123 
124  Rng rng(basic_rnd_gen, Distribution_type(dist.lambda()));
125  return rng();
126 }
127 
131 inline double sample(const Gaussian_distribution& dist)
132 {
133  typedef boost::normal_distribution<> Distribution_type;
134  typedef boost::variate_generator<Base_generator_type&, Distribution_type> Rng;
135 
136  Rng rng(basic_rnd_gen, Distribution_type(dist.mean(), dist.standard_deviation()));
137  return rng();
138 }
139 
143 inline double sample(const Poisson_distribution& dist)
144 {
145  typedef boost::poisson_distribution<> Distribution_type;
146  typedef boost::variate_generator<Base_generator_type&, Distribution_type> Rng;
147 
148  Rng rng(basic_rnd_gen, Distribution_type(dist.mean()));
149  return rng();
150 }
151 
152 #if BOOST_VERSION < 103400
153 inline double sample(const Geometric_distribution& dist)
154 {
155 #warning "sample(Geometric_distribution) not implemented in Boost prior to 1.034"
157 }
158 #else
159 inline double sample(const Geometric_distribution& dist)
160 {
161  // this might not be available in older boost versions but exactly which version it was added is kind of a pain.
162  // If you can't compile because this isn't available, look in /usr/local/boost/version.hpp and determine which version you have.
163 #if BOOST_VERSION >= 104700
164  double dist_param = dist.success_fraction();
165 #else /* BOOST_VERSION >= 103400 */
166  KJB(UNTESTED_CODE());
167  double dist_param = 1.0-dist.success_fraction();
168 #endif
169 
170  typedef boost::geometric_distribution<> Distribution_type;
171  typedef boost::variate_generator<Base_generator_type&, Distribution_type> Rng;
172 
173  Rng rng(basic_rnd_gen, Distribution_type(dist_param));
174  return rng();
175 }
176 #endif /* BOOST_VERSION < 10340 */
177 
181 template<class T>
183 {
184  // TODO: This is currently O(log n), but approaches exist that
185  // make this constant, see the Alias Table methods described here:
186  // http://www.keithschwarz.com/darts-dice-coins/
187  // Also boost's discrete_distribution implements most of what
188  // this class does, so we could replace this with that.
189  double u = sample(Uniform_distribution());
190 
191  using namespace boost;
192 
193  if(dist.cdf_.empty())
194  {
195  KJB_THROW_2(Runtime_error, "Attempting to sample from an empty set.");
196  }
197 
198  assert(dist.cdf_.size() == dist.db.size()); // init_cdf() was called
199  double total_weight = dist.cdf_.back().second;
200  u *= total_weight;
201 
202  typedef Categorical_distribution<T> Cd;
203  typedef typename Cd::Cdf_pair Cdf_pair;
204  typedef typename std::vector<Cdf_pair>::const_iterator Const_iterator;
205 
206  // use binary search to find first element in CDF that exceeds u
207  Const_iterator r =
208  std::lower_bound(
209  dist.cdf_.begin(),
210  dist.cdf_.end(),
211  u,
212  typename Cd::cdf_pair_less_than_scalar());
213 
214  assert(r != dist.cdf_.end());
215 
216  return *r->first;
217 
218 }
219 
226 template<class Iterator, class distance_type>
227 inline
228 Iterator element_uar(Iterator first, distance_type size)
229 {
230  int dist = kjb::sample(kjb::Categorical_distribution<size_t>(0, size - 1, 1));
231  Iterator p = first;
232  std::advance(p, dist);
233 
234  return p;
235 }
236 
240 Vector sample(const MV_gaussian_distribution& dist);
241 
242 inline double sample(const Log_normal_distribution& dist)
243 {
244  return exp(sample(dist.dist_));
245 }
246 
250 template<class Distribution>
251 inline
252 typename Distribution_traits<Mixture_distribution<Distribution> >::type
254 {
255  size_t i = sample(dist.coeffs);
256  return sample(dist.dists[i - 1]);
257 }
258 
263 template <size_t D> inline kjb::Vector_d<D> sample(const Uniform_sphere_distribution<D>& /* dist */)
264 {
265  kjb::Vector_d<D> result;
266 
267  static const Gaussian_distribution norm_dist(0, 1);
268 
269  for(size_t d = 0; d < D; ++d)
270  {
271  result[d] = kjb::sample(norm_dist);
272  }
273 
274  return result.normalize();
275 }
276 
277 
283 template <size_t D, class Vector_d_iterator>
284 inline
285 void sample(const Von_mises_fisher_distribution<D>& dist, size_t n, Vector_d_iterator it)
286 {
287  size_t m = D;
288  static const kjb::Vector_d<D> z_hat = kjb::create_unit_vector<D>(D-1);
289 
290  const Vector_d<D>& mu_ = dist.mu();
291  double kappa_ = dist.kappa();
292 
293  // TODO: Quaternion may be slower than is needed here. Consider
294  // constructing the rotation matrix by hand or move q into a member variable
295  // I replaced it with a function I wrote to find rotation matrices
296  // between two directions in any dimension. I haven't tested it as
297  // thoroughly as it needs, but I'm pretty confident it's correct.
298  // -- Ernesto [2014/10/28]
299  //kjb::Quaternion q; q.set_from_directions(z_hat, mu_);
301 
302  double b = (-2*kappa_ + sqrt(4*kappa_*kappa_ + (m-1)*(m-1)))/(m-1);
303  double x0 = (1-b)/(1+b);
304  double c = kappa_*x0 + (m-1)*log(1-x0*x0);
305 
306  Uniform_sphere_distribution<D-1> subdir_dist;
307  for(size_t i = 0; i < n; ++i)
308  {
309  double W, U;
310  do
311  {
312  // rejection sampling for height on unit sphere,
313  // distributed as f(w) = k * exp(kappa*w) ; for w \in [-1, 1], zero elsewhere
314  // see Sungkyu Jung's treatment:.
315  // http://www.stat.pitt.edu/sungkyu/software/randvonMisesFisher3.pdf
316  double Z = kjb::sample(kjb::Beta_distribution((m-1)/2,(m-1)/2));
317  W = (1-(1+b)*Z)/(1-(1-b)*Z);
319  } while(kappa_*W + (m-1)*log(1-x0*W) - c < log(U));
320 
321 
322  kjb::Vector_d<D-1> subdir = kjb::sample(subdir_dist);
323  subdir *= sqrt(1- W*W);
324 
325  kjb::Vector_d<D> dir;
326  std::copy(subdir.begin(), subdir.end(), dir.begin());
327  dir.back() = W;
328 
329  //dir = q.rotate(dir);
330  dir = R*dir;
331  *it = dir;
332  ++it;
333  }
334 }
335 
339 template <size_t D>
341 {
342  Vector_d<D> result;
343  sample(dist, 1, &result);
344  return result;
345 }
346 
348 Crp::Type sample(const Chinese_restaurant_process& crp);
349 
355 size_t sample_occupied_tables(const Chinese_restaurant_process& crp);
356 
357 } //namespace kjb
358 
359 #endif /*PROB_SAMPLE_H_INCLUDED */
360 
361 
362 
363 
364 
365 
366 
367 
368 
369 
370 
Definition: gr_opengl.h:41
Base_generator_type basic_rnd_gen
const kjb::Vector_d< D > & mu() const
Definition: prob_distribution.h:996
boost::math::bernoulli Bernoulli_distribution
Definition: prob_distribution.h:60
boost::mt19937 Base_generator_type
Definition: prob_sample.h:46
Definition of various standard probability distributions.
double kappa() const
Definition: prob_distribution.h:998
std::vector< std::vector< size_t > > Type
Definition: prob_distribution.h:1019
This class implements a mixture distribution. In other words, it is the sum of a finite number of fra...
Definition: prob_distribution.h:867
void seed_sampling_rand(unsigned int x0)
Seed random number generator.
Definition: prob_sample.h:55
#define KJB(x)
Definition: l_util.h:9
boost::math::poisson Poisson_distribution
Definition: prob_distribution.h:69
Log-normal distribution.
Definition: prob_distribution.h:827
boost::math::normal Gaussian_distribution
Definition: prob_distribution.h:66
r
Definition: APPgetLargeConnectedEdges.m:127
Definition: prob_distribution.h:984
#define KJB_THROW(ex)
Definition: l_exception.h:46
Vector sample(const MV_gaussian_distribution &dist)
Sample from a multivariate normal distribution.
Definition: prob_sample.cpp:42
A categorical distribution.
Definition: prob_distribution.h:131
const unsigned int DEFAULT_SEED
Random seed used to initialize the random number generator.
Definition: prob_sample.cpp:34
double dist(const pt a, const pt b)
compute approx. Great Circle distance between two UTM points
Definition: layer.cpp:45
Definition: prob_distribution.h:966
boost::math::beta_distribution Beta_distribution
Definition: prob_distribution.h:61
boost::math::exponential Exponential_distribution
Definition: prob_distribution.h:64
PDFs and CDFs for the different distributions defined in "prob_distribution.h".
Definition: prob_distribution.h:79
Vector_d< D > & normalize()
normalize this vector to have l2-norm of 1.0
Definition: m_vector_d.impl.h:376
boost::math::binomial Binomial_distribution
Definition: prob_distribution.h:62
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
#define W(X)
Definition: Wide.h:45
Iterator element_uar(Iterator first, distance_type size)
Pick an element uniformly at random (UAR) from a sequence, represented by a beginning iterator and a ...
Definition: prob_sample.h:228
Object thrown when attempting to use unimplemented functionality.
Definition: l_exception.h:281
Definition: g_quaternion.h:37
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48
Matrix get_rotation_matrix(double theta)
Creates a (2D) rotation matrix from the given angle.
Definition: g_util.cpp:41
boost::math::uniform Uniform_distribution
Definition: prob_distribution.h:70
for m
Definition: APPgetLargeConnectedEdges.m:64
D
Definition: APPgetLargeConnectedEdges.m:106
size_t sample_occupied_tables(const Chinese_restaurant_process &crp)
Sample the number of occupied tables from a CRP (don't store the actual partition).
Definition: prob_sample.cpp:107
Definition for the Vector class, a thin wrapper on the KJB Vector struct and its related functionalit...
Object thrown when computation fails somehow during execution.
Definition: l_exception.h:321