bpp-phyl  2.2.0
MixedSubstitutionModelSet.cpp
Go to the documentation of this file.
1 //
2 // File: MixedSubstitutionModelSet.cpp
3 // Created by: Laurent Guéguen
4 // Created on: mercredi 25 mai 2011, à 22h 12
5 //
6 
7 /*
8  Copyright or <A9> or Copr. Bio++ Development Team, (November 16, 2004)
9 
10  This software is a computer program whose purpose is to provide classes
11  for phylogenetic data analysis.
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 "MixedSubstitutionModel.h"
43 
44 using namespace bpp;
45 using namespace std;
46 
49  vpHyperNodes_()
50 {
51  for (size_t i = 0; i < set.vpHyperNodes_.size(); i++)
52  {
53  vpHyperNodes_.push_back(new HyperNode(*set.vpHyperNodes_[i]));
54  }
55 }
56 
59  vpHyperNodes_()
60 {}
61 
63 {
64  for (size_t i = 0; i < vpHyperNodes_.size(); i++)
65  {
66  delete vpHyperNodes_[i];
67  }
68 }
69 
71 {
73  for (size_t i = 0; i < vpHyperNodes_.size(); i++)
74  {
75  delete vpHyperNodes_[i];
76  }
77 }
78 
80 {
82  for (size_t i = 0; i < vpHyperNodes_.size(); i++)
83  {
84  if (vpHyperNodes_[i] != NULL)
85  delete vpHyperNodes_[i];
86  }
87  vpHyperNodes_.clear();
88 
89  for (size_t i = 0; i < set.vpHyperNodes_.size(); i++)
90  {
91  vpHyperNodes_.push_back(new HyperNode(*set.vpHyperNodes_[i]));
92  }
93 
94  return *this;
95 }
96 
98 {
99  vpHyperNodes_.push_back(new HyperNode(this));
100 }
101 
103 {
104  vpHyperNodes_.push_back(new HyperNode(hn));
105 }
106 
108 {
110  size_t i;
111  for (i = 0; i < vpHyperNodes_.size(); i++)
112  {
113  nhn += *vpHyperNodes_[i];
114  }
115 
116  size_t nbm = getNumberOfModels();
117  for (i = 0; i < nbm; i++)
118  {
119  const MixedSubstitutionModel* pSM = dynamic_cast<const MixedSubstitutionModel*>(getModel(i));
120  if (pSM)
121  {
122  if (nhn.getNode(i).size() != pSM->getNumberOfModels())
123  break;
124  }
125  }
126 
127  if (i == nbm)
128  return false;
129 
131  for (i = 0; i < nbm; i++)
132  {
133  const MixedSubstitutionModel* pSM = dynamic_cast<const MixedSubstitutionModel*>(getModel(i));
134  if (pSM)
135  {
137  int snd = static_cast<int>(nd.size());
138  int vs = static_cast<int>(pSM->getNumberOfModels());
139  Vint an;
140 
141  int j(0), k(0);
142  while (j < vs)
143  {
144  while ((k < snd) && (nd[static_cast<size_t>(k)] < j))
145  k++;
146  if ((k >= snd) || (nd[static_cast<size_t>(k)] > j))
147  an.push_back(j);
148  j++;
149  }
150  addToHyperNode(i, an);
151  }
152  }
153 
154  return true;
155 }
156 
157 void MixedSubstitutionModelSet::addToHyperNode(size_t nM, const Vint& vnS, int nH)
158 {
159  if (nH >= static_cast<int>(vpHyperNodes_.size()))
160  throw BadIntegerException("MixedSubstitutionModelSet::addToHyperNode. Bad HyperNode number", nH);
161  if (nH < 0)
162  nH = static_cast<int>(vpHyperNodes_.size() - 1);
163 
164  if (nM >= getNumberOfModels())
165  throw IndexOutOfBoundsException("MixedSubstitutionModelSet::addToHyperNode. Bad Mixed Model number", nM, 0, getNumberOfModels());
166 
167  vpHyperNodes_[static_cast<size_t>(nH)]->addToModel(nM, vnS);
168 }
169 
171 {
172  HyperNode tthn(this);
173 
174  size_t nhn = getNumberOfHyperNodes();
175  for (size_t i = 0; i < nhn; i++)
176  {
177  if (tthn.intersects(getHyperNode(i)))
178  return false;
179  else
180  tthn += getHyperNode(i);
181  }
182 
183  return true;
184 }
185 
186 void MixedSubstitutionModelSet::fireParameterChanged(const ParameterList& parameters)
187 {
189 
190  // should be restricted only when probability related parameters are changed
192 }
193 
194 
196 {
197  size_t nbm = getNumberOfModels();
198 
199  // Looking for the first Mixed model
200 
201  size_t fmM = 0;
202 
203  MixedSubstitutionModel* pfSM = 0;
204  for (fmM = 0; fmM < nbm; fmM++)
205  {
206  pfSM = dynamic_cast<MixedSubstitutionModel*>(getModel(fmM));
207  if (pfSM != NULL)
208  break;
209  }
210  if (fmM == nbm)
211  return;
212 
213  // Compute the probabilities of the hypernodes from the first mixed
214  // model
215 
216  size_t nbh = getNumberOfHyperNodes();
217 
218 
219  for (size_t nh = 0; nh < nbh; nh++)
220  {
223 
224  double fprob = 0;
225  for (size_t i = 0; i < fnd.size(); i++)
226  {
227  fprob += pfSM->getNProbability(static_cast<size_t>(fnd[i]));
228  }
229  h.setProbability(fprob);
230  }
231 
232  // Sets the new probabilities & rates of the mixmodels
233 
234  for (size_t iM = fmM + 1; iM < nbm; iM++)
235  {
236  pfSM = dynamic_cast<MixedSubstitutionModel*>(getModel(iM));
237  if (pfSM != NULL)
238  {
239  for (size_t nh = 0; nh < nbh; nh++)
240  {
243  double prob = 0;
244  for (size_t j = 0; j < fnd.size(); j++)
245  {
246  prob += pfSM->getNProbability(static_cast<size_t>(fnd[j]));
247  }
248 
249  // sets the real probabilities
250  for (size_t j = 0; j < fnd.size(); j++)
251  {
252  pfSM->setNProbability(static_cast<size_t>(fnd[j]), h.getProbability() * pfSM->getNProbability(static_cast<size_t>(fnd[j])) / prob);
253  }
254  }
255 
256  // normalizes Vrates with the real probabilities
257 
258  pfSM->normalizeVRates();
259 
260  // sets the conditional probabilities
261 
262  for (size_t nh = 0; nh < nbh; nh++)
263  {
266  for (size_t j = 0; j < fnd.size(); j++)
267  {
268  pfSM->setNProbability(static_cast<size_t>(fnd[j]), pfSM->getNProbability(static_cast<size_t>(fnd[j])) / h.getProbability());
269  }
270  }
271  }
272  }
273 }
274 
276 {
277  size_t nbm = getNumberOfModels();
278  double fprob = 1;
279 
280  for (size_t fmM = 0; fmM < nbm; fmM++)
281  {
283  const MixedSubstitutionModel* pfSM = dynamic_cast<const MixedSubstitutionModel*>(getModel(fmM));
284  if (pfSM != NULL)
285  {
286  double x = 0;
287 
288  for (size_t i = 0; i < fnd.size(); i++)
289  {
290  x += pfSM->getNProbability(static_cast<size_t>(fnd[i]));
291  }
292 
293  fprob *= x;
294  }
295  }
296 
297  return fprob;
298 }
299 
300 /**********************************************************/
301 /*************** HYPERNODE ********************************/
302 /***********************************************************/
303 
304 
305 MixedSubstitutionModelSet::HyperNode::HyperNode(const MixedSubstitutionModelSet* pMSMS) : vNumbers_(pMSMS->getNumberOfModels()),
306  vUnused_(),
307  proba_(1)
308 {
309  for (size_t i = 0; i < pMSMS->getNumberOfModels(); i++)
310  {
311  const MixedSubstitutionModel* pSM = dynamic_cast<const MixedSubstitutionModel*>(pMSMS->getModel(i));
312  if (!pSM)
313  vUnused_.push_back(static_cast<int>(i));
314  }
315 }
316 
317 MixedSubstitutionModelSet::HyperNode::HyperNode(const HyperNode& hn) : vNumbers_(hn.vNumbers_),
318  vUnused_(hn.vUnused_),
319  proba_(hn.proba_)
320 {}
321 
322 
324 {
325  vNumbers_.clear();
326  vNumbers_.resize(hn.vNumbers_.size());
327  for (size_t i = 0; i < hn.vNumbers_.size(); i++)
328  {
329  vNumbers_[i] = hn.vNumbers_[i];
330  }
331  vUnused_.clear();
332  vUnused_.resize(hn.vUnused_.size());
333  for (size_t i = 0; i < hn.vUnused_.size(); i++)
334  {
335  vUnused_[i] = hn.vUnused_[i];
336  }
337 
338  proba_ = hn.proba_;
339 
340  return *this;
341 }
342 
343 void MixedSubstitutionModelSet::HyperNode::addToModel(size_t nM, const Vint& vnS)
344 {
345  if (nM >= vNumbers_.size())
346  throw IndexOutOfBoundsException("MixedSubstitutionModelSet::HyperNode::addToModel. Bad Mixed model Number", nM, 0, vNumbers_.size());
347 
348  vNumbers_[nM].insertN(vnS);
349 }
350 
351 void MixedSubstitutionModelSet::HyperNode::setModel(size_t nM, const Vint& vnS)
352 {
353  if (nM >= vNumbers_.size())
354  throw IndexOutOfBoundsException("MixedSubstitutionModelSet::HyperNode::setModel. Bad Mixed model Number", nM, 0, vNumbers_.size());
355 
356  vNumbers_[nM] = vnS;
357 }
358 
360 {
361  size_t k;
362  size_t vUs = vUnused_.size();
363  for (size_t i = 0; i < vNumbers_.size(); ++i)
364  {
365  for (k = 0; k < vUs; k++)
366  {
367  if (vUnused_[k] == static_cast<int>(i))
368  break;
369  }
370  if ((k == vUs) && vNumbers_[i].size() == 0)
371  return false;
372  }
373  return true;
374 }
375 
377 {
378  for (size_t i = 0; i < vNumbers_.size(); i++)
379  {
380  if (!( vNumbers_[i] <= hn.vNumbers_[i]))
381  return false;
382  }
383 
384  return true;
385 }
386 
388 {
389  for (size_t i = 0; i < vNumbers_.size(); i++)
390  {
391  if (vNumbers_[i].intersects(hn.vNumbers_[i]))
392  return true;
393  }
394 
395  return false;
396 }
397 
399 {
400  return hn >= *this;
401 }
402 
404 {
405  for (size_t i = 0; i < vNumbers_.size(); i++)
406  {
407  vNumbers_[i] += hn.vNumbers_[i];
408  }
409 
410  return *this;
411 }
412 
413 /**********************************************************/
414 /******************** NODE ********************************/
415 /***********************************************************/
416 
418 {
419  vector<int>::iterator it;
420  vector<int>::const_iterator it2;
421 
422  for (it2 = vn.begin(); it2 != vn.end(); it2++)
423  {
424  for (it = vNumb_.begin(); it != vNumb_.end(); it++)
425  {
426  if (*it >= *it2)
427  break;
428  }
429  if (it == vNumb_.end())
430  vNumb_.push_back(*it2);
431  else if (*it != *it2)
432  vNumb_.insert(it, *it2);
433  }
434 }
435 
437 {
438  insertN(n.vNumb_);
439 
440  return *this;
441 }
442 
444 {
445  vector<int>::const_iterator it(vNumb_.begin());
446  vector<int>::const_iterator it2(n.vNumb_.begin());
447 
448  for ( ; it != vNumb_.end(); it++)
449  {
450  while (it2 != n.vNumb_.end() && (*it2 < *it))
451  it2++;
452  if (it2 == n.vNumb_.end() || (*it2 > *it))
453  return false;
454  it++;
455  }
456  return true;
457 }
458 
460 {
461  return n <= *this;
462 }
463 
465 {
466  vector<int>::const_iterator it(vNumb_.begin());
467  vector<int>::const_iterator it2(n.vNumb_.begin());
468 
469  for ( ; it != vNumb_.end(); it++)
470  {
471  while (it2 != n.vNumb_.end() && (*it2 < *it))
472  it2++;
473 
474  if (it2 == n.vNumb_.end())
475  return false;
476  if (*it2 == *it)
477  return true;
478  it++;
479  }
480  return false;
481 }
482 
Vint vNumb_
A vector<int> where all elements are different and in increasing order.
Substitution models manager for non-homogeneous / non-reversible models of evolution.
void setModel(size_t nM, const Vint &vnS)
sets submodel numbers in the nMth mixed model. Checks if all the numbers are valid.
bool operator>=(const Node &) const
checks if this HyperNode includes another one.
const SubstitutionModel * getModel(size_t i) const
Get one model from the set knowing its index.
MixedSubstitutionModelSet(const Alphabet *alpha)
Create a model set according to the specified alphabet.
virtual double getNProbability(size_t i) const =0
Returns the probability of a specific model from the mixture.
MixedSubstitutionModelSet & operator=(const MixedSubstitutionModelSet &set)
double getHyperNodeProbability(const HyperNode &hn) const
bool operator>=(const HyperNode &) const
checks if this HyperNode includes another one.
void setProbability(double x)
sets the probability
STL namespace.
bool isComplete() const
checks if this HyperNode includes at least a submodel of each mixed model
bool operator<=(const Node &) const
checks if this Node is included in another one.
void clear()
Resets the list of the HyperNodes.
double proba_
probability of this HyperNode.
void clear()
Resets all the information contained in this object.
virtual void normalizeVRates()=0
Normalizes the rates of the submodels so that the mean rate of the mixture equals rate_...
Vint vUnused_
the coordinates of the Nodes that are not used.
void addToHyperNode(size_t nM, const Vint &vnS, int nH=-1)
virtual void setNProbability(size_t i, double prob)=0
Sets the probability of a specific model from the mixture.
double getProbability() const
returns the probability
Substitution models manager for Mixed Substitution Models. This class inherits from SubstitutionModel...
HyperNode & operator+=(const HyperNode &)
Cumulates the Nodes of the given HyperNode into this one.
virtual void fireParameterChanged(const ParameterList &parameters)
void addToModel(size_t nM, const Vint &vnS)
adds submodel numbers to the nMth mixed model. Checks if all the numbers are valid.
virtual size_t getNumberOfModels() const =0
SubstitutionModelSet & operator=(const SubstitutionModelSet &set)
bool intersects(const HyperNode &) const
checks if this HyperNode intersects another one.
void fireParameterChanged(const ParameterList &parameters)
bool operator<=(const HyperNode &) const
checks if this HyperNode is included in another one.
bool intersects(const Node &) const
checks if this Node intersects another one.
std::vector< HyperNode * > vpHyperNodes_
Node & operator+=(const Node &)
Cumulates the elements of the given Node into this one.
Interface for Substitution models, defined as a mixture of "simple" substitution models.