bpp-core3  3.0.0
TreeGraphImpl.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #ifndef BPP_GRAPH_TREEGRAPHIMPL_H
6 #define BPP_GRAPH_TREEGRAPHIMPL_H
7 
8 #include <iostream>
9 #include <ostream>
10 #include <string>
11 #include <vector>
12 
13 #include "../Exceptions.h"
14 #include "../Numeric/VectorTools.h"
15 #include "GlobalGraph.h"
16 #include "TreeGraph.h"
17 
18 namespace bpp
19 {
20 template<class GraphImpl>
22  public virtual TreeGraph,
23  public GraphImpl
24 {
25 private:
29  mutable bool isValid_;
30 
31  // unvalidate the tree
32  void topologyHasChanged_() const;
33 
34  // will throw an exception if the tree is not valid
35  void mustBeValid_() const;
36 
37  // will throw an exception if the tree is not rooted
38  void mustBeRooted_() const;
39 
40  // test the validity of the tree
41  bool validate_() const;
42 
48 
49  // recursive function for getSubtreeNodes
50  void fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const;
51 
52  // recursive function for getSubtreeEdges
53  void fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const;
54 
55  // recursive function for getLeavesUnderNode
56  void fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const;
57 
58 public:
59  TreeGraphImpl();
60 
61  TreeGraphImpl(bool rooted = true);
62 
67  bool isValid() const;
68 
75  bool isRooted() const;
76 
83 
90 
95  bool hasFather(Graph::NodeId node) const;
96 
101  bool isLeaf(Graph::NodeId node) const;
102 
109  std::vector<Graph::NodeId> getLeavesUnderNode(Graph::NodeId node) const;
110 
115  std::vector<Graph::NodeId> getSons(Graph::NodeId node) const;
116 
121  std::vector<Graph::EdgeId> getBranches(Graph::NodeId node) const;
122 
127  std::unique_ptr<Graph::NodeIterator> sonsIterator(Graph::NodeId node);
128 
129  std::unique_ptr<Graph::NodeIterator> sonsIterator(Graph::NodeId node) const;
130 
135  std::unique_ptr<Graph::EdgeIterator> branchesIterator(Graph::NodeId node);
136 
137  std::unique_ptr<Graph::EdgeIterator> branchesIterator(Graph::NodeId node) const;
138 
143  size_t getNumberOfSons(Graph::NodeId node) const;
144 
149  void setFather(Graph::NodeId node, Graph::NodeId fatherNode);
150  void setFather(Graph::NodeId node, Graph::NodeId fatherNode, Graph::EdgeId edgeId);
151 
156  void addSon(Graph::NodeId node, Graph::NodeId sonNode);
157 
158  void addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edgeId);
159 
164  std::vector<Graph::NodeId> removeSons(Graph::NodeId node);
165 
170  void removeSon(Graph::NodeId node, Graph::NodeId son);
171 
176  void rootAt(Graph::NodeId newRoot);
177 
184  void unRoot(bool joinRootSons);
185 
191  void setOutGroup(Graph::NodeId newOutGroup);
192 
197  std::vector<Graph::NodeId> getSubtreeNodes(Graph::NodeId localRoot) const;
198 
203  std::vector<Graph::EdgeId> getSubtreeEdges(Graph::NodeId localRoot) const;
204 
205  // ///FROM TREETOOLS & TREETOOLS COMPAT
206 
207 
208  std::vector<Graph::NodeId> getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor = true) const;
209  std::vector<Graph::EdgeId> getEdgePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB) const;
210 
211 
212  /*
213  * @bref Compute the MRCA of the gven nodes
214  *
215  */
216 
217  Graph::NodeId MRCA(const std::vector<Graph::NodeId>& nodes) const;
218 };
219 
220 
221 /******************/
222 
224 
225 /*****************/
226 
227 
228 template<class GraphImpl>
230  GraphImpl(rooted),
231  isValid_(false)
232 {}
233 
234 
235 template<class GraphImpl>
237 {
238  return isValid_ || validate_();
239 }
240 
241 template<class GraphImpl>
243 {
244  std::vector<Graph::NodeId> incomers = getIncomingNeighbors(node);
245  if (incomers.size() > 1)
246  throw Exception("TreeGraphImpl<GraphImpl>::getFather: more than one father for Node " + TextTools::toString(node) + " : " + VectorTools::paste(incomers, ",") + ". Should never happen since validity has been controlled. Please report this bug.");
247  if (incomers.size() == 0)
248  throw Exception("TreeGraphImpl<GraphImpl>::getFather: node " + TextTools::toString(node) + " has no father.");
249  return *incomers.begin();
250 }
251 
252 template<class GraphImpl>
254 {
255  Graph::NodeId father = getFatherOfNode(node);
256  return GraphImpl::getEdge(father, node);
257 }
258 
259 template<class GraphImpl>
261 {
262  return GraphImpl::getNumberOfIncomingNeighbors(node) >= 1;
263 }
264 
265 template<class GraphImpl>
267 {
268  return (!GraphImpl::isDirected() && GraphImpl::getNumberOfOutgoingNeighbors(node) <= 1)
269  || (GraphImpl::isDirected() && GraphImpl::getNumberOfOutgoingNeighbors(node) == 0);
270 }
271 
272 template<class GraphImpl>
273 void TreeGraphImpl<GraphImpl>::fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const
274 {
275  const std::vector<Graph::NodeId> sons = getSons(startingNode);
276  if (sons.size() > 1)
277  {
278  for (std::vector<Graph::NodeId>::const_iterator currNeighbor = sons.begin(); currNeighbor != sons.end(); currNeighbor++)
279  {
280  fillListOfLeaves_(*currNeighbor, foundLeaves);
281  }
282  }
283  else
284  {
285  foundLeaves.push_back(startingNode);
286  }
287 }
288 
289 template<class GraphImpl>
290 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getLeavesUnderNode(Graph::NodeId node) const
291 {
292  std::vector<Graph::NodeId> foundLeaves;
293  fillListOfLeaves_(node, foundLeaves);
294 
295  return foundLeaves;
296 }
297 
298 template<class GraphImpl>
300 {
301  if (!isRooted())
302  throw Exception("TreeGraphImpl<GraphImpl>: The tree must be rooted.");
303 }
304 
305 template<class GraphImpl>
307 {
308  if (!isValid())
309  throw Exception("TreeGraphImpl<GraphImpl>: The tree is not valid.");
310 }
311 
312 template<class GraphImpl>
314 {
315  return GraphImpl::isDirected();
316 }
317 
318 template<class GraphImpl>
320 {
321  isValid_ = GraphImpl::isTree();
322  return isValid_;
323 }
324 
325 template<class GraphImpl>
327 {
328  isValid_ = false;
329 }
330 
331 template<class GraphImpl>
333 {
334  if (!isValid())
335  throw Exception("TreeGraphImpl::rootAt: Tree is not Valid.");
336 
337  GraphImpl::makeDirected();
338  // set the new root on the Graph
339  GraphImpl::setRoot(newRoot);
340  // change edge direction between the new node and the former one
341  propagateDirection_(newRoot);
342 }
343 
344 template<class GraphImpl>
346 {
347  if (hasFather(node))
348  {
349  NodeId father = getFatherOfNode(node);
350  propagateDirection_(father);
351  GraphImpl::switchNodes(father, node);
352  }
353 }
354 
355 template<class GraphImpl>
357 {
358  if (hasFather(node))
359  GraphImpl::unlink(getFatherOfNode(node), node);
360  GraphImpl::link(fatherNode, node);
362 }
363 
364 template<class GraphImpl>
366 {
367  if (hasFather(node))
368  GraphImpl::unlink(getFatherOfNode(node), node);
369  GraphImpl::link(fatherNode, node, edgeId);
371 }
372 
373 
374 template<class GraphImpl>
376 {
377  GraphImpl::link(node, sonNode);
379 }
380 
381 template<class GraphImpl>
383 {
384  GraphImpl::link(node, sonNode, edgeId);
386 }
387 
388 template<class GraphImpl>
389 void TreeGraphImpl<GraphImpl>::unRoot(bool joinRootSons)
390 {
391  if (joinRootSons)
392  {
393  // the root must have exactly two joinRootSons
394  std::vector<Graph::NodeId> sons = getSons(GraphImpl::getRoot());
395  if (sons.size() != 2)
396  throw Exception("The root must have two sons to join them.");
397  GraphImpl::unlink(GraphImpl::getRoot(), sons.at(0));
398  GraphImpl::unlink(GraphImpl::getRoot(), sons.at(1));
399  GraphImpl::link(sons.at(0), sons.at(1));
400  GraphImpl::setRoot(sons.at(0));
401  }
402  GraphImpl::makeUndirected();
403 }
404 
405 template<class GraphImpl>
406 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getSons(Graph::NodeId node) const
407 {
408  return GraphImpl::getOutgoingNeighbors(node);
409 }
410 
411 template<class GraphImpl>
412 std::vector<Graph::EdgeId> TreeGraphImpl<GraphImpl>::getBranches(Graph::NodeId node) const
413 {
414  return GraphImpl::getOutgoingEdges(node);
415 }
416 
417 template<class GraphImpl>
418 std::unique_ptr<Graph::NodeIterator> TreeGraphImpl<GraphImpl>::sonsIterator(Graph::NodeId node)
419 {
420  return GraphImpl::outgoingNeighborNodesIterator(node);
421 }
422 
423 template<class GraphImpl>
424 std::unique_ptr<Graph::NodeIterator> TreeGraphImpl<GraphImpl>::sonsIterator(Graph::NodeId node) const
425 {
426  return GraphImpl::outgoingNeighborNodesIterator(node);
427 }
428 
429 template<class GraphImpl>
430 std::unique_ptr<Graph::EdgeIterator> TreeGraphImpl<GraphImpl>::branchesIterator(Graph::NodeId node)
431 {
432  return GraphImpl::outgoingEdgesIterator(node);
433 }
434 
435 template<class GraphImpl>
436 std::unique_ptr<Graph::EdgeIterator> TreeGraphImpl<GraphImpl>::branchesIterator(Graph::NodeId node) const
437 {
438  return GraphImpl::outgoingEdgesIterator(node);
439 }
440 
441 template<class GraphImpl>
443 {
444  return GraphImpl::getNumberOfOutgoingNeighbors(node);
445 }
446 
447 template<class GraphImpl>
448 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::removeSons(Graph::NodeId node)
449 {
450  std::vector<Graph::NodeId> sons = getSons(node);
451  for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
452  {
453  removeSon(node, *currSon);
454  }
455  return sons;
456 }
457 
458 template<class GraphImpl>
460 {
461  GraphImpl::unlink(node, son);
463 }
464 
465 template<class GraphImpl>
467 {
468  mustBeRooted_();
469  deleteNode(GraphImpl::getRoot());
470 
471  Graph::NodeId newRoot = GraphImpl::createNodeFromEdge(getEdge(getFatherOfNode(newOutGroup), newOutGroup));
472  rootAt(newRoot);
473 }
474 
475 template<class GraphImpl>
476 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor) const
477 {
478  GraphImpl::nodeMustExist_(nodeA);
479  GraphImpl::nodeMustExist_(nodeB);
480  std::vector<Graph::NodeId> path;
481  std::vector<Graph::NodeId> pathMatrix1;
482  std::vector<Graph::NodeId> pathMatrix2;
483 
484  Graph::NodeId nodeUp = nodeA;
485  while (hasFather(nodeUp))
486  {
487  pathMatrix1.push_back(nodeUp);
488  nodeUp = getFatherOfNode(nodeUp);
489  }
490  pathMatrix1.push_back(nodeUp); // The root.
491 
492  nodeUp = nodeB;
493  while (hasFather(nodeUp))
494  {
495  pathMatrix2.push_back(nodeUp);
496  nodeUp = getFatherOfNode(nodeUp);
497  }
498  pathMatrix2.push_back(nodeUp); // The root.
499  // Must check that the two nodes have the same root!!!
500 
501  size_t tmp1 = pathMatrix1.size();
502  size_t tmp2 = pathMatrix2.size();
503 
504  while ((tmp1 > 0) && (tmp2 > 0))
505  {
506  if (pathMatrix1[tmp1 - 1] != pathMatrix2[tmp2 - 1])
507  break;
508  tmp1--; tmp2--;
509  }
510  // (tmp1 - 1) and (tmp2 - 1) now point toward the first non-common nodes
511 
512  for (size_t y = 0; y < tmp1; ++y)
513  {
514  path.push_back(pathMatrix1[y]);
515  }
516  if (includeAncestor) // FIXME: one of the extremities may be the ancestor!!!
517  path.push_back(pathMatrix1[tmp1]); // pushing once, the Node that was common to both.
518  for (size_t j = tmp2; j > 0; --j)
519  {
520  path.push_back(pathMatrix2[j - 1]);
521  }
522  return path;
523 }
524 
525 template<class GraphImpl>
527 {
528  std::vector<Graph::EdgeId> path;
529  std::vector<Graph::NodeId> pathNodes = getNodePathBetweenTwoNodes(nodeA, nodeB, true);
530  for (size_t currNodeNr = 0; currNodeNr + 1 < pathNodes.size(); currNodeNr++)
531  {
532  path.push_back(GraphImpl::getAnyEdge(pathNodes.at(currNodeNr), pathNodes.at(currNodeNr + 1)));
533  }
534  return path;
535 }
536 
537 template<class GraphImpl>
538 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getSubtreeNodes(Graph::NodeId localRoot) const
539 {
540  mustBeValid_();
541  std::vector<Graph::EdgeId> metNodes;
542  fillSubtreeMetNodes_(metNodes, localRoot);
543  return metNodes;
544 }
545 
546 template<class GraphImpl>
547 std::vector<Graph::EdgeId> TreeGraphImpl<GraphImpl>::getSubtreeEdges(Graph::NodeId localRoot) const
548 {
549  mustBeValid_();
550  std::vector<Graph::EdgeId> metEdges;
551  fillSubtreeMetEdges_(metEdges, localRoot);
552  return metEdges;
553 }
554 
555 
556 template<class GraphImpl>
557 void TreeGraphImpl<GraphImpl>::fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const
558 {
559  metNodes.push_back(localRoot);
560  std::vector<Graph::NodeId> sons = GraphImpl::getOutgoingNeighbors(localRoot);
561  for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
562  {
563  fillSubtreeMetNodes_(metNodes, *currSon);
564  }
565 }
566 
567 template<class GraphImpl>
568 void TreeGraphImpl<GraphImpl>::fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const
569 {
570  std::vector<Graph::EdgeId> edgesToSons = GraphImpl::getOutgoingEdges(localRoot);
571  for (std::vector<Graph::EdgeId>::iterator currEdgeToSon = edgesToSons.begin(); currEdgeToSon != edgesToSons.end(); currEdgeToSon++)
572  {
573  metEdges.push_back(*currEdgeToSon);
574  fillSubtreeMetEdges_(metEdges, GraphImpl::getBottom(*currEdgeToSon));
575  }
576 }
577 
578 template<class GraphImpl>
579 Graph::NodeId TreeGraphImpl<GraphImpl>::MRCA(const std::vector<Graph::NodeId>& nodes) const
580 {
581  mustBeRooted_();
582 
583  size_t nbnodes = nodes.size();
584 
585  if (nbnodes == 0)
586  throw getRoot();
587 
588  if (nbnodes == 1)
589  return nodes[0];
590 
591  // Forward counts
592  auto fathers = std::make_shared<std::map<Graph::NodeId, unsigned int>>();
593  auto sons = std::make_shared<std::map<Graph::NodeId, unsigned int>>();
594 
595  for (auto nodeid:nodes)
596  {
597  (*sons)[nodeid] = 1;
598  }
599 
600  while (sons->size() > 1)
601  {
602  // From sons to fathers
603  for (auto son:(*sons))
604  {
605  Graph::NodeId here = (!hasFather(son.first)) ? son.first : getFatherOfNode(son.first);
606 
607  if (fathers->find(here) == fathers->end())
608  (*fathers)[here] = son.second;
609  else
610  (*fathers)[here] += son.second;
611 
612  if ((*fathers)[here] == nbnodes)
613  return here;
614  }
615 
616  auto temp = sons;
617  sons = fathers;
618  fathers = temp;
619  fathers->clear();
620  }
621 
622  throw Exception("TreeGraphImpl::MRCA not found");
623 }
624 }
625 #endif // BPP_GRAPH_TREEGRAPHIMPL_H
void setFather(Graph::NodeId node, Graph::NodeId fatherNode)
void removeSon(Graph::NodeId node, Graph::NodeId son)
void mustBeValid_() const
bool validate_() const
std::unique_ptr< Graph::EdgeIterator > branchesIterator(Graph::NodeId node)
std::vector< Graph::NodeId > getSubtreeNodes(Graph::NodeId localRoot) const
std::vector< Graph::NodeId > getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor=true) const
void fillSubtreeMetNodes_(std::vector< Graph::NodeId > &metNodes, Graph::NodeId localRoot) const
bool isLeaf(Graph::NodeId node) const
void unRoot(bool joinRootSons)
void topologyHasChanged_() const
TreeGraphImpl< GlobalGraph > TreeGlobalGraph
std::unique_ptr< Graph::NodeIterator > sonsIterator(Graph::NodeId node)
static std::string paste(const std::vector< T > &v, const std::string &delim=" ")
Concatenate a std::vector after converting to string.
Definition: VectorTools.h:856
bool isRooted() const
std::vector< Graph::EdgeId > getBranches(Graph::NodeId node) const
bool hasFather(Graph::NodeId node) const
unsigned int NodeId
Definition: Graph.h:30
std::vector< Graph::NodeId > getSons(Graph::NodeId node) const
void setOutGroup(Graph::NodeId newOutGroup)
virtual std::vector< NodeId > getIncomingNeighbors(NodeId node) const =0
std::vector< Graph::EdgeId > getSubtreeEdges(Graph::NodeId localRoot) const
Graph::NodeId MRCA(const std::vector< Graph::NodeId > &nodes) const
Graph::EdgeId getEdgeToFather(Graph::NodeId node) const
size_t getNumberOfSons(Graph::NodeId node) const
Get the number of sons node.
virtual EdgeId getEdge(NodeId nodeA, NodeId nodeB) const =0
void rootAt(Graph::NodeId newRoot)
Graph::NodeId getFatherOfNode(Graph::NodeId nodeid) const
virtual void deleteNode(NodeId node)=0
void propagateDirection_(Graph::NodeId node)
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
std::vector< Graph::NodeId > removeSons(Graph::NodeId node)
void fillListOfLeaves_(Graph::NodeId startingNode, std::vector< Graph::NodeId > &foundLeaves) const
void mustBeRooted_() const
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:115
virtual NodeId getRoot() const =0
std::vector< Graph::NodeId > getLeavesUnderNode(Graph::NodeId node) const
bool isValid() const
void fillSubtreeMetEdges_(std::vector< Graph::EdgeId > &metEdges, Graph::NodeId localRoot) const
unsigned int EdgeId
Definition: Graph.h:31
std::vector< Graph::EdgeId > getEdgePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB) const
void addSon(Graph::NodeId node, Graph::NodeId sonNode)