bpp-phyl  2.2.0
RE08.cpp
Go to the documentation of this file.
1 //
2 // File: RE08.cpp
3 // Created by: Julien Dutheil
4 // Created on: Mon Dec 29 10:15 2008
5 //
6 
7 /*
8 Copyright or © or Copr. Bio++ Development Team, (November 16, 2004)
9 
10 This software is a computer program whose purpose is to provide classes
11 for phylogenetic data analysis.
12 
13 This software is governed by the CeCILL license under French law and
14 abiding by the rules of distribution of free software. You can use,
15 modify and/ or redistribute the software under the terms of the CeCILL
16 license as circulated by CEA, CNRS and INRIA at the following URL
17 "http://www.cecill.info".
18 
19 As a counterpart to the access to the source code and rights to copy,
20 modify and redistribute granted by the license, users are provided only
21 with a limited warranty and the software's author, the holder of the
22 economic rights, and the successive licensors have only limited
23 liability.
24 
25 In this respect, the user's attention is drawn to the risks associated
26 with loading, using, modifying and/or developing or reproducing the
27 software by the user in light of its specific status of free software,
28 that may mean that it is complicated to manipulate, and that also
29 therefore means that it is reserved for developers and experienced
30 professionals having in-depth computer knowledge. Users are therefore
31 encouraged to load and test the software's suitability as regards their
32 requirements in conditions enabling the security of their systems and/or
33 data to be ensured and, more generally, to use and operate it in the
34 same conditions as regards security.
35 
36 The fact that you are presently reading this means that you have had
37 knowledge of the CeCILL license and that you accept its terms.
38 */
39 
40 #include "RE08.h"
41 
42 using namespace bpp;
43 
44 #include <cmath>
45 
46 using namespace std;
47 
48 /******************************************************************************/
49 
50 RE08::RE08(ReversibleSubstitutionModel* simpleModel, double lambda, double mu) :
51  AbstractParameterAliasable("RE08."),
52  AbstractReversibleSubstitutionModel(simpleModel->getAlphabet(), new CanonicalStateMap(simpleModel->getStateMap(), true), "RE08."),
53  simpleModel_(simpleModel),
54  simpleGenerator_(),
55  simpleExchangeabilities_(),
56  exp_(), p_(), lambda_(lambda), mu_(mu),
57  nestedPrefix_("model_" + simpleModel->getNamespace())
58 {
59  addParameter_(new Parameter("RE08.lambda", lambda, &Parameter::R_PLUS));
60  addParameter_(new Parameter("RE08.mu", mu, &Parameter::R_PLUS));
61  simpleModel_->setNamespace("RE08." + nestedPrefix_);
62  addParameters_(simpleModel->getParameters());
63  //We need to overrired this from the AbstractSubstitutionModel constructor,
64  //since the number of states in the model is no longer equal to the size of the alphabet.
65  size_ = simpleModel->getNumberOfStates() + 1;
66  generator_.resize(size_, size_);
67  exchangeability_.resize(size_, size_);
68  freq_.resize(size_);
69  eigenValues_.resize(size_);
70  leftEigenVectors_.resize(size_, size_);
72  p_.resize(size_,size_);
74 }
75 
76 /******************************************************************************/
77 
79 {
80  double f = (lambda_ == 0 && mu_ == 0) ? 1 : lambda_ / (lambda_ + mu_);
81 
82  // Frequencies:
83  for(size_t i = 0; i < size_ - 1; i++)
84  freq_[i] = simpleModel_->freq(i) * f;
85 
86  freq_[size_-1] = (1. - f);
87 
88  simpleGenerator_ = simpleModel_->getGenerator();
89  simpleExchangeabilities_ = simpleModel_->getExchangeabilityMatrix();
90 
91  // Generator and exchangeabilities:
92  for (size_t i = 0; i < size_ - 1; i++)
93  {
94  for (size_t j = 0; j < size_ - 1; j++)
95  {
96  generator_(i, j) = simpleGenerator_(i, j);
98  if (i == j)
99  {
100  generator_(i, j) -= mu_;
101  exchangeability_(i, j) -= (mu_ / f) / simpleModel_->freq(i);
102  }
103  }
104  generator_(i, size_ - 1) = mu_;
105  generator_(size_ - 1, i) = lambda_ * simpleModel_->freq(i);
106  exchangeability_(i, size_ - 1) = lambda_ + mu_;
107  exchangeability_(size_ - 1, i) = lambda_ + mu_;
108  }
109  generator_(size_ - 1, size_ - 1) = -lambda_;
110  exchangeability_(size_ - 1, size_ - 1) = -(lambda_ + mu_);
111 
112  //It is very likely that we are able to compute the eigen values and vector from the one of the simple model.
113  //For now however, we will use a numerical diagonalization:
115  //We do not use the one from AbstractReversibleSubstitutionModel, since we already computed the generator.
116 }
117 
118 /******************************************************************************/
119 
120 double RE08::Pij_t(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_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
126  + freq_[j] + (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
127  }
128  else
129  {
130  if (i == size_ - 1)
131  {
132  if (j < size_ - 1)
133  {
134  return freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
135  }
136  else
137  {
138  return 1. - f * (1. - exp(-(lambda_ + mu_) * d));
139  }
140  }
141  else
142  {
143  return freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
144  }
145  }
146 }
147 
148 /******************************************************************************/
149 
150 double RE08::dPij_dt(size_t i, size_t j, double d) const
151 {
152  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
153  if(i < size_ - 1 && j < size_ - 1)
154  {
155  return simpleModel_->dPij_dt(i, j, d) * exp(-mu_ * d)
156  - mu_ * (simpleModel_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
157  - (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
158  }
159  else
160  {
161  if (i == size_ - 1)
162  {
163  if (j < size_ - 1)
164  {
165  return (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
166  }
167  else
168  {
169  return - f * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
170  }
171  }
172  else
173  {
174  return (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
175  }
176  }
177 }
178 
179 /******************************************************************************/
180 
181 double RE08::d2Pij_dt2(size_t i, size_t j, double d) const
182 {
183  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
184  if(i < size_ - 1 && j < size_ - 1)
185  {
186  return simpleModel_->d2Pij_dt2(i, j, d) * exp(-mu_ * d)
187  - 2 * mu_ * simpleModel_->dPij_dt(i, j, d) * exp(-mu_ * d)
188  + mu_ * mu_ * (simpleModel_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
189  + (lambda_ + mu_) * (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
190  }
191  else
192  {
193  if (i == size_ - 1)
194  {
195  if (j < size_ - 1)
196  {
197  return - (lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
198  }
199  else
200  {
201  return f * (lambda_ + mu_) * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
202  }
203  }
204  else
205  {
206  return - (lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
207  }
208  }
209 }
210 
211 /******************************************************************************/
212 
213 const Matrix<double>& RE08::getPij_t(double d) const
214 {
215  RowMatrix<double> simpleP = simpleModel_->getPij_t(d);
216  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
217  for (size_t i = 0; i < size_ - 1; i++)
218  {
219  for (size_t j = 0; j < size_ - 1; j++)
220  {
221  p_(i, j) = (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
222  + freq_[j] + (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
223  }
224  }
225  for(size_t j = 0; j < size_ - 1; j++)
226  {
227  p_(size_ - 1, j) = freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
228  }
229  p_(size_ - 1, size_ - 1) = 1. - f * (1. - exp(-(lambda_ + mu_) * d));
230  for(size_t i = 0; i < size_ - 1; i++)
231  {
232  p_(i, size_ - 1) = freq_[size_ - 1] * (1. - exp(-(lambda_ + mu_) * d));
233  }
234  return p_;
235 }
236 
237 /******************************************************************************/
238 
239 const Matrix<double>& RE08::getdPij_dt(double d) const
240 {
241  RowMatrix<double> simpleP = simpleModel_->getPij_t(d);
242  RowMatrix<double> simpleDP = simpleModel_->getdPij_dt(d);
243  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
244  for (size_t i = 0; i < size_ - 1; i++)
245  {
246  for (size_t j = 0; j < size_ - 1; j++)
247  {
248  p_(i, j) = simpleDP(i, j) * exp(-mu_ * d)
249  - mu_ * (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
250  - (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_) * freq_[j] * exp(-(lambda_ + mu_) * d);
256  }
257  p_(size_ - 1, size_ - 1) = - f * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
258  for (size_t i = 0; i < size_ - 1; i++)
259  {
260  p_(i, size_ - 1) = (lambda_ + mu_) * freq_[size_ - 1] * exp(-(lambda_ + mu_) * d);
261  }
262  return p_;
263 }
264 
265 /******************************************************************************/
266 
267 const Matrix<double>& RE08::getd2Pij_dt2(double d) const
268 {
269  RowMatrix<double> simpleP = simpleModel_->getPij_t(d);
270  RowMatrix<double> simpleDP = simpleModel_->getdPij_dt(d);
271  RowMatrix<double> simpleD2P = simpleModel_->getd2Pij_dt2(d);
272  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
273  for (size_t i = 0; i < size_ - 1; i++)
274  {
275  for (size_t j = 0; j < size_ - 1; j++)
276  {
277  p_(i, j) = simpleD2P(i, j) * exp(-mu_ * d)
278  - 2 * mu_ * simpleDP(i, j) * exp(-mu_ * d)
279  + mu_ * mu_ * (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
280  + (lambda_ + mu_) * (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
281  }
282  }
283  for (size_t j = 0; j < size_ - 1; j++)
284  {
285  p_(size_ - 1, j) = - (lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
286  }
287  p_(size_ - 1, size_ - 1) = f * (lambda_ + mu_) * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
288  for(size_t i = 0; i < size_ - 1; i++)
289  {
290  p_(i, size_ - 1) = - (lambda_ + mu_) * (lambda_ + mu_) * freq_[size_ - 1] * exp(-(lambda_ + mu_) * d);
291  }
292  return p_;
293 }
294 
295 /******************************************************************************/
296 
297 double RE08::getInitValue(size_t i, int state) const throw (IndexOutOfBoundsException, BadIntException)
298 {
299  if (i >= size_) throw IndexOutOfBoundsException("RE08::getInitValue", i, 0, size_ - 1);
300  if (state < -1 || !getAlphabet()->isIntInAlphabet(state))
301  throw BadIntException(state, "RE08::getInitValue. Character " + getAlphabet()->intToChar(state) + " is not allowed in model.");
302  if (i == size_ - 1 && state == -1) return 1.;
303  vector<int> states = getAlphabet()->getAlias(state);
304  for (size_t j = 0; j < states.size(); j++)
305  if ((int)i == states[j]) return 1.;
306  return 0.;
307 }
308 
309 /******************************************************************************/
310 
311 void RE08::setNamespace(const string& prefix)
312 {
313  AbstractSubstitutionModel::setNamespace(prefix);
314  //We also need to update the namespace of the nested model:
315  simpleModel_->setNamespace(prefix + nestedPrefix_);
316 }
317 
318 /******************************************************************************/
319 
const Matrix< double > & getd2Pij_dt2(double d) const
Definition: RE08.cpp:267
virtual void updateMatrices()
Diagonalize the matrix, and fill the eigenValues_, iEigenValues_, leftEigenVectors_ and rightEigenVe...
void setNamespace(const std::string &prefix)
Definition: RE08.cpp:311
RowMatrix< double > exchangeability_
The exchangeability matrix of the model, defined as . When the model is reversible, this matrix is symetric.
const Matrix< double > & getPij_t(double d) const
Definition: RE08.cpp:213
This class implements a state map where all resolved states are modeled.
Definition: StateMap.h:161
RowMatrix< double > simpleGenerator_
Definition: RE08.h:101
RowMatrix< double > rightEigenVectors_
The matrix made of right eigen vectors (by column).
Vdouble eigenValues_
The vector of eigen values.
STL namespace.
RowMatrix< double > p_
Definition: RE08.h:104
Vdouble freq_
The vector of equilibrium frequencies.
const Matrix< double > & getdPij_dt(double d) const
Definition: RE08.cpp:239
double mu_
Definition: RE08.h:106
void updateMatrices()
Compute and diagonalize the matrix, and fill the eigenValues_, leftEigenVectors_ and rightEigenVecto...
Definition: RE08.cpp:78
Partial implementation of the ReversibleSubstitutionModel interface.
double d2Pij_dt2(size_t i, size_t j, double d) const
Definition: RE08.cpp:181
Interface for reversible substitution models.
double lambda_
Definition: RE08.h:105
RowMatrix< double > leftEigenVectors_
The matrix made of left eigen vectors (by row) if rightEigenVectors_ is non-singular.
RowMatrix< double > generator_
The generator matrix of the model.
RowMatrix< double > simpleExchangeabilities_
Definition: RE08.h:102
size_t size_
The size of the generator, i.e. the number of states.
double dPij_dt(size_t i, size_t j, double d) const
Definition: RE08.cpp:150
RE08(ReversibleSubstitutionModel *simpleModel, double lambda=0, double mu=0)
Build a new Rivas & Eddy model from a standard substitution model.
Definition: RE08.cpp:50
std::string nestedPrefix_
Definition: RE08.h:107
virtual size_t getNumberOfStates() const =0
Get the number of states.
double getInitValue(size_t i, int state) const
Definition: RE08.cpp:297
std::auto_ptr< ReversibleSubstitutionModel > simpleModel_
Definition: RE08.h:100
double Pij_t(size_t i, size_t j, double d) const
Definition: RE08.cpp:120