hpp-statistics  4.9.0
Classes for doing statistics.
distribution.hh
Go to the documentation of this file.
1 // Copyright (c) 2014, LAAS-CNRS
2 // Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
3 //
4 // This file is part of hpp-statistics.
5 // hpp-statistics is free software: you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation, either version
8 // 3 of the License, or (at your option) any later version.
9 //
10 // hpp-statistics is distributed in the hope that it will be
11 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Lesser Public License for more details. You should have
14 // received a copy of the GNU Lesser General Public License along with
15 // hpp-statistics. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef HPP_STATISTICS_DISTRIBUTION_HH
18 # define HPP_STATISTICS_DISTRIBUTION_HH
19 
20 # include <vector>
21 # include <assert.h>
22 # include <stdlib.h>
23 # include <climits>
24 
25 # include "hpp/statistics/fwd.hh"
26 
27 namespace hpp {
28  namespace statistics {
29  template < typename Value_t >
31  {
32  public:
33  typedef std::size_t Weight_t;
34  typedef typename std::pair < Weight_t, Value_t> ProbaTPair;
35  typedef typename std::vector < ProbaTPair >::iterator iterator;
36  typedef typename std::vector < ProbaTPair >::const_iterator const_iterator;
37 
38  DiscreteDistribution () : values_(), cumulative_weights_() {}
39 
40  Value_t operator() () const {
41  assert (values_.size() > 0);
42  Weight_t r = rand() % cumulative_weights_.back();
43  return operator() (r);
44  }
45  Value_t operator() (const Proba_t& p) const {
46  return operator() ((Weight_t)(p * cumulative_weights_.back ()));
47  }
48  Value_t operator() (const Weight_t& w) const {
49  assert (values_.size() > 0);
50  return values_[dichotomy (w % cumulative_weights_.back())].second;
51  }
52 
56  void insert (Value_t v, Weight_t w = 1) {
57  iterator itv = values_.begin ();
58  WeightsIterator itcumul = cumulative_weights_.begin();
59  Weight_t c = 0;
60  while (itv != values_.end()) {
61  if (itv->second == v)
62  break;
63  c = *itcumul;
64  itv++; itcumul++;
65  }
66  if (itv == values_.end ()) {
67  values_.push_back (ProbaTPair(w,v));
68  cumulative_weights_.push_back (c + w);
69  if (cumulative_weights_.back () >= INT_MAX / 2)
70  shrink ();
71  return;
72  }
73  itv->first = w;
74  while (itv != values_.end()) {
75  c = c + itv->first;
76  *itcumul = c;
77  itv++; itcumul++;
78  }
79  if (cumulative_weights_.back () >= INT_MAX / 2)
80  shrink ();
81  }
82 
85  Weight_t get (const Value_t& v) const {
86  const_iterator itv = values_.begin ();
87  while (itv != values_.end()) {
88  if (itv->second == v)
89  return itv->first;
90  itv++;
91  }
92  return 0;
93  }
94 
96  size_t size () const {
97  return values_.size ();
98  }
99 
101  std::vector < Proba_t > probabilities () const {
102  if (values_.empty ()) return std::vector < Proba_t > (0);
103  std::vector < Proba_t > proba (values_.size());
104  Proba_t total = (double)cumulative_weights_.back();
105  for (size_t i = 0; i < values_.size (); i++)
106  proba[i] = (Proba_t)values_[i].first / total;
107  return proba;
108  }
109 
111  std::vector < Value_t > values () const {
112  if (values_.empty ()) return std::vector < Value_t > (0);
113  std::vector < Value_t > v (values_.size());
114  for (size_t i = 0; i < values_.size (); i++)
115  v[i] = values_[i].second;
116  return v;
117  }
118 
120  Weight_t totalWeight () const {
121  if (cumulative_weights_.empty ()) return 0;
122  return cumulative_weights_.back ();
123  }
124 
128  iterator begin () {
129  return values_.begin ();
130  }
131  const_iterator begin () const {
132  return values_.begin ();
133  }
134  iterator end () {
135  return values_.end ();
136  }
137  const_iterator end () const {
138  return values_.end ();
139  }
141  private:
142  size_t dichotomy (const Weight_t& r) const {
143  if (r < cumulative_weights_[0]) return 0;
144  size_t l = 0, h = values_.size () - 1, m;
145  while (l < h - 1) {
146  m = (l + h) / 2;
147  if (cumulative_weights_[m] <= r)
148  l = m;
149  else if (cumulative_weights_[m] > r)
150  h = m;
151  else
152  return m;
153  }
154  return h;
155  }
156 
158  void shrink () {
159  iterator itv = values_.begin ();
160  WeightsIterator itcumul = cumulative_weights_.begin();
161  Weight_t total = 0;
162  while (itv != values_.end()) {
163  if (itv->first > 1) {
164  itv->first = itv->first >> 1;
165  }
166  total += itv->first;
167  *itcumul = total;
168  itv++; itcumul++;
169  }
170  }
171 
172  std::vector < ProbaTPair > values_;
173  std::vector < Weight_t > cumulative_weights_;
174 
175  typedef std::vector < Weight_t >::iterator WeightsIterator;
176  };
177  } // namespace statistics
178 } // namespace hpp
179 
180 #endif // HPP_STATISTICS_DISTRIBUTION_HH
size_t size() const
Return the number of value.
Definition: distribution.hh:96
Implementation.
Value_t operator()() const
Definition: distribution.hh:40
double Proba_t
Definition: fwd.hh:22
std::vector< ProbaTPair >::iterator iterator
Definition: distribution.hh:35
std::vector< Value_t > values() const
Return the values.
Definition: distribution.hh:111
iterator end()
Definition: distribution.hh:134
std::size_t Weight_t
Definition: distribution.hh:33
const_iterator end() const
Definition: distribution.hh:137
iterator begin()
Definition: distribution.hh:128
const_iterator begin() const
Definition: distribution.hh:131
std::pair< Weight_t, Value_t > ProbaTPair
Definition: distribution.hh:34
std::vector< ProbaTPair >::const_iterator const_iterator
Definition: distribution.hh:36
DiscreteDistribution()
Definition: distribution.hh:38
Definition: distribution.hh:30
std::vector< Proba_t > probabilities() const
Return the probabilities.
Definition: distribution.hh:101
Weight_t totalWeight() const
Return the total weight.
Definition: distribution.hh:120
void insert(Value_t v, Weight_t w=1)
Definition: distribution.hh:56