bpp-core3  3.0.0
SimpleDiscreteDistribution.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include "../../Text/TextTools.h"
6 #include "../../Utils/MapTools.h"
7 #include "../NumConstants.h"
9 
10 using namespace bpp;
11 using namespace std;
12 
13 
14 SimpleDiscreteDistribution::SimpleDiscreteDistribution(const map<double, double>& distribution,
15  double prec,
16  bool fixed) :
17  AbstractDiscreteDistribution(distribution.size(), prec, "Simple."),
18  givenRanges_()
19 {
20  double sum = 0;
21  for (map<double, double>::const_iterator i = distribution.begin(); i != distribution.end(); i++)
22  {
23  distribution_[i->first] = i->second;
24  sum += i->second;
25  }
26  if (fabs(1. - sum) > precision())
27  throw Exception("SimpleDiscreteDistribution. Probabilities must equal 1 (sum =" + TextTools::toString(sum) + ").");
28 
29  if (!fixed)
30  {
31  unsigned int n = 1;
32  double x, y = 1;
33  for (map<double, double>::const_iterator i = distribution.begin(); i != distribution.end(); i++)
34  {
35  addParameter_(new Parameter("Simple.V" + TextTools::toString(n), i->first));
36 
37  if (n != numberOfCategories_)
38  {
39  x = i->second;
41  y -= x;
42  }
43  n++;
44  }
45  }
46  discretize();
47 }
48 
50  const vector<double>& probas,
51  double prec,
52  bool fixed
53  ) :
54  AbstractDiscreteDistribution(values.size(), prec, "Simple."),
55  givenRanges_()
56 {
57  if (values.size() != probas.size())
58  {
59  throw Exception("SimpleDiscreteDistribution. Values and probabilities vectors must have the same size (" + TextTools::toString(values.size()) + " != " + TextTools::toString(probas.size()) + ").");
60  }
61  size_t size = values.size();
62 
63  for (size_t i = 0; i < size; i++)
64  {
65  if (distribution_.find(values[i]) != distribution_.end())
66  throw Exception("SimpleDiscreteDistribution: two given values are equal");
67  else
68  distribution_[values[i]] = probas[i];
69  }
70 
71  double sum = VectorTools::sum(probas);
72  if (fabs(1. - sum) > precision())
73  throw Exception("SimpleDiscreteDistribution. Probabilities must equal 1 (sum =" + TextTools::toString(sum) + ").");
74 
75  if (!fixed)
76  {
77  double y = 1;
78  for (size_t i = 0; i < size - 1; i++)
79  {
80  addParameter_(new Parameter("Simple.V" + TextTools::toString(i + 1), values[i]));
81  addParameter_(new Parameter("Simple.theta" + TextTools::toString(i + 1), probas[i] / y, Parameter::PROP_CONSTRAINT_IN));
82  y -= probas[i];
83  }
84  addParameter_(new Parameter("Simple.V" + TextTools::toString(size), values[size - 1]));
85  }
86 
87  discretize();
88 }
89 
91  const std::map<size_t, std::vector<double>>& ranges,
92  const std::vector<double>& probas,
93  double prec,
94  bool fixed) :
95  AbstractDiscreteDistribution(values.size(), prec, "Simple."),
96  givenRanges_()
97 {
98  if (values.size() != probas.size())
99  {
100  throw Exception("SimpleDiscreteDistribution. Values and probabilities vectors must have the same size (" + TextTools::toString(values.size()) + " != " + TextTools::toString(probas.size()) + ").");
101  }
102  size_t size = values.size();
103 
104  for (size_t i = 0; i < size; i++)
105  {
106  if (distribution_.find(values[i]) != distribution_.end())
107  throw Exception("SimpleDiscreteDistribution: two given values are equal");
108  else
109  distribution_[values[i]] = probas[i];
110  }
111 
112  double sum = VectorTools::sum(probas);
113  if (fabs(1. - sum) > precision())
114  throw Exception("SimpleDiscreteDistribution. Probabilities must equal 1 (sum =" + TextTools::toString(sum) + ").");
115 
116  if (!fixed)
117  {
118  double y = 1;
119  for (size_t i = 0; i < size - 1; i++)
120  {
121  map<size_t, vector<double>>::const_iterator it = ranges.find(i + 1);
122  if (it == ranges.end())
123  addParameter_(new Parameter("Simple.V" + TextTools::toString(i + 1), values[i]));
124  else
125  {
126  if (values[i] >= it->second[0] && values[i] <= it->second[1])
127  {
128  addParameter_(new Parameter("Simple.V" + TextTools::toString(i + 1), values[i], std::make_shared<IntervalConstraint>(it->second[0], it->second[1], true, true)));
129  givenRanges_[i + 1] = it->second;
130  }
131  else
132  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]) + "]");
133  }
134  addParameter_(new Parameter("Simple.theta" + TextTools::toString(i + 1), probas[i] / y, Parameter::PROP_CONSTRAINT_IN));
135  y -= probas[i];
136  }
137 
138  map<size_t, vector<double>>::const_iterator it = ranges.find(size);
139  if (it == ranges.end())
140  addParameter_(new Parameter("Simple.V" + TextTools::toString(size), values[size - 1]));
141  else
142  {
143  if (values[size - 1] >= it->second[0] && values[size - 1] <= it->second[1])
144  {
145  addParameter_(new Parameter("Simple.V" + TextTools::toString(size), values[size - 1], std::make_shared<IntervalConstraint>(it->second[0], it->second[1], true, true)));
146  givenRanges_[size] = it->second;
147  }
148  else
149  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]) + "]");
150  }
151  }
152 
153  discretize();
154 }
155 
156 
160 {}
161 
163 {
166 
167  return *this;
168 }
169 
171 {
172  if (getNumberOfParameters() != 0)
173  {
175  size_t size = distribution_.size();
176 
177  distribution_.clear();
178  double x = 1.0;
179  double v;
180  for (size_t i = 0; i < size; i++)
181  {
182  v = getParameterValue("V" + TextTools::toString(i + 1));
183  double v2(v);
184  if (distribution_.find(v2) != distribution_.end())
185  {
186  int j(1);
187  while (true)
188  {
189  v2 = v + j * precision();
190  if (v2 < intMinMax_->getUpperBound() && (distribution_.find(v2) == distribution_.end()))
191  break;
192 
193  v2 = v - j * precision();
194  if (v2 > intMinMax_->getLowerBound() && (distribution_.find(v2) == distribution_.end()))
195  break;
196  j++;
197  }
198  // approximation to avoid useless computings:
199  // setParameterValue("V"+TextTools::toString(i+1),v);
200  }
201  if (i < size - 1)
202  {
203  distribution_[v2] = getParameterValue("theta" + TextTools::toString(i + 1)) * x;
204  x *= 1 - getParameterValue("theta" + TextTools::toString(i + 1));
205  }
206  else
207  distribution_[v2] = x;
208  }
209  }
210 
211  discretize();
212 }
213 
214 double SimpleDiscreteDistribution::qProb(double x) const
215 {
216  double s = -NumConstants::VERY_BIG();
217  double x2 = x;
218  for (map<double, double>::const_iterator it = distribution_.begin(); it != distribution_.end(); it++)
219  {
220  x2 -= it->second;
221  if (x2 < 0)
222  return s;
223  else
224  s = it->second;
225  }
226 
227  return s;
228 }
229 
230 double SimpleDiscreteDistribution::pProb(double x) const
231 {
232  double s = 0;
233  for (map<double, double>::const_iterator it = distribution_.begin(); it != distribution_.end(); it++)
234  {
235  if (it->first >= x)
236  s += it->second;
237  else
238  break;
239  }
240 
241  return s;
242 }
243 
245 {
246  double s = 0;
247  for (map<double, double>::const_iterator it = distribution_.begin(); it != distribution_.end(); it++)
248  {
249  if (it->first >= a)
250  s += it->second;
251  else
252  break;
253  }
254 
255  return s;
256 }
257 
258 
260 {
261  // Compute a new arbitray bounderi:
262  vector<double> values = MapTools::getKeys<double, double, AbstractDiscreteDistribution::Order>(distribution_);
263 
264  // Fill from 0 to numberOfCategories_-2 with midpoints:
265  for (unsigned int i = 0; i < numberOfCategories_ - 1; i++)
266  {
267  bounds_[i] = (values[i] + values[i + 1]) / 2.;
268  }
269 }
270 
272 {
273  if (getNumberOfParameters() == 0)
274  return;
275 
276  const IntervalConstraint* pi = dynamic_cast<const IntervalConstraint*>(&c);
277 
278  if (!pi)
279  throw Exception("SimpleDiscreteDistribution::restrictToConstraint: Non-interval exception");
280 
281  map<double, double>::const_iterator it;
282 
283  for (it = distribution_.begin(); it != distribution_.end(); it++)
284  {
285  if (!pi->isCorrect(it->first))
286  throw Exception("Impossible to restrict to Constraint value " + TextTools::toString(it->first));
287  }
288 
290 
291  size_t size = distribution_.size();
292  for (size_t i = 0; i < size; i++)
293  {
294  map<size_t, vector<double>>::const_iterator itr = givenRanges_.find(i + 1);
295  if (itr == givenRanges_.end())
297  else
298  {
299  auto pc = getParameter_("V" + TextTools::toString(i + 1)).removeConstraint();
300  getParameter_("V" + TextTools::toString(i + 1)).setConstraint(std::shared_ptr<ConstraintInterface>(*pc & *intMinMax_));
301  }
302  }
303 }
virtual void restrictToConstraint(const ConstraintInterface &c)
Restricts the distribution to the domain where the constraint is respected, in addition of other pred...
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:101
The constraint interface.
Definition: Constraints.h:28
double pProb(double x) const
Return the cumulative quantile of the continuous version of the distribution, ie .
void setConstraint(const std::string &name, std::shared_ptr< ConstraintInterface > constraint) override
Set/Change the constraint associated with one parameter.
static T sum(const std::vector< T > &v1)
Definition: VectorTools.h:587
SimpleDiscreteDistribution & operator=(const SimpleDiscreteDistribution &)
STL namespace.
This class is designed to facilitate the manipulation of parameters.
Definition: Parameter.h:97
void addParameter_(Parameter *parameter)
virtual void setConstraint(std::shared_ptr< ConstraintInterface > constraint)
Set a constraint to this parameter.
Definition: Parameter.cpp:76
double getParameterValue(const std::string &name) const override
Get the value for parameter of name &#39;name&#39;.
The parameter list object.
Definition: ParameterList.h:27
virtual void fireParameterChanged(const ParameterList &parameters)
Notify the class when one or several parameters have changed.
A Discrete distribution object, where some specific probabilities are assigned to a finite set of val...
AbstractDiscreteDistribution & operator=(const AbstractDiscreteDistribution &adde)
std::shared_ptr< IntervalConstraint > intMinMax_
the interval where the distribution is defined/restricted.
void discretize()
Discretizes the distribution in equiprobable classes.
static double VERY_BIG()
Definition: NumConstants.h:48
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_
static const std::shared_ptr< IntervalConstraint > PROP_CONSTRAINT_IN
Definition: Parameter.h:311
void fireParameterChanged(const ParameterList &parameters)
Notify the class when one or several parameters have changed.
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
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...
Parameter & getParameter_(const std::string &name)
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:115
size_t getNumberOfParameters() const override
Get the number of parameters.
virtual std::shared_ptr< ConstraintInterface > removeConstraint()
Remove the constraint associated to this parameter.
Definition: Parameter.cpp:85
void restrictToConstraint(const ConstraintInterface &c)
Restricts the distribution to the domain where the constraint is respected, in addition of other pred...
virtual bool isCorrect(double value) const override
Tell if a given value is correct.
Definition: Constraints.h:189