bpp-core3  3.0.0
SimpleDiscreteDistribution.cpp
Go to the documentation of this file.
1 //
2 // File: SimpleDiscreteDistribution.cpp
3 // Authors:
4 // Julien Dutheil
5 // Created: ?
6 //
7 
8 /*
9  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
10 
11  This software is a computer program whose purpose is to provide classes
12  for numerical calculus.
13 
14  This software is governed by the CeCILL license under French law and
15  abiding by the rules of distribution of free software. You can use,
16  modify and/ or redistribute the software under the terms of the CeCILL
17  license as circulated by CEA, CNRS and INRIA at the following URL
18  "http://www.cecill.info".
19 
20  As a counterpart to the access to the source code and rights to copy,
21  modify and redistribute granted by the license, users are provided only
22  with a limited warranty and the software's author, the holder of the
23  economic rights, and the successive licensors have only limited
24  liability.
25 
26  In this respect, the user's attention is drawn to the risks associated
27  with loading, using, modifying and/or developing or reproducing the
28  software by the user in light of its specific status of free software,
29  that may mean that it is complicated to manipulate, and that also
30  therefore means that it is reserved for developers and experienced
31  professionals having in-depth computer knowledge. Users are therefore
32  encouraged to load and test the software's suitability as regards their
33  requirements in conditions enabling the security of their systems and/or
34  data to be ensured and, more generally, to use and operate it in the
35  same conditions as regards security.
36 
37  The fact that you are presently reading this means that you have had
38  knowledge of the CeCILL license and that you accept its terms.
39 */
40 
41 
42 #include "../../Text/TextTools.h"
43 #include "../../Utils/MapTools.h"
44 #include "../NumConstants.h"
46 
47 using namespace bpp;
48 using namespace std;
49 
50 
51 SimpleDiscreteDistribution::SimpleDiscreteDistribution(const map<double, double>& distribution,
52  double prec,
53  bool fixed) :
54  AbstractDiscreteDistribution(distribution.size(), prec, "Simple."),
55  givenRanges_()
56 {
57  double sum = 0;
58  for (map<double, double>::const_iterator i = distribution.begin(); i != distribution.end(); i++)
59  {
60  distribution_[i->first] = i->second;
61  sum += i->second;
62  }
63  if (fabs(1. - sum) > precision())
64  throw Exception("SimpleDiscreteDistribution. Probabilities must equal 1 (sum =" + TextTools::toString(sum) + ").");
65 
66  if (!fixed)
67  {
68  unsigned int n = 1;
69  double x, y = 1;
70  for (map<double, double>::const_iterator i = distribution.begin(); i != distribution.end(); i++)
71  {
72  addParameter_(new Parameter("Simple.V" + TextTools::toString(n), i->first));
73 
74  if (n != numberOfCategories_)
75  {
76  x = i->second;
78  y -= x;
79  }
80  n++;
81  }
82  }
83  discretize();
84 }
85 
87  const vector<double>& probas,
88  double prec,
89  bool fixed
90  ) :
91  AbstractDiscreteDistribution(values.size(), prec, "Simple."),
92  givenRanges_()
93 {
94  if (values.size() != probas.size())
95  {
96  throw Exception("SimpleDiscreteDistribution. Values and probabilities vectors must have the same size (" + TextTools::toString(values.size()) + " != " + TextTools::toString(probas.size()) + ").");
97  }
98  size_t size = values.size();
99 
100  for (size_t i = 0; i < size; i++)
101  {
102  if (distribution_.find(values[i]) != distribution_.end())
103  throw Exception("SimpleDiscreteDistribution: two given values are equal");
104  else
105  distribution_[values[i]] = probas[i];
106  }
107 
108  double sum = VectorTools::sum(probas);
109  if (fabs(1. - sum) > precision())
110  throw Exception("SimpleDiscreteDistribution. Probabilities must equal 1 (sum =" + TextTools::toString(sum) + ").");
111 
112  if (!fixed)
113  {
114  double y = 1;
115  for (size_t i = 0; i < size - 1; i++)
116  {
117  addParameter_(new Parameter("Simple.V" + TextTools::toString(i + 1), values[i]));
118  addParameter_(new Parameter("Simple.theta" + TextTools::toString(i + 1), probas[i] / y, Parameter::PROP_CONSTRAINT_IN));
119  y -= probas[i];
120  }
121  addParameter_(new Parameter("Simple.V" + TextTools::toString(size), values[size - 1]));
122  }
123 
124  discretize();
125 }
126 
128  const std::map<size_t, std::vector<double> >& ranges,
129  const std::vector<double>& probas,
130  double prec,
131  bool fixed) :
132  AbstractDiscreteDistribution(values.size(), prec, "Simple."),
133  givenRanges_()
134 {
135  if (values.size() != probas.size())
136  {
137  throw Exception("SimpleDiscreteDistribution. Values and probabilities vectors must have the same size (" + TextTools::toString(values.size()) + " != " + TextTools::toString(probas.size()) + ").");
138  }
139  size_t size = values.size();
140 
141  for (size_t i = 0; i < size; i++)
142  {
143  if (distribution_.find(values[i]) != distribution_.end())
144  throw Exception("SimpleDiscreteDistribution: two given values are equal");
145  else
146  distribution_[values[i]] = probas[i];
147  }
148 
149  double sum = VectorTools::sum(probas);
150  if (fabs(1. - sum) > precision())
151  throw Exception("SimpleDiscreteDistribution. Probabilities must equal 1 (sum =" + TextTools::toString(sum) + ").");
152 
153  if (!fixed)
154  {
155  double y = 1;
156  for (size_t i = 0; i < size - 1; i++)
157  {
158  map<size_t, vector<double> >::const_iterator it = ranges.find(i + 1);
159  if (it == ranges.end())
160  addParameter_(new Parameter("Simple.V" + TextTools::toString(i + 1), values[i]));
161  else
162  {
163  if (values[i] >= it->second[0] && values[i] <= it->second[1])
164  {
165  addParameter_(new Parameter("Simple.V" + TextTools::toString(i + 1), values[i], std::make_shared<IntervalConstraint>(it->second[0], it->second[1], true, true)));
166  givenRanges_[i + 1] = it->second;
167  }
168  else
169  throw Exception("SimpleDiscreteDistribution. Value and given range of parameter V" + TextTools::toString(i + 1) + " do not match: " + TextTools::toString(values[i]) + " vs [" + TextTools::toString(it->second[0]) + ";" + TextTools::toString(it->second[1]) + "]");
170  }
171  addParameter_(new Parameter("Simple.theta" + TextTools::toString(i + 1), probas[i] / y, Parameter::PROP_CONSTRAINT_IN));
172  y -= probas[i];
173  }
174 
175  map<size_t, vector<double> >::const_iterator it = ranges.find(size);
176  if (it == ranges.end())
177  addParameter_(new Parameter("Simple.V" + TextTools::toString(size), values[size - 1]));
178  else
179  {
180  if (values[size - 1] >= it->second[0] && values[size - 1] <= it->second[1])
181  {
182  addParameter_(new Parameter("Simple.V" + TextTools::toString(size), values[size - 1], std::make_shared<IntervalConstraint>(it->second[0], it->second[1], true, true)));
183  givenRanges_[size] = it->second;
184  }
185  else
186  throw Exception("SimpleDiscreteDistribution. Value and given range of parameter V" + TextTools::toString(size) + " do not match: " + TextTools::toString(values[size - 1]) + " vs [" + TextTools::toString(it->second[0]) + ";" + TextTools::toString(it->second[1]) + "]");
187  }
188  }
189 
190  discretize();
191 }
192 
193 
196  givenRanges_(sdd.givenRanges_)
197 {}
198 
200 {
203 
204  return *this;
205 }
206 
208 {
209  if (getNumberOfParameters() != 0)
210  {
212  size_t size = distribution_.size();
213 
214  distribution_.clear();
215  double x = 1.0;
216  double v;
217  for (size_t i = 0; i < size; i++)
218  {
219  v = getParameterValue("V" + TextTools::toString(i + 1));
220  double v2(v);
221  if (distribution_.find(v2) != distribution_.end())
222  {
223  int j(1);
224  while (true)
225  {
226  v2 = v + j * precision();
227  if (v2 < intMinMax_->getUpperBound() && (distribution_.find(v2) == distribution_.end()))
228  break;
229 
230  v2 = v - j * precision();
231  if (v2 > intMinMax_->getLowerBound() && (distribution_.find(v2) == distribution_.end()))
232  break;
233  j++;
234  }
235  // approximation to avoid useless computings:
236  // setParameterValue("V"+TextTools::toString(i+1),v);
237  }
238  if (i < size - 1)
239  {
240  distribution_[v2] = getParameterValue("theta" + TextTools::toString(i + 1)) * x;
241  x *= 1 - getParameterValue("theta" + TextTools::toString(i + 1));
242  }
243  else
244  distribution_[v2] = x;
245  }
246  }
247 
248  discretize();
249 }
250 
251 double SimpleDiscreteDistribution::qProb(double x) const
252 {
253  double s = -NumConstants::VERY_BIG();
254  double x2 = x;
255  for (map<double, double>::const_iterator it = distribution_.begin(); it != distribution_.end(); it++)
256  {
257  x2 -= it->second;
258  if (x2 < 0)
259  return s;
260  else
261  s = it->second;
262  }
263 
264  return s;
265 }
266 
267 double SimpleDiscreteDistribution::pProb(double x) const
268 {
269  double s = 0;
270  for (map<double, double>::const_iterator it = distribution_.begin(); it != distribution_.end(); it++)
271  {
272  if (it->first >= x)
273  s += it->second;
274  else
275  break;
276  }
277 
278  return s;
279 }
280 
282 {
283  double s = 0;
284  for (map<double, double>::const_iterator it = distribution_.begin(); it != distribution_.end(); it++)
285  {
286  if (it->first >= a)
287  s += it->second;
288  else
289  break;
290  }
291 
292  return s;
293 }
294 
295 
297 {
298  // Compute a new arbitray bounderi:
299  vector<double> values = MapTools::getKeys<double, double, AbstractDiscreteDistribution::Order>(distribution_);
300 
301  // Fill from 0 to numberOfCategories_-2 with midpoints:
302  for (unsigned int i = 0; i < numberOfCategories_ - 1; i++)
303  {
304  bounds_[i] = (values[i] + values[i + 1]) / 2.;
305  }
306 }
307 
309 {
310  if (getNumberOfParameters() == 0)
311  return;
312 
313  const IntervalConstraint* pi = dynamic_cast<const IntervalConstraint*>(&c);
314 
315  if (!pi)
316  throw Exception("SimpleDiscreteDistribution::restrictToConstraint: Non-interval exception");
317 
318  map<double, double>::const_iterator it;
319 
320  for (it = distribution_.begin(); it != distribution_.end(); it++)
321  {
322  if (!pi->isCorrect(it->first))
323  throw Exception("Impossible to restrict to Constraint value " + TextTools::toString(it->first));
324  }
325 
327 
328  size_t size = distribution_.size();
329  for (size_t i = 0; i < size; i++)
330  {
331  map<size_t, vector<double> >::const_iterator itr = givenRanges_.find(i + 1);
332  if (itr == givenRanges_.end())
334  else
335  {
336  std::shared_ptr<Constraint> pc = getParameter_("V" + TextTools::toString(i + 1)).removeConstraint();
337  getParameter_("V" + TextTools::toString(i + 1)).setConstraint(std::shared_ptr<Constraint>(*pc & *intMinMax_));
338  }
339  }
340 }
Partial implementation of the DiscreteDistribution interface.
virtual void restrictToConstraint(const Constraint &c)
Restricts the distribution to the domain where the constraint is respected, in addition of other pred...
std::map< double, double, Order > distribution_
AbstractDiscreteDistribution & operator=(const AbstractDiscreteDistribution &adde)
std::shared_ptr< IntervalConstraint > intMinMax_
the interval where the distribution is defined/restricted.
void addParameter_(Parameter *parameter)
virtual void fireParameterChanged(const ParameterList &parameters)
Notify the class when one or several parameters have changed.
size_t getNumberOfParameters() const
Get the number of parameters.
double getParameterValue(const std::string &name) const
Get the value for parameter of name 'name'.
Parameter & getParameter_(const std::string &name)
The constraint interface.
Definition: Constraints.h:66
Exception base class. Overload exception constructor (to control the exceptions mechanism)....
Definition: Exceptions.h:59
An interval, either bounded or not, which can also have infinite bounds.
Definition: Constraints.h:139
virtual bool isCorrect(double value) const
Tell if a given value is correct.
Definition: Constraints.h:230
static double VERY_BIG()
Definition: NumConstants.h:84
The parameter list object.
Definition: ParameterList.h:65
This class is designed to facilitate the manipulation of parameters.
Definition: Parameter.h:135
virtual std::shared_ptr< Constraint > removeConstraint()
Remove the constraint associated to this parameter.
Definition: Parameter.cpp:140
static const std::shared_ptr< IntervalConstraint > PROP_CONSTRAINT_IN
Definition: Parameter.h:329
virtual void setConstraint(std::shared_ptr< Constraint > constraint)
Set a constraint to this parameter.
Definition: Parameter.cpp:131
A Discrete distribution object, where some specific probabilities are assigned to a finite set of val...
SimpleDiscreteDistribution & operator=(const SimpleDiscreteDistribution &)
double pProb(double x) const
Return the cumulative quantile of the continuous version of the distribution, ie .
double Expectation(double a) const
Return a primitive function used for the expectation of the continuous version of the distribution,...
std::map< size_t, std::vector< double > > givenRanges_
void fireParameterChanged(const ParameterList &parameters)
Notify the class when one or several parameters have changed.
void discretize()
Discretizes the distribution in equiprobable classes.
void restrictToConstraint(const Constraint &c)
Restricts the distribution to the domain where the constraint is respected, in addition of other pred...
SimpleDiscreteDistribution(const std::map< double, double > &distribution, double precision=NumConstants::TINY(), bool fixed=false)
Builds a new SimpleDiscreteDistribution object from a map<double,double> object. With this constructo...
double qProb(double x) const
Return the quantile of the continuous version of the distribution, ie y such that .
static T sum(const std::vector< T > &v1)
Definition: VectorTools.h:624
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:153