bpp-phyl3 3.0.0
OneChangeRegisterTransitionModel.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: The Bio++ Development Group
2//
3// SPDX-License-Identifier: CECILL-2.1
4
7
9
10using namespace bpp;
11using namespace std;
12
13OneChangeRegisterTransitionModel::OneChangeRegisterTransitionModel(
14 unique_ptr<SubstitutionModelInterface> originalModel,
16 size_t numReg) :
17 AbstractParameterAliasable("OneChange."),
18 AbstractWrappedModel("OneChange."),
20 AbstractFromSubstitutionModelTransitionModel(std::move(originalModel), "OneChange."),
21 noChangedStates_(getNumberOfStates(), getNumberOfStates()),
22 modelChanged_(),
23 registerName_(reg.getName()),
24 vNumRegs_(vector<size_t>(1, numReg))
25{
26 if ((numReg <= 0) || (numReg > reg.getNumberOfSubstitutionTypes()))
27 throw IndexOutOfBoundsException("OneChangeRegisterTransitionModel::OneChangeRegisterTransitionModel : wrong number for register category", numReg, 1, reg.getNumberOfSubstitutionTypes());
28
29 // new alphabet to handle pit state
30 auto ialph = make_shared<IntegerAlphabet>(alphabet().getSize() + 1);
31
32 modelChanged_.reset(new AnonymousSubstitutionModel(ialph, make_shared<CanonicalStateMap>(ialph, false)));
33 modelChanged_->setScalable(false);
34
35 // setting nonchanging states
36 for (size_t i = 0; i < size_; ++i)
37 {
38 vector<uint>& chS_i = noChangedStates_.getRow(i);
39
40 for (size_t j = 0; j < size_; ++j)
41 {
42 chS_i[j] = (reg.getType(i, j) != numReg);
43 }
44 }
45
47}
48
50 unique_ptr<SubstitutionModelInterface> originalModel,
52 vector<size_t> vNumRegs) :
53 AbstractParameterAliasable("OneChange."),
54 AbstractWrappedModel("OneChange."),
56 AbstractFromSubstitutionModelTransitionModel(std::move(originalModel), "OneChange."),
57 noChangedStates_(getNumberOfStates(), getNumberOfStates()),
58 modelChanged_(),
59 registerName_(reg.getName()),
60 vNumRegs_(vNumRegs)
61{
62 for (const auto& numReg : vNumRegs_)
63 {
64 if ((numReg <= 0) || (numReg > reg.getNumberOfSubstitutionTypes()))
65 throw IndexOutOfBoundsException("OneChangeRegisterTransitionModel::OneChangeRegisterTransitionModel : wrong number for register category", numReg, 1, reg.getNumberOfSubstitutionTypes());
66 }
67
68 auto ialph = make_shared<IntegerAlphabet>(getAlphabet()->getSize() + 1);
69
70 modelChanged_.reset(new AnonymousSubstitutionModel(ialph, make_shared<CanonicalStateMap>(ialph, false)));
71 modelChanged_->setScalable(false);
72
73 for (size_t i = 0; i < size_; ++i)
74 {
75 vector<uint>& chS_i = noChangedStates_.getRow(i);
76
77 for (size_t j = 0; j < size_; ++j)
78 {
79 chS_i[j] = (std::find(vNumRegs_.begin(), vNumRegs_.end(), reg.getType(i, j)) == vNumRegs_.end());
80 }
81 }
82
84}
85
86/******************************************************************************/
87
89{
91
92 for (size_t i = 0; i < size_; ++i)
93 {
94 double si = 0;
95 const vector<double>& gen_i = gen.getRow(i);
96 const vector<uint>& chS_i = noChangedStates_.getRow(i);
97
98 for (size_t j = 0; j < size_; j++)
99 {
100 if (chS_i[j] || i == j)
101 modelChanged_->setGenerator()(i, j) = gen_i[j];
102 else
103 {
104 modelChanged_->setGenerator()(i, j) = 0;
105 si += gen_i[j];
106 }
107 }
108 modelChanged_->setGenerator()(i, size_) = si;
109 }
110
111 modelChanged_->updateMatrices_();
112}
113
114/******************************************************************************/
115
116double OneChangeRegisterTransitionModel::Pij_t(size_t i, size_t j, double t) const
117{
118 double ch_ijt = modelChanged_->Pij_t(i, j, t * transitionModel().getRate());
119 double ch_ist = modelChanged_->Pij_t(i, size_, t * transitionModel().getRate());
120
121 if (t == 0)
122 {
124 if (ch_ist != 0)
125 return (gen(i, j) - ch_ijt) / ch_ist;
126 else
127 return (i == j) ? 1 : 0;
128 }
129
130 if (ch_ist == 0) // no proba from i to pit
131 return transitionModel().Pij_t(i, j, t);
132 else
133 return (transitionModel().Pij_t(i, j, t) - ch_ijt) / ch_ist;
134}
135
136double OneChangeRegisterTransitionModel::dPij_dt(size_t i, size_t j, double t) const
137{
138 double rate = transitionModel().getRate();
139 const Matrix<double>& ch_t = modelChanged_->getPij_t(t * rate);
140
141 if (t == 0)
142 {
143 const RowMatrix<double>& Qch = modelChanged_->generator();
144 double si = Qch(i, size_);
145
146 if (si == 0)
147 return 0;
148
150
151 MatrixTools::mult<double>(Qch, Qch, Qch2);
152 double dsi = Qch2(i, size_);
153
155 double q2ij(0);
156
157 for (size_t k = 0; k < size_; ++k)
158 {
159 q2ij += Q(i, k) * Q(k, j);
160 }
161
162 return rate * ((-q2ij + Qch2(i, j)) / si + (Q(i, j) - Qch(i, j)) * dsi / (si * si)) / 2;
163 }
164
165 double si = ch_t(i, size_);
166 if (si == 0)
167 return 0;
168
169 const Matrix<double>& dch_dt = modelChanged_->getdPij_dt(t * rate);
170
171 return ((transitionModel().dPij_dt(i, j, t) - dch_dt(i, j)) * si - dch_dt(i, size_) * (transitionModel().Pij_t(i, j, t) - ch_t(i, j))) / (si * si);
172}
173
174double OneChangeRegisterTransitionModel::d2Pij_dt2(size_t i, size_t j, double t) const
175{
176 double rate = transitionModel().getRate();
177 double r2 = rate * rate;
178
179 if (t == 0)
180 {
182 const RowMatrix<double>& Qch = modelChanged_->generator();
183 double si = Qch(i, size_);
184
185 if (si == 0)
186 return 0;
187
189 MatrixTools::mult<double>(Q, Q, Q2);
190
191 RowMatrix<double> Qch2, Qch3;
192 MatrixTools::mult<double>(Qch, Qch, Qch2);
193 MatrixTools::mult<double>(Qch, Qch2, Qch3);
194
195 double dsi = Qch2(i, size_);
196 double d2si = Qch3(i, size_);
197
198 double q3ij(0);
199
200 for (size_t k = 0; k < size_; ++k)
201 {
202 q3ij += Q2(i, k) * Q(k, j);
203 }
204
205 return r2 * ((Q(i, j) - Qch(i, j)) * (si * d2si / 3 - dsi * dsi / 2) + (Q2(i, j) - Qch2(i, j)) * si * dsi / 2 - (q3ij - Qch3(i, j)) * si * si / 3) / (si * si * si);
206 }
207
208 const Matrix<double>& ch_t = modelChanged_->getPij_t(rate * t);
209 const Matrix<double>& dch_dt = modelChanged_->getdPij_dt(rate * t);
210 const Matrix<double>& d2ch_dt2 = modelChanged_->getd2Pij_dt2(rate * t);
211
212 double d2u = transitionModel().d2Pij_dt2(i, j, t) - d2ch_dt2(i, j);
213 double du = transitionModel().dPij_dt(i, j, t) - dch_dt(i, j);
214 double u = transitionModel().Pij_t(i, j, t) - ch_t(i, j);
215
216 double si = ch_t(i, size_);
217 if (si == 0)
218 return 0;
219
220 double si2 = si * si;
221 double dsi = dch_dt(i, size_);
222 double d2si = d2ch_dt2(i, size_);
223
224 return (d2u * si - d2si * u) / si - 2 * dsi * du / si2 + 2 * dsi * dsi * u / (si2 * si);
225}
226
227
229{
230 double rate = transitionModel().getRate();
231
232 if (t == 0)
233 {
235 const RowMatrix<double>& Qch = modelChanged_->generator();
236
237 for (size_t i = 0; i < size_; ++i)
238 {
239 vector<double>& pi_t = pij_t.getRow(i);
240
241 double si = Qch(i, size_);
242 if (si != 0)
243 {
244 const vector<double>& qi = Q.getRow(i);
245 const vector<double>& qchi = Qch.getRow(i);
246
247 for (size_t j = 0; j < size_; ++j)
248 {
249 pi_t[j] = (qi[j] - qchi[j]) / si;
250 }
251 }
252 else
253 for (size_t j = 0; j < size_; ++j)
254 {
255 pi_t[j] = (i == j) ? 1 : 0;
256 }
257 }
258 return pij_t;
259 }
260
261 const RowMatrix<double>& orig_t = transitionModel().getPij_t(t);
262 const RowMatrix<double>& ch_t = modelChanged_->getPij_t(t * rate);
263
264 for (unsigned int i = 0; i < size_; ++i)
265 {
266 vector<double>& pi_t = pij_t.getRow(i);
267 const vector<double>& origi_t = orig_t.getRow(i);
268 const vector<double>& chi_t = ch_t.getRow(i);
269
270 double si = chi_t[size_];
271 if (si == 0)
272 for (auto& x : pi_t)
273 {
274 x = 0;
275 }
276 else
277 for (unsigned int j = 0; j < size_; ++j)
278 {
279 pi_t[j] = (origi_t[j] - chi_t[j]) / si;
280 }
281 }
282
283 return pij_t;
284}
285
286
288{
289 double rate = transitionModel().getRate();
290
291 if (t == 0)
292 {
294 const RowMatrix<double>& Qch = modelChanged_->generator();
295
297 MatrixTools::mult<double>(Qch, Qch, Qch2);
298
300 MatrixTools::mult<double>(Q, Q, Q2);
301
302 for (size_t i = 0; i < size_; i++)
303 {
304 vector<double>& dpi_t = dpij_t.getRow(i);
305
306 const vector<double>& qchi = Qch.getRow(i);
307 double si = qchi[size_];
308
309 if (si != 0)
310 {
311 const vector<double>& qi = Q.getRow(i);
312 const vector<double>& q2i = Q2.getRow(i);
313 const vector<double>& q2chi = Qch2.getRow(i);
314 double dsi = q2chi[size_];
315
316 for (size_t j = 0; j < size_; ++j)
317 {
318 dpi_t[j] = rate * ((-q2i[j] + q2chi[j]) / si + (qi[j] - qchi[j]) * dsi / (si * si)) / 2;
319 }
320 }
321 else
322 for (auto& x : dpi_t)
323 {
324 x = 0;
325 }
326 }
327 return dpij_t;
328 }
329
330 const RowMatrix<double>& orig_t = transitionModel().getPij_t(t);
331 const RowMatrix<double>& ch_t = modelChanged_->getPij_t(rate * t);
332 const RowMatrix<double>& dorig_dt = transitionModel().getdPij_dt(t);
333 const RowMatrix<double>& dch_dt = modelChanged_->getdPij_dt(rate * t);
334
335 for (unsigned int i = 0; i < size_; ++i)
336 {
337 vector<double>& dpi_dt = dpij_t.getRow(i);
338 const vector<double>& chi_t = ch_t.getRow(i);
339
340 double si = chi_t[size_];
341 if (si == 0)
342 {
343 for (auto& x : dpi_dt)
344 {
345 x = 0;
346 }
347 continue;
348 }
349
350 const vector<double>& origi_t = orig_t.getRow(i);
351 const vector<double>& dorigi_dt = dorig_dt.getRow(i);
352 const vector<double>& dchi_dt = dch_dt.getRow(i);
353
354 double dsi = dchi_dt[size_];
355
356 for (unsigned int j = 0; j < size_; ++j)
357 {
358 dpi_dt[j] = ((dorigi_dt[j] - dchi_dt[j]) * si - dsi * (origi_t[j] - chi_t[j])) / (si * si);
359 }
360 }
361
362 return dpij_t;
363}
364
365
367{
368 double rate = transitionModel().getRate();
369 double r2 = rate * rate;
370
371 if (t == 0)
372 {
374 const RowMatrix<double>& Qch = modelChanged_->generator();
375
376 RowMatrix<double> Qch2, Qch3;
377 MatrixTools::mult<double>(Qch, Qch, Qch2);
378 MatrixTools::mult<double>(Qch, Qch2, Qch3);
379
380 RowMatrix<double> Q2, Q3;
381 MatrixTools::mult<double>(Q, Q, Q2);
382 MatrixTools::mult<double>(Q, Q2, Q3);
383
384 for (size_t i = 0; i < size_; ++i)
385 {
386 vector<double>& d2pi_t = d2pij_t.getRow(i);
387
388 const vector<double>& qchi = Qch.getRow(i);
389 double si = qchi[size_];
390 if (si != 0)
391 {
392 const vector<double>& qi = Q.getRow(i);
393 const vector<double>& q2i = Q2.getRow(i);
394 const vector<double>& q2chi = Qch2.getRow(i);
395 const vector<double>& q3i = Q3.getRow(i);
396 const vector<double>& q3chi = Qch3.getRow(i);
397 double dsi = Qch2(i, size_);
398 double d2si = Qch3(i, size_);
399
400 for (size_t j = 0; j < size_; ++j)
401 {
402 d2pi_t[j] = -r2 * ((qi[j] - qchi[j]) * (si * d2si / 3 - dsi * dsi / 2) + (q2i[j] - q2chi[j]) * si * dsi / 2 - (q3i[j] - q3chi[j]) * si * si / 3) / (si * si * si);
403 }
404 }
405 else
406 for (auto& x : d2pi_t)
407 {
408 x = 0;
409 }
410 }
411 return d2pij_t;
412 }
413
414 const RowMatrix<double>& orig_t = transitionModel().getPij_t(t);
415 const RowMatrix<double>& ch_t = modelChanged_->getPij_t(rate * t);
416 const RowMatrix<double>& dorig_dt = transitionModel().getdPij_dt(t);
417 const RowMatrix<double>& dch_dt = modelChanged_->getdPij_dt(rate * t);
418 const RowMatrix<double>& d2orig_dt2 = transitionModel().getd2Pij_dt2(t);
419 const RowMatrix<double>& d2ch_dt2 = modelChanged_->getd2Pij_dt2(rate * t);
420
421 for (unsigned int i = 0; i < size_; ++i)
422 {
423 vector<double>& d2pi_dt2 = d2pij_t.getRow(i);
424 const vector<double>& chi_t = ch_t.getRow(i);
425
426 double si = chi_t[size_];
427 if (si == 0)
428 {
429 for (auto& x : d2pi_dt2)
430 {
431 x = 0;
432 }
433 continue;
434 }
435
436 const vector<double>& origi_t = orig_t.getRow(i);
437 const vector<double>& dorigi_dt = dorig_dt.getRow(i);
438 const vector<double>& dchi_dt = dch_dt.getRow(i);
439 const vector<double>& d2origi_dt2 = d2orig_dt2.getRow(i);
440 const vector<double>& d2chi_dt2 = d2ch_dt2.getRow(i);
441
442 double dsi = dchi_dt[size_];
443 double d2si = d2chi_dt2[size_];
444
445 double si2 = si * si;
446
447 for (unsigned int j = 0; j < size_; ++j)
448 {
449 double d2u = d2origi_dt2[j] - d2chi_dt2[j];
450 double du = dorigi_dt[j] - dchi_dt[j];
451 double u = origi_t[j] - chi_t[j];
452
453 d2pi_dt2[j] = -((d2u * si - d2si * u - 2 * dsi * du) / si2 + 2 * dsi * dsi * u / (si2 * si));
454 }
455 }
456
457 return d2pij_t;
458}
Virtual class of a Transition Model related to a given SubstitutionModel.
const TransitionModelInterface & transitionModel() const override
Abstract class of Wrapping model class, where all methods are redirected from model().
const Alphabet & alphabet() const override
std::shared_ptr< const Alphabet > getAlphabet() const override
virtual double getRate() const =0
Get the rate.
double Pij_t(size_t i, size_t j, double t) const override
const Matrix< double > & getd2Pij_dt2(double t) const override
std::unique_ptr< AnonymousSubstitutionModel > modelChanged_
const Matrix< double > & getPij_t(double t) const override
OneChangeRegisterTransitionModel(std::unique_ptr< SubstitutionModelInterface > originalModel, const SubstitutionRegisterInterface &reg, size_t numReg)
const Matrix< double > & getdPij_dt(double t) const override
double getRate() const override
Get the rate.
double d2Pij_dt2(size_t i, size_t j, double t) const override
double dPij_dt(size_t i, size_t j, double t) const override
const std::vector< Scalar > & getRow(size_t i) const
virtual const Matrix< double > & generator() const =0
The SubstitutionRegister interface.
virtual size_t getNumberOfSubstitutionTypes() const =0
virtual size_t getType(size_t fromState, size_t toState) const =0
Get the substitution type far a given pair of model states.
virtual const Matrix< double > & getPij_t(double t) const =0
virtual const Matrix< double > & getdPij_dt(double t) const =0
virtual double Pij_t(size_t i, size_t j, double t) const =0
virtual double d2Pij_dt2(size_t i, size_t j, double t) const =0
virtual const Matrix< double > & getd2Pij_dt2(double t) const =0
virtual double dPij_dt(size_t i, size_t j, double t) const =0
Defines the basic types of data flow nodes.