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
9using namespace bpp;
10using namespace std;
11
12MixedSubstitutionModelSet::MixedSubstitutionModelSet(const MixedSubstitutionModelSet& set) :
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
126void 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
274MixedSubstitutionModelSet::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
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