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 
10 using namespace bpp;
11 using namespace std;
12 
14  unique_ptr<SubstitutionModelInterface> originalModel,
16  size_t numReg) :
17  AbstractParameterAliasable("OneChange."),
18  AbstractWrappedModel("OneChange."),
19  AbstractWrappedTransitionModel("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."),
55  AbstractWrappedTransitionModel("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 
116 double 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  {
123  const Matrix<double>& gen = substitutionModel().generator();
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 
136 double 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 
149  RowMatrix<double> Qch2;
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 
174 double 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 
296  RowMatrix<double> Qch2;
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 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 > & getPij_t(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
virtual const Matrix< double > & getdPij_dt(double t) const =0
Defines the basic types of data flow nodes.