2
// File: AbstractWordReversibleSubstitutionModel.cpp
3
// Created by: Laurent Gueguen
4
// Created on: Jan 2009
8
Copyright or Ā© or Copr. CNRS, (November 16, 2004)
9
This software is a computer program whose purpose is to provide classes
10
for phylogenetic data analysis.
12
This software is governed by the CeCILL license under French law and
13
abiding by the rules of distribution of free software. You can use,
14
modify and/ or redistribute the software under the terms of the CeCILL
15
license as circulated by CEA, CNRS and INRIA at the following URL
16
"http://www.cecill.info".
18
As a counterpart to the access to the source code and rights to copy,
19
modify and redistribute granted by the license, users are provided only
20
with a limited warranty and the software's author, the holder of the
21
economic rights, and the successive licensors have only limited
24
In this respect, the user's attention is drawn to the risks associated
25
with loading, using, modifying and/or developing or reproducing the
26
software by the user in light of its specific status of free software,
27
that may mean that it is complicated to manipulate, and that also
28
therefore means that it is reserved for developers and experienced
29
professionals having in-depth computer knowledge. Users are therefore
30
encouraged to load and test the software's suitability as regards their
31
requirements in conditions enabling the security of their systems and/or
32
data to be ensured and, more generally, to use and operate it in the
33
same conditions as regards security.
35
The fact that you are presently reading this means that you have had
36
knowledge of the CeCILL license and that you accept its terms.
39
#include "AbstractWordReversibleSubstitutionModel.h"
41
#include <Bpp/Numeric/Matrix/MatrixTools.h>
42
#include <Bpp/Numeric/Matrix/EigenValue.h>
43
#include <Bpp/Numeric/VectorTools.h>
46
#include <Bpp/Seq/Alphabet/WordAlphabet.h>
47
#include <Bpp/Seq/Alphabet/AlphabetTools.h>
48
#include <Bpp/Seq/Container/SequenceContainerTools.h>
57
/******************************************************************************/
59
AbstractWordReversibleSubstitutionModel::AbstractWordReversibleSubstitutionModel(
60
const std::vector<SubstitutionModel*>& modelVector,
61
const std::string& st) :
62
AbstractReversibleSubstitutionModel(AbstractWordReversibleSubstitutionModel::extractAlph(modelVector), st),
66
Vrate_ (modelVector.size())
68
enableEigenDecomposition(false);
70
unsigned int n = modelVector.size();
72
// test whether two models are identical
77
while (!flag && i < (n - 1))
79
if (modelVector[i] == modelVector[j])
94
for (i = 0; i < n; i++)
96
VSubMod_.push_back(modelVector[i]);
97
VnestedPrefix_.push_back(modelVector[i]->getNamespace());
98
VSubMod_[i]->setNamespace(st + TextTools::toString(i+1) + "_" + VnestedPrefix_[i]);
99
addParameters_(VSubMod_[i]->getParameters());
105
for (i = 0; i < n; i++)
107
VSubMod_.push_back(modelVector[0]);
108
VnestedPrefix_.push_back(modelVector[0]->getNamespace());
109
t += TextTools::toString(i+1);
111
VSubMod_[0]->setNamespace(st + t + "_" + VnestedPrefix_[0]);
112
addParameters_(VSubMod_[0]->getParameters());
115
for (i = 0; i < n; i++)
121
AbstractWordReversibleSubstitutionModel::AbstractWordReversibleSubstitutionModel(
122
const Alphabet* alph,
123
const std::string& st) :
124
AbstractReversibleSubstitutionModel(alph, st),
125
new_alphabet_ (false),
130
enableEigenDecomposition(false);
133
AbstractWordReversibleSubstitutionModel::AbstractWordReversibleSubstitutionModel(
134
SubstitutionModel* pmodel,
136
const std::string& st) :
137
AbstractReversibleSubstitutionModel(new WordAlphabet(pmodel->getAlphabet(), num),st),
138
new_alphabet_ (true),
143
enableEigenDecomposition(false);
147
for (i = 0; i < num; i++)
149
VSubMod_.push_back(pmodel);
150
VnestedPrefix_.push_back(pmodel->getNamespace());
151
Vrate_[i] = 1.0 / num;
152
t += TextTools::toString(i+1);
155
pmodel->setNamespace(st + t + "_" + VnestedPrefix_[0]);
156
addParameters_(pmodel->getParameters());
159
AbstractWordReversibleSubstitutionModel::AbstractWordReversibleSubstitutionModel(
160
const AbstractWordReversibleSubstitutionModel& wrsm) :
161
AbstractReversibleSubstitutionModel(wrsm),
162
new_alphabet_ (wrsm.new_alphabet_),
164
VnestedPrefix_(wrsm.VnestedPrefix_),
168
unsigned int num = wrsm.VSubMod_.size();
170
if (wrsm.new_alphabet_)
171
alphabet_ = new WordAlphabet(*(dynamic_cast<const WordAlphabet*>(wrsm.getAlphabet())));
173
SubstitutionModel* pSM = 0;
174
if ((num > 1) & (wrsm.VSubMod_[0] == wrsm.VSubMod_[1]))
175
pSM = wrsm.VSubMod_[0]->clone();
177
for (i = 0; i < num; i++)
179
VSubMod_.push_back(pSM ? pSM : wrsm.VSubMod_[i]->clone());
183
AbstractWordReversibleSubstitutionModel& AbstractWordReversibleSubstitutionModel::operator=(
184
const AbstractWordReversibleSubstitutionModel& wrsm)
186
AbstractReversibleSubstitutionModel::operator=(wrsm);
187
new_alphabet_ = wrsm.new_alphabet_;
188
VnestedPrefix_ = wrsm.VnestedPrefix_;
189
Vrate_ = wrsm.Vrate_;
192
unsigned int num = wrsm.VSubMod_.size();
194
if (wrsm.new_alphabet_)
195
alphabet_ = new WordAlphabet(*(dynamic_cast<const WordAlphabet*>(wrsm.getAlphabet())));
197
SubstitutionModel* pSM = 0;
198
if ((num > 1) & (wrsm.VSubMod_[0] == wrsm.VSubMod_[1]))
199
pSM = wrsm.VSubMod_[0]->clone();
201
for (i = 0; i < num; i++)
203
VSubMod_[i] = (pSM ? pSM : wrsm.VSubMod_[i]->clone());
209
AbstractWordReversibleSubstitutionModel::~AbstractWordReversibleSubstitutionModel()
211
if ((VSubMod_.size() > 1) && (VSubMod_[0] == VSubMod_[1]))
217
for (size_t i = 0; i < VSubMod_.size(); i++)
226
unsigned int AbstractWordReversibleSubstitutionModel::getNumberOfStates() const
228
return getAlphabet()->getSize();
231
Alphabet* AbstractWordReversibleSubstitutionModel::extractAlph(const vector<SubstitutionModel*>& modelVector)
235
vector<const Alphabet*> vAlph;
237
for (i = 0; i < modelVector.size(); i++)
239
vAlph.push_back(modelVector[i]->getAlphabet());
242
return new WordAlphabet(vAlph);
245
void AbstractWordReversibleSubstitutionModel::setNamespace(const std::string& prefix)
247
AbstractReversibleSubstitutionModel::setNamespace(prefix);
249
if (VSubMod_.size() < 2 || VSubMod_[0] == VSubMod_[1])
252
for (unsigned int i = 0; i < VSubMod_.size(); i++)
254
t += TextTools::toString(i+1);
256
VSubMod_[0]->setNamespace(prefix + t + "_" + VnestedPrefix_[0]);
260
for (unsigned int i = 0; i < VSubMod_.size(); i++)
262
VSubMod_[i]->setNamespace(prefix + TextTools::toString(i+1) + "_" + VnestedPrefix_[i]);
267
/******************************************************************************/
269
void AbstractWordReversibleSubstitutionModel::updateMatrices()
271
//First we update position specific models. This need to be done here and not
272
//in fireParameterChanged, has some parameter aliases might have been defined
273
//and need to be resolved first.
274
if (VSubMod_.size() < 2 || VSubMod_[0] == VSubMod_[1])
275
VSubMod_[0]->matchParametersValues(getParameters());
277
for (unsigned int i = 0; i < VSubMod_.size(); i++)
279
VSubMod_[i]->matchParametersValues(getParameters());
282
unsigned int nbmod = VSubMod_.size();
283
unsigned int salph = getNumberOfStates();
287
if (enableEigenDecomposition())
289
unsigned int i, j, n, l, k, m;
291
vector<unsigned int> vsize;
293
for (k = 0; k < nbmod; k++)
295
vsize.push_back(VSubMod_[k]->getNumberOfStates());
298
RowMatrix<double> gk, exch;
302
for (k = nbmod; k > 0; k--)
304
gk = VSubMod_[k - 1]->getGenerator();
305
exch = (dynamic_cast<AbstractReversibleSubstitutionModel*>(VSubMod_[k - 1]))->getExchangeabilityMatrix();
306
for (i = 0; i < vsize[k - 1]; i++)
308
for (j = 0; j < vsize[k - 1]; j++)
315
for (l = 0; l < m; l++)
317
generator_(n + i * m + l, n + j * m + l) = gk(i,j) * Vrate_[k - 1];
318
exchangeability_(n + i * m + l, n + j * m + l) = exch(i,j) * Vrate_[k - 1];
320
n += m * vsize[k - 1];
329
// modification of generator_ and freq_
333
// at that point generator_ and freq_ are done for models without
334
// enableEigenDecomposition
338
if (enableEigenDecomposition())
346
for (i = 0; i < salph; i++)
349
for (j = 0; j < salph; j++)
352
x += generator_(i, j);
354
generator_(i, i) = -x;
357
//02/03/10 Julien: this should be avoided, we have to find a way to avoid particular cases like this...
358
if (AlphabetTools::isCodonAlphabet(getAlphabet()))
362
const CodonAlphabet* pca = dynamic_cast<const CodonAlphabet*>(getAlphabet());
364
RowMatrix<double> gk;
366
nbStop = pca->numberOfStopCodons();
367
gk.resize(salph - nbStop, salph - nbStop);
368
for (i = 0; i < salph; i++)
373
for (j = 0; j < salph; j++)
377
gk(i - gi, j - gj) = generator_(i, j);
387
EigenValue<double> ev(gk);
388
eigenValues_ = ev.getRealEigenValues();
389
vi = ev.getImagEigenValues();
391
for (i = 0; i < nbStop; i++)
393
eigenValues_.push_back(0);
396
RowMatrix<double> rev = ev.getV();
397
rightEigenVectors_.resize(salph, salph);
399
for (i = 0; i < salph; i++)
404
for (j = 0; j < salph; j++)
406
rightEigenVectors_(i,j) = 0;
408
rightEigenVectors_(i,salph - nbStop + gi - 1) = 1;
412
for (j = 0; j < salph - nbStop; j++)
414
rightEigenVectors_(i, j) = rev(i - gi,j);
416
for (j = salph - nbStop; j < salph; j++)
418
rightEigenVectors_(i,j) = 0;
425
EigenValue<double> ev(generator_);
426
eigenValues_ = ev.getRealEigenValues();
427
vi = ev.getImagEigenValues();
428
rightEigenVectors_ = ev.getV();
432
MatrixTools::inv(rightEigenVectors_, leftEigenVectors_);
434
// looking for the 0 eigenvector for which the eigen vector
435
// elements are of the same sign.
436
// There is a threshold value in case of approximations
438
double seuil=0.00000001;
440
unsigned int nulleigen;
446
while (flag && (nulleigen < salph - nbStop)) {
447
if (abs(eigenValues_[nulleigen]) < 0.0000001 && abs(vi[nulleigen]) < 0.0000001){
450
while (signe==0 && i< salph){
451
x=leftEigenVectors_(nulleigen, i);
452
signe=x>seuil?1:x< -seuil?-1:0;
459
x=leftEigenVectors_(nulleigen, i);
460
if ((signe==-1 && x>seuil) || (signe==1 && x<-seuil))
476
for (i = 0; i < salph; i++)
478
freq_[i] = leftEigenVectors_(nulleigen, i);
482
for (i = 0; i < salph; i++)
487
for (i = 0; i < salph; i++)
495
for (i = 0; i < salph; i++)
497
x += freq_[i] * generator_(i, i);
500
MatrixTools::scale(generator_, -1. / x);
502
for (i = 0; i < salph; i++)
504
eigenValues_[i] /= -x;
510
void AbstractWordReversibleSubstitutionModel::setFreq(std::map<int, double>& freqs)
512
map<int, double> tmpFreq;
513
unsigned int nbmod = VSubMod_.size();
515
unsigned int i, j, s, k, d, size;
516
d = size = getNumberOfStates();
518
if (VSubMod_.size() < 2 || VSubMod_[0] == VSubMod_[1]){
519
s = VSubMod_[0]->getAlphabet()->getSize();
520
for (j = 0; j < s; j++)
523
for (i = 0; i < nbmod; i++){
525
for (k = 0; k < size; k++)
526
tmpFreq[(k / d) % s] += freqs[k];
532
VSubMod_[0]->setFreq(tmpFreq);
533
matchParametersValues(VSubMod_[0]->getParameters());
536
for (i = 0; i < nbmod; i++){
538
s = VSubMod_[i]->getAlphabet()->getSize();
540
for (j = 0; j < s; j++)
544
for (k = 0; k < size; k++)
546
tmpFreq[(k / d) % s] += freqs[k];
548
VSubMod_[i]->setFreq(tmpFreq);
549
matchParametersValues(VSubMod_[i]->getParameters());