bpp-core3  3.0.0
TreeGraphImpl.h
Go to the documentation of this file.
1 //
2 // File: TreeGraphImpl.h
3 // Authors:
4 // Thomas Bigot
5 // Last modified: vendredi 4 novembre 2016, à 10h 21
6 //
7 
8 /*
9  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
10 
11  This software is a computer program whose purpose is to provide utilitary
12  classes. This file belongs to the Bio++ Project.
13 
14  This software is governed by the CeCILL license under French law and
15  abiding by the rules of distribution of free software. You can use,
16  modify and/ or redistribute the software under the terms of the CeCILL
17  license as circulated by CEA, CNRS and INRIA at the following URL
18  "http://www.cecill.info".
19 
20  As a counterpart to the access to the source code and rights to copy,
21  modify and redistribute granted by the license, users are provided only
22  with a limited warranty and the software's author, the holder of the
23  economic rights, and the successive licensors have only limited
24  liability.
25 
26  In this respect, the user's attention is drawn to the risks associated
27  with loading, using, modifying and/or developing or reproducing the
28  software by the user in light of its specific status of free software,
29  that may mean that it is complicated to manipulate, and that also
30  therefore means that it is reserved for developers and experienced
31  professionals having in-depth computer knowledge. Users are therefore
32  encouraged to load and test the software's suitability as regards their
33  requirements in conditions enabling the security of their systems and/or
34  data to be ensured and, more generally, to use and operate it in the
35  same conditions as regards security.
36 
37  The fact that you are presently reading this means that you have had
38  knowledge of the CeCILL license and that you accept its terms.
39 */
40 
41 #ifndef BPP_GRAPH_TREEGRAPHIMPL_H
42 #define BPP_GRAPH_TREEGRAPHIMPL_H
43 
44 #include <iostream>
45 #include <ostream>
46 #include <string>
47 #include <vector>
48 
49 #include "../Exceptions.h"
50 #include "../Numeric/VectorTools.h"
51 #include "GlobalGraph.h"
52 #include "TreeGraph.h"
53 
54 namespace bpp
55 {
56 template<class GraphImpl>
58  public virtual TreeGraph,
59  public GraphImpl
60 {
61 private:
65  mutable bool isValid_;
66 
67  // unvalidate the tree
68  void topologyHasChanged_() const;
69 
70  // will throw an exception if the tree is not valid
71  void mustBeValid_() const;
72 
73  // will throw an exception if the tree is not rooted
74  void mustBeRooted_() const;
75 
76  // test the validity of the tree
77  bool validate_() const;
78 
84 
85  // recursive function for getSubtreeNodes
86  void fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const;
87 
88  // recursive function for getSubtreeEdges
89  void fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const;
90 
91  // recursive function for getLeavesUnderNode
92  void fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const;
93 
94 public:
96 
97  TreeGraphImpl(bool rooted = true);
98 
103  bool isValid() const;
104 
111  bool isRooted() const;
112 
119 
126 
131  bool hasFather(Graph::NodeId node) const;
132 
137  bool isLeaf(Graph::NodeId node) const;
138 
145  std::vector<Graph::NodeId> getLeavesUnderNode(Graph::NodeId node) const;
146 
151  std::vector<Graph::NodeId> getSons(Graph::NodeId node) const;
152 
157  std::vector<Graph::EdgeId> getBranches(Graph::NodeId node) const;
158 
163  std::unique_ptr<Graph::NodeIterator> sonsIterator(Graph::NodeId node);
164 
165  std::unique_ptr<Graph::NodeIterator> sonsIterator(Graph::NodeId node) const;
166 
171  std::unique_ptr<Graph::EdgeIterator> branchesIterator(Graph::NodeId node);
172 
173  std::unique_ptr<Graph::EdgeIterator> branchesIterator(Graph::NodeId node) const;
174 
179  size_t getNumberOfSons(Graph::NodeId node) const;
180 
185  void setFather(Graph::NodeId node, Graph::NodeId fatherNode);
186  void setFather(Graph::NodeId node, Graph::NodeId fatherNode, Graph::EdgeId edgeId);
187 
192  void addSon(Graph::NodeId node, Graph::NodeId sonNode);
193 
194  void addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edgeId);
195 
200  std::vector<Graph::NodeId> removeSons(Graph::NodeId node);
201 
206  void removeSon(Graph::NodeId node, Graph::NodeId son);
207 
212  void rootAt(Graph::NodeId newRoot);
213 
220  void unRoot(bool joinRootSons);
221 
227  void setOutGroup(Graph::NodeId newOutGroup);
228 
233  std::vector<Graph::NodeId> getSubtreeNodes(Graph::NodeId localRoot) const;
234 
239  std::vector<Graph::EdgeId> getSubtreeEdges(Graph::NodeId localRoot) const;
240 
241  // ///FROM TREETOOLS & TREETOOLS COMPAT
242 
243 
244  std::vector<Graph::NodeId> getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor = true) const;
245  std::vector<Graph::EdgeId> getEdgePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB) const;
246 
247 
248  /*
249  * @bref Compute the MRCA of the gven nodes
250  *
251  */
252 
253  Graph::NodeId MRCA(const std::vector<Graph::NodeId>& nodes) const;
254 };
255 
256 
257 /******************/
258 
260 
261 /*****************/
262 
263 
264 template<class GraphImpl>
266  GraphImpl(rooted),
267  isValid_(false)
268 {}
269 
270 
271 template<class GraphImpl>
273 {
274  return isValid_ || validate_();
275 }
276 
277 template<class GraphImpl>
279 {
280  std::vector<Graph::NodeId> incomers = getIncomingNeighbors(node);
281  if (incomers.size() > 1)
282  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.");
283  if (incomers.size() == 0)
284  throw Exception("TreeGraphImpl<GraphImpl>::getFather: node " + TextTools::toString(node) + " has no father.");
285  return *incomers.begin();
286 }
287 
288 template<class GraphImpl>
290 {
291  Graph::NodeId father = getFatherOfNode(node);
292  return GraphImpl::getEdge(father, node);
293 }
294 
295 template<class GraphImpl>
297 {
298  return GraphImpl::getNumberOfIncomingNeighbors(node) >= 1;
299 }
300 
301 template<class GraphImpl>
303 {
304  return (!GraphImpl::isDirected() && GraphImpl::getNumberOfOutgoingNeighbors(node) <= 1)
305  || (GraphImpl::isDirected() && GraphImpl::getNumberOfOutgoingNeighbors(node) == 0);
306 }
307 
308 template<class GraphImpl>
309 void TreeGraphImpl<GraphImpl>::fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const
310 {
311  const std::vector<Graph::NodeId> sons = getSons(startingNode);
312  if (sons.size() > 1)
313  {
314  for (std::vector<Graph::NodeId>::const_iterator currNeighbor = sons.begin(); currNeighbor != sons.end(); currNeighbor++)
315  {
316  fillListOfLeaves_(*currNeighbor, foundLeaves);
317  }
318  }
319  else
320  {
321  foundLeaves.push_back(startingNode);
322  }
323 }
324 
325 template<class GraphImpl>
326 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getLeavesUnderNode(Graph::NodeId node) const
327 {
328  std::vector<Graph::NodeId> foundLeaves;
329  fillListOfLeaves_(node, foundLeaves);
330 
331  return foundLeaves;
332 }
333 
334 template<class GraphImpl>
336 {
337  if (!isRooted())
338  throw Exception("TreeGraphImpl<GraphImpl>: The tree must be rooted.");
339 }
340 
341 template<class GraphImpl>
343 {
344  if (!isValid())
345  throw Exception("TreeGraphImpl<GraphImpl>: The tree is not valid.");
346 }
347 
348 template<class GraphImpl>
350 {
351  return GraphImpl::isDirected();
352 }
353 
354 template<class GraphImpl>
356 {
357  isValid_ = GraphImpl::isTree();
358  return isValid_;
359 }
360 
361 template<class GraphImpl>
363 {
364  isValid_ = false;
365 }
366 
367 template<class GraphImpl>
369 {
370  if (!isValid())
371  throw Exception("TreeGraphImpl::rootAt: Tree is not Valid.");
372 
373  GraphImpl::makeDirected();
374  // set the new root on the Graph
375  GraphImpl::setRoot(newRoot);
376  // change edge direction between the new node and the former one
377  propagateDirection_(newRoot);
378 }
379 
380 template<class GraphImpl>
382 {
383  if (hasFather(node))
384  {
385  NodeId father = getFatherOfNode(node);
386  propagateDirection_(father);
387  GraphImpl::switchNodes(father, node);
388  }
389 }
390 
391 template<class GraphImpl>
393 {
394  if (hasFather(node))
395  GraphImpl::unlink(getFatherOfNode(node), node);
396  GraphImpl::link(fatherNode, node);
397  topologyHasChanged_();
398 }
399 
400 template<class GraphImpl>
402 {
403  if (hasFather(node))
404  GraphImpl::unlink(getFatherOfNode(node), node);
405  GraphImpl::link(fatherNode, node, edgeId);
406  topologyHasChanged_();
407 }
408 
409 
410 template<class GraphImpl>
412 {
413  GraphImpl::link(node, sonNode);
414  topologyHasChanged_();
415 }
416 
417 template<class GraphImpl>
419 {
420  GraphImpl::link(node, sonNode, edgeId);
421  topologyHasChanged_();
422 }
423 
424 template<class GraphImpl>
425 void TreeGraphImpl<GraphImpl>::unRoot(bool joinRootSons)
426 {
427  if (joinRootSons)
428  {
429  // the root must have exactly two joinRootSons
430  std::vector<Graph::NodeId> sons = getSons(GraphImpl::getRoot());
431  if (sons.size() != 2)
432  throw Exception("The root must have two sons to join them.");
433  GraphImpl::unlink(GraphImpl::getRoot(), sons.at(0));
434  GraphImpl::unlink(GraphImpl::getRoot(), sons.at(1));
435  GraphImpl::link(sons.at(0), sons.at(1));
436  GraphImpl::setRoot(sons.at(0));
437  }
438  GraphImpl::makeUndirected();
439 }
440 
441 template<class GraphImpl>
442 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getSons(Graph::NodeId node) const
443 {
444  return GraphImpl::getOutgoingNeighbors(node);
445 }
446 
447 template<class GraphImpl>
448 std::vector<Graph::EdgeId> TreeGraphImpl<GraphImpl>::getBranches(Graph::NodeId node) const
449 {
450  return GraphImpl::getOutgoingEdges(node);
451 }
452 
453 template<class GraphImpl>
454 std::unique_ptr<Graph::NodeIterator> TreeGraphImpl<GraphImpl>::sonsIterator(Graph::NodeId node)
455 {
456  return GraphImpl::outgoingNeighborNodesIterator(node);
457 }
458 
459 template<class GraphImpl>
460 std::unique_ptr<Graph::NodeIterator> TreeGraphImpl<GraphImpl>::sonsIterator(Graph::NodeId node) const
461 {
462  return GraphImpl::outgoingNeighborNodesIterator(node);
463 }
464 
465 template<class GraphImpl>
466 std::unique_ptr<Graph::EdgeIterator> TreeGraphImpl<GraphImpl>::branchesIterator(Graph::NodeId node)
467 {
468  return GraphImpl::outgoingEdgesIterator(node);
469 }
470 
471 template<class GraphImpl>
472 std::unique_ptr<Graph::EdgeIterator> TreeGraphImpl<GraphImpl>::branchesIterator(Graph::NodeId node) const
473 {
474  return GraphImpl::outgoingEdgesIterator(node);
475 }
476 
477 template<class GraphImpl>
479 {
480  return GraphImpl::getNumberOfOutgoingNeighbors(node);
481 }
482 
483 template<class GraphImpl>
484 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::removeSons(Graph::NodeId node)
485 {
486  std::vector<Graph::NodeId> sons = getSons(node);
487  for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
488  {
489  removeSon(node, *currSon);
490  }
491  return sons;
492 }
493 
494 template<class GraphImpl>
496 {
497  GraphImpl::unlink(node, son);
498  topologyHasChanged_();
499 }
500 
501 template<class GraphImpl>
503 {
504  mustBeRooted_();
505  deleteNode(GraphImpl::getRoot());
506 
507  Graph::NodeId newRoot = GraphImpl::createNodeFromEdge(getEdge(getFatherOfNode(newOutGroup), newOutGroup));
508  rootAt(newRoot);
509 }
510 
511 template<class GraphImpl>
512 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor) const
513 {
514  GraphImpl::nodeMustExist_(nodeA);
515  GraphImpl::nodeMustExist_(nodeB);
516  std::vector<Graph::NodeId> path;
517  std::vector<Graph::NodeId> pathMatrix1;
518  std::vector<Graph::NodeId> pathMatrix2;
519 
520  Graph::NodeId nodeUp = nodeA;
521  while (hasFather(nodeUp))
522  {
523  pathMatrix1.push_back(nodeUp);
524  nodeUp = getFatherOfNode(nodeUp);
525  }
526  pathMatrix1.push_back(nodeUp); // The root.
527 
528  nodeUp = nodeB;
529  while (hasFather(nodeUp))
530  {
531  pathMatrix2.push_back(nodeUp);
532  nodeUp = getFatherOfNode(nodeUp);
533  }
534  pathMatrix2.push_back(nodeUp); // The root.
535  // Must check that the two nodes have the same root!!!
536 
537  size_t tmp1 = pathMatrix1.size();
538  size_t tmp2 = pathMatrix2.size();
539 
540  while ((tmp1 > 0) && (tmp2 > 0))
541  {
542  if (pathMatrix1[tmp1 - 1] != pathMatrix2[tmp2 - 1])
543  break;
544  tmp1--; tmp2--;
545  }
546  // (tmp1 - 1) and (tmp2 - 1) now point toward the first non-common nodes
547 
548  for (size_t y = 0; y < tmp1; ++y)
549  {
550  path.push_back(pathMatrix1[y]);
551  }
552  if (includeAncestor) // FIXME: one of the extremities may be the ancestor!!!
553  path.push_back(pathMatrix1[tmp1]); // pushing once, the Node that was common to both.
554  for (size_t j = tmp2; j > 0; --j)
555  {
556  path.push_back(pathMatrix2[j - 1]);
557  }
558  return path;
559 }
560 
561 template<class GraphImpl>
563 {
564  std::vector<Graph::EdgeId> path;
565  std::vector<Graph::NodeId> pathNodes = getNodePathBetweenTwoNodes(nodeA, nodeB, true);
566  for (size_t currNodeNr = 0; currNodeNr + 1 < pathNodes.size(); currNodeNr++)
567  {
568  path.push_back(GraphImpl::getAnyEdge(pathNodes.at(currNodeNr), pathNodes.at(currNodeNr + 1)));
569  }
570  return path;
571 }
572 
573 template<class GraphImpl>
574 std::vector<Graph::NodeId> TreeGraphImpl<GraphImpl>::getSubtreeNodes(Graph::NodeId localRoot) const
575 {
576  mustBeValid_();
577  std::vector<Graph::EdgeId> metNodes;
578  fillSubtreeMetNodes_(metNodes, localRoot);
579  return metNodes;
580 }
581 
582 template<class GraphImpl>
583 std::vector<Graph::EdgeId> TreeGraphImpl<GraphImpl>::getSubtreeEdges(Graph::NodeId localRoot) const
584 {
585  mustBeValid_();
586  std::vector<Graph::EdgeId> metEdges;
587  fillSubtreeMetEdges_(metEdges, localRoot);
588  return metEdges;
589 }
590 
591 
592 template<class GraphImpl>
593 void TreeGraphImpl<GraphImpl>::fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const
594 {
595  metNodes.push_back(localRoot);
596  std::vector<Graph::NodeId> sons = GraphImpl::getOutgoingNeighbors(localRoot);
597  for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
598  {
599  fillSubtreeMetNodes_(metNodes, *currSon);
600  }
601 }
602 
603 template<class GraphImpl>
604 void TreeGraphImpl<GraphImpl>::fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const
605 {
606  std::vector<Graph::EdgeId> edgesToSons = GraphImpl::getOutgoingEdges(localRoot);
607  for (std::vector<Graph::EdgeId>::iterator currEdgeToSon = edgesToSons.begin(); currEdgeToSon != edgesToSons.end(); currEdgeToSon++)
608  {
609  metEdges.push_back(*currEdgeToSon);
610  fillSubtreeMetEdges_(metEdges, GraphImpl::getBottom(*currEdgeToSon));
611  }
612 }
613 
614 template<class GraphImpl>
615 Graph::NodeId TreeGraphImpl<GraphImpl>::MRCA(const std::vector<Graph::NodeId>& nodes) const
616 {
617  mustBeRooted_();
618 
619  size_t nbnodes = nodes.size();
620 
621  if (nbnodes == 0)
622  throw getRoot();
623 
624  if (nbnodes == 1)
625  return nodes[0];
626 
627  // Forward counts
628  auto fathers = std::make_shared<std::map<Graph::NodeId, uint> >();
629  auto sons = std::make_shared<std::map<Graph::NodeId, uint> >();
630 
631  for (auto nodeid:nodes)
632  (*sons)[nodeid] = 1;
633 
634  while (sons->size() > 1)
635  {
636  // From sons to fathers
637  for (auto son:(*sons))
638  {
639  Graph::NodeId here=(!hasFather(son.first))?son.first:getFatherOfNode(son.first);
640 
641  if (fathers->find(here) == fathers->end())
642  (*fathers)[here] = son.second;
643  else
644  (*fathers)[here] += son.second;
645 
646  if ((*fathers)[here] == nbnodes)
647  return here;
648  }
649 
650  auto temp = sons;
651  sons = fathers;
652  fathers = temp;
653  fathers->clear();
654  }
655 
656  throw Exception("TreeGraphImpl::MRCA not found");
657 }
658 }
659 #endif // BPP_GRAPH_TREEGRAPHIMPL_H
Exception base class. Overload exception constructor (to control the exceptions mechanism)....
Definition: Exceptions.h:59
unsigned int NodeId
Definition: Graph.h:66
unsigned int EdgeId
Definition: Graph.h:67
std::unique_ptr< Graph::NodeIterator > sonsIterator(Graph::NodeId node)
void unRoot(bool joinRootSons)
void removeSon(Graph::NodeId node, Graph::NodeId son)
void rootAt(Graph::NodeId newRoot)
void addSon(Graph::NodeId node, Graph::NodeId sonNode)
void propagateDirection_(Graph::NodeId node)
Graph::EdgeId getEdgeToFather(Graph::NodeId node) const
std::unique_ptr< Graph::EdgeIterator > branchesIterator(Graph::NodeId node)
bool isLeaf(Graph::NodeId node) const
std::vector< Graph::NodeId > getSons(Graph::NodeId node) const
void fillListOfLeaves_(Graph::NodeId startingNode, std::vector< Graph::NodeId > &foundLeaves) const
std::vector< Graph::NodeId > getLeavesUnderNode(Graph::NodeId node) const
bool hasFather(Graph::NodeId node) const
std::vector< Graph::NodeId > getSubtreeNodes(Graph::NodeId localRoot) const
std::vector< Graph::NodeId > removeSons(Graph::NodeId node)
void topologyHasChanged_() const
void fillSubtreeMetNodes_(std::vector< Graph::NodeId > &metNodes, Graph::NodeId localRoot) const
std::vector< Graph::EdgeId > getSubtreeEdges(Graph::NodeId localRoot) const
void fillSubtreeMetEdges_(std::vector< Graph::EdgeId > &metEdges, Graph::NodeId localRoot) const
void mustBeRooted_() const
void setOutGroup(Graph::NodeId newOutGroup)
bool validate_() const
size_t getNumberOfSons(Graph::NodeId node) const
Get the number of sons node.
Graph::NodeId MRCA(const std::vector< Graph::NodeId > &nodes) const
void mustBeValid_() const
Graph::NodeId getFatherOfNode(Graph::NodeId nodeid) const
bool isRooted() const
std::vector< Graph::EdgeId > getEdgePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB) const
std::vector< Graph::NodeId > getNodePathBetweenTwoNodes(Graph::NodeId nodeA, Graph::NodeId nodeB, bool includeAncestor=true) const
void setFather(Graph::NodeId node, Graph::NodeId fatherNode)
std::vector< Graph::EdgeId > getBranches(Graph::NodeId node) const
bool isValid() const
static std::string paste(const std::vector< T > &v, const std::string &delim=" ")
Concatenate a std::vector after converting to string.
Definition: VectorTools.h:895
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:153
TreeGraphImpl< GlobalGraph > TreeGlobalGraph