source: trunk/yat/random/random.h @ 1797

Last change on this file since 1797 was 1797, checked in by Peter, 14 years ago

updating copyright statements

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.9 KB
Line 
1#ifndef _theplu_yat_random_
2#define _theplu_yat_random_
3
4// $Id: random.h 1797 2009-02-12 18:07:10Z peter $
5
6/*
7  Copyright (C) 2005, 2006, 2007, 2008 Jari Häkkinen, Peter Johansson
8
9  This file is part of the yat library, http://dev.thep.lu.se/yat
10
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with yat. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "yat/statistics/Histogram.h"
26
27#include <gsl/gsl_rng.h>
28#include <gsl/gsl_randist.h>
29
30#include <algorithm>
31#include <string>
32#include <vector>
33
34namespace theplu {
35namespace yat {
36namespace random {
37
38  //forward declarion
39  class RNG_state;
40
41  ///
42  /// @brief Random Number Generator
43  ///
44  /// The RNG class is wrapper to the GSL random number generator
45  /// (rng). This class provides a single global instance of the rng,
46  /// and makes sure there is only one point of access to the
47  /// generator.
48  ///
49  /// There is information about how to change seeding and generators
50  /// at run time without recompilation using environment variables in
51  /// the GSL manual (Chapter on random number generators). RNG of
52  /// course support seeding at compile time if you don't want to
53  /// bother about environment variables and GSL.
54  ///
55  /// There are many different rng's available in GSL. Currently only
56  /// the default generator is implemented and no other one is
57  /// choosable through the class interface. This means that you have
58  /// to fall back to the use of environment variables as described in
59  /// the GSL documentation, or be bold and request support for other
60  /// rng's through the class interface.
61  ///
62  /// Not all GSL functionality is implemented, we'll add
63  /// functionality when needed and may do it when requested. Better
64  /// yet, supply us with code and we will probably add it to the code
65  /// (BUT remember to implement reasonable tests for your code and
66  /// follow the coding style.)
67  ///
68  /// The current implementation is NOT thread safe since the RNG is
69  /// implemented as a singleton. However, the underlying GSL rng's
70  /// support thread safety since each instance of GSL rng's keep
71  /// track of their own state accordning to GSL documentation.
72  ///
73  /// @see Design Patterns (the singleton and adapter pattern). GSL
74  /// documentation.
75  ///
76  class RNG
77  {
78  public:
79
80    ///
81    /// @brief Get an instance of the random number generator.
82    ///
83    /// Get an instance of the random number generator. If the random
84    /// number generator is not already created, the call will create
85    /// a new generator and use the default seed. The seed must be
86    /// changed with the seed or seed_from_devurandom member
87    /// functions.
88    ///
89    /// @return A pointer to the random number generator.
90    ///
91    /// @see seed and seed_from_devurandom
92    ///
93    static RNG* instance(void);
94
95    ///
96    /// @brief Returns the largest number that the random number
97    /// generator can return.
98    ///
99    unsigned long max(void) const;
100
101    ///
102    /// @brief Returns the smallest number that the random number
103    /// generator can return.
104    ///
105    unsigned long min(void) const;
106
107    ///
108    /// @brief Returns the name of the random number generator
109    ///
110    std::string name(void) const;
111
112    ///
113    /// @return const pointer to underlying GSL random generator.
114    ///
115    const gsl_rng* rng(void) const;
116
117    ///
118    /// @brief Set the seed \a s for the rng.
119    ///
120    /// Set the seed \a s for the rng. If \a s is zero, a default
121    /// value from the rng's original implementation is used (cf. GSL
122    /// documentation).
123    ///
124    /// @see seed_from_devurandom
125    ///
126    void seed(unsigned long s) const;
127
128    ///
129    /// @brief Seed the rng using the /dev/urandom device.
130    ///
131    /// @return The seed acquired from /dev/urandom.
132    ///
133    unsigned long seed_from_devurandom(void);
134
135    /**
136       \brief Set the state to \a state.
137
138       \return 0 on success, non-zero otherwise.
139
140       \see gsl_rng_memcpy
141    */
142    int set_state(const RNG_state&);
143
144  private:
145    RNG(void);
146
147    /**
148       \brief Not implemented.
149
150       This copy contructor is not implemented. The constructor is
151       declared in order to avoid compiler generated default copy
152       constructor.
153     */
154    RNG(const RNG&);
155
156    /**
157       There can be only one RNG so assignment is always
158       self-assignment and we do not allow it
159    */
160    RNG& operator=(const RNG&);
161
162    virtual ~RNG(void);
163
164    static RNG* instance_;
165    gsl_rng* rng_;
166  };
167
168
169  ///
170  /// @brief Class holding state of a random generator
171  ///
172  class RNG_state
173  {
174  public:
175    ///
176    /// @brief Constructor
177    ///
178    RNG_state(const RNG*);
179
180    /**
181       Copy Constructor
182
183       \since Explicitely declared since yat 0.5
184     */
185    RNG_state(const RNG_state&);
186
187    ///
188    /// @brief Destructor
189    ///
190    ~RNG_state(void);
191
192    ///
193    /// @return const pointer to underlying GSL random generator.
194    ///
195    const gsl_rng* rng(void) const;
196
197    /**
198       Assignment operator
199
200       \since Explicitely declared since yat 0.5
201     */
202    RNG_state& operator=(const RNG_state&);
203
204  private:
205    gsl_rng* rng_;
206
207    void clone(const gsl_rng&);
208  };
209   
210
211  // --------------------- Discrete distribtuions ---------------------
212
213  ///
214  /// @brief Discrete random number distributions.
215  ///
216  /// Abstract base class for discrete random number
217  /// distributions. Given K discrete events with different
218  /// probabilities \f$ P[k] \f$, produce a random value k consistent
219  /// with its probability.
220  ///
221  class Discrete
222  {
223  public:
224    ///
225    /// @brief Constructor
226    ///
227    Discrete(void);
228
229    ///
230    /// @brief The destructor
231    ///
232    virtual ~Discrete(void);
233
234    ///
235    /// @brief Set the seed to \a s.
236    ///
237    /// Set the seed to \a s in the underlying rng. If \a s is zero, a
238    /// default value from the rng's original implementation is used
239    /// (cf. GSL documentation).
240    ///
241    /// @see seed_from_devurandom, RNG::seed_from_devurandom, RNG::seed
242    ///
243    void seed(unsigned long s) const;
244
245    ///
246    /// @brief Set the seed using the /dev/urandom device.
247    ///
248    /// @return The seed acquired from /dev/urandom.
249    ///
250    /// @see seed, RNG::seed_from_devurandom, RNG::seed
251    ///
252    unsigned long seed_from_devurandom(void);
253
254    ///
255    /// @return A random number.
256    ///
257    virtual unsigned long operator()(void) const = 0;
258   
259  protected:
260    /// GSL random gererator
261    RNG* rng_;
262  };
263
264  ///
265  /// @brief General
266  ///
267  class DiscreteGeneral : public Discrete
268  {
269  public:
270    ///
271    /// @brief Constructor
272    ///
273    /// @param hist is a Histogram defining the probability distribution
274    ///
275    DiscreteGeneral(const statistics::Histogram& hist);
276   
277    /**
278       \brief Copy constructor
279
280       \since Explicitely implemented in yat 0.5
281     */
282    DiscreteGeneral(const DiscreteGeneral&);
283
284    ///
285    /// @brief Destructor
286    ///
287    ~DiscreteGeneral(void);
288
289    ///
290    /// The generated number is an integer and proportinal to the
291    /// frequency in the corresponding histogram bin. In other words,
292    /// the probability that 0 is returned is proportinal to the size
293    /// of the first bin.
294    ///
295    /// @return A random number.
296    ///
297    unsigned long operator()(void) const;
298
299    /**
300       \brief Assignment operator
301
302       \since Explicitely implemented in yat 0.5
303     */
304    DiscreteGeneral& operator=(const DiscreteGeneral&);
305
306  private:
307    void free(void);
308    void preproc(void);
309
310    gsl_ran_discrete_t* gen_;
311    std::vector<double> p_;
312  };
313
314  /**
315     @brief Discrete uniform distribution
316 
317     Discrete uniform distribution also known as the "equally likely
318     outcomes" distribution. Each outcome, in this case an integer
319     from [0,n-1] , have equal probability to occur.
320     
321     Distribution function \f$ p(k) = \frac{1}{n+1} \f$ for \f$ 0 \le
322     k < n \f$ \n
323     Expectation value: \f$ \frac{n-1}{2} \f$ \n
324     Variance: \f$ \frac{1}{12}(n-1)(n+1) \f$
325  */
326  class DiscreteUniform : public Discrete
327  {
328  public:
329    /**
330       \brief Constructor.
331
332       The generator will generate integers within the range \f$
333       [0,n-1] \f$. If \a n is zero, then the whole range of the
334       underlying RNG will be used \f$ [min,max] \f$. Setting \a n to
335       zero is the preferred way to sample the whole range of the
336       underlying RNG, i.e. not setting \n to RNG.max.
337
338       \throw If \a n is larger than the maximum number the underlying
339       random number generator can return, then a GSL_error exception
340       is thrown.
341    */
342    DiscreteUniform(unsigned long n=0);
343
344    /**
345       \brief Get a random number
346
347       The returned integer is either in the range [RNG.min,RNG.max]
348       or [0,n-1] depending on how the random number generator was
349       created.
350
351       \see DiscreteUniform(const unsigned long n=0)
352    */
353    unsigned long operator()(void) const;
354
355    /**
356       \brief Get a random integer in the range \f$ [0,n-1] \f$.
357
358       All integers in the range [0,n-1] are equally likely. This
359       function should be avoided for sampling the whole range of the
360       underlying RNG.
361
362       \throw GSL_error if \a n is larger than the range of the
363       underlying generator.
364    */
365    unsigned long operator()(unsigned long n) const;
366
367  private:
368    unsigned long range_;
369  };
370
371  /**
372     @brief Poisson Distribution
373 
374     Having a Poisson process (i.e. no memory), number of occurences
375     within a given time window is Poisson distributed. This
376     distribution is the limit of a Binomial distribution when number
377     of attempts is large, and the probability for one attempt to be
378     succesful is small (in such a way that the expected number of
379     succesful attempts is \f$ m \f$.
380     
381     Probability function \f$ p(k) = e^{-m}\frac{m^k}{k!} \f$ for \f$ 0 \le
382     k  \f$ \n
383     Expectation value: \f$ m \f$ \n
384     Variance: \f$ m \f$
385  */
386  class Poisson : public Discrete
387  {
388  public:
389    ///
390    /// @brief Constructor
391    ///
392    /// @param m is expectation value
393    ///
394    Poisson(const double m=1);
395
396    ///
397    /// @return A Poisson distributed number.
398    ///
399    unsigned long operator()(void) const;
400
401    ///
402    /// @return A Poisson distributed number with expectation value
403    /// \a m
404    ///
405    /// @note this operator ignores parameters set in Constructor
406    ///
407    unsigned long operator()(const double m) const;
408
409  private:
410    double m_;
411  };
412
413  // --------------------- Continuous distribtuions ---------------------
414
415  ///
416  /// @brief Continuous random number distributions.
417  ///
418  /// Abstract base class for continuous random number distributions.
419  ///
420  class Continuous
421  {
422  public:
423
424    ///
425    /// @brief Constructor
426    ///
427    Continuous(void);
428
429    ///
430    /// @brief The destructor
431    ///
432    virtual ~Continuous(void);
433
434    ///
435    /// @brief Set the seed to \a s.
436    ///
437    /// Set the seed to \a s in the underlying rng. If \a s is zero, a
438    /// default value from the rng's original implementation is used
439    /// (cf. GSL documentation).
440    ///
441    /// @see seed_from_devurandom, RNG::seed_from_devurandom, RNG::seed
442    ///
443    void seed(unsigned long s) const;
444
445    ///
446    /// @brief Set the seed using the /dev/urandom device.
447    ///
448    /// @return The seed acquired from /dev/urandom.
449    ///
450    /// @see seed, RNG::seed_from_devurandom, RNG::seed
451    ///
452    unsigned long seed_from_devurandom(void) 
453    { return rng_->seed_from_devurandom(); }
454
455    ///
456    /// @return A random number
457    ///
458    virtual double operator()(void) const = 0;
459
460  protected:
461    /// pointer to GSL random generator
462    RNG* rng_;
463  };
464
465  // ContinuousUniform is declared before ContinuousGeneral to avoid
466  // forward declaration
467  ///
468  /// @brief Uniform distribution
469  ///
470  /// Class for generating a random number from a uniform distribution
471  /// in the range [0,1), i.e. zero is included but not 1.
472  ///
473  /// Distribution function \f$ f(x) = 1 \f$ for \f$ 0 \le x < 1 \f$ \n
474  /// Expectation value: 0.5 \n
475  /// Variance: \f$ \frac{1}{12} \f$
476  ///
477  class ContinuousUniform : public Continuous
478  {
479  public:
480    double operator()(void) const;
481  };
482
483  ///
484  /// @brief Generates numbers from a histogram in a continuous manner.
485  ///
486  class ContinuousGeneral : public Continuous
487  {
488  public:
489    ///
490    /// @brief Constructor
491    ///
492    /// @param hist is a Histogram defining the probability distribution
493    ///
494    ContinuousGeneral(const statistics::Histogram& hist);
495
496    ///
497    /// The number is generated in a two step process. First the bin
498    /// in the histogram is randomly selected (see
499    /// DiscreteGeneral). Then a number is generated uniformly from
500    /// the interval defined by the bin.
501    ///
502    /// @return A random number.
503    ///
504    double operator()(void) const;
505
506  private:
507    const DiscreteGeneral discrete_;
508    const statistics::Histogram hist_;
509    ContinuousUniform u_;
510  };
511
512  /**
513     \brief Generator of random numbers from an exponential
514     distribution.
515     
516     The distribution function is \f$ f(x) = \frac{1}{m}\exp(-x/a)
517     \f$ for \f$ x \f$ with the expectation value \f$ m \f$ and
518     variance \f$ m^2 \f$
519  */
520  class Exponential : public Continuous
521  {
522  public:
523    ///
524    /// @brief Constructor
525    ///
526    /// @param m is the expectation value of the distribution.
527    ///
528    Exponential(const double m=1);
529
530    ///
531    /// @return A random number from exponential distribution.
532    ///
533    double operator()(void) const;
534
535    ///
536    /// @return A random number from exponential distribution, with
537    /// expectation value \a m
538    ///
539    /// @note This operator ignores parameters given in constructor.
540    ///
541    double operator()(const double m) const;
542
543  private:
544    double m_;
545  };
546
547  /**
548     @brief Gaussian distribution
549     
550     Class for generating a random number from a Gaussian distribution
551     between zero and unity. Utilizes the Box-Muller algorithm, which
552     needs two calls to random generator.
553     
554     Distribution function \f$ f(x) =
555     \frac{1}{\sqrt{2\pi\sigma^2}}\exp(-\frac{(x-\mu)^2}{2\sigma^2})
556     \f$ \n
557     Expectation value: \f$ \mu \f$ \n
558     Variance: \f$ \sigma^2 \f$
559  */
560  class Gaussian : public Continuous
561  {
562  public:
563    ///
564    /// @brief Constructor
565    ///
566    /// @param s is the standard deviation \f$ \sigma \f$ of distribution
567    /// @param m is the expectation value \f$ \mu \f$ of the distribution
568    ///
569    Gaussian(const double s=1, const double m=0);
570
571    ///
572    /// @return A random Gaussian number
573    ///
574    double operator()(void) const;
575
576    ///
577    /// @return A random Gaussian number with standard deviation \a s
578    /// and expectation value 0.
579    ///
580    /// @note this operator ignores parameters given in Constructor
581    ///
582    double operator()(const double s) const;
583
584    ///
585    /// @return A random Gaussian number with standard deviation \a s
586    /// and expectation value \a m.
587    ///
588    /// @note this operator ignores parameters given in Constructor
589    ///
590    double operator()(const double s, const double m) const;
591
592  private:
593    double m_;
594    double s_;
595  };
596
597  /**
598     \brief Convenience function to shuffle a range with singleton RNG.
599
600     Wrapper around std::random_shuffle using DiscreteUniform as
601     random generator and thereby using the underlying RNG class,
602     which is singleton.
603   */
604  template<typename T>
605  void random_shuffle(T first, T last)
606  {
607    DiscreteUniform rnd;
608    std::random_shuffle(first, last, rnd);
609  }
610
611}}} // of namespace random, yat, and theplu
612
613#endif
Note: See TracBrowser for help on using the repository browser.