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
10
11using namespace std;
12
13using namespace bpp;
14
15/******************************************************************************/
16
17DecompositionMethods::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{
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{
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
117void 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
135void 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
196void 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{
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;
254 }
255
256
257 if (!model_->isDiagonalizable())
258 {
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_);
311 for (size_t i = 0; i < nbTypes_; ++i)
312 {
313 bMatrices_[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)