bpp-phyl  2.2.0
MarkovModulatedSubstitutionModel.cpp
Go to the documentation of this file.
1 //
2 // File: MarkovModulatedSubstitutionModel.cpp
3 // Created by: Julien Dutheil
4 // Created on: Sat Aug 05 08:21 2006
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 
41 
42 #include <Bpp/Numeric/VectorTools.h>
43 #include <Bpp/Numeric/Matrix/MatrixTools.h>
44 #include <Bpp/Numeric/Matrix/EigenValue.h>
45 
46 using namespace bpp;
47 using namespace std;
48 
49 /******************************************************************************/
50 
52  const MarkovModulatedSubstitutionModel& model) :
53  AbstractParameterAliasable(model),
54  model_ (dynamic_cast<ReversibleSubstitutionModel*>(model.model_->clone())),
55  stateMap_ (model.stateMap_),
56  nbStates_ (model.nbStates_),
57  nbRates_ (model.nbRates_),
58  rates_ (model.rates_),
59  ratesExchangeability_(model.ratesExchangeability_),
60  ratesFreq_ (model.ratesFreq_),
61  ratesGenerator_ (model.ratesGenerator_),
62  generator_ (model.generator_),
63  exchangeability_ (model.exchangeability_),
64  leftEigenVectors_ (model.leftEigenVectors_),
65  rightEigenVectors_ (model.rightEigenVectors_),
66  eigenValues_ (model.eigenValues_),
67  iEigenValues_ (model.iEigenValues_),
68  eigenDecompose_ (model.eigenDecompose_),
69  pijt_ (model.pijt_),
70  dpijt_ (model.dpijt_),
71  d2pijt_ (model.d2pijt_),
72  freq_ (model.freq_),
73  normalizeRateChanges_(model.normalizeRateChanges_),
74  nestedPrefix_ (model.nestedPrefix_)
75 {}
76 
79 {
80  AbstractParametrizable::operator=(model);
81  model_ = dynamic_cast<ReversibleSubstitutionModel*>(model.model_->clone());
82  stateMap_ = model.stateMap_;
83  nbStates_ = model.nbStates_;
84  nbRates_ = model.nbRates_;
85  rates_ = model.rates_;
87  ratesFreq_ = model.ratesFreq_;
89  generator_ = model.generator_;
93  eigenValues_ = model.eigenValues_;
96  pijt_ = model.pijt_;
97  dpijt_ = model.dpijt_;
98  d2pijt_ = model.d2pijt_;
99  freq_ = model.freq_;
102  return *this;
103 }
104 
105 /******************************************************************************/
106 
108 {
109  // ratesGenerator_ and rates_ must be initialized!
111  nbRates_ = rates_.getNumberOfColumns();
112  RowMatrix<double> Tmp1, Tmp2;
113  MatrixTools::diag(ratesFreq_, Tmp1);
114  MatrixTools::mult(ratesExchangeability_, Tmp1, ratesGenerator_);
115  MatrixTools::kroneckerMult(rates_, model_->getGenerator(), generator_);
116 
117  MatrixTools::MatrixTools::getId< RowMatrix<double> >(nbStates_, Tmp1);
118  MatrixTools::kroneckerMult(ratesGenerator_, Tmp1, Tmp2);
119  MatrixTools::add(generator_, Tmp2);
120 
121  MatrixTools::diag(1. / ratesFreq_, Tmp1);
122  MatrixTools::mult(rates_, Tmp1, Tmp2);
123  MatrixTools::kroneckerMult(Tmp2, model_->getExchangeabilityMatrix(), exchangeability_);
124 
125  MatrixTools::diag(1 / model_->getFrequencies(), Tmp1);
126  MatrixTools::kroneckerMult(ratesExchangeability_, Tmp1, Tmp2);
127  MatrixTools::add(exchangeability_, Tmp2);
128  freq_ = VectorTools::kroneckerMult(ratesFreq_, model_->getFrequencies());
130  {
131  // Normalization:
132  Vdouble Tmp;
133  MatrixTools::diag(generator_, Tmp);
134  double scale = -VectorTools::scalar<double, double>(Tmp, freq_);
135  MatrixTools::scale(generator_, 1. / scale);
136 
137  // Normalize exchangeability matrix too:
138  MatrixTools::scale(exchangeability_, 1. / scale);
139  }
140 
141  // Compute eigen values and vectors:
142  eigenValues_.resize(nbRates_ * nbStates_);
143  iEigenValues_.resize(nbRates_ * nbStates_);
148 
149  vector<double> modelEigenValues = model_->getEigenValues();
150  RowMatrix<double> modelRightEigenVectors = model_->getColumnRightEigenVectors();
151  for (unsigned int i = 0; i < nbStates_; i++)
152  {
153  RowMatrix<double> tmp = rates_;
154  MatrixTools::scale(tmp, modelEigenValues[i]);
155  MatrixTools::add(tmp, ratesGenerator_);
156  EigenValue<double> ev(tmp);
157  vector<double> values = ev.getRealEigenValues();
158  RowMatrix<double> vectors = ev.getV();
159  for (size_t j = 0; j < nbRates_; j++)
160  {
161  size_t c = i * nbRates_ + j; // Current eigen value index.
162  eigenValues_[c] = values[j];
163  // Compute the Kronecker product of the jth vector and the ith modelRightEigenVector.
164  for (unsigned int ii = 0; ii < nbRates_; ii++)
165  {
166  double vii = vectors(ii, j);
167  for (unsigned int jj = 0; jj < nbStates_; jj++)
168  {
169  rightEigenVectors_(ii * nbStates_ + jj, c) = vii * modelRightEigenVectors(jj, i);
170  }
171  }
172  }
173  }
174  // Now compute left eigen vectors by inversion:
175  MatrixTools::inv(rightEigenVectors_, leftEigenVectors_);
176 }
177 
178 /******************************************************************************/
179 
180 const Matrix<double>& MarkovModulatedSubstitutionModel::getPij_t(double t) const
181 {
182  if (t == 0)
183  MatrixTools::getId< RowMatrix<double> >(nbStates_ * nbRates_, pijt_);
184  else
185  MatrixTools::mult(rightEigenVectors_, VectorTools::exp(eigenValues_ * t), leftEigenVectors_, pijt_);
186  return pijt_;
187 }
188 
189 const Matrix<double>& MarkovModulatedSubstitutionModel::getdPij_dt(double t) const
190 {
191  MatrixTools::mult(rightEigenVectors_, eigenValues_ * VectorTools::exp(eigenValues_ * t), leftEigenVectors_, dpijt_);
192  return dpijt_;
193 }
194 
195 const Matrix<double>& MarkovModulatedSubstitutionModel::getd2Pij_dt2(double t) const
196 {
197  MatrixTools::mult(rightEigenVectors_, VectorTools::sqr(eigenValues_) * VectorTools::exp(eigenValues_ * t), leftEigenVectors_, d2pijt_);
198  return d2pijt_;
199 }
200 
201 /******************************************************************************/
202 
203 double MarkovModulatedSubstitutionModel::getInitValue(size_t i, int state) const throw (IndexOutOfBoundsException, BadIntException)
204 {
205  if (i >= (nbStates_ * nbRates_))
206  throw IndexOutOfBoundsException("MarkovModulatedSubstitutionModel::getInitValue", i, 0, nbStates_ * nbRates_ - 1);
207  if (state < 0 || !model_->getAlphabet()->isIntInAlphabet(state))
208  throw BadIntException(state, "MarkovModulatedSubstitutionModel::getInitValue. Character " + model_->getAlphabet()->intToChar(state) + " is not allowed in model.");
209  vector<int> states = model_->getAlphabet()->getAlias(state);
210  for (size_t j = 0; j < states.size(); j++)
211  {
212  if (getAlphabetStateAsInt(i) == states[j])
213  return 1.;
214  }
215  return 0.;
216 }
217 
218 /******************************************************************************/
219 
221 {
222  AbstractParameterAliasable::setNamespace(prefix);
223  // We also need to update the namespace of the nested model:
224  model_->setNamespace(prefix + nestedPrefix_);
225 }
226 
227 /******************************************************************************/
228 
virtual const Matrix< double > & getExchangeabilityMatrix() const =0
Vdouble freq_
The vector of equilibrium frequencies.
const Matrix< double > & getd2Pij_dt2(double t) const
Vdouble iEigenValues_
The vector of imaginary parts of the eigen values (zero in case of reversible pmodel).
STL namespace.
virtual const Vdouble & getFrequencies() const =0
MarkovModulatedSubstitutionModel & operator=(const MarkovModulatedSubstitutionModel &model)
virtual const Vdouble & getEigenValues() const =0
RowMatrix< double > generator_
The generator matrix of the model.
Interface for reversible substitution models.
Vdouble eigenValues_
The vector of real parts of eigen values.
RowMatrix< double > pijt_
These ones are for bookkeeping:
virtual const Matrix< double > & getGenerator() const =0
RowMatrix< double > leftEigenVectors_
The matrix made of left eigen vectors (by row).
const Matrix< double > & getdPij_dt(double t) const
bool eigenDecompose_
Tell if the eigen decomposition should be performed.
Partial implementation of the Markov-modulated class of substitution models.
MarkovModulatedSubstitutionModel(ReversibleSubstitutionModel *model, unsigned int nbRates, bool normalizeRateChanges, const std::string &prefix)
Build a new MarkovModulatedSubstitutionModel object.
ReversibleSubstitutionModel * clone() const =0
virtual const Matrix< double > & getColumnRightEigenVectors() const =0
virtual size_t getNumberOfStates() const =0
Get the number of states.
RowMatrix< double > rightEigenVectors_
The matrix made of right eigen vectors (by column).
const Matrix< double > & getPij_t(double t) const
RowMatrix< double > exchangeability_
The exchangeability matrix of the model.