bpp-phyl3  3.0.0
RE08.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 "RE08.h"
6 
7 using namespace bpp;
8 
9 #include <cmath>
10 
11 using namespace std;
12 
13 /******************************************************************************/
14 
16  unique_ptr<ReversibleSubstitutionModelInterface> simpleModel,
17  double lambda,
18  double mu) :
20  AbstractReversibleSubstitutionModel(simpleModel->getAlphabet(), make_shared<CanonicalStateMap>(simpleModel->stateMap(), true), "RE08."),
21  simpleModel_(std::move(simpleModel)),
22  simpleGenerator_(),
23  simpleExchangeabilities_(),
24  exp_(), p_(), lambda_(lambda), mu_(mu),
25  nestedPrefix_("model_" + simpleModel->getNamespace())
26 {
27  addParameter_(new Parameter("RE08.lambda", lambda, Parameter::R_PLUS));
28  addParameter_(new Parameter("RE08.mu", mu, Parameter::R_PLUS));
29  simpleModel_->setNamespace("RE08." + nestedPrefix_);
30  addParameters_(simpleModel_->getParameters());
31  // We need to overrired this from the AbstractSubstitutionModel constructor,
32  // since the number of states in the model is no longer equal to the size of the alphabet.
33  size_ = simpleModel_->getNumberOfStates() + 1;
36  freq_.resize(size_);
37  eigenValues_.resize(size_);
40  p_.resize(size_, size_);
42 }
43 
44 /******************************************************************************/
45 
47 {
48  double f = (lambda_ == 0 && mu_ == 0) ? 1 : lambda_ / (lambda_ + mu_);
49 
50  // Frequencies:
51  for (size_t i = 0; i < size_ - 1; ++i)
52  {
53  freq_[i] = simpleModel_->freq(i) * f;
54  }
55 
56  freq_[size_ - 1] = (1. - f);
57 
58  simpleGenerator_ = simpleModel_->generator();
59  simpleExchangeabilities_ = simpleModel_->exchangeabilityMatrix();
60 
61  // Generator and exchangeabilities:
62  for (size_t i = 0; i < size_ - 1; ++i)
63  {
64  for (size_t j = 0; j < size_ - 1; ++j)
65  {
66  generator_(i, j) = simpleGenerator_(i, j);
68  if (i == j)
69  {
70  generator_(i, j) -= mu_;
71  exchangeability_(i, j) -= (mu_ / f) / simpleModel_->freq(i);
72  }
73  }
74  generator_(i, size_ - 1) = mu_;
75  generator_(size_ - 1, i) = lambda_ * simpleModel_->freq(i);
76  exchangeability_(i, size_ - 1) = lambda_ + mu_;
77  exchangeability_(size_ - 1, i) = lambda_ + mu_;
78  }
79  generator_(size_ - 1, size_ - 1) = -lambda_;
80  exchangeability_(size_ - 1, size_ - 1) = -(lambda_ + mu_);
81 
82  // It is very likely that we are able to compute the eigen values and vector from the one of the simple model.
83  // For now however, we will use a numerical diagonalization:
85  // We do not use the one from AbstractReversibleSubstitutionModel, since we already computed the generator.
86 }
87 
88 /******************************************************************************/
89 
90 double RE08::Pij_t(size_t i, size_t j, double d) const
91 {
92  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
93  if (i < size_ - 1 && j < size_ - 1)
94  {
95  return (simpleModel_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
96  + freq_[j] + (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
97  }
98  else
99  {
100  if (i == size_ - 1)
101  {
102  if (j < size_ - 1)
103  {
104  return freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
105  }
106  else
107  {
108  return 1. - f * (1. - exp(-(lambda_ + mu_) * d));
109  }
110  }
111  else
112  {
113  return freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
114  }
115  }
116 }
117 
118 /******************************************************************************/
119 
120 double RE08::dPij_dt(size_t i, size_t j, double d) const
121 {
122  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
123  if (i < size_ - 1 && j < size_ - 1)
124  {
125  return simpleModel_->dPij_dt(i, j, d) * exp(-mu_ * d)
126  - mu_ * (simpleModel_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
127  - (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
128  }
129  else
130  {
131  if (i == size_ - 1)
132  {
133  if (j < size_ - 1)
134  {
135  return (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
136  }
137  else
138  {
139  return -f * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
140  }
141  }
142  else
143  {
144  return (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
145  }
146  }
147 }
148 
149 /******************************************************************************/
150 
151 double RE08::d2Pij_dt2(size_t i, size_t j, double d) const
152 {
153  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
154  if (i < size_ - 1 && j < size_ - 1)
155  {
156  return simpleModel_->d2Pij_dt2(i, j, d) * exp(-mu_ * d)
157  - 2 * mu_ * simpleModel_->dPij_dt(i, j, d) * exp(-mu_ * d)
158  + mu_ * mu_ * (simpleModel_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
159  + (lambda_ + mu_) * (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
160  }
161  else
162  {
163  if (i == size_ - 1)
164  {
165  if (j < size_ - 1)
166  {
167  return -(lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
168  }
169  else
170  {
171  return f * (lambda_ + mu_) * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
172  }
173  }
174  else
175  {
176  return -(lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
177  }
178  }
179 }
180 
181 /******************************************************************************/
182 
183 const Matrix<double>& RE08::getPij_t(double d) const
184 {
185  RowMatrix<double> simpleP = simpleModel_->getPij_t(d);
186  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
187  for (size_t i = 0; i < size_ - 1; i++)
188  {
189  for (size_t j = 0; j < size_ - 1; j++)
190  {
191  p_(i, j) = (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
192  + freq_[j] + (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
193  }
194  }
195  for (size_t j = 0; j < size_ - 1; j++)
196  {
197  p_(size_ - 1, j) = freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
198  }
199  p_(size_ - 1, size_ - 1) = 1. - f * (1. - exp(-(lambda_ + mu_) * d));
200  for (size_t i = 0; i < size_ - 1; i++)
201  {
202  p_(i, size_ - 1) = freq_[size_ - 1] * (1. - exp(-(lambda_ + mu_) * d));
203  }
204  return p_;
205 }
206 
207 /******************************************************************************/
208 
209 const Matrix<double>& RE08::getdPij_dt(double d) const
210 {
211  RowMatrix<double> simpleP = simpleModel_->getPij_t(d);
212  RowMatrix<double> simpleDP = simpleModel_->getdPij_dt(d);
213  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
214  for (size_t i = 0; i < size_ - 1; i++)
215  {
216  for (size_t j = 0; j < size_ - 1; j++)
217  {
218  p_(i, j) = simpleDP(i, j) * exp(-mu_ * d)
219  - mu_ * (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
220  - (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
221  }
222  }
223  for (size_t j = 0; j < size_ - 1; j++)
224  {
225  p_(size_ - 1, j) = (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
226  }
227  p_(size_ - 1, size_ - 1) = -f * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
228  for (size_t i = 0; i < size_ - 1; i++)
229  {
230  p_(i, size_ - 1) = (lambda_ + mu_) * freq_[size_ - 1] * exp(-(lambda_ + mu_) * d);
231  }
232  return p_;
233 }
234 
235 /******************************************************************************/
236 
237 const Matrix<double>& RE08::getd2Pij_dt2(double d) const
238 {
239  RowMatrix<double> simpleP = simpleModel_->getPij_t(d);
240  RowMatrix<double> simpleDP = simpleModel_->getdPij_dt(d);
241  RowMatrix<double> simpleD2P = simpleModel_->getd2Pij_dt2(d);
242  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
243  for (size_t i = 0; i < size_ - 1; i++)
244  {
245  for (size_t j = 0; j < size_ - 1; j++)
246  {
247  p_(i, j) = simpleD2P(i, j) * exp(-mu_ * d)
248  - 2 * mu_ * simpleDP(i, j) * exp(-mu_ * d)
249  + mu_ * mu_ * (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
250  + (lambda_ + mu_) * (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
251  }
252  }
253  for (size_t j = 0; j < size_ - 1; j++)
254  {
255  p_(size_ - 1, j) = -(lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
256  }
257  p_(size_ - 1, size_ - 1) = f * (lambda_ + mu_) * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
258  for (size_t i = 0; i < size_ - 1; i++)
259  {
260  p_(i, size_ - 1) = -(lambda_ + mu_) * (lambda_ + mu_) * freq_[size_ - 1] * exp(-(lambda_ + mu_) * d);
261  }
262  return p_;
263 }
264 
265 /******************************************************************************/
266 
267 double RE08::getInitValue(size_t i, int state) const
268 {
269  if (i >= size_)
270  throw IndexOutOfBoundsException("RE08::getInitValue", i, 0, size_ - 1);
271  if (state < -1 || !getAlphabet()->isIntInAlphabet(state))
272  throw BadIntException(state, "RE08::getInitValue. Character " + alphabet_->intToChar(state) + " is not allowed in model.", alphabet_.get());
273  if (i == size_ - 1 && state == -1)
274  return 1.;
275  vector<int> states = alphabet_->getAlias(state);
276  for (size_t j = 0; j < states.size(); j++)
277  {
278  if ((int)i == states[j])
279  return 1.;
280  }
281  return 0.;
282 }
283 
284 /******************************************************************************/
285 
286 void RE08::setNamespace(const string& prefix)
287 {
289  // We also need to update the namespace of the nested model:
290  simpleModel_->setNamespace(prefix + nestedPrefix_);
291 }
292 
293 /******************************************************************************/
void addParameters_(const ParameterList &parameters)
void addParameter_(Parameter *parameter)
void setNamespace(const std::string &prefix)
Partial implementation of the ReversibleSubstitutionModel interface.
RowMatrix< double > generator_
The generator matrix of the model.
Vdouble eigenValues_
The vector of eigen values.
RowMatrix< double > exchangeability_
The exchangeability matrix of the model, defined as . When the model is reversible,...
RowMatrix< double > leftEigenVectors_
The matrix made of left eigen vectors (by row) if rightEigenVectors_ is non-singular.
virtual void updateMatrices_()
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
RowMatrix< double > rightEigenVectors_
The matrix made of right eigen vectors (by column).
std::shared_ptr< const Alphabet > getAlphabet() const override
size_t size_
The number of states.
Vdouble freq_
The vector of equilibrium frequencies.
std::shared_ptr< const Alphabet > alphabet_
The alphabet relevant to this model.
This class implements a state map where all resolved states are modeled.
Definition: StateMap.h:168
static const std::shared_ptr< IntervalConstraint > R_PLUS
std::unique_ptr< ReversibleSubstitutionModelInterface > simpleModel_
Definition: RE08.h:68
const Matrix< double > & getdPij_dt(double d) const override
Definition: RE08.cpp:209
RowMatrix< double > simpleExchangeabilities_
Definition: RE08.h:70
double getInitValue(size_t i, int state) const override
Definition: RE08.cpp:267
double Pij_t(size_t i, size_t j, double d) const override
Definition: RE08.cpp:90
void setNamespace(const std::string &prefix) override
Definition: RE08.cpp:286
RowMatrix< double > p_
Definition: RE08.h:72
double d2Pij_dt2(size_t i, size_t j, double d) const override
Definition: RE08.cpp:151
std::string nestedPrefix_
Definition: RE08.h:75
double lambda_
Definition: RE08.h:73
const Matrix< double > & getPij_t(double d) const override
Definition: RE08.cpp:183
void updateMatrices_() override
Compute and diagonalize the matrix, and fill the eigenValues_, leftEigenVectors_ and rightEigenVecto...
Definition: RE08.cpp:46
const Matrix< double > & getd2Pij_dt2(double d) const override
Definition: RE08.cpp:237
RowMatrix< double > simpleGenerator_
Definition: RE08.h:69
double mu_
Definition: RE08.h:74
RE08(std::unique_ptr< ReversibleSubstitutionModelInterface > simpleModel, double lambda=0.1, double mu=0.1)
Build a new Rivas & Eddy model from a standard substitution model.
Definition: RE08.cpp:15
double dPij_dt(size_t i, size_t j, double d) const override
Definition: RE08.cpp:120
void resize(size_t nRows, size_t nCols)
Defines the basic types of data flow nodes.
ExtendedFloat exp(const ExtendedFloat &ef)