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
7using namespace bpp;
8
9#include <cmath>
10
11using namespace std;
12
13/******************************************************************************/
14
15RE08::RE08(
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_);
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);
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
90double 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
120double 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
151double 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
183const 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
209const 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
237const 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
267double 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
286void 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).
size_t size_
The number of states.
Vdouble freq_
The vector of equilibrium frequencies.
std::shared_ptr< const Alphabet > getAlphabet() const override
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
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)