HyperGeometric.h
Go to the documentation of this file.
1 /*!
2  *
3  *
4  * \brief Hypergeometric 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_HYPERGEOMETRIC_H
33 #define SHARK_RNG_HYPERGEOMETRIC_H
34 
35 
36 
37 
38 #include <cmath>
39 #include <boost/random/uniform_01.hpp>
40 
41 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
42 #include <iostream>
43 #endif
44 
45 namespace shark{
46 /// \brief Hypergeometric distribution.
47  template<class IntType=int,class RealType = double>
49  {
50  public:
51  typedef RealType input_type;
52  typedef IntType result_type;
53 
54  explicit HyperGeometric_distribution(RealType mean,RealType variance)
55  :mean_(mean),variance_(variance)
56  {
57  if (mean == 0)
58  {
59  p = 0.;
60  }
61  else
62  {
63  double z = variance / (mean * mean);
64  p = (1 - std::sqrt((z - 1) / (z + 1))) / 2;
65 
66  if (p < 0.) p = 0.;
67  }
68  }
69 
70  RealType mean() const
71  {
72  return mean_;
73  }
74  RealType variance()const
75  {
76  return variance_;
77  }
78 
79  void reset() { }
80 
81  template<class Engine>
82  result_type operator()(Engine& eng)
83  {
84  double uni1 = boost::uniform_01<RealType>(eng);
85  double uni2 = boost::uniform_01<RealType>(eng);
86  return -mean_ * ::log( uni1) / (2 *( uni2 > p? 1 - p : p));
87  }
88 
89 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
90  template<class CharT, class Traits>
91  friend std::basic_ostream<CharT,Traits>&
92  operator<<(std::basic_ostream<CharT,Traits>& os, const HyperGeometric_distribution& d)
93  {
94  os << d.mean_;
95  os << d.variance_;
96  return os;
97  }
98 
99  template<class CharT, class Traits>
100  friend std::basic_istream<CharT,Traits>&
101  operator>>(std::basic_istream<CharT,Traits>& is, HyperGeometric_distribution& d)
102  {
103  is >> d.mean_;
104  is >> d.variance_;
105  return is;
106  }
107 #endif
108  private:
109  RealType mean_;
110  RealType variance_;
111  RealType p;
112  };
113 
114  /**
115  * \brief Random variable with a hypergeometric distribution.
116  */
117  template<typename RngType = shark::DefaultRngType>
118  class HyperGeometric:public boost::variate_generator<RngType*,HyperGeometric_distribution<> > {
119  private:
120  typedef boost::variate_generator<RngType*,HyperGeometric_distribution<> > Base;
121  public:
122 
123  HyperGeometric( RngType & rng, double k=1, double theta=1 )
124  :Base(&rng,HyperGeometric_distribution<>(k,theta))
125  {}
126 
127  using Base::operator();
128 
129  double operator()(double k,double theta)
130  {
131  HyperGeometric_distribution<> dist(k,theta);
132  return dist(Base::engine());
133  }
134 
135  double mean()const
136  {
137  return Base::distribution().mean();
138  }
139  double variance()const
140  {
141  return Base::distribution().variance();
142  }
143  void mean(double newMean)
144  {
145  Base::distribution()=HyperGeometric_distribution<>(newMean,variance());
146  }
147  void variance(double newVariance)
148  {
149  Base::distribution()=HyperGeometric_distribution<>(mean(),newVariance);
150  }
151 
152  double p(double x)const
153  {
154  return 0.0;///!!!
155  }
156 
157  };
158 }
159 #endif
160