bpp-phyl3 3.0.0
OneChangeTransitionModel.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: The Bio++ Development Group
2//
3// SPDX-License-Identifier: CECILL-2.1
4
6
8
9using namespace bpp;
10using namespace std;
11
12/******************************************************************************/
13
14double OneChangeTransitionModel::Pij_t(size_t i, size_t j, double t) const
15{
16 double qii = substitutionModel().Qij(i, i);
17 if (qii == 0)
18 {
19 return i == j ? 1 : 0;
20 }
21 else
22 {
23 if (t != 0)
24 {
25 double rate = model().getRate();
26 double v = exp(qii * t * rate);
27 return (transitionModel().Pij_t(i, j, t) - (i == j ? v : 0)) / (1 - v);
28 }
29 else
30 return i == j ? 0 : -substitutionModel().Qij(i, j) / qii;
31 }
32}
33
34double OneChangeTransitionModel::dPij_dt(size_t i, size_t j, double t) const
35{
37 double qii = Q(i, i);
38
39 if (qii == 0)
40 return 0;
41
42 double rate = transitionModel().getRate();
43 if (t != 0)
44 {
45 double v = exp(qii * t * rate);
46 return (transitionModel().dPij_dt(i, j, t) * (1 - v) + (transitionModel().Pij_t(i, j, t) - (i == j ? 1 : 0)) * qii * rate * v) / ((1 - v) * (1 - v));
47 }
48 else
49 {
50 double q2ij = 0;
51 for (size_t k = 0; k < size_; ++k)
52 {
53 q2ij += Q(i, k) * Q(k, j);
54 }
55
56 return rate * (-q2ij + qii * Q(i, j)) / (2 * qii);
57 }
58}
59
60double OneChangeTransitionModel::d2Pij_dt2(size_t i, size_t j, double t) const
61{
62 double rate = transitionModel().getRate();
63 if (t != 0)
64 {
65 double qii = substitutionModel().Qij(i, i);
66
67 if (qii == 0)
68 {
69 return 0;
70 }
71 else
72 {
73 double v = exp(qii * t * rate);
74 double mv = 1 - v;
75
76 return -((mv * transitionModel().d2Pij_dt2(i, j, t) + 2 * qii * rate * v * transitionModel().dPij_dt(i, j, t)) * mv + (transitionModel().Pij_t(i, j, t) - (i == j ? 1 : 0)) * qii * qii * rate * rate * (v + v * v)) / (mv * mv * mv);
77 }
78 }
79 else
80 {
82 double qii = Q(i, i);
83
84 if (qii == 0)
85 return 0;
86
87 double q2ik, q2ij = 0, q3ij = 0;
88
89 for (size_t k = 0; k < size_; ++k)
90 {
91 q2ik = 0;
92 for (size_t l = 0; l < size_; ++l)
93 {
94 q2ik += Q(i, l) * Q(l, k);
95 }
96 if (k == j)
97 q2ij = q2ik;
98
99 q3ij += q2ik * Q(k, j);
100 }
101
102 return -rate * rate * (2 * q3ij - 3 * qii * q2ij + qii * qii * Q(i, j)) / (12 * qii);
103 }
104}
105
107{
108 const RowMatrix<double>& origPij = transitionModel().getPij_t(t);
110 double rate = transitionModel().getRate();
111
112 for (unsigned int i = 0; i < size_; ++i)
113 {
114 vector<double>& pi_t = pij_t.getRow(i);
115
116 double qii = Q(i, i);
117 if (qii == 0)
118 {
119 for (unsigned int j = 0; j < size_; ++j)
120 {
121 pi_t[j] = (i == j ? 1 : 0);
122 }
123 }
124 else
125 {
126 if (t != 0)
127 {
128 const vector<double>& origPij_i = origPij.getRow(i);
129
130 double v = exp(qii * t * rate);
131 for (unsigned int j = 0; j < size_; ++j)
132 {
133 pi_t[j] = (origPij_i[j] - (i == j ? v : 0)) / (1 - v);
134 }
135 }
136 else
137 {
138 const vector<double>& Q_i = Q.getRow(i);
139 for (unsigned int j = 0; j < size_; ++j)
140 {
141 pi_t[j] = (i == j ? 0 : -Q_i[j] / qii);
142 }
143 }
144 }
145 }
146 return pij_t;
147}
148
149
151{
152 double rate = transitionModel().getRate();
153 if (t != 0)
154 {
155 const RowMatrix<double>& origPij = transitionModel().getPij_t(t);
156 const RowMatrix<double>& origdPij = transitionModel().getdPij_dt(t);
157
158 for (unsigned int i = 0; i < size_; ++i)
159 {
160 vector<double>& dpi_t = dpij_t.getRow(i);
161 double qii = substitutionModel().Qij(i, i);
162
163 if (qii == 0)
164 {
165 for (unsigned int j = 0; j < size_; ++j)
166 {
167 dpi_t[j] = 0;
168 }
169 }
170 else
171 {
172 {
173 double v = exp(qii * t * rate);
174 double mv2 = (1 - v) * (1 - v);
175 const vector<double>& origPij_i = origPij.getRow(i);
176 const vector<double>& origdPij_i = origdPij.getRow(i);
177
178 for (unsigned int j = 0; j < size_; ++j)
179 {
180 dpi_t[j] = (origdPij_i[j] * (1 - v) + (origPij_i[j] - (i == j ? 1 : 0)) * qii * rate * v) / mv2;
181 }
182 }
183 }
184 }
185 }
186 else
187 {
190 MatrixTools::mult<double>(Q, Q, Q2);
191
192 for (unsigned int i = 0; i < size_; ++i)
193 {
194 const vector<double>& Q_i = Q.getRow(i);
195 vector<double>& dpi_t = dpij_t.getRow(i);
196 double qii = Q_i[i];
197
198 if (qii == 0)
199 {
200 for (unsigned int j = 0; j < size_; ++j)
201 {
202 dpi_t[j] = 0;
203 }
204 }
205 else
206 {
207 const vector<double>& Q2_i = Q2.getRow(i);
208
209 for (unsigned int j = 0; j < size_; ++j)
210 {
211 dpi_t[j] = rate * (-Q2_i[j] + qii * Q_i[j]) / (2 * qii);
212 }
213 }
214 }
215 }
216
217 return dpij_t;
218}
219
220
222{
223 double rate = transitionModel().getRate();
224 double r2 = rate * rate;
225
226 if (t != 0)
227 {
228 const RowMatrix<double>& origPij = transitionModel().getPij_t(t);
229 const RowMatrix<double>& origdPij = transitionModel().getdPij_dt(t);
230 const RowMatrix<double>& origd2Pij = transitionModel().getd2Pij_dt2(t);
231
232 for (unsigned int i = 0; i < size_; ++i)
233 {
234 double qii = substitutionModel().Qij(i, i);
235 vector<double>& d2pi_t = d2pij_t.getRow(i);
236
237 if (qii == 0)
238 {
239 for (unsigned int j = 0; j < size_; ++j)
240 {
241 d2pi_t[j] = 0;
242 }
243 }
244 else
245 {
246 {
247 double v = exp(rate * qii * t);
248 double mv = 1 - v;
249 double q2 = qii * qii;
250
251 double mv3 = mv * mv * mv;
252 double vpv2 = v + v * v;
253
254 const vector<double>& origPij_i = origPij.getRow(i);
255 const vector<double>& origdPij_i = origdPij.getRow(i);
256 const vector<double>& origd2Pij_i = origd2Pij.getRow(i);
257
258 for (unsigned int j = 0; j < size_; ++j)
259 {
260 d2pi_t[j] = -((mv * origd2Pij_i[j] + 2 * qii * rate * v * origdPij_i[j]) * mv + (origPij_i[j] - (i == j ? 1 : 0)) * q2 * r2 * vpv2) / mv3;
261 }
262 }
263 }
264 }
265 }
266 else
267 {
270 MatrixTools::mult<double>(Q, Q, Q2);
272 MatrixTools::mult<double>(Q, Q2, Q3);
273
274 for (unsigned int i = 0; i < size_; ++i)
275 {
276 const vector<double>& Q_i = Q.getRow(i);
277 double qii = Q_i[i];
278 vector<double>& d2pi_t = d2pij_t.getRow(i);
279
280 if (qii == 0)
281 {
282 for (unsigned int j = 0; j < size_; ++j)
283 {
284 d2pi_t[j] = 0;
285 }
286 }
287 else
288 {
289 const vector<double>& Q2_i = Q2.getRow(i);
290 const vector<double>& Q3_i = Q3.getRow(i);
291
292 for (unsigned int j = 0; j < size_; ++j)
293 {
294 d2pi_t[j] = -r2 * (2 * Q3_i[j] - 3 * qii * Q2_i[j] + qii * qii * Q_i[j]) / (12 * qii);
295 }
296 }
297 }
298 }
299 return d2pij_t;
300}
const TransitionModelInterface & transitionModel() const override
virtual double getRate() const =0
Get the rate.
const Matrix< double > & getPij_t(double t) const override
const Matrix< double > & getd2Pij_dt2(double t) const override
double Pij_t(size_t i, size_t j, double t) const override
double dPij_dt(size_t i, size_t j, double t) const override
const Matrix< double > & getdPij_dt(double t) const override
double d2Pij_dt2(size_t i, size_t j, double t) const override
const std::vector< double > & getRow(size_t i) const
virtual const Matrix< double > & generator() const =0
virtual double Qij(size_t i, size_t j) const =0
A method for computing all necessary matrices.
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.
ExtendedFloat exp(const ExtendedFloat &ef)