bpp-phyl3  3.0.0
ForwardLikelihoodTree.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 "Model.h"
7 #include "Parametrizable.h"
8 #include "Sequence_DF.h"
9 
10 
11 #include <string> // debug
12 
13 
14 using namespace bpp;
15 using namespace std;
16 
18  const string& sequenceName,
19  const AlignmentDataInterface& sites)
20 {
21  size_t nbSites = sites.getNumberOfSites();
22 
23  const auto sequenceIndex = sites.getSequencePosition (sequenceName);
24  Eigen::MatrixXd initCondLik ((int)nbState_, (int)nbSites);
25  for (size_t site = 0; site < nbSites; ++site)
26  {
27  for (auto state = 0; state < nbState_; ++state)
28  {
29  initCondLik (Eigen::Index (state), Eigen::Index (site)) =
30  sites (site, sequenceIndex, statemap_.getAlphabetStateAsInt(size_t(state)));
31  }
32  }
33 
34  return Sequence_DF::create (context_, std::move(initCondLik), sequenceName);
35 }
36 
38  shared_ptr<ProcessEdge> processEdge,
39  const AlignmentDataInterface& sites)
40 {
41  const auto brlen = processEdge->getBrLen();
42  const auto model = processEdge->getModel();
43  const auto nMod = processEdge->getNMod();
44  const auto brprob = processEdge->getProba();
45 
46  auto childConditionalLikelihood = makeForwardLikelihoodAtNode (processTree_->getSon(processEdge), sites);
47 
48  ForwardLikelihoodBelowRef forwardEdge;
49 
50  auto zero = context_.getZero();
51 
52  if (brlen) // Branch with transition through a model
53  {
54  if (dynamic_pointer_cast<const TransitionModelInterface>(model->targetValue()))
55  {
56  auto transitionMatrix = ConfiguredParametrizable::createMatrix<ConfiguredModel, TransitionMatrixFromModel, Eigen::MatrixXd>(context_, {model, brlen, zero, nMod}, transitionMatrixDimension (size_t(nbState_)));
57 
58  processEdge->setTransitionMatrix(transitionMatrix);
59 
60  forwardEdge = ForwardTransition::create (
61  context_, {transitionMatrix, childConditionalLikelihood}, likelihoodMatrixDim_);
62  }
63  else
64  {
65  auto transitionFunction = TransitionFunctionFromModel::create(context_, {model, brlen, zero}, transitionFunctionDimension(nbState_));
66 
67  forwardEdge = ForwardTransitionFunction::create(context_, {childConditionalLikelihood, transitionFunction}, likelihoodMatrixDim_);
68  }
69  }
70  else if (brprob)
71  {
72  forwardEdge = ForwardProportion::create(
73  context_, {brprob, childConditionalLikelihood}, likelihoodMatrixDim_);
74  }
75  else // junction branch above a mixture node
76  {
77  forwardEdge = childConditionalLikelihood;
78  }
79 
80  if (!hasEdgeIndex(forwardEdge)) // ie this edge does not exist before
81  {
82  // false (root) top-node of the edge (only way to build an edge in
83  // the DAG). Correct top-node will be set afterwards.
84 
85  link(getRoot(), childConditionalLikelihood, forwardEdge);
86 
87  setEdgeIndex(forwardEdge, processTree_->getEdgeIndex(processEdge)); // gets the index of the corresponding branch in the processTree_
88 
89  auto spIndex = processEdge->getSpeciesIndex();
90 
91  if (brprob || brlen)
92  {
93  if (mapEdgesIndexes_.find(spIndex) == mapEdgesIndexes_.end())
94  mapEdgesIndexes_[spIndex] = DAGindexes();
95  mapEdgesIndexes_[spIndex].push_back(getEdgeIndex(forwardEdge));
96  }
97  }
98 
99 #ifdef DEBUG
100  std::cerr << "E " << getEdgeIndex(forwardEdge) << " : forwardEdge " << forwardEdge << endl;
101  std::cerr << " -> N " << processTree_->getNodeIndex(processTree_->getSon(processEdge)) << std::endl;
102 #endif
103 
104  return forwardEdge;
105 }
106 
108 {
109  const auto childBranches = processTree_->getBranches (processNode);
110 
111  auto spIndex = processNode->getSpeciesIndex();
112 
114 
115  if (childBranches.empty ())
116  {
117  forwardNode = makeInitialConditionalLikelihood (processNode->getName (), sites);
118 
119  if (!hasNodeIndex(forwardNode))
120  {
121  createNode(forwardNode);
122  setNodeIndex(forwardNode, processTree_->getNodeIndex(processNode));
123  if (mapNodesIndexes_.find(spIndex) == mapNodesIndexes_.end())
124  mapNodesIndexes_[spIndex] = DAGindexes();
125  mapNodesIndexes_[spIndex].push_back(getNodeIndex(forwardNode));
126  }
127  }
128  else
129  {
130  // depE are edges used to link ForwardLikelihoodTree edges to this
131  // node
132  std::vector<ForwardLikelihoodBelowRef> depE(childBranches.size());
133  NodeRefVec deps(childBranches.size());
134 
135  for (size_t i = 0; i < childBranches.size (); ++i)
136  {
137  depE[i] = makeForwardLikelihoodAtEdge (childBranches[i], sites);
138  deps[i] = depE[i];
139  }
140 
141  if (processNode->isSpeciation())
142  forwardNode = SpeciationForward::create(context_, std::move(deps),
143  likelihoodMatrixDim_);
144  else if (processNode->isMixture())
145  forwardNode = MixtureForward::create(context_, std::move(deps),
146  likelihoodMatrixDim_);
147  else
148  throw Exception("ForwardLikelihoodTree::makeConditionalLikelihoodAtNode : event not recognized for node " + TextTools::toString(processNode->getSpeciesIndex()));
149 
150  // Fix the DAG
151  if (!hasNodeIndex(forwardNode))
152  {
153  createNode(forwardNode);
154  setNodeIndex(forwardNode, processTree_->getNodeIndex(processNode));
155 
156  // Put the node in speciesIndex map if it is not son of a
157  // mixture node (which would hold the species index)
158 
159  bool fathmixture(false);
160 
161  if (processTree_->hasFather(processNode))
162  {
163  auto fatherNode = processTree_->getFatherOfNode (processNode);
164  fathmixture = fatherNode->isMixture();
165  }
166 
167  if (!fathmixture)
168  {
169  if (mapNodesIndexes_.find(spIndex) == mapNodesIndexes_.end())
170  mapNodesIndexes_[spIndex] = DAGindexes();
171  mapNodesIndexes_[spIndex].push_back(getNodeIndex(forwardNode));
172  }
173 
174  for (size_t i = 0; i < depE.size (); ++i)
175  {
176  auto fs = getNodes(depE[i]);
177  // fix the top node of the edge (because it was set to bidon
178  unlink(fs.first, fs.second);
179  link(forwardNode, fs.second, depE[i]);
180  }
181  }
182  }
183 
184 #ifdef DEBUG
185  std::cerr << "N " << getNodeIndex(forwardNode) << " : forwardNode " << forwardNode << endl;
186  for (size_t i = 0; i < childBranches.size (); ++i)
187  {
188  std::cerr << " -> E " << processTree_->getEdgeIndex(childBranches[i]) << std::endl;
189  }
190 
191 #endif
192 
193  return forwardNode;
194 }
195 
196 /************************************************************/
197 /************************************************************
198  * For ProbabilityDAG
199  */
200 
201 ProbabilityDAG::ProbabilityDAG(std::shared_ptr<ForwardLikelihoodTree> forwardTree) :
202  DAProb(forwardTree->getGraph()), context_(forwardTree->getContext())
203 {
205 
206  associateNode(rootProb, forwardTree->getNodeGraphid(forwardTree->getRoot()));
207  setNodeIndex(rootProb, forwardTree->getRootIndex());
208 
209  auto allIndex = forwardTree->getAllNodesIndexes();
210  std::vector<const Node_DF*> vN;
211 
212  for (auto id: allIndex)
213  {
214  // Start from external nodes (which may be not leaves)
215  if (forwardTree->getOutgoingEdges(id).size() == 0)
216  {
217  auto n = makeProbaAtNode_(id, forwardTree).get();
218  n->targetValue();
219  vN.push_back(n);
220  }
221  }
222 
223  // using bpp::DotOptions;
224  // writeGraphToDot("proba.dot", vN, DotOptions::DetailedNodeInfo);
225 }
226 
227 
228 ProbaRef ProbabilityDAG::makeProbaAtEdge_ (PhyloTree::EdgeIndex edgeIndex, std::shared_ptr<ForwardLikelihoodTree> forwardTree)
229 {
230  auto fatherIndex = forwardTree->getFatherOfEdge(edgeIndex);
231  auto edgeForward = forwardTree->getEdge(edgeIndex);
232 
233  // get/check if node with backward likelihood exists
234  auto probaNode = hasNode(fatherIndex)
235  ? getNode(fatherIndex)
236  : makeProbaAtNode_(fatherIndex, forwardTree);
237 
238  const auto processEdge = forwardTree->getProcessTree()->getEdge(edgeIndex);
239 
240  const auto brprob = processEdge->getProba();
241 
242  ProbaRef probaEdge;
243 
244  if (brprob)
245  {
246  probaEdge = ProbaMul::create(context_, {brprob, probaNode}, Dimension<double>());
247  }
248  else
249  {
250  probaEdge = Identity<double>::create(context_, {probaNode}, Dimension<double>(), edgeIndex);
251  }
252 
253  // put object in the tree
254  if (!hasEdge(probaEdge))
255  {
256  associateEdge(probaEdge, forwardTree->getEdgeGraphid(edgeForward));
257  setEdgeIndex(probaEdge, edgeIndex);
258  }
259 
260  return probaEdge;
261 }
262 
263 
264 ProbaRef ProbabilityDAG::makeProbaAtNode_ (PhyloTree::NodeIndex nodeIndex, std::shared_ptr<ForwardLikelihoodTree> forwardTree)
265 {
266  // else get incoming edges
267  const auto edgesIndexes = forwardTree->getIncomingEdges(nodeIndex);
268 
269  // get upper dependencies
270  NodeRefVec deps;
271 
272  ProbaRef probaNode;
273  auto forwardNode = forwardTree->getNode(nodeIndex);
274 
275  for (const auto& edgeIndex:edgesIndexes)
276  {
277  auto backEdge = hasEdge(edgeIndex)
278  ? getEdge(edgeIndex)
279  : makeProbaAtEdge_(edgeIndex, forwardTree);
280 
281  if (edgesIndexes.size() == 1)
282  {
283  probaNode = Identity<double>::create(context_, {backEdge}, Dimension<double>(), nodeIndex);
284  break;
285  }
286  else
287  deps.push_back(backEdge);
288  }
289 
290  // Then compute sum if several incoming nodes
291  if (deps.size() > 1)
292  probaNode = ProbaSum::create(context_, std::move(deps), Dimension<double>());
293 
294  if (!hasNode(probaNode))
295  {
296  associateNode(probaNode, forwardTree->getNodeGraphid(forwardNode));
297  setNodeIndex(probaNode, nodeIndex);
298  }
299 
300  return probaNode;
301 }
AssociationGraphObserver< N, E >::EdgeIndex EdgeIndex
AssociationGraphObserver< N, E >::NodeIndex NodeIndex
virtual std::shared_ptr< N > getNode(NodeIndex nodeIndex) const=0
virtual NodeIndex setNodeIndex(const std::shared_ptr< N > nodeObject, NodeIndex index)=0
virtual void associateNode(std::shared_ptr< N > nodeObject, NodeGraphid node)=0
virtual EdgeIndex setEdgeIndex(const std::shared_ptr< E > edgeObject, EdgeIndex index)=0
virtual bool hasNode(NodeIndex nodeIndex) const=0
virtual std::shared_ptr< E > getEdge(EdgeIndex edgeIndex) const=0
virtual bool hasEdge(EdgeIndex edgeIndex) const=0
virtual void associateEdge(std::shared_ptr< E > edgeObject, EdgeGraphid edge)=0
static ValueRef< R > create(Context &c, NodeRefVec &&deps, const Dimension< R > &dim)
Build a new CWiseAdd node with the given output dimensions.
static ValueRef< R > create(Context &c, NodeRefVec &&deps, const Dimension< R > &dim)
Build a new CWiseApply node.
static std::shared_ptr< Self > create(Context &c, const Dimension< T > &dim)
Build a new ConstantOne node of the given dimension.
ConditionalLikelihoodForwardRef makeInitialConditionalLikelihood(const std::string &sequenceName, const AlignmentDataInterface &sites)
Compute ConditionalLikelihood for leaf.
ForwardLikelihoodBelowRef makeForwardLikelihoodAtEdge(std::shared_ptr< ProcessEdge > edge, const AlignmentDataInterface &sites)
Compute ConditionalLikelihood after reading edge on the forward process (ie at top of the edge).
ConditionalLikelihoodForwardRef makeForwardLikelihoodAtNode(std::shared_ptr< ProcessNode > node, const AlignmentDataInterface &sites)
static ValueRef< R > create(Context &c, NodeRefVec &&deps, const Dimension< R > &dim, size_t id=0)
Build a new Convert node with the given output dimensions.
static ValueRef< R > create(Context &c, NodeRefVec &&deps, const Dimension< R > &dim)
Build a new MatrixProduct node with the given output dimensions.
ProbaRef makeProbaAtNode_(PhyloTree::EdgeIndex edgeIndex, std::shared_ptr< ForwardLikelihoodTree > tree)
ProbabilityDAG(std::shared_ptr< ForwardLikelihoodTree > tree)
ProbaRef makeProbaAtEdge_(PhyloTree::EdgeIndex edgeIndex, std::shared_ptr< ForwardLikelihoodTree > tree)
computation of the probabilities with the same approach as for BackwardLikelihoodTree.
static ValueRef< T > create(Context &c, T &&value, const std::string &name)
Definition: Sequence_DF.h:31
virtual size_t getNumberOfSites() const=0
virtual size_t getSequencePosition(const std::string &sequenceKey) const =0
static std::shared_ptr< Self > create(Context &c, NodeRefVec &&deps, const Dimension< T > &dim)
Definition: Model.cpp:273
std::string toString(T t)
T zero(const Dimension< T > &)
Defines the basic types of data flow nodes.
std::vector< uint > DAGindexes
Helper: create a map with mutable dataflow nodes for each branch of the tree. The map is indexed by b...
ValueRef< MatrixLik > ConditionalLikelihoodForwardRef
std::vector< NodeRef > NodeRefVec
Alias for a dependency vector (of NodeRef).
Definition: DataFlow.h:81
Dimension< TransitionFunction > transitionFunctionDimension(Eigen::Index nbState)
std::shared_ptr< Value< double > > ProbaRef
ValueRef< MatrixLik > ForwardLikelihoodBelowRef
MatrixDimension transitionMatrixDimension(std::size_t nbState)
Definition: Model.h:19
Specialisation of Dimension<T> for floating point types.