hpp-statistics  5.0.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 <assert.h>
21 #include <stdlib.h>
22 
23 #include <climits>
24 #include <vector>
25 
26 #include "hpp/statistics/fwd.hh"
27 
28 namespace hpp {
29 namespace statistics {
30 template <typename Value_t>
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() = default;
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) break;
62  c = *itcumul;
63  itv++;
64  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) shrink();
70  return;
71  }
72  itv->first = w;
73  while (itv != values_.end()) {
74  c = c + itv->first;
75  *itcumul = c;
76  itv++;
77  itcumul++;
78  }
79  if (cumulative_weights_.back() >= INT_MAX / 2) shrink();
80  }
81 
84  Weight_t get(const Value_t& v) const {
85  const_iterator itv = values_.begin();
86  while (itv != values_.end()) {
87  if (itv->second == v) return itv->first;
88  itv++;
89  }
90  return 0;
91  }
92 
94  size_t size() const { return values_.size(); }
95 
97  std::vector<Proba_t> probabilities() const {
98  if (values_.empty()) return std::vector<Proba_t>(0);
99  std::vector<Proba_t> proba(values_.size());
100  Proba_t total = (double)cumulative_weights_.back();
101  for (size_t i = 0; i < values_.size(); i++)
102  proba[i] = (Proba_t)values_[i].first / total;
103  return proba;
104  }
105 
107  std::vector<Value_t> values() const {
108  if (values_.empty()) return std::vector<Value_t>(0);
109  std::vector<Value_t> v(values_.size());
110  for (size_t i = 0; i < values_.size(); i++) v[i] = values_[i].second;
111  return v;
112  }
113 
116  if (cumulative_weights_.empty()) return 0;
117  return cumulative_weights_.back();
118  }
119 
123  iterator begin() { return values_.begin(); }
124  const_iterator begin() const { return values_.begin(); }
125  iterator end() { return values_.end(); }
126  const_iterator end() const { return values_.end(); }
128  private:
129  size_t dichotomy(const Weight_t& r) const {
130  if (r < cumulative_weights_[0]) return 0;
131  size_t l = 0, h = values_.size() - 1, m;
132  while (l < h - 1) {
133  m = (l + h) / 2;
134  if (cumulative_weights_[m] <= r)
135  l = m;
136  else if (cumulative_weights_[m] > r)
137  h = m;
138  else
139  return m;
140  }
141  return h;
142  }
143 
145  void shrink() {
146  iterator itv = values_.begin();
147  WeightsIterator itcumul = cumulative_weights_.begin();
148  Weight_t total = 0;
149  while (itv != values_.end()) {
150  if (itv->first > 1) {
151  itv->first = itv->first >> 1;
152  }
153  total += itv->first;
154  *itcumul = total;
155  itv++;
156  itcumul++;
157  }
158  }
159 
160  std::vector<ProbaTPair> values_;
161  std::vector<Weight_t> cumulative_weights_;
162 
163  typedef std::vector<Weight_t>::iterator WeightsIterator;
164 };
165 } // namespace statistics
166 } // namespace hpp
167 
168 #endif // HPP_STATISTICS_DISTRIBUTION_HH
Definition: distribution.hh:31
std::vector< ProbaTPair >::iterator iterator
Definition: distribution.hh:35
const_iterator begin() const
Definition: distribution.hh:124
size_t size() const
Return the number of value.
Definition: distribution.hh:94
Weight_t get(const Value_t &v) const
Definition: distribution.hh:84
iterator end()
Definition: distribution.hh:125
std::vector< ProbaTPair >::const_iterator const_iterator
Definition: distribution.hh:36
Value_t operator()(const Proba_t &p) const
Definition: distribution.hh:45
iterator begin()
Definition: distribution.hh:123
std::size_t Weight_t
Definition: distribution.hh:33
std::vector< Value_t > values() const
Return the values.
Definition: distribution.hh:107
Value_t operator()() const
Definition: distribution.hh:40
Weight_t totalWeight() const
Return the total weight.
Definition: distribution.hh:115
std::pair< Weight_t, Value_t > ProbaTPair
Definition: distribution.hh:34
std::vector< Proba_t > probabilities() const
Return the probabilities.
Definition: distribution.hh:97
void insert(Value_t v, Weight_t w=1)
Definition: distribution.hh:56
Value_t operator()(const Weight_t &w) const
Definition: distribution.hh:48
const_iterator end() const
Definition: distribution.hh:126
double Proba_t
Definition: fwd.hh:22
Implementation.
Definition: main.hh:17