bpp-phyl  2.1.0
 All Classes Namespaces Files Functions Variables Friends Pages
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) :
52  AbstractSubstitutionModel(simpleModel->getAlphabet(), "RE08."),
53  AbstractReversibleSubstitutionModel(simpleModel->getAlphabet(), "RE08."),
54  simpleModel_(simpleModel),
55  simpleGenerator_(),
56  simpleExchangeabilities_(),
57  exp_(), p_(), lambda_(lambda), mu_(mu),
58  nestedPrefix_("model_" + simpleModel->getNamespace())
59 {
60  addParameter_(new Parameter("RE08.lambda", lambda, &Parameter::R_PLUS));
61  addParameter_(new Parameter("RE08.mu", mu, &Parameter::R_PLUS));
62  simpleModel_->setNamespace("RE08." + nestedPrefix_);
63  addParameters_(simpleModel->getParameters());
64  //We need to overrired this from the AbstractSubstitutionModel constructor,
65  //since the number of states in the model is no longer equal to the size of the alphabet.
66  size_ = simpleModel->getNumberOfStates() + 1;
67  chars_.insert(chars_.begin(), -1);
68  generator_.resize(size_, size_);
69  exchangeability_.resize(size_, size_);
70  freq_.resize(size_);
71  eigenValues_.resize(size_);
72  leftEigenVectors_.resize(size_, size_);
73  rightEigenVectors_.resize(size_, size_);
74  p_.resize(size_,size_);
76 }
77 
78 /******************************************************************************/
79 
81 {
82  double f = (lambda_ == 0 && mu_ == 0) ? 1 : lambda_ / (lambda_ + mu_);
83 
84  // Frequencies:
85  for(size_t i = 0; i < size_ - 1; i++)
86  freq_[i] = simpleModel_->freq(i) * f;
87 
88  freq_[size_-1] = (1. - f);
89 
92 
93  // Generator and exchangeabilities:
94  for (size_t i = 0; i < size_ - 1; i++)
95  {
96  for (size_t j = 0; j < size_ - 1; j++)
97  {
98  generator_(i, j) = simpleGenerator_(i, j);
100  if (i == j)
101  {
102  generator_(i, j) -= mu_;
103  exchangeability_(i, j) -= (mu_ / f) / simpleModel_->freq(i);
104  }
105  }
106  generator_(i, size_ - 1) = mu_;
107  generator_(size_ - 1, i) = lambda_ * simpleModel_->freq(i);
108  exchangeability_(i, size_ - 1) = lambda_ + mu_;
109  exchangeability_(size_ - 1, i) = lambda_ + mu_;
110  }
111  generator_(size_ - 1, size_ - 1) = -lambda_;
112  exchangeability_(size_ - 1, size_ - 1) = -(lambda_ + mu_);
113 
114  //It is very likely that we are able to compute the eigen values and vector from the one of the simple model.
115  //For now however, we will use a numerical diagonalization:
117  //We do not use the one from AbstractReversibleSubstitutionModel, since we already computed the generator.
118 }
119 
120 /******************************************************************************/
121 
122 double RE08::Pij_t(size_t i, size_t j, double d) const
123 {
124  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
125  if(i < size_ - 1 && j < size_ - 1)
126  {
127  return (simpleModel_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
128  + freq_[j] + (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
129  }
130  else
131  {
132  if (i == size_ - 1)
133  {
134  if (j < size_ - 1)
135  {
136  return freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
137  }
138  else
139  {
140  return 1. - f * (1. - exp(-(lambda_ + mu_) * d));
141  }
142  }
143  else
144  {
145  return freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
146  }
147  }
148 }
149 
150 /******************************************************************************/
151 
152 double RE08::dPij_dt(size_t i, size_t j, double d) const
153 {
154  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
155  if(i < size_ - 1 && j < size_ - 1)
156  {
157  return simpleModel_->dPij_dt(i, j, d) * exp(-mu_ * d)
158  - mu_ * (simpleModel_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
159  - (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_) * freq_[j] * exp(-(lambda_ + mu_) * d);
168  }
169  else
170  {
171  return - f * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
172  }
173  }
174  else
175  {
176  return (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
177  }
178  }
179 }
180 
181 /******************************************************************************/
182 
183 double RE08::d2Pij_dt2(size_t i, size_t j, double d) const
184 {
185  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
186  if(i < size_ - 1 && j < size_ - 1)
187  {
188  return simpleModel_->d2Pij_dt2(i, j, d) * exp(-mu_ * d)
189  - 2 * mu_ * simpleModel_->dPij_dt(i, j, d) * exp(-mu_ * d)
190  + mu_ * mu_ * (simpleModel_->Pij_t(i, j, d) - simpleModel_->freq(j)) * exp(-mu_ * d)
191  + (lambda_ + mu_) * (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
192  }
193  else
194  {
195  if (i == size_ - 1)
196  {
197  if (j < size_ - 1)
198  {
199  return - (lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
200  }
201  else
202  {
203  return f * (lambda_ + mu_) * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
204  }
205  }
206  else
207  {
208  return - (lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
209  }
210  }
211 }
212 
213 /******************************************************************************/
214 
215 const Matrix<double> & RE08::getPij_t(double d) const
216 {
218  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
219  for (size_t i = 0; i < size_ - 1; i++)
220  {
221  for (size_t j = 0; j < size_ - 1; j++)
222  {
223  p_(i, j) = (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
224  + freq_[j] + (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
225  }
226  }
227  for(size_t j = 0; j < size_ - 1; j++)
228  {
229  p_(size_ - 1, j) = freq_[j] * (1. - exp(-(lambda_ + mu_) * d));
230  }
231  p_(size_ - 1, size_ - 1) = 1. - f * (1. - exp(-(lambda_ + mu_) * d));
232  for(size_t i = 0; i < size_ - 1; i++)
233  {
234  p_(i, size_ - 1) = freq_[size_ - 1] * (1. - exp(-(lambda_ + mu_) * d));
235  }
236  return p_;
237 }
238 
239 /******************************************************************************/
240 
241 const Matrix<double> & RE08::getdPij_dt(double d) const
242 {
245  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
246  for (size_t i = 0; i < size_ - 1; i++)
247  {
248  for (size_t j = 0; j < size_ - 1; j++)
249  {
250  p_(i, j) = simpleDP(i, j) * exp(-mu_ * d)
251  - mu_ * (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
252  - (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
253  }
254  }
255  for (size_t j = 0; j < size_ - 1; j++)
256  {
257  p_(size_ - 1, j) = (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
258  }
259  p_(size_ - 1, size_ - 1) = - f * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
260  for (size_t i = 0; i < size_ - 1; i++)
261  {
262  p_(i, size_ - 1) = (lambda_ + mu_) * freq_[size_ - 1] * exp(-(lambda_ + mu_) * d);
263  }
264  return p_;
265 }
266 
267 /******************************************************************************/
268 
269 const Matrix<double> & RE08::getd2Pij_dt2(double d) const
270 {
274  double f = (lambda_ == 0 && mu_ == 0) ? 1. : lambda_ / (lambda_ + mu_);
275  for (size_t i = 0; i < size_ - 1; i++)
276  {
277  for (size_t j = 0; j < size_ - 1; j++)
278  {
279  p_(i, j) = simpleD2P(i, j) * exp(-mu_ * d)
280  - 2 * mu_ * simpleDP(i, j) * exp(-mu_ * d)
281  + mu_ * mu_ * (simpleP(i, j) - simpleModel_->freq(j)) * exp(-mu_ * d)
282  + (lambda_ + mu_) * (lambda_ + mu_) * (simpleModel_->freq(j) - freq_[j]) * exp(-(lambda_ + mu_) * d);
283  }
284  }
285  for (size_t j = 0; j < size_ - 1; j++)
286  {
287  p_(size_ - 1, j) = - (lambda_ + mu_) * (lambda_ + mu_) * freq_[j] * exp(-(lambda_ + mu_) * d);
288  }
289  p_(size_ - 1, size_ - 1) = f * (lambda_ + mu_) * (lambda_ + mu_) * exp(-(lambda_ + mu_) * d);
290  for(size_t i = 0; i < size_ - 1; i++)
291  {
292  p_(i, size_ - 1) = - (lambda_ + mu_) * (lambda_ + mu_) * freq_[size_ - 1] * exp(-(lambda_ + mu_) * d);
293  }
294  return p_;
295 }
296 
297 /******************************************************************************/
298 
299 double RE08::getInitValue(size_t i, int state) const throw (IndexOutOfBoundsException, BadIntException)
300 {
301  if (i >= size_) throw IndexOutOfBoundsException("RE08::getInitValue", i, 0, size_ - 1);
302  if (state < -1 || !getAlphabet()->isIntInAlphabet(state))
303  throw BadIntException(state, "RE08::getInitValue. Character " + getAlphabet()->intToChar(state) + " is not allowed in model.");
304  if (i == size_ - 1 && state == -1) return 1.;
305  vector<int> states = getAlphabet()->getAlias(state);
306  for (size_t j = 0; j < states.size(); j++)
307  if ((int)i == states[j]) return 1.;
308  return 0.;
309 }
310 
311 /******************************************************************************/
312 
313 void RE08::setNamespace(const string& prefix)
314 {
316  //We also need to update the namespace of the nested model:
317  simpleModel_->setNamespace(prefix + nestedPrefix_);
318 }
319 
320 /******************************************************************************/
321