Erlang.h
Go to the documentation of this file.
1 /*!
2  *
3  *
4  * \brief Implements an Erlang 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_ERLANG_H
33 #define SHARK_RNG_ERLANG_H
34 
35 
36 
37 #include <shark/Rng/Gamma.h>
38 #include <boost/random/uniform_01.hpp>
39 #include <cmath>
40 #include <vector>
41 
42 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
43 #include <iostream>
44 #endif
45 
46 namespace shark{
47 
48 /// \brief Implements an Erlang distribution.
49 template<class RealType=double>
51 {
52  public:
53  typedef RealType input_type;
54  typedef RealType result_type;
55 
56  explicit Erlang_distribution(RealType mean=0,RealType variance=1)
57  :mean_(mean),variance_(variance)
58  {
59  k = static_cast<std::size_t>(std::ceil(mean * mean / variance));
60  if (k == 0)
61  k = 1;
62 
63  if (mean > 0)
64  a = k / mean;
65  else
66  a = 0.5;
67  }
68 
69  RealType mean() const
70  {
71  return mean_;
72  }
73  RealType variance() const
74  {
75  return variance_;
76  }
77 
78  void reset() { }
79 
80  template<class Engine>
81  result_type operator()(Engine& eng)
82  {
83  double prod = 1;
84 
85  if (k == 0 || a <= 0) return 0.;
86 
87  //double maxEng = eng.max();
88  //double minEng = eng.min();
89 
90  unsigned int kPrime = k;
91  while(kPrime--){
92  double uni = boost::uniform_01<RealType>()(eng);
93  prod *= uni;
94  }
95  return -std::log(prod) / a;
96  }
97 
98 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
99  template<class CharT, class Traits>
100  friend std::basic_ostream<CharT,Traits>&
101  operator<<(std::basic_ostream<CharT,Traits>& os, const Erlang_distribution& d)
102  {
103  os << d.alphas.size();
104  for(int i=0;i!=d.alphas_.size();++i)
105  os << d.alphas_[i];
106  return os;
107  }
108 
109  template<class CharT, class Traits>
110  friend std::basic_istream<CharT,Traits>&
111  operator>>(std::basic_istream<CharT,Traits>& is, Erlang_distribution& d)
112  {
113  size_t size;
114  is >> size;
115  for(int i=0;i!=size;++i)
116  {
117  double element;
118  is >> element;
119  d.alphas_.push_back(element);
120  }
121  return is;
122  }
123 #endif
124  private:
125  double mean_;
126  double variance_;
127  std::size_t k;
128  RealType a;
129 };
130 
131 /**
132 * \brief Erlang distributed random variable.
133 */
134 template<typename RngType = shark::DefaultRngType>
135 class Erlang:public boost::variate_generator<RngType*,Erlang_distribution<> >
136 {
137  private:
138  /** \brief The base type this class inherits from. */
139  typedef boost::variate_generator<RngType*,Erlang_distribution<> > Base;
140  public:
141 
142  /**
143  * \brief Default c'tor, associates the distribution with the supplied RNG.
144  * \param [in,out] rng The RNG to associate the distribution with.
145  * \param [in] mean The parameter mean, default value 0.
146  * \param [in] variance The parameter variance, default value 1.
147  */
148  explicit Erlang( RngType & rng, double mean=0,double variance=1 )
149  :Base(&rng,Erlang_distribution<>(mean,variance))
150  {}
151 
152  /**
153  * \brief Injects the default sampling operator.
154  */
155  using Base::operator();
156 
157  /**
158  * \brief Reinitializes the distribution for the supplied parameters and samples a new random number.
159  * Default values are omitted to distinguish the operator from the default one.
160  *
161  * \param [in] mean The new mean.
162  * \param [in] variance The new variance.
163  */
164  double operator()(double mean,double variance)
165  {
166  Erlang_distribution<> dist(mean,variance);
167  return dist(Base::engine());
168  }
169 
170  /**
171  * \brief Accesses the mean of the distribution.
172  */
173  double mean()const
174  {
175  return Base::distribution().mean();
176  }
177 
178  /**
179  * \brief Accesses the variance of the distribution.
180  */
181  double variance()const
182  {
183  return Base::distribution().variance();
184  }
185 
186  /**
187  * \brief Adjusts the mean of the distribution.
188  */
189  void mean(double newMean)
190  {
191  Base::distribution()=Erlang_distribution<>(newMean,Base::distribution().variance());
192  }
193 
194  /**
195  * \brief Adjusts the variance of the distribution.
196  */
197  void variance(double newVariance)
198  {
199  Base::distribution()=Erlang_distribution<>(mean(),newVariance);
200  }
201 
202  /**
203  * \brief Calculates the probability of x.
204  */
205  double p(double&x)const
206  {
207  double k = mean() * mean() / variance() + 0.5;
208  if (k == 0)
209  k = 1;
210 
211  double a=0;
212  if (mean() > 0)
213  a = k / mean();
214  else
215  a = 0.5;
216 
217  if (k == 0 || a <= 0 || x < 0) return 0.;
218 
219  return std::pow(k * a, k) * std::pow(x, k - 1) * std::exp(- k * a * x);
220  }
221 
222 };
223 }
224 #endif
225