bpp-core3  3.0.0
DAGraphImpl.h
Go to the documentation of this file.
1 //
2 // File: DAGraphImpl.h
3 // Authors:
4 // Laurent Guéguen
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_DAGRAPHIMPL_H
42 #define BPP_GRAPH_DAGRAPHIMPL_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 "DAGraph.h"
52 #include "GlobalGraph.h"
53 
54 namespace bpp
55 {
56 template<class GraphImpl>
57 class DAGraphImpl :
58  public virtual DAGraph,
59  public GraphImpl
60 {
61 protected:
66  mutable bool isValid_;
67 
73  mutable bool isRooted_;
74 
75  // unvalidate the DAG
76  virtual void topologyHasChanged_() const;
77 
78  // will throw an exception if the DA is not valid
79  void mustBeValid_() const;
80 
81  // will throw an exception if the DA is not rooted, ie as more
82  // than one node with no father.
83 
84  void mustBeRooted_() const;
85 
86  // test the validity of the DAG
87  bool validate_() const;
88 
97 
104  void orientGraphFrom_(std::set<Graph::NodeId>& metNodes, Graph::NodeId localRoot);
105 
106 public:
112  DAGraphImpl(bool b = true);
113 
118  bool isValid() const;
119 
126  bool isRooted() const;
127 
132  bool isLeaf(Graph::NodeId node) const;
133 
138  bool hasFather(Graph::NodeId node) const;
139 
145  std::vector<Graph::NodeId> getFathers(Graph::NodeId nodeid) const;
146 
151  size_t getNumberOfFathers(Graph::NodeId node) const;
152 
157  void addFather(Graph::NodeId node, Graph::NodeId father);
158 
159  void addFather(Graph::NodeId node, Graph::NodeId father, Graph::EdgeId edgeId);
160 
165  void removeFather(Graph::NodeId node, Graph::NodeId father);
166 
171  std::vector<Graph::NodeId> removeFathers(Graph::NodeId node);
172 
179  std::vector<Graph::NodeId> getLeavesUnderNode(Graph::NodeId node) const;
180 
185  std::vector<Graph::NodeId> getSons(Graph::NodeId node) const;
186 
191  size_t getNumberOfSons(Graph::NodeId node) const;
192 
197  void addSon(Graph::NodeId node, Graph::NodeId sonNode);
198 
199  void addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edge);
200 
205  std::vector<Graph::NodeId> removeSons(Graph::NodeId node);
206 
211  void removeSon(Graph::NodeId node, Graph::NodeId son);
212 
217  void rootAt(Graph::NodeId newRoot);
218 
223  std::vector<Graph::NodeId> getBelowNodes(Graph::NodeId localRoot) const;
224 
229  std::vector<Graph::EdgeId> getBelowEdges(Graph::NodeId localRoot) const;
230 
231  // recursive function for getSubtreeNodes
232  void fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const;
233 
234  // recursive function for getSubtreeEdges
235  void fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const;
236 
237  // recursive function for getLeavesUnderNode
238  void fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const;
239 };
240 
241 
242 /******************/
243 
245 
246 /*****************/
247 
248 
249 template<class GraphImpl>
251  GraphImpl(true),
252  isValid_(false),
253  isRooted_(false)
254 {}
255 
256 
257 template<class GraphImpl>
259 {
260  return isValid_ || validate_();
261 }
262 
263 
264 template<class GraphImpl>
266 {
267  if (isRooted_)
268  return true;
269 
270  std::unique_ptr<Graph::NodeIterator> allIt = allNodesIterator();
271  bool seen = false;
272 
273  for ( ; !allIt->end(); allIt->next())
274  {
275  if (getNumberOfFathers(**allIt) == 0)
276  {
277  if (seen)
278  return false;
279  seen = true;
280  }
281  }
282 
283  isRooted_ = seen;
284  return true;
285 }
286 
287 template<class GraphImpl>
289 {
290  return GraphImpl::isLeaf(node);
291 }
292 
293 template<class GraphImpl>
295 {
296  return GraphImpl::getNumberOfIncomingNeighbors(node) >= 1;
297 }
298 
299 template<class GraphImpl>
300 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getFathers(Graph::NodeId node) const
301 {
302  return getIncomingNeighbors(node);
303 }
304 
305 template<class GraphImpl>
307 {
308  return GraphImpl::getNumberOfIncomingNeighbors(node);
309 }
310 
311 template<class GraphImpl>
313 {
314  GraphImpl::link(fatherNode, node);
315  topologyHasChanged_();
316  isRooted_ = false;
317 }
318 
319 template<class GraphImpl>
321 {
322  GraphImpl::link(fatherNode, node, edge);
323  topologyHasChanged_();
324  isRooted_ = false;
325 }
326 
327 template<class GraphImpl>
328 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::removeFathers(Graph::NodeId node)
329 {
330  std::vector<Graph::NodeId> fathers = getFathers(node);
331  for (std::vector<Graph::NodeId>::iterator currFather = fathers.begin(); currFather != fathers.end(); currFather++)
332  {
333  removeFather(node, *currFather);
334  }
335  return fathers;
336 }
337 
338 template<class GraphImpl>
340 {
341  if (getNumberOfIncomingNeighbors(node) == 1)
342  isRooted_ = false;
343 
344  GraphImpl::unlink(father, node);
345 }
346 
347 template<class GraphImpl>
348 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getLeavesUnderNode(Graph::NodeId node) const
349 {
350  std::vector<Graph::NodeId> foundLeaves;
351  fillListOfLeaves_(node, foundLeaves);
352 
353  return foundLeaves;
354 }
355 
356 template<class GraphImpl>
357 void DAGraphImpl<GraphImpl>::fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const
358 {
359  const std::vector<Graph::NodeId> sons = getSons(startingNode);
360  if (sons.size() > 1)
361  {
362  for (std::vector<Graph::NodeId>::const_iterator currNeighbor = sons.begin(); currNeighbor != sons.end(); currNeighbor++)
363  {
364  fillListOfLeaves_(*currNeighbor, foundLeaves);
365  }
366  }
367  else
368  {
369  foundLeaves.push_back(startingNode);
370  }
371 }
372 
373 template<class GraphImpl>
375 {
376  if (!isRooted())
377  throw Exception("DAGraphImpl<GraphImpl>: The DAG must be rooted.");
378 }
379 
380 template<class GraphImpl>
382 {
383  if (!isValid())
384  throw Exception("DAGraphImpl<GraphImpl>: The DAG is not valid.");
385 }
386 
387 
388 template<class GraphImpl>
390 {
391  isValid_ = GraphImpl::isDA();
392  return isValid_;
393 }
394 
395 template<class GraphImpl>
397 {
398  isValid_ = false;
399 }
400 
401 
402 template<class GraphImpl>
403 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getSons(Graph::NodeId node) const
404 {
405  return GraphImpl::getOutgoingNeighbors(node);
406 }
407 
408 template<class GraphImpl>
410 {
411  return GraphImpl::getNumberOfOutgoingNeighbors(node);
412 }
413 
414 template<class GraphImpl>
416 {
417  GraphImpl::link(node, sonNode);
418  topologyHasChanged_();
419 }
420 
421 template<class GraphImpl>
423 {
424  GraphImpl::link(node, sonNode, edge);
425  topologyHasChanged_();
426 }
427 
428 
429 template<class GraphImpl>
430 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::removeSons(Graph::NodeId node)
431 {
432  std::vector<Graph::NodeId> sons = getSons(node);
433  for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
434  {
435  removeSon(node, *currSon);
436  }
437  return sons;
438 }
439 
440 
441 template<class GraphImpl>
443 {
444  GraphImpl::unlink(node, son);
445 }
446 
447 
448 template<class GraphImpl>
450 {
451  GraphImpl::setRoot(newRoot);
452 
453  // change edge direction between the new node and the former fathers
454  if (isRooted() && isValid())
455  propagateDirection_(newRoot);
456  else
457  {
458  GraphImpl::orientate();
459  isRooted_ = true;
460  }
461 }
462 
463 
464 template<class GraphImpl>
466 {
467  std::vector<Graph::NodeId> vFat = getFathers(node);
468  for (auto fat:vFat)
469  {
470  propagateDirection_(fat);
471  }
472 
473  for (auto fat:vFat)
474  {
475  GraphImpl::switchNodes(fat, node);
476  }
477 }
478 
479 
480 template<class GraphImpl>
481 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getBelowNodes(Graph::NodeId localRoot) const
482 {
483  mustBeValid_();
484  std::vector<Graph::EdgeId> metNodes;
485  fillSubtreeMetNodes_(metNodes, localRoot);
486  return metNodes;
487 }
488 
489 template<class GraphImpl>
490 std::vector<Graph::EdgeId> DAGraphImpl<GraphImpl>::getBelowEdges(Graph::NodeId localRoot) const
491 {
492  mustBeValid_();
493  std::vector<Graph::EdgeId> metEdges;
494  fillSubtreeMetEdges_(metEdges, localRoot);
495  return metEdges;
496 }
497 
498 
499 template<class GraphImpl>
500 void DAGraphImpl<GraphImpl>::fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const
501 {
502  metNodes.push_back(localRoot);
503  std::vector<Graph::NodeId> sons = GraphImpl::getOutgoingNeighbors(localRoot);
504  for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
505  {
506  fillSubtreeMetNodes_(metNodes, *currSon);
507  }
508 }
509 
510 template<class GraphImpl>
511 void DAGraphImpl<GraphImpl>::fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const
512 {
513  std::vector<Graph::EdgeId> edgesToSons = GraphImpl::getOutgoingEdges(localRoot);
514  for (std::vector<Graph::EdgeId>::iterator currEdgeToSon = edgesToSons.begin(); currEdgeToSon != edgesToSons.end(); currEdgeToSon++)
515  {
516  metEdges.push_back(*currEdgeToSon);
517  fillSubtreeMetEdges_(metEdges, GraphImpl::getBottom(*currEdgeToSon));
518  }
519 }
520 }
521 #endif // BPP_GRAPH_DAGRAPHIMPL_H
bool validate_() const
Definition: DAGraphImpl.h:389
void fillSubtreeMetEdges_(std::vector< Graph::EdgeId > &metEdges, Graph::NodeId localRoot) const
Definition: DAGraphImpl.h:511
std::vector< Graph::NodeId > getFathers(Graph::NodeId nodeid) const
Definition: DAGraphImpl.h:300
std::vector< Graph::NodeId > getSons(Graph::NodeId node) const
Definition: DAGraphImpl.h:403
std::vector< Graph::NodeId > getBelowNodes(Graph::NodeId localRoot) const
Definition: DAGraphImpl.h:481
std::vector< Graph::NodeId > removeSons(Graph::NodeId node)
Definition: DAGraphImpl.h:430
bool isLeaf(Graph::NodeId node) const
Definition: DAGraphImpl.h:288
DAGraphImpl(bool b=true)
Definition: DAGraphImpl.h:250
void removeFather(Graph::NodeId node, Graph::NodeId father)
Definition: DAGraphImpl.h:339
void orientGraphFrom_(std::set< Graph::NodeId > &metNodes, Graph::NodeId localRoot)
size_t getNumberOfSons(Graph::NodeId node) const
Get the number of sons node.
Definition: DAGraphImpl.h:409
std::vector< Graph::EdgeId > getBelowEdges(Graph::NodeId localRoot) const
Definition: DAGraphImpl.h:490
void addFather(Graph::NodeId node, Graph::NodeId father)
Definition: DAGraphImpl.h:312
void addSon(Graph::NodeId node, Graph::NodeId sonNode)
Definition: DAGraphImpl.h:415
bool hasFather(Graph::NodeId node) const
Definition: DAGraphImpl.h:294
void rootAt(Graph::NodeId newRoot)
Definition: DAGraphImpl.h:449
void propagateDirection_(Graph::NodeId node)
Definition: DAGraphImpl.h:465
void removeSon(Graph::NodeId node, Graph::NodeId son)
Definition: DAGraphImpl.h:442
std::vector< Graph::NodeId > getLeavesUnderNode(Graph::NodeId node) const
Definition: DAGraphImpl.h:348
void fillSubtreeMetNodes_(std::vector< Graph::NodeId > &metNodes, Graph::NodeId localRoot) const
Definition: DAGraphImpl.h:500
std::vector< Graph::NodeId > removeFathers(Graph::NodeId node)
Definition: DAGraphImpl.h:328
void mustBeValid_() const
Definition: DAGraphImpl.h:381
void mustBeRooted_() const
Definition: DAGraphImpl.h:374
virtual void topologyHasChanged_() const
Definition: DAGraphImpl.h:396
bool isValid() const
Definition: DAGraphImpl.h:258
void fillListOfLeaves_(Graph::NodeId startingNode, std::vector< Graph::NodeId > &foundLeaves) const
Definition: DAGraphImpl.h:357
bool isRooted() const
Definition: DAGraphImpl.h:265
size_t getNumberOfFathers(Graph::NodeId node) const
Get the number of fathers nodes.
Definition: DAGraphImpl.h:306
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
DAGraphImpl< GlobalGraph > DAGlobalGraph
Definition: DAGraphImpl.h:244