LogNormal.h
Go to the documentation of this file.
1 /*!
2  *
3  *
4  * \brief Provides a log-normal distribution.
5  *
6  *
7  *
8  * \author O. Krause
9  * \date 2010-01-01
10  *
11  *
12  * \par Copyright 1995-2017 Shark Development Team
13  *
14  * <BR><HR>
15  * This file is part of Shark.
16  * <http://shark-ml.org/>
17  *
18  * Shark is free software: you can redistribute it and/or modify
19  * it under the terms of the GNU Lesser General Public License as published
20  * by the Free Software Foundation, either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * Shark is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU Lesser General Public License for more details.
27  *
28  * You should have received a copy of the GNU Lesser General Public License
29  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
30  *
31  */
32 #ifndef SHARK_RNG_LOGNORMAL_H
33 #define SHARK_RNG_LOGNORMAL_H
34 
35 #include <shark/Core/Math.h>
36 
37 #include <boost/random/lognormal_distribution.hpp>
38 
39 #include <cmath>
40 
41 namespace shark {
42  /**
43  * \brief Implements a log-normal distribution with parameters location m and Scale s.
44  *
45  * The propability distribution is
46  * \f[ p(x)= \frac {1} {x s \sqrt{2 \pi}}e^{-\frac{(\ln x -m)^2}{2 s^2}}\f]
47  */
48  //unfortunately, boost::math::lognormal_distribution uses scale/location as parameters as well as the next c++ standard, while
49  //boost::lognormal_distribution uses mean and sigma. in boost 1.47 there exists boost::random::lognormal_distribution which uses
50  //scale/location as well, but we use boost 1.44. For forward compliance, we use the new parameter set but transform them back to boost
51  //parameters.
52  template<typename RngType = shark::DefaultRngType>
53  class LogNormal : public boost::variate_generator<RngType*,boost::lognormal_distribution<> >
54  {
55  private:
56  typedef boost::variate_generator<RngType*,boost::lognormal_distribution<> > Base;
57  double m_location;
58  double m_scale;
59 
60 
61  boost::lognormal_distribution<> createDistribution(double location,double scale){
62  double mean = std::exp(location+scale*scale/2.0);
63  double variance = (std::exp(scale*scale)-1.0)* std::exp(2*location+scale*scale);
64  return boost::lognormal_distribution<>(mean,std::sqrt(variance));
65  }
66  public:
67  /**
68  * \brief C'tor, associates the distribution with a custom RNG.
69  * \param [in,out] rng The custom rng.
70  * \param [in] location The location of the distribution, default value is 0.
71  * \param [in] scale The scale of the distribution, default value is 1.
72  */
73  LogNormal( RngType & rng,
74  double location = 0,
75  double scale= 1 )
76  : Base(&rng,boost::lognormal_distribution<>(1,1)),m_location(location),m_scale(scale)
77  {
78  Base::distribution() = createDistribution(location,scale);
79  }
80 
81  /** \brief Injects the default sampling operator. */
82  using Base::operator();
83 
84  /**
85  * \brief Samples a random number.
86  * \param [in] location The location of the distribution.
87  * \param [in] scale The scale of the distribution.
88  */
89  double operator()(double location, double scale) {
90  return dist(createDistribution(location,scale) );
91  }
92 
93  /**
94  * \brief Accesses the location of the distribution.
95  */
96  double location() const {
97  return m_location;
98  }
99 
100  /**
101  * \brief Accesses the scale of the distribution.
102  */
103  double scale() const {
104  return m_scale;
105  }
106 
107  /**
108  * \brief Adjusts the location of the distribution.
109  */
110  void location(double newLocation)
111  {
112  m_location = newLocation;
113 
114  Base::distribution() = createDistribution(location(),scale());
115  }
116 
117  /**
118  * \brief Adjusts the scale of the distribution.
119  */
120  void scale(double newScale)
121  {
122  m_scale = newScale;
123  Base::distribution() = createDistribution(location(),scale());
124  }
125 
126  /**
127  * \brief Calculates the probability of x > 0.
128  */
129  double p(double x) const {
130 
131  double y = (std::log(x) - location()) / scale();
132  return x > 0 ? std::exp(-y*y / 2.0) / (boost::math::constants::root_two_pi<double>() * scale() * x) : 0;
133  }
134  };
135 
136 
137 }
138 #endif