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 
9 using namespace bpp;
10 using namespace std;
11 
12 /******************************************************************************/
13 
14 double 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 
34 double OneChangeTransitionModel::dPij_dt(size_t i, size_t j, double t) const
35 {
36  const RowMatrix<double>& Q = substitutionModel().generator();
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 
60 double 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  {
81  const RowMatrix<double>& Q = substitutionModel().generator();
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);
109  const RowMatrix<double>& Q = substitutionModel().generator();
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  {
188  const RowMatrix<double>& Q = substitutionModel().generator();
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  {
268  const RowMatrix<double>& Q = substitutionModel().generator();
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 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
Defines the basic types of data flow nodes.
ExtendedFloat exp(const ExtendedFloat &ef)