bpp-phyl3  3.0.0
MixedSubstitutionModelSet.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 "../../Model/MixedTransitionModel.h"
6 #include "../../Model/MixtureOfASubstitutionModel.h"
8 
9 using namespace bpp;
10 using namespace std;
11 
14  vpHyperNodes_()
15 {
16  for (size_t i = 0; i < set.vpHyperNodes_.size(); i++)
17  {
18  vpHyperNodes_.push_back(new HyperNode(*set.vpHyperNodes_[i]));
19  }
20 }
21 
24  vpHyperNodes_()
25 {}
26 
28 {
29  for (size_t i = 0; i < vpHyperNodes_.size(); i++)
30  {
31  delete vpHyperNodes_[i];
32  }
33 }
34 
36 {
38  for (size_t i = 0; i < vpHyperNodes_.size(); i++)
39  {
40  delete vpHyperNodes_[i];
41  }
42 }
43 
45 {
47  for (size_t i = 0; i < vpHyperNodes_.size(); i++)
48  {
49  if (vpHyperNodes_[i] != NULL)
50  delete vpHyperNodes_[i];
51  }
52  vpHyperNodes_.clear();
53 
54  for (size_t i = 0; i < set.vpHyperNodes_.size(); i++)
55  {
56  vpHyperNodes_.push_back(new HyperNode(*set.vpHyperNodes_[i]));
57  }
58 
59  return *this;
60 }
61 
63 {
64  vpHyperNodes_.push_back(new HyperNode(shared_from_this()));
65 }
66 
68 {
69  vpHyperNodes_.push_back(new HyperNode(hn));
70 }
71 
73 {
74  MixedSubstitutionModelSet::HyperNode nhn(shared_from_this());
75  size_t i;
76  for (auto nodei:vpHyperNodes_)
77  {
78  nhn += *nodei;
79  }
80 
81  size_t nbm = getNumberOfModels();
82  for (i = 0; i < nbm; i++)
83  {
84  try
85  {
86  auto& pSM = dynamic_cast<const MixedTransitionModelInterface&>(model(i));
87  if (nhn.getNode(i).size() != pSM.getNumberOfModels())
88  break;
89  }
90  catch (exception&)
91  {}
92  }
93 
94  if (i == nbm)
95  return false;
96 
98  for (i = 0; i < nbm; i++)
99  {
100  try
101  {
102  auto& pSM = dynamic_cast<const MixedTransitionModelInterface&>(model(i));
104  auto snd = nd.size();
105  auto vs = pSM.getNumberOfModels();
106  Vuint an;
107 
108  uint j(0), k(0);
109  while (j < vs)
110  {
111  while ((k < snd) && ((uint)nd[k] < j))
112  k++;
113  if ((k >= snd) || ((uint)nd[k] > j))
114  an.push_back(j);
115  j++;
116  }
117  addToHyperNode(i, an);
118  }
119  catch (exception&)
120  {}
121  }
122 
123  return true;
124 }
125 
126 void MixedSubstitutionModelSet::addToHyperNode(size_t nM, const Vuint& vnS, int nH)
127 {
128  if (nH >= static_cast<int>(vpHyperNodes_.size()))
129  throw BadIntegerException("MixedSubstitutionModelSet::addToHyperNode. Bad HyperNode number", nH);
130  if (nH < 0)
131  nH = static_cast<int>(vpHyperNodes_.size() - 1);
132 
133  if (nM >= getNumberOfModels())
134  throw IndexOutOfBoundsException("MixedSubstitutionModelSet::addToHyperNode. Bad Mixed Model number", nM, 0, getNumberOfModels());
135 
136  vpHyperNodes_[static_cast<size_t>(nH)]->addToModel(nM, vnS);
137 }
138 
140 {
141  HyperNode tthn(shared_from_this());
142 
143  size_t nhn = getNumberOfHyperNodes();
144  for (size_t i = 0; i < nhn; i++)
145  {
146  if (tthn.intersects(getHyperNode(i)))
147  return false;
148  else
149  tthn += getHyperNode(i);
150  }
151 
152  return true;
153 }
154 
156 {
158 
159  // should be restricted only when probability related parameters are changed
161 }
162 
163 
165 {
166  size_t nbm = getNumberOfModels();
167 
168  // Looking for the first Mixed model
169 
170  size_t fmM = 0;
171 
172  MixedTransitionModelInterface* pfSM = nullptr;
173  for (fmM = 0; fmM < nbm; fmM++)
174  {
175  pfSM = dynamic_cast<MixedTransitionModelInterface*>(&model(fmM));
176  if (pfSM)
177  break;
178  }
179  if (fmM == nbm)
180  return;
181 
182  // Compute the probabilities of the hypernodes from the first mixed
183  // model
184 
185  size_t nbh = getNumberOfHyperNodes();
186 
187  for (size_t nh = 0; nh < nbh; nh++)
188  {
191 
192  double fprob = 0;
193  for (size_t i = 0; i < fnd.size(); i++)
194  {
195  fprob += pfSM->getNProbability(static_cast<size_t>(fnd[i]));
196  }
197  h.setProbability(fprob);
198  }
199 
200  // Sets the new probabilities & rates of the mixmodels
201 
202  for (size_t iM = fmM + 1; iM < nbm; iM++)
203  {
204  pfSM = dynamic_cast<MixedTransitionModelInterface*>(&model(iM));
205  if (pfSM != NULL)
206  {
207  for (size_t nh = 0; nh < nbh; nh++)
208  {
211  double prob = 0;
212  for (size_t j = 0; j < fnd.size(); j++)
213  {
214  prob += pfSM->getNProbability(static_cast<size_t>(fnd[j]));
215  }
216  // sets the REAL probabilities
217  for (size_t j = 0; j < fnd.size(); j++)
218  {
219  pfSM->setNProbability(static_cast<size_t>(fnd[j]), h.getProbability() * pfSM->getNProbability(static_cast<size_t>(fnd[j])) / prob);
220  }
221  }
222 
223  // normalizes Vrates with the real probabilities
224 
225  pfSM->normalizeVRates();
226 
227  // and now sets the CONDITIONAL probabilities
228 
229  for (size_t nh = 0; nh < nbh; nh++)
230  {
233  for (size_t j = 0; j < fnd.size(); j++)
234  {
235  pfSM->setNProbability(static_cast<size_t>(fnd[j]), pfSM->getNProbability(static_cast<size_t>(fnd[j])) / h.getProbability());
236  }
237  }
238  }
239  }
240 }
241 
243 {
244  size_t nbm = getNumberOfModels();
245  double fprob = 1;
246 
247  for (size_t fmM = 0; fmM < nbm; fmM++)
248  {
250  try
251  {
252  auto& pfSM = dynamic_cast<const MixedTransitionModelInterface&>(model(fmM));
253  double x = 0;
254 
255  for (size_t i = 0; i < fnd.size(); ++i)
256  {
257  x += pfSM.getNProbability(static_cast<size_t>(fnd[i]));
258  }
259 
260  fprob *= x;
261  }
262  catch (exception&)
263  {}
264  }
265 
266  return fprob;
267 }
268 
269 /**********************************************************/
270 /*************** HYPERNODE ********************************/
271 /***********************************************************/
272 
273 
274 MixedSubstitutionModelSet::HyperNode::HyperNode(std::shared_ptr<const MixedSubstitutionModelSet> pMSMS) :
275  vNumbers_(pMSMS->getNumberOfModels()),
276  vUnused_(),
277  proba_(1)
278 {
279  for (size_t i = 0; i < pMSMS->getNumberOfModels(); i++)
280  {
281  auto pSM = dynamic_cast<const MixedTransitionModelInterface*>(&pMSMS->model(i));
282  if (!pSM)
283  vUnused_.push_back(uint(i));
284  }
285 }
286 
287 MixedSubstitutionModelSet::HyperNode::HyperNode(const HyperNode& hn) : vNumbers_(hn.vNumbers_),
288  vUnused_(hn.vUnused_),
289  proba_(hn.proba_)
290 {}
291 
292 
294 {
295  vNumbers_.clear();
296  vNumbers_.resize(hn.vNumbers_.size());
297  for (size_t i = 0; i < hn.vNumbers_.size(); i++)
298  {
299  vNumbers_[i] = hn.vNumbers_[i];
300  }
301  vUnused_.clear();
302  vUnused_.resize(hn.vUnused_.size());
303  for (size_t i = 0; i < hn.vUnused_.size(); i++)
304  {
305  vUnused_[i] = hn.vUnused_[i];
306  }
307 
308  proba_ = hn.proba_;
309 
310  return *this;
311 }
312 
314 {
315  if (nM >= vNumbers_.size())
316  throw IndexOutOfBoundsException("MixedSubstitutionModelSet::HyperNode::addToModel. Bad Mixed model Number", nM, 0, vNumbers_.size());
317 
318  vNumbers_[nM].insertN(vnS);
319 }
320 
322 {
323  if (nM >= vNumbers_.size())
324  throw IndexOutOfBoundsException("MixedSubstitutionModelSet::HyperNode::setModel. Bad Mixed model Number", nM, 0, vNumbers_.size());
325 
326  vNumbers_[nM] = vnS;
327 }
328 
330 {
331  size_t k;
332  size_t vUs = vUnused_.size();
333  for (size_t i = 0; i < vNumbers_.size(); ++i)
334  {
335  for (k = 0; k < vUs; k++)
336  {
337  if (vUnused_[k] == i)
338  break;
339  }
340  if ((k == vUs) && vNumbers_[i].size() == 0)
341  return false;
342  }
343  return true;
344 }
345 
347 {
348  for (size_t i = 0; i < vNumbers_.size(); i++)
349  {
350  if (!( vNumbers_[i] <= hn.vNumbers_[i]))
351  return false;
352  }
353 
354  return true;
355 }
356 
358 {
359  for (size_t i = 0; i < vNumbers_.size(); i++)
360  {
361  if (vNumbers_[i].intersects(hn.vNumbers_[i]))
362  return true;
363  }
364 
365  return false;
366 }
367 
369 {
370  return hn <= *this;
371 }
372 
374 {
375  for (size_t i = 0; i < vNumbers_.size(); i++)
376  {
377  vNumbers_[i] += hn.vNumbers_[i];
378  }
379 
380  return *this;
381 }
382 
383 /**********************************************************/
384 /******************** NODE ********************************/
385 /***********************************************************/
386 
388 {
389  vector<uint>::iterator it;
390  vector<uint>::const_iterator it2;
391 
392  for (it2 = vn.begin(); it2 != vn.end(); it2++)
393  {
394  for (it = vNumb_.begin(); it != vNumb_.end(); it++)
395  {
396  if (*it >= *it2)
397  break;
398  }
399  if (it == vNumb_.end())
400  vNumb_.push_back(*it2);
401  else if (*it != *it2)
402  vNumb_.insert(it, *it2);
403  }
404 }
405 
407 {
408  insertN(n.vNumb_);
409 
410  return *this;
411 }
412 
414 {
415  vector<uint>::const_iterator it2(n.vNumb_.begin());
416 
417  for (const auto& it : vNumb_)
418  {
419  while (it2 != n.vNumb_.end() && (*it2 < it))
420  it2++;
421  if (it2 == n.vNumb_.end() || (*it2 > it))
422  return false;
423  }
424  return true;
425 }
426 
428 {
429  return n <= *this;
430 }
431 
433 {
434  vector<uint>::const_iterator it2(n.vNumb_.begin());
435 
436  for (const auto& it : vNumb_)
437  {
438  while (it2 != n.vNumb_.end() && (*it2 < it))
439  it2++;
440 
441  if (it2 == n.vNumb_.end())
442  return false;
443  if (*it2 == it)
444  return true;
445  }
446  return false;
447 }
bool intersects(const Node &) const
checks if this Node intersects another one.
bool operator<=(const Node &) const
checks if this Node is included in another one.
bool operator>=(const Node &) const
checks if this HyperNode includes another one.
Node & operator+=(const Node &)
Cumulates the elements of the given Node into this one.
Vuint vNumb_
A vector<int> where all elements are different and in increasing order.
HyperNode & operator+=(const HyperNode &)
Cumulates the Nodes of the given HyperNode into this one.
void addToModel(size_t nM, const Vuint &vnS)
adds submodel numbers to the nMth mixed model. Checks if all the numbers are valid.
bool operator>=(const HyperNode &) const
checks if this HyperNode includes another one.
void setProbability(double x)
sets the probability
bool isComplete() const
checks if this HyperNode includes at least a submodel of each mixed model
HyperNode(std::shared_ptr< const MixedSubstitutionModelSet >)
bool operator<=(const HyperNode &) const
checks if this HyperNode is included in another one.
bool intersects(const HyperNode &) const
checks if this HyperNode intersects another one.
double getProbability() const
returns the probability
void setModel(size_t nM, const Vuint &vnS)
sets submodel numbers in the nMth mixed model. Checks if all the numbers are valid.
Vuint vUnused_
the coordinates of the Nodes that are not used.
double proba_
probability of this HyperNode.
Substitution models manager for Mixed Substitution Models. This class inherits from SubstitutionModel...
void fireParameterChanged(const ParameterList &parameters)
MixedSubstitutionModelSet(std::shared_ptr< const Alphabet > alpha)
Create a model set according to the specified alphabet.
double getHyperNodeProbability(const HyperNode &hn) const
void addToHyperNode(size_t nM, const Vuint &vnS, int nH=-1)
void clear()
Resets the list of the HyperNodes.
std::vector< HyperNode * > vpHyperNodes_
MixedSubstitutionModelSet & operator=(const MixedSubstitutionModelSet &set)
Interface for Transition models, defined as a mixture of "simple" transition models.
virtual double getNProbability(size_t i) const =0
Returns the probability of a specific model from the mixture.
virtual void setNProbability(size_t i, double prob)=0
Sets the probability of a specific model from the mixture.
virtual void normalizeVRates()=0
Normalizes the rates of the submodels so that the mean rate of the mixture equals rate_.
Substitution models manager for non-homogeneous / non-reversible models of evolution.
virtual void fireParameterChanged(const ParameterList &parameters)
const TransitionModelInterface & model(size_t i) const
SubstitutionModelSet & operator=(const SubstitutionModelSet &set)
void clear()
Resets all the information contained in this object.
Defines the basic types of data flow nodes.
std::vector< unsigned int > Vuint