bpp-phyl3  3.0.0
HmmLikelihoodComputation.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include "HmmLikelihood_DF.h"
6 
7 // from the STL:
8 #include <iostream>
9 #include <algorithm>
10 using namespace bpp;
11 using namespace std;
12 using namespace numeric;
13 
14 /***********************************/
15 /* Forward Likelihood */
16 /***********************************/
17 
19 {
20  const auto& hmmEq = accessValueConstCast<Eigen::VectorXd>(*this->dependency(0));
21 
22  const auto& hmmTrans = accessValueConstCast<Eigen::MatrixXd>(*this->dependency(1));
23  const auto& hmmEmis = accessValueConstCast<MatrixLik>(*this->dependency(2));
24 
25  auto& condLik = dynamic_pointer_cast<CondLikelihood>(condLik_)->accessValueMutable();
26 
27  auto nbSites = hmmEmis.cols();
28  auto nbStates = hmmEmis.rows();
29 
30  VDataLik tscales((size_t)nbSites);
31 
32  VectorLik tmp((int)nbStates);
33 
34  // Initialisation:
35  parCondLik_[0] = hmmTrans.transpose() * hmmEq;
36 
37  cwise(tmp) = cwise(parCondLik_[0]) * cwise(hmmEmis.col(0));
38  tscales[0] = tmp.sum();
39 
40  for (auto s = 0; s < nbStates; s++)
41  {
42  condLik(s, 0) = convert(tmp(s) / tscales[0]);
43  }
44 
45  // Iteration
46  for (auto i = 1; i < nbSites; i++)
47  {
48  parCondLik_[(size_t)i] = hmmTrans.transpose() * condLik.col(i - 1);
49 
50  cwise(tmp) = cwise(hmmEmis.col(i)) * cwise(parCondLik_[(size_t)i]);
51  tscales[(size_t)i] = tmp.sum();
52 
53  // tmp = condLik * scales
54  for (auto s = 0; s < nbStates; s++)
55  {
56  condLik(s, i) = convert(tmp(s) / tscales[(size_t)i]);
57  }
58  }
59  copyBppToEigen(tscales, this->accessValueMutable ());
60 
61 }
62 
64 {
65  if (&node == this)
66  {
67  return ConstantOne<RowLik>::create (c, targetDimension_);
68  }
69 
70  /*
71  * 1st order derivatives of Forward Likelihood Arrays
72  *
73  * Dependencies are:
74  * Value<VectorXd> : Starting vector of states probabililies
75  * Value<MatrixXd> : TransitionMatrix
76  * Value<MatrixLik> : Matrix of Emission likelihoods states X sites
77  *
78  * ForwardHmmLikelihood_DF : Forward Computations
79  *
80  * Value<VectorXd> : Derivatives of starting vector of states probabililies
81  * Value<MatrixXd> : Derivatives of TransitionMatrix
82  * Value<MatrixLik> : Derivatives Matrix of Emission likelihoods states X sites
83  */
84 
86  this->dependency(0),
87  this->dependency(1),
88  this->dependency(2),
89  this->shared_from_this(),
90  this->dependency(0)->derive (c, node),
91  this->dependency(1)->derive (c, node),
92  this->dependency(2)->derive (c, node)}, targetDimension_);
93 }
94 
95 /***********************************/
96 /* 1st order derivative of Forward Likelihood */
97 /***********************************/
98 
99 
101 {
102  const auto& hmmEq = accessValueConstCast<Eigen::VectorXd>(*this->dependency(0));
103 
104  const auto& hmmTrans = accessValueConstCast<Eigen::MatrixXd>(*this->dependency(1));
105  const auto& hmmEmis = accessValueConstCast<MatrixLik>(*this->dependency(2));
106 
107 
108  auto forwardNode = dynamic_pointer_cast<ForwardHmmLikelihood_DF>(this->dependency(3));
109 
110  const auto& condLik = forwardNode->getForwardCondLikelihood()->targetValue();
111 
112  const auto& parCondLik = forwardNode->getParCondLik();
113 
114  const auto& scales = forwardNode->targetValue();
115 
116  const auto& dHmmEq = accessValueConstCast<Eigen::VectorXd>(*this->dependency(4));
117 
118  const auto& dHmmTrans = accessValueConstCast<Eigen::MatrixXd>(*this->dependency(5));
119 
120  const auto& dHmmEmis = accessValueConstCast<MatrixLik>(*this->dependency(6));
121 
122  auto nbSites = hmmEmis.cols();
123  const int nbStates = (int)hmmEmis.rows();
124 
125  VDataLik tdScales((size_t)nbSites);
126 
127  auto& dCondLik = dynamic_pointer_cast<CondLikelihood>(dCondLik_)->accessValueMutable();
128 
129  VectorLik dtmp(nbStates);
130 
131  // Initialisation
132  dParCondLik_[0] = dHmmTrans.transpose() * hmmEq + hmmTrans.transpose() * dHmmEq;
133 
134  cwise(dtmp) = (cwise(dParCondLik_[0]) * cwise(hmmEmis.col(0))
135  + cwise(dHmmEmis.col(0)) * cwise(parCondLik[0]));
136  tdScales[0] = dtmp.sum();
137 
138  // dtmp = dCondLik * scales + CondLik * dScales
139 
140  for (auto s = 0; s < nbStates; s++)
141  {
142  dCondLik(s, 0) = convert((dtmp(s) - condLik(s, 0) * tdScales[0]) / scales(0));
143  }
144 
145  // Iteration
146  for (auto i = 1; i < nbSites; i++)
147  {
148  dParCondLik_[(size_t)i] = dHmmTrans.transpose() * condLik.col(i - 1) + hmmTrans.transpose() * dCondLik.col(i - 1);
149 
150  cwise(dtmp) = cwise(dParCondLik_[(size_t)i]) * cwise(hmmEmis.col(i)) + cwise(parCondLik[(size_t)i]) * cwise(dHmmEmis.col(i));
151  tdScales[(size_t)i] = dtmp.sum();
152 
153  for (auto s = 0; s < nbStates; s++)
154  {
155  dCondLik(s, i) = convert((dtmp(s) - condLik(s, i) * tdScales[(size_t)i]) / scales(i));
156  }
157  }
158 
159  copyBppToEigen(tdScales, this->accessValueMutable ());
160 }
161 
163 {
164  if (&node == this)
165  {
166  return ConstantOne<RowLik>::create (c, targetDimension_);
167  }
168 
169  /*
170  *
171  * 2nd order derivatives of Forward Likelihood Arrays
172  *
173  * Dependencies are:
174  * Value<VectorXd> : Starting vector of states probabililies
175  * Value<MatrixXd> : TransitionMatrix
176  * Value<MatrixLik> : Matrix of Emission likelihoods states X sites
177  *
178  * ForwardHmmLikelihood_DF : Forward Computations
179  *
180  * Value<VectorXd> : 1st Derivatives of starting vector of states probabililies
181  * Value<MatrixXd> : 1st Derivatives of TransitionMatrix
182  * Value<MatrixLik> : 1st Derivatives Matrix of Emission likelihoods states X sites
183  *
184  * ForwardHmmDLikelihood_DF : 1st order derivatives Forward Computations
185  *
186  * Value<VectorXd> : 2nd Derivatives of starting vector of states probabililies
187  * Value<MatrixXd> : 2nd Derivatives of TransitionMatrix
188  * Value<MatrixLik> : 2nd Derivatives Matrix of Emission likelihoods states X sites
189  */
190 
192  this->dependency(0),
193  this->dependency(1),
194  this->dependency(2),
195 
196  this->dependency(3),
197 
198  this->dependency(4),
199  this->dependency(5),
200  this->dependency(6),
201 
202  this->shared_from_this(),
203 
204  this->dependency(4)->derive (c, node),
205  this->dependency(5)->derive (c, node),
206  this->dependency(6)->derive (c, node)},
207 
208  targetDimension_);
209 }
210 
211 
212 /***********************************/
213 /* 2nd order derivative of Forward Likelihood */
214 /***********************************/
215 
216 
218 {
219  const auto& hmmEq = accessValueConstCast<Eigen::VectorXd>(*this->dependency(0));
220 
221  const auto& hmmTrans = accessValueConstCast<Eigen::MatrixXd>(*this->dependency(1));
222  const auto& hmmEmis = accessValueConstCast<MatrixLik>(*this->dependency(2));
223 
224 
225  auto forwardNode = dynamic_pointer_cast<ForwardHmmLikelihood_DF>(this->dependency(3));
226 
227  const auto& condLik = forwardNode->getForwardCondLikelihood()->targetValue();
228 
229  const auto& parCondLik = forwardNode->getParCondLik();
230 
231  const auto& scales = forwardNode->targetValue();
232 
233 
234  const auto& dHmmEq = accessValueConstCast<Eigen::VectorXd>(*this->dependency(4));
235 
236  const auto& dHmmTrans = accessValueConstCast<Eigen::MatrixXd>(*this->dependency(5));
237 
238  const auto& dHmmEmis = accessValueConstCast<MatrixLik>(*this->dependency(6));
239 
240 
241  auto forwardDNode = dynamic_pointer_cast<ForwardHmmDLikelihood_DF>(this->dependency(7));
242 
243  const auto& dCondLik = forwardDNode->getForwardDCondLikelihood()->targetValue();
244 
245  const auto& parDCondLik = forwardDNode->getParDCondLik();
246 
247  const auto& dScales = forwardDNode->targetValue();
248 
249 
250  const auto& d2HmmEq = accessValueConstCast<Eigen::VectorXd>(*this->dependency(8));
251 
252  const auto& d2HmmTrans = accessValueConstCast<Eigen::MatrixXd>(*this->dependency(9));
253 
254  const auto& d2HmmEmis = accessValueConstCast<MatrixLik>(*this->dependency(10));
255 
256 
258 
259  auto nbSites = hmmEmis.cols();
260  const int nbStates = static_cast<int>(hmmEmis.rows());
261 
262  VDataLik td2Scales(static_cast<size_t>(nbSites));
263 
264  Eigen::VectorXd d2CondLik(static_cast<int>(hmmEmis.rows()));
265 
266  Eigen::VectorXd d2ParCondLik;
267  VectorLik d2tmp(nbStates);
268 
269  // Initialisation:
270  d2ParCondLik = d2HmmTrans.transpose() * hmmEq + 2 * dHmmTrans.transpose() * dHmmEq + hmmTrans.transpose() * d2HmmEq;
271 
272  cwise(d2tmp) = cwise(d2ParCondLik) * cwise(hmmEmis.col(0))
273  + 2 * cwise(parDCondLik[0]) * cwise(dHmmEmis.col(0))
274  + cwise(parCondLik[0]) * cwise(d2HmmEmis.col(0));
275 
276  td2Scales[0] = d2tmp.sum();
277 
278  // d2tmp = d2CondLik * scales + 2 * dCondLik * dScales + CondLik * d2Scales
279 
280  for (auto s = 0; s < nbStates; s++)
281  {
282  d2CondLik(s, 0) = convert((d2tmp(s) - 2 * dCondLik(s, 0) * dScales(0) - condLik(s, 0) * td2Scales[0]) / scales(0));
283  }
284 
285  // Iteration
286  for (auto i = 1; i < nbSites; i++)
287  {
288  d2ParCondLik = d2HmmTrans.transpose() * condLik.col(i)
289  + 2 * dHmmTrans.transpose() * dCondLik.col(i) + hmmTrans.transpose() * d2CondLik;
290 
291  cwise(d2tmp) = cwise(d2ParCondLik) * cwise(hmmEmis.col(i))
292  + 2 * cwise(parDCondLik[(size_t)i]) * cwise(dHmmEmis.col(i))
293  + cwise(parCondLik[(size_t)i]) * cwise(d2HmmEmis.col(i));
294 
295  td2Scales[(size_t)i] = d2tmp.sum();
296 
297  for (auto s = 0; s < nbStates; s++)
298  {
299  d2CondLik(s, i) = convert((d2tmp(s) - 2 * dCondLik(s, i) * dScales(i) - condLik(s, i) * td2Scales[(size_t)i]) / scales(i));
300  }
301  }
302 
303  copyBppToEigen(td2Scales, this->accessValueMutable ());
304 }
305 
306 /*****************************************
307 ** Backward
308 *****************************************/
310 {
311  const auto& scales = accessValueConstCast<RowLik>(*this->dependency(0));
312 
313  const auto& hmmTrans = accessValueConstCast<Eigen::MatrixXd>(*this->dependency(1));
314 
315  const auto& hmmEmis = accessValueConstCast<MatrixLik>(*this->dependency(2));
316 
317  auto nbSites = hmmEmis.cols();
318  auto nbStates = hmmEmis.rows();
319 
320  std::vector<Eigen::VectorXd> tScales((size_t)nbSites);
321 
322  VectorLik tmp((int)nbStates);
323 
324  // Initialisation:
325  tScales[(size_t)(nbSites - 1)] = Eigen::VectorXd::Constant(nbStates, 1);
326 
327  // Iteration
328  for (auto i = nbSites - 1; i > 0; i--)
329  {
330  tScales[(size_t)(i - 1)].resize(nbStates);
331 
332  cwise(tmp) = cwise(hmmEmis.col(i)) * cwise(tScales[(size_t)i]);
333 
334  auto tmp2 = hmmTrans * tmp;
335 
336  for (auto s = 0; s < nbStates; s++)
337  tScales[(size_t)(i - 1)](s) = convert(tmp2(s) / scales(i));
338  }
339 
340  copyBppToEigen(tScales, this->accessValueMutable ());
341 
342 }
void compute() override
Computation implementation.
static std::shared_ptr< Self > create(Context &c, const Dimension< T > &dim)
Build a new ConstantOne node of the given dimension.
Context for dataflow node construction.
Definition: DataFlow.h:527
const ExtendedFloat & sum() const
void compute() override
Computation implementation.
static ValueRef< RowLik > create(Context &c, NodeRefVec &&deps, const Dimension< Eigen::MatrixXd > &dim)
void compute() override
Computation implementation.
static ValueRef< RowLik > create(Context &c, NodeRefVec &&deps, const Dimension< Eigen::MatrixXd > &dim)
NodeRef derive(Context &c, const Node_DF &node) final
Returns a node computing d(this_node_expression)/d(node_expression).
void compute() override
Computation implementation.
NodeRef derive(Context &c, const Node_DF &node) final
Returns a node computing d(this_node_expression)/d(node_expression).
Base dataflow Node class.
Definition: DataFlow.h:152
T & cwise(T &t)
Definition: DataFlowCWise.h:29
Defines the basic types of data flow nodes.
std::vector< DataLik > VDataLik
Definition: Definitions.h:23
template void copyBppToEigen(const std::vector< ExtendedFloat > &bppVector, Eigen::RowVectorXd &eigenVector)
double convert(const bpp::ExtendedFloat &ef)
std::shared_ptr< Node_DF > NodeRef
Definition: DataFlow.h:78