bpp-core3  3.0.0
DAGraphImpl.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_DAGRAPHIMPL_H
6 #define BPP_GRAPH_DAGRAPHIMPL_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 "DAGraph.h"
16 #include "GlobalGraph.h"
17 
18 namespace bpp
19 {
20 template<class GraphImpl>
21 class DAGraphImpl :
22  public virtual DAGraph,
23  public GraphImpl
24 {
25 protected:
30  mutable bool isValid_;
31 
37  mutable bool isRooted_;
38 
39  // unvalidate the DAG
40  virtual void topologyHasChanged_() const;
41 
42  // will throw an exception if the DA is not valid
43  void mustBeValid_() const;
44 
45  // will throw an exception if the DA is not rooted, ie as more
46  // than one node with no father.
47 
48  void mustBeRooted_() const;
49 
50  // test the validity of the DAG
51  bool validate_() const;
52 
61 
68  void orientGraphFrom_(std::set<Graph::NodeId>& metNodes, Graph::NodeId localRoot);
69 
70 public:
76  DAGraphImpl(bool b = true);
77 
82  bool isValid() const;
83 
90  bool isRooted() const;
91 
96  bool isLeaf(Graph::NodeId node) const;
97 
102  bool hasFather(Graph::NodeId node) const;
103 
109  std::vector<Graph::NodeId> getFathers(Graph::NodeId nodeid) const;
110 
115  size_t getNumberOfFathers(Graph::NodeId node) const;
116 
121  void addFather(Graph::NodeId node, Graph::NodeId father);
122 
123  void addFather(Graph::NodeId node, Graph::NodeId father, Graph::EdgeId edgeId);
124 
129  void removeFather(Graph::NodeId node, Graph::NodeId father);
130 
135  std::vector<Graph::NodeId> removeFathers(Graph::NodeId node);
136 
143  std::vector<Graph::NodeId> getLeavesUnderNode(Graph::NodeId node) const;
144 
149  std::vector<Graph::NodeId> getSons(Graph::NodeId node) const;
150 
155  size_t getNumberOfSons(Graph::NodeId node) const;
156 
161  void addSon(Graph::NodeId node, Graph::NodeId sonNode);
162 
163  void addSon(Graph::NodeId node, Graph::NodeId sonNode, Graph::EdgeId edge);
164 
169  std::vector<Graph::NodeId> removeSons(Graph::NodeId node);
170 
175  void removeSon(Graph::NodeId node, Graph::NodeId son);
176 
181  void rootAt(Graph::NodeId newRoot);
182 
187  std::vector<Graph::NodeId> getBelowNodes(Graph::NodeId localRoot) const;
188 
193  std::vector<Graph::EdgeId> getBelowEdges(Graph::NodeId localRoot) const;
194 
195  // recursive function for getSubtreeNodes
196  void fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const;
197 
198  // recursive function for getSubtreeEdges
199  void fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const;
200 
201  // recursive function for getLeavesUnderNode
202  void fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const;
203 };
204 
205 
206 /******************/
207 
209 
210 /*****************/
211 
212 
213 template<class GraphImpl>
215  GraphImpl(true),
216  isValid_(false),
217  isRooted_(false)
218 {}
219 
220 
221 template<class GraphImpl>
223 {
224  return isValid_ || validate_();
225 }
226 
227 
228 template<class GraphImpl>
230 {
231  if (isRooted_)
232  return true;
233 
234  std::unique_ptr<Graph::NodeIterator> allIt = allNodesIterator();
235  bool seen = false;
236 
237  for ( ; !allIt->end(); allIt->next())
238  {
239  if (getNumberOfFathers(**allIt) == 0)
240  {
241  if (seen)
242  return false;
243  seen = true;
244  }
245  }
246 
247  isRooted_ = seen;
248  return true;
249 }
250 
251 template<class GraphImpl>
253 {
254  return GraphImpl::isLeaf(node);
255 }
256 
257 template<class GraphImpl>
259 {
260  return GraphImpl::getNumberOfIncomingNeighbors(node) >= 1;
261 }
262 
263 template<class GraphImpl>
264 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getFathers(Graph::NodeId node) const
265 {
266  return getIncomingNeighbors(node);
267 }
268 
269 template<class GraphImpl>
271 {
272  return GraphImpl::getNumberOfIncomingNeighbors(node);
273 }
274 
275 template<class GraphImpl>
277 {
278  GraphImpl::link(fatherNode, node);
280  isRooted_ = false;
281 }
282 
283 template<class GraphImpl>
285 {
286  GraphImpl::link(fatherNode, node, edge);
288  isRooted_ = false;
289 }
290 
291 template<class GraphImpl>
292 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::removeFathers(Graph::NodeId node)
293 {
294  std::vector<Graph::NodeId> fathers = getFathers(node);
295  for (std::vector<Graph::NodeId>::iterator currFather = fathers.begin(); currFather != fathers.end(); currFather++)
296  {
297  removeFather(node, *currFather);
298  }
299  return fathers;
300 }
301 
302 template<class GraphImpl>
304 {
305  if (getNumberOfIncomingNeighbors(node) == 1)
306  isRooted_ = false;
307 
308  GraphImpl::unlink(father, node);
309 }
310 
311 template<class GraphImpl>
312 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getLeavesUnderNode(Graph::NodeId node) const
313 {
314  std::vector<Graph::NodeId> foundLeaves;
315  fillListOfLeaves_(node, foundLeaves);
316 
317  return foundLeaves;
318 }
319 
320 template<class GraphImpl>
321 void DAGraphImpl<GraphImpl>::fillListOfLeaves_(Graph::NodeId startingNode, std::vector<Graph::NodeId>& foundLeaves) const
322 {
323  const std::vector<Graph::NodeId> sons = getSons(startingNode);
324  if (sons.size() > 1)
325  {
326  for (std::vector<Graph::NodeId>::const_iterator currNeighbor = sons.begin(); currNeighbor != sons.end(); currNeighbor++)
327  {
328  fillListOfLeaves_(*currNeighbor, foundLeaves);
329  }
330  }
331  else
332  {
333  foundLeaves.push_back(startingNode);
334  }
335 }
336 
337 template<class GraphImpl>
339 {
340  if (!isRooted())
341  throw Exception("DAGraphImpl<GraphImpl>: The DAG must be rooted.");
342 }
343 
344 template<class GraphImpl>
346 {
347  if (!isValid())
348  throw Exception("DAGraphImpl<GraphImpl>: The DAG is not valid.");
349 }
350 
351 
352 template<class GraphImpl>
354 {
355  isValid_ = GraphImpl::isDA();
356  return isValid_;
357 }
358 
359 template<class GraphImpl>
361 {
362  isValid_ = false;
363 }
364 
365 
366 template<class GraphImpl>
367 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getSons(Graph::NodeId node) const
368 {
369  return GraphImpl::getOutgoingNeighbors(node);
370 }
371 
372 template<class GraphImpl>
374 {
375  return GraphImpl::getNumberOfOutgoingNeighbors(node);
376 }
377 
378 template<class GraphImpl>
380 {
381  GraphImpl::link(node, sonNode);
383 }
384 
385 template<class GraphImpl>
387 {
388  GraphImpl::link(node, sonNode, edge);
390 }
391 
392 
393 template<class GraphImpl>
394 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::removeSons(Graph::NodeId node)
395 {
396  std::vector<Graph::NodeId> sons = getSons(node);
397  for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
398  {
399  removeSon(node, *currSon);
400  }
401  return sons;
402 }
403 
404 
405 template<class GraphImpl>
407 {
408  GraphImpl::unlink(node, son);
409 }
410 
411 
412 template<class GraphImpl>
414 {
415  GraphImpl::setRoot(newRoot);
416 
417  // change edge direction between the new node and the former fathers
418  if (isRooted() && isValid())
419  propagateDirection_(newRoot);
420  else
421  {
422  GraphImpl::orientate();
423  isRooted_ = true;
424  }
425 }
426 
427 
428 template<class GraphImpl>
430 {
431  std::vector<Graph::NodeId> vFat = getFathers(node);
432  for (auto fat:vFat)
433  {
434  propagateDirection_(fat);
435  }
436 
437  for (auto fat:vFat)
438  {
439  GraphImpl::switchNodes(fat, node);
440  }
441 }
442 
443 
444 template<class GraphImpl>
445 std::vector<Graph::NodeId> DAGraphImpl<GraphImpl>::getBelowNodes(Graph::NodeId localRoot) const
446 {
447  mustBeValid_();
448  std::vector<Graph::EdgeId> metNodes;
449  fillSubtreeMetNodes_(metNodes, localRoot);
450  return metNodes;
451 }
452 
453 template<class GraphImpl>
454 std::vector<Graph::EdgeId> DAGraphImpl<GraphImpl>::getBelowEdges(Graph::NodeId localRoot) const
455 {
456  mustBeValid_();
457  std::vector<Graph::EdgeId> metEdges;
458  fillSubtreeMetEdges_(metEdges, localRoot);
459  return metEdges;
460 }
461 
462 
463 template<class GraphImpl>
464 void DAGraphImpl<GraphImpl>::fillSubtreeMetNodes_(std::vector<Graph::NodeId>& metNodes, Graph::NodeId localRoot) const
465 {
466  metNodes.push_back(localRoot);
467  std::vector<Graph::NodeId> sons = GraphImpl::getOutgoingNeighbors(localRoot);
468  for (std::vector<Graph::NodeId>::iterator currSon = sons.begin(); currSon != sons.end(); currSon++)
469  {
470  fillSubtreeMetNodes_(metNodes, *currSon);
471  }
472 }
473 
474 template<class GraphImpl>
475 void DAGraphImpl<GraphImpl>::fillSubtreeMetEdges_(std::vector<Graph::EdgeId>& metEdges, Graph::NodeId localRoot) const
476 {
477  std::vector<Graph::EdgeId> edgesToSons = GraphImpl::getOutgoingEdges(localRoot);
478  for (std::vector<Graph::EdgeId>::iterator currEdgeToSon = edgesToSons.begin(); currEdgeToSon != edgesToSons.end(); currEdgeToSon++)
479  {
480  metEdges.push_back(*currEdgeToSon);
481  fillSubtreeMetEdges_(metEdges, GraphImpl::getBottom(*currEdgeToSon));
482  }
483 }
484 }
485 #endif // BPP_GRAPH_DAGRAPHIMPL_H
void mustBeValid_() const
Definition: DAGraphImpl.h:345
std::vector< Graph::NodeId > getLeavesUnderNode(Graph::NodeId node) const
Definition: DAGraphImpl.h:312
DAGraphImpl(bool b=true)
Definition: DAGraphImpl.h:214
virtual std::unique_ptr< NodeIterator > allNodesIterator()=0
std::vector< Graph::NodeId > getFathers(Graph::NodeId nodeid) const
Definition: DAGraphImpl.h:264
void addFather(Graph::NodeId node, Graph::NodeId father)
Definition: DAGraphImpl.h:276
std::vector< Graph::NodeId > getSons(Graph::NodeId node) const
Definition: DAGraphImpl.h:367
bool validate_() const
Definition: DAGraphImpl.h:353
bool isRooted() const
Definition: DAGraphImpl.h:229
void removeFather(Graph::NodeId node, Graph::NodeId father)
Definition: DAGraphImpl.h:303
size_t getNumberOfSons(Graph::NodeId node) const
Get the number of sons node.
Definition: DAGraphImpl.h:373
unsigned int NodeId
Definition: Graph.h:30
void fillSubtreeMetEdges_(std::vector< Graph::EdgeId > &metEdges, Graph::NodeId localRoot) const
Definition: DAGraphImpl.h:475
void propagateDirection_(Graph::NodeId node)
Definition: DAGraphImpl.h:429
bool isLeaf(Graph::NodeId node) const
Definition: DAGraphImpl.h:252
void fillListOfLeaves_(Graph::NodeId startingNode, std::vector< Graph::NodeId > &foundLeaves) const
Definition: DAGraphImpl.h:321
virtual std::vector< NodeId > getIncomingNeighbors(NodeId node) const =0
std::vector< Graph::NodeId > getBelowNodes(Graph::NodeId localRoot) const
Definition: DAGraphImpl.h:445
void addSon(Graph::NodeId node, Graph::NodeId sonNode)
Definition: DAGraphImpl.h:379
void orientGraphFrom_(std::set< Graph::NodeId > &metNodes, Graph::NodeId localRoot)
std::vector< Graph::NodeId > removeFathers(Graph::NodeId node)
Definition: DAGraphImpl.h:292
std::vector< Graph::EdgeId > getBelowEdges(Graph::NodeId localRoot) const
Definition: DAGraphImpl.h:454
void rootAt(Graph::NodeId newRoot)
Definition: DAGraphImpl.h:413
virtual void topologyHasChanged_() const
Definition: DAGraphImpl.h:360
void removeSon(Graph::NodeId node, Graph::NodeId son)
Definition: DAGraphImpl.h:406
void mustBeRooted_() const
Definition: DAGraphImpl.h:338
size_t getNumberOfFathers(Graph::NodeId node) const
Get the number of fathers nodes.
Definition: DAGraphImpl.h:270
Exception base class. Overload exception constructor (to control the exceptions mechanism). Destructor is already virtual (from std::exception)
Definition: Exceptions.h:20
bool hasFather(Graph::NodeId node) const
Definition: DAGraphImpl.h:258
bool isValid() const
Definition: DAGraphImpl.h:222
DAGraphImpl< GlobalGraph > DAGlobalGraph
Definition: DAGraphImpl.h:208
unsigned int EdgeId
Definition: Graph.h:31
std::vector< Graph::NodeId > removeSons(Graph::NodeId node)
Definition: DAGraphImpl.h:394
virtual size_t getNumberOfIncomingNeighbors(const NodeId node) const =0
void fillSubtreeMetNodes_(std::vector< Graph::NodeId > &metNodes, Graph::NodeId localRoot) const
Definition: DAGraphImpl.h:464