bpp-phyl3  3.0.0
DecompositionMethods.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
6 #include <typeinfo>
7 #include <vector>
8 
9 #include "DecompositionMethods.h"
10 
11 using namespace std;
12 
13 using namespace bpp;
14 
15 /******************************************************************************/
16 
17 DecompositionMethods::DecompositionMethods(
18  std::shared_ptr<const SubstitutionModelInterface> model,
19  std::shared_ptr<const SubstitutionRegisterInterface> reg) :
20  model_(model),
21  nbStates_(model->getNumberOfStates()),
22  nbTypes_(reg->getNumberOfSubstitutionTypes()),
23  jMat_(nbStates_, nbStates_),
24  jIMat_(0, 0),
25  rightEigenVectors_(0, 0),
26  rightIEigenVectors_(0, 0),
27  leftEigenVectors_(0, 0),
28  leftIEigenVectors_(0, 0),
29  bMatrices_(reg->getNumberOfSubstitutionTypes()),
30  insideProducts_(reg->getNumberOfSubstitutionTypes()),
31  insideIProducts_(0)
32 {
34  setSubstitutionModel(model);
35 }
36 
38  std::shared_ptr<const SubstitutionRegisterInterface> reg) :
39  model_(0),
40  nbStates_(reg->stateMap().getNumberOfModelStates()),
41  nbTypes_(reg->getNumberOfSubstitutionTypes()),
42  jMat_(nbStates_, nbStates_),
43  jIMat_(0, 0),
44  rightEigenVectors_(0, 0),
45  rightIEigenVectors_(0, 0),
46  leftEigenVectors_(0, 0),
47  leftIEigenVectors_(0, 0),
48  bMatrices_(reg->getNumberOfSubstitutionTypes()),
49  insideProducts_(reg->getNumberOfSubstitutionTypes()),
50  insideIProducts_(0)
51 {
53 }
54 
56  model_(0),
57  nbStates_(stateMap.getNumberOfModelStates()),
58  nbTypes_(1),
59  jMat_(nbStates_, nbStates_),
60  jIMat_(0, 0),
61  rightEigenVectors_(0, 0),
62  rightIEigenVectors_(0, 0),
63  leftEigenVectors_(0, 0),
64  leftIEigenVectors_(0, 0),
65  bMatrices_(1),
66  insideProducts_(1),
67  insideIProducts_(0)
68 {
70 }
71 
72 
74  std::shared_ptr<const SubstitutionModelInterface> model) :
75  model_(model),
76  nbStates_(model->getNumberOfStates()),
77  nbTypes_(1),
78  jMat_(nbStates_, nbStates_),
79  jIMat_(0, 0),
80  rightEigenVectors_(0, 0),
81  rightIEigenVectors_(0, 0),
82  leftEigenVectors_(0, 0),
83  leftIEigenVectors_(0, 0),
84  bMatrices_(1),
85  insideProducts_(1),
86  insideIProducts_(0)
87 {
88  setSubstitutionModel(model);
89 }
90 
92 {
93  // vInv_ %*% bMatrices_[i] %*% v_;
94  if (model_->isDiagonalizable())
95  {
96  for (size_t i = 0; i < nbTypes_; ++i)
97  {
99  MatrixTools::mult(model_->getRowLeftEigenVectors(), bMatrices_[i], tmp);
100  MatrixTools::mult(tmp, model_->getColumnRightEigenVectors(), insideProducts_[i]);
101  }
102  }
103  else
104  {
105  for (size_t i = 0; i < nbTypes_; ++i)
106  {
107  // vInv_ %*% bMatrices_[i] %*% v_;
109 
113  }
114  }
115 }
116 
117 void DecompositionMethods::jFunction_(const std::vector<double>& lambda, double t, RowMatrix<double>& result) const
118 {
119  vector<double> expLam = VectorTools::exp(lambda * t);
120  for (unsigned int i = 0; i < nbStates_; ++i)
121  {
122  for (unsigned int j = 0; j < nbStates_; ++j)
123  {
124  double dd = lambda[i] - lambda[j];
125  if (abs(dd) < NumConstants::TINY())
126  result(i, j) = t * expLam[i];
127  else
128  {
129  result(i, j) = (expLam[i] - expLam[j]) / dd;
130  }
131  }
132  }
133 }
134 
135 void DecompositionMethods::jFunction_(const std::vector<double>& lambda, const std::vector<double>& ilambda, double t, RowMatrix<double>& result, RowMatrix<double>& iresult) const
136 {
137  vector<double> expLam = VectorTools::exp(lambda * t);
138  vector<double> cosLam = expLam * VectorTools::cos(ilambda * t);
139  vector<double> sinLam = expLam * VectorTools::sin(ilambda * t);
140 
141  for (unsigned int i = 0; i < nbStates_; ++i)
142  {
143  for (unsigned int j = 0; j < nbStates_; ++j)
144  {
145  double dd = lambda[i] - lambda[j];
146  double idd = ilambda[i] - ilambda[j];
147  if ((abs(dd) < NumConstants::TINY()) && (abs(idd) < NumConstants::TINY()))
148  {
149  result(i, j) = t * cosLam[i];
150  iresult(i, j) = t * sinLam[i];
151  }
152  else
153  {
154  double es = sinLam[i] - sinLam[j];
155  double ec = cosLam[i] - cosLam[j];
156  double num = dd * dd + idd * idd;
157 
158  result(i, j) = (dd * ec + idd * es) / num;
159  iresult(i, j) = (dd * es - idd * ec) / num;
160  }
161  }
162  }
163 }
164 
165 
167 {
168  if (!model_)
169  throw Exception("DecompositionMethods::computeExpectations: model not defined.");
170 
172  if (model_->isDiagonalizable())
173  {
174  jFunction_(model_->getEigenValues(), length, jMat_);
175 
177  MatrixTools::mult(model_->getColumnRightEigenVectors(), tmp1, tmp2);
178  MatrixTools::mult(tmp2, model_->getRowLeftEigenVectors(), mapping);
179  }
180  else if (model_->isNonSingular())
181  {
182  jFunction_(model_->getEigenValues(), model_->getIEigenValues(), length, jMat_, jIMat_);
183 
186 
188  MatrixTools::mult(rightEigenVectors_, rightIEigenVectors_, tmp1, itmp1, tmp2, itmp2);
189  MatrixTools::mult(tmp2, itmp2, leftEigenVectors_, leftIEigenVectors_, mapping, imat);
190  }
191  else
192  throw Exception("void DecompositionMethods::computeMappings : substitution mapping is not implemented for singular generators.");
193 }
194 
195 
196 void DecompositionMethods::computeExpectations(std::vector< RowMatrix<double>>& mappings, double length) const
197 {
198  if (!model_)
199  throw Exception("DecompositionMethods::computeExpectations: model not defined.");
200 
202 
203  if (model_->isDiagonalizable())
204  {
205  jFunction_(model_->getEigenValues(), length, jMat_);
206 
207  for (size_t i = 0; i < nbTypes_; ++i)
208  {
210  MatrixTools::mult(model_->getColumnRightEigenVectors(), tmp1, tmp2);
211  MatrixTools::mult(tmp2, model_->getRowLeftEigenVectors(), mappings[i]);
212  }
213  }
214  else if (model_->isNonSingular())
215  {
216  jFunction_(model_->getEigenValues(), model_->getIEigenValues(), length, jMat_, jIMat_);
217 
220 
221  for (size_t i = 0; i < nbTypes_; ++i)
222  {
224  MatrixTools::mult(rightEigenVectors_, rightIEigenVectors_, tmp1, itmp1, tmp2, itmp2);
225  MatrixTools::mult(tmp2, itmp2, leftEigenVectors_, leftIEigenVectors_, mappings[i], imat);
226  }
227  }
228  else
229  throw Exception("void DecompositionMethods::computeMappings : substitution mapping is not implemented for singular generators.");
230 }
231 
232 
234 {
236  initBMatrices_();
237 }
238 
239 /******************************************************************************/
240 
242  std::shared_ptr<const SubstitutionModelInterface> model)
243 {
244  model_ = model;
245  if (!model)
246  return;
247 
248  size_t n = model->getNumberOfStates();
249  if (n != nbStates_)
250  {
251  nbStates_ = n;
253  initBMatrices_();
254  }
255 
256 
257  if (!model_->isDiagonalizable())
258  {
260  insideIProducts_.resize(nbTypes_);
261  for (size_t i = 0; i < nbTypes_; ++i)
262  {
264  }
265 
266  // sets the imaginary parts of the eigenvectors
268  {
273  }
274 
275  const ColMatrix<double>& rEV = model_->getColumnRightEigenVectors();
276  const RowMatrix<double>& lEV = model_->getRowLeftEigenVectors();
277  const vector<double>& vi = model_->getIEigenValues();
278 
279  for (size_t i = 0; i < nbStates_; i++)
280  {
281  if (vi[i] == 0)
282  {
283  rightEigenVectors_.getCol(i) = rEV.col(i);
285  leftEigenVectors_.getRow(i) = lEV.row(i);
287  }
288  else if (vi[i] > 0)
289  {
290  rightEigenVectors_.getCol(i) = rEV.col(i);
291  rightIEigenVectors_.getCol(i) = rEV.col(i + 1);
292  leftEigenVectors_.getRow(i) = lEV.row(i) / 2;
293  leftIEigenVectors_.getRow(i) = lEV.row(i + 1) * (-1. / 2);
294  }
295  else
296  {
297  rightEigenVectors_.getCol(i) = rEV.col(i - 1);
298  rightIEigenVectors_.getCol(i) = rEV.col(i) * (-1);
299  leftEigenVectors_.getRow(i) = lEV.row(i - 1) / 2;
300  leftIEigenVectors_.getRow(i) = lEV.row(i) / 2;
301  }
302  }
303  }
304 }
305 
307 {
308  // Re-initialize all B matrices according to substitution register.
309  bMatrices_.resize(nbTypes_);
310  insideProducts_.resize(nbTypes_);
311  for (size_t i = 0; i < nbTypes_; ++i)
312  {
313  bMatrices_[i].resize(nbStates_, nbStates_);
314  insideProducts_[i].resize(nbStates_, nbStates_);
315  }
316 }
std::vector< Scalar > col(size_t j) const
const std::vector< Scalar > & getCol(size_t i) const
void resize(size_t nRows, size_t nCols)
size_t getNumberOfRows() const
ColMatrix< double > rightEigenVectors_
Real and imaginary eigenvectors, for non-reversible computation.
RowMatrix< double > leftIEigenVectors_
void computeExpectations(RowMatrix< double > &mapping, double length) const
RowMatrix< double > leftEigenVectors_
std::vector< RowMatrix< double > > insideIProducts_
void jFunction_(const std::vector< double > &lambda, double t, RowMatrix< double > &result) const
Compute the integral part of the computation.
ColMatrix< double > rightIEigenVectors_
std::vector< RowMatrix< double > > insideProducts_
DecompositionMethods(std::shared_ptr< const SubstitutionModelInterface > model, std::shared_ptr< const SubstitutionRegisterInterface > reg)
void setSubstitutionModel(std::shared_ptr< const SubstitutionModelInterface > model)
Set the substitution model.
std::shared_ptr< const SubstitutionModelInterface > model_
std::vector< RowMatrix< double > > bMatrices_
computation matrices
static void mult(const Matrix< Scalar > &A, const Matrix< Scalar > &B, Matrix< Scalar > &O)
static void hadamardMult(const Matrix< Scalar > &A, const Matrix< Scalar > &B, Matrix< Scalar > &O)
static double TINY()
const std::vector< double > & getRow(size_t i) const
std::vector< double > row(size_t i) const
void resize(size_t nRows, size_t nCols)
Map the states of a given alphabet which have a model state.
Definition: StateMap.h:25
static OutputType cos(const std::vector< InputType > &v1, const std::vector< InputType > &v2)
static double exp(const T &x)
static void fill(std::vector< T > &v, T value)
static std::vector< double > sin(const std::vector< T > &v1)
Defines the basic types of data flow nodes.
ExtendedFloat abs(const ExtendedFloat &ef)