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