bpp-phyl3  3.0.0
LaplaceSubstitutionCount.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 
8 
9 using namespace bpp;
10 using namespace std;
11 
12 /******************************************************************************/
13 
14 void LaplaceSubstitutionCount::computeCounts(double length) const
15 {
16  RowMatrix<double> Q = model_->generator();
17  // L is the diagonal matrix with all substitution rates.
18  size_t s = Q.getNumberOfRows();
19  RowMatrix<double> QL(s, s);
20  for (size_t i = 0; i < s; i++)
21  {
22  for (size_t j = 0; j < s; j++)
23  {
24  QL(i, j) = ((i == j) ? 0. : Q(i, j));
25  }
26  }
27 
28  MatrixTools::fill(m_, 0.);
29  RowMatrix<double> M2(s, s);
30  RowMatrix<double> M3(s, s);
31  RowMatrix<double> M4(s, s);
32  RowMatrix<double> M5(s, s);
33  for (size_t n = 1; n < cutOff_; ++n)
34  {
35  MatrixTools::fill(M2, 0.);
36  for (size_t p = 0; p < n; ++p)
37  {
38  MatrixTools::pow(Q, p, M3); // Q^p -> M5
39  MatrixTools::mult(M3, QL, M4); // Q^p . QL -> M4
40  MatrixTools::pow(Q, n - p - 1, M3); // Q^(n-p-1) -> M3
41  MatrixTools::mult(M4, M3, M5); // Q^p . QL . Q^(n-p-1) -> M5
42  MatrixTools::add(M2, M5);
43  }
44  MatrixTools::scale(M2, pow(length, static_cast<double>(n)) / static_cast<double>(NumTools::fact(n)));
45  MatrixTools::add(m_, M2);
46  }
47 
48  // Now we must divide by pijt:
49  RowMatrix<double> P = model_->getPij_t(length);
50  for (size_t i = 0; i < s; i++)
51  {
52  for (size_t j = 0; j < s; j++)
53  {
54  m_(i, j) /= P(i, j);
55  }
56  }
57 }
58 
59 /******************************************************************************/
60 
61 double LaplaceSubstitutionCount::getNumberOfSubstitutions(size_t initialState, size_t finalState, double length, size_t type) const
62 {
63  if (!model_)
64  throw Exception("LaplaceSubstitutionCount::getNumberOfSubstitutions: model not defined.");
65 
66  if (length == currentLength_)
67  return m_(initialState, finalState);
68  if (length < 0.000001)
69  return initialState == finalState ? 0. : 1.; // Limit case!
70  // Else we need to recompute M:
71  computeCounts(length);
72 
73  currentLength_ = length;
74  return m_(initialState, finalState);
75 }
76 
77 /******************************************************************************/
78 
79 unique_ptr<Matrix<double>> LaplaceSubstitutionCount::getAllNumbersOfSubstitutions(double length, size_t type) const
80 {
81  if (!model_)
82  throw Exception("LaplaceSubstitutionCount::getAllNumbersOfSubstitutions: model not defined.");
83 
84  if (length == currentLength_)
85  return make_unique<RowMatrix<double>>(m_);
86  if (length < 0.000001) // Limit case!
87  {
88  size_t s = model_->getAlphabet()->getSize();
89  for (size_t i = 0; i < s; i++)
90  {
91  for (size_t j = 0; j < s; j++)
92  {
93  m_(i, j) = i == j ? 0. : 1.;
94  }
95  }
96  }
97  else
98  {
99  // Else we need to recompute M:
100  computeCounts(length);
101  }
102 
103  currentLength_ = length;
104 
105  return make_unique<RowMatrix<double>>(m_);
106 }
107 
108 /******************************************************************************/
109 
110 void LaplaceSubstitutionCount::storeAllNumbersOfSubstitutions(double length, size_t type, Eigen::MatrixXd& mat) const
111 {
112  if (!model_)
113  throw Exception("LaplaceSubstitutionCount::storeAllNumbersOfSubstitutions: model not defined.");
114 
115  auto s = Eigen::Index(model_->getAlphabet()->getSize());
116  if (length == currentLength_)
117  mat = Eigen::MatrixXd::Zero(s, s);
118 
119  if (length < 0.000001) // Limit case!
120  {
121  for (auto i = 0; i < s; i++)
122  {
123  for (auto j = 0; j < s; j++)
124  {
125  mat(i, j) = i == j ? 0. : 1.;
126  }
127  }
128  }
129  else
130  {
131  // Else we need to recompute M:
132  computeCounts(length);
133  }
134 
135  currentLength_ = length;
136 
137  mat.resize(s, s);
138 
139  for (auto i = 0; i < s; i++)
140  {
141  for (auto j = 0; j < s; j++)
142  {
143  mat(i, j) = std::isnan(m_(size_t(i), size_t(j))) ? 0 : m_(size_t(i), size_t(j));
144  }
145  }
146 }
147 
148 /******************************************************************************/
149 
151  shared_ptr<const SubstitutionModelInterface> model)
152 {
153  model_ = model;
154  if (!model)
155  return;
156 
157  size_t n = model->alphabet().getSize();
158  m_.resize(n, n);
159  // Recompute counts:
160  if (currentLength_ > 0)
161  computeCounts(currentLength_);
162 }
163 
164 /******************************************************************************/
void storeAllNumbersOfSubstitutions(double length, size_t type, Eigen::MatrixXd &mat) const override
Stores the numbers of susbstitutions on a branch, for each initial and final states,...
void setSubstitutionModel(std::shared_ptr< const SubstitutionModelInterface > model) override
Set the substitution model associated with this count, if relevant.
void computeCounts(double length) const
double getNumberOfSubstitutions(size_t initialState, size_t finalState, double length, size_t type=1) const override
Get the number of susbstitutions on a branch, given the initial and final states, and the branch leng...
std::unique_ptr< Matrix< double > > getAllNumbersOfSubstitutions(double length, size_t type=1) const override
Get the numbers of susbstitutions on a branch, for each initial and final states, and given the branc...
static void pow(const Matrix &A, size_t p, Matrix &O)
static void add(MatrixA &A, const MatrixB &B)
static void mult(const Matrix< Scalar > &A, const Matrix< Scalar > &B, Matrix< Scalar > &O)
static void scale(Matrix &A, Scalar a, Scalar b=0)
static void fill(Matrix &M, Scalar x)
static T fact(T n)
size_t getNumberOfRows() const
Defines the basic types of data flow nodes.
ExtendedFloat pow(const ExtendedFloat &ef, double exp)