bpp-core3  3.0.0
GlobalGraph.cpp
Go to the documentation of this file.
1 //
2 // File: GlobalGraph.cpp
3 // Authors:
4 // Thomas Bigot
5 // Last modified: 2017-06-27 00:00:00
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 #include <algorithm>
42 #include <sstream>
43 #include <string>
44 #include <vector>
45 
46 #include "../Exceptions.h"
47 #include "../Text/TextTools.h"
48 #include "GlobalGraph.h"
49 #include "GraphObserver.h"
50 
51 using namespace bpp;
52 using namespace std;
53 
54 GlobalGraph::GlobalGraph(bool directed_p) :
55  directed_(directed_p),
56  observers_(set<GraphObserver*>()),
57  highestNodeID_(0),
58  highestEdgeID_(0),
59  nodeStructure_(nodeStructureType()),
60  edgeStructure_(edgeStructureType()),
61  root_(0)
62 {}
63 
64 
66  directed_(gg.directed_),
67  observers_(gg.observers_),
68  highestNodeID_(gg.highestNodeID_),
69  highestEdgeID_(gg.highestEdgeID_),
70  nodeStructure_(gg.nodeStructure_),
71  edgeStructure_(gg.edgeStructure_),
72  root_(gg.root_)
73 {}
74 
76 {
77  directed_ = gg.directed_;
83  root_ = gg.root_;
84 
85  return *this;
86 }
87 
88 
89 void GlobalGraph::nodeMustExist_(const GlobalGraph::Node& node, string name) const
90 {
91  if (nodeStructure_.find(node) == nodeStructure_.end())
92  throw Exception("This node must exist: " + TextTools::toString(node) + " as " + name + ".");
93 }
94 
95 void GlobalGraph::edgeMustExist_(const GlobalGraph::Edge& edge, string name) const
96 {
97  if (edgeStructure_.find(edge) == edgeStructure_.end())
98  throw Exception("This edge must exist: " + TextTools::toString(edge) + " as " + name + ".");
99 }
100 
101 
103 {
104  // which ID is available?
106 
107  // writing the new relation to the structure
108  linkInNodeStructure_(nodeA, nodeB, edgeID);
109  if (!directed_)
110  {
111  linkInNodeStructure_(nodeB, nodeA, edgeID);
112  }
113  linkInEdgeStructure_(nodeA, nodeB, edgeID);
114  return edgeID;
115 }
116 
118 {
119  if (edgeStructure_.find(edgeID) != edgeStructure_.end())
120  throw Exception("GlobalGraph::link : already existing edgeId " + TextTools::toString(edgeID));
121 
122  // writing the new relation to the structure
123  linkInNodeStructure_(nodeA, nodeB, edgeID);
124  if (!directed_)
125  {
126  linkInNodeStructure_(nodeB, nodeA, edgeID);
127  }
128  linkInEdgeStructure_(nodeA, nodeB, edgeID);
129 }
130 
131 vector<GlobalGraph::Edge> GlobalGraph::unlink(Graph::NodeId nodeA, Graph::NodeId nodeB)
132 {
133  // unlinking in the structure
134  vector<GlobalGraph::Edge> deletedEdges; // what edges ID are affected by this unlinking
135  deletedEdges.push_back(unlinkInNodeStructure_(nodeA, nodeB));
136 
137  for (auto& currEdgeToDelete : deletedEdges)
138  {
139  unlinkInEdgeStructure_(currEdgeToDelete);
140  }
141 
142  // telling the observers
143  notifyDeletedEdges(deletedEdges);
144 
145  return deletedEdges;
146 }
147 
149 {
150  Graph::NodeId father, son;
151 
152  nodeStructureType::iterator nodeARow = nodeStructure_.find(nodeA);
153  nodeStructureType::iterator nodeBRow = nodeStructure_.find(nodeB);
154  nodeStructureType::iterator nodeSonRow, nodeFatherRow;
155 
156  // Forwards
157  map<GlobalGraph::Node, GlobalGraph::Edge>::iterator foundForwardRelation = nodeARow->second.first.find(nodeB);
158  if (foundForwardRelation == nodeARow->second.first.end())
159  {
160  foundForwardRelation = nodeBRow->second.first.find(nodeA);
161  if (foundForwardRelation == nodeBRow->second.first.end())
162  throw Exception("GlobalGraph::exchangeNodes : no edge between nodes " + TextTools::toString(nodeA) + " and " + TextTools::toString(nodeB));
163  father = nodeB;
164  son = nodeA;
165  nodeFatherRow = nodeBRow;
166  nodeSonRow = nodeARow;
167  }
168  else
169  {
170  father = nodeA;
171  son = nodeB;
172  nodeFatherRow = nodeARow;
173  nodeSonRow = nodeBRow;
174  }
175 
176  // Edge
177  GlobalGraph::Edge foundEdge = foundForwardRelation->second;
178 
179  // Backwards
180  map<GlobalGraph::Node, GlobalGraph::Edge>::iterator foundBackwardsRelation = nodeSonRow->second.second.find(father);
181 
182 
183  // Exchange
184  nodeFatherRow->second.first.erase(foundForwardRelation);
185  nodeSonRow->second.second.erase(foundBackwardsRelation);
186 
187 
188  nodeSonRow->second.first[father] = foundEdge;
189 
190  nodeFatherRow->second.second[son] = foundEdge;
191 
192 
193 // std::map<GlobalGraph::Node, std::pair<std::map<GlobalGraph::Node, GlobalGraph::Edge>, std::map<GlobalGraph::Node, GlobalGraph::Edge> > >::iterator ita = nodeStructure_.find(nodeA);
194 
195  edgeStructure_[foundEdge] = pair<Node, Node>(son, father);
196 
197  this->topologyHasChanged_();
198 }
199 
200 
202 {
203  edgeStructureType::iterator foundEdge = edgeStructure_.find(edge);
204  if (foundEdge == edgeStructure_.end())
205  throw Exception("GlobalGraph::unlinkInEdgeStructure_ : no edge to erase " + TextTools::toString(edge));
206 
207  edgeStructure_.erase(foundEdge);
208  this->topologyHasChanged_();
209 }
210 
212 {
213  edgeStructure_[edge] = pair<Node, Node>(nodeA, nodeB);
214  this->topologyHasChanged_();
215 }
216 
217 
219 {
220  // Forward
221  nodeStructureType::iterator nodeARow = nodeStructure_.find(nodeA);
222  map<GlobalGraph::Node, GlobalGraph::Edge>::iterator foundForwardRelation = nodeARow->second.first.find(nodeB);
223  if (foundForwardRelation == nodeARow->second.first.end())
224  throw Exception("GlobalGraph::unlinkInNodeStructure_ : no edge to erase " + TextTools::toString(nodeA) + "->" + TextTools::toString(nodeB));
225 
226  GlobalGraph::Edge foundEdge = foundForwardRelation->second;
227  nodeARow->second.first.erase(foundForwardRelation);
228 
229  // Backwards
230  nodeStructureType::iterator nodeBRow = nodeStructure_.find(nodeB);
231  map<GlobalGraph::Node, GlobalGraph::Edge>::iterator foundBackwardsRelation = nodeBRow->second.second.find(nodeA);
232  if (foundBackwardsRelation == nodeBRow->second.first.end())
233  throw Exception("GlobalGraph::unlinkInNodeStructure_ : no edge to erase " + TextTools::toString(nodeB) + "<-" + TextTools::toString(nodeA));
234 
235  nodeBRow->second.second.erase(foundBackwardsRelation);
236 
237  this->topologyHasChanged_();
238  return foundEdge;
239 }
240 
242 {
243  auto ita = nodeStructure_.find(nodeA);
244  if (ita != nodeStructure_.end())
245  ita->second.first.insert( pair<GlobalGraph::Node, GlobalGraph::Edge>(nodeB, edge));
246 
247  auto itb = nodeStructure_.find(nodeB);
248  if (itb != nodeStructure_.end())
249  nodeStructure_.find(nodeB)->second.second.insert( pair<GlobalGraph::Node, GlobalGraph::Edge>(nodeA, edge));
250 
251  this->topologyHasChanged_();
252 }
253 
255 {
256  GlobalGraph::Node newNode = highestNodeID_++;
257  nodeStructure_[newNode] = std::pair<std::map<GlobalGraph::Node, GlobalGraph::Edge>, std::map<GlobalGraph::Node, GlobalGraph::Edge> >();
258  this->topologyHasChanged_();
259 
260  return newNode;
261 }
262 
264 {
265  Graph::NodeId newNode = createNode();
266  link(origin, newNode);
267  this->topologyHasChanged_();
268  return newNode;
269 }
270 
272 {
273  // origin must be an existing edge
274  edgeMustExist_(edge, "");
275 
276  Graph::NodeId newNode = createNode();
277 
278  // determining the nodes on the border of the edge
279  pair<GlobalGraph::Node, GlobalGraph::Node> nodes = edgeStructure_[edge];
280  GlobalGraph::Node nodeA = nodes.first;
281  GlobalGraph::Node nodeB = nodes.second;
282 
283  unlink(nodeA, nodeB);
284  link(nodeA, newNode);
285  link(newNode, nodeB);
286  this->topologyHasChanged_();
287  return newNode;
288 }
289 
290 
292 {
293  // origin must be an existing edge
294  edgeMustExist_(origin, "origin edge");
295 
296  // splitting the edge
297  Graph::NodeId anchor = createNodeOnEdge(origin);
298 
299  Graph::NodeId newNode = createNodeFromNode(anchor);
300  this->topologyHasChanged_();
301  return newNode;
302 }
303 
304 /*********************************************/
305 
307 {
308  if (!observers_.insert(observer).second)
309  throw (Exception("This GraphObserver was already an observer of this Graph"));
310  ;
311 }
312 
314 {
315  if (!observers_.erase(observer))
316  throw (Exception("This GraphObserver was not an observer of this Graph"));
317 }
318 
319 
320 /**********************************************/
321 
322 std::vector< GlobalGraph::Node > GlobalGraph::getNeighbors_(const GlobalGraph::Node& node, bool outgoing) const
323 {
324  nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
325  if (foundNode == nodeStructure_.end())
326  throw (Exception("The requested node is not in the structure."));
327  const std::map<GlobalGraph::Node, GlobalGraph::Edge>& forOrBack = (outgoing ? foundNode->second.first : foundNode->second.second);
328  vector<GlobalGraph::Node> result;
329  for (auto& currNeighbor : forOrBack)
330  {
331  result.push_back(currNeighbor.first);
332  }
333 
334  return result;
335 }
336 
337 std::vector< GlobalGraph::Edge > GlobalGraph::getEdges_(const GlobalGraph::Node& node, bool outgoing) const
338 {
339  nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
340  if (foundNode == nodeStructure_.end())
341  throw (Exception("The requested node is not in the structure."));
342  const std::map<GlobalGraph::Node, GlobalGraph::Edge>& forOrBack = (outgoing ? foundNode->second.first : foundNode->second.second);
343 
344  vector<GlobalGraph::Edge> result;
345  for (const auto& currNeighbor : forOrBack)
346  {
347  result.push_back(currNeighbor.second);
348  }
349 
350  return result;
351 }
352 
353 vector< Graph::NodeId > GlobalGraph::getIncomingNeighbors(Graph::NodeId node) const
354 {
355  return getNeighbors_(node, false);
356 }
357 
358 vector< Graph::EdgeId > GlobalGraph::getIncomingEdges(const Graph::NodeId node) const
359 {
360  return getEdges_(node, false);
361 }
362 
363 vector< Graph::NodeId > GlobalGraph::getOutgoingNeighbors(const Graph::NodeId node) const
364 {
365  return getNeighbors_(node, true);
366 }
367 
368 vector< Graph::EdgeId > GlobalGraph::getOutgoingEdges(const Graph::NodeId node) const
369 {
370  return getEdges_(node, true);
371 }
372 
373 std::unique_ptr<Graph::NodeIterator> GlobalGraph::allNodesIterator()
374 {
375  return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::ALLGRAPHITER, false>(*this));
376 }
377 
378 std::unique_ptr<Graph::NodeIterator> GlobalGraph::allNodesIterator() const
379 {
380  return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::ALLGRAPHITER, true>(*this));
381 }
382 
383 
384 std::unique_ptr<Graph::NodeIterator> GlobalGraph::outgoingNeighborNodesIterator(Graph::NodeId node)
385 {
386  return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::OUTGOINGNEIGHBORITER, false>(*this, node));
387 }
388 
389 
390 std::unique_ptr<Graph::NodeIterator> GlobalGraph::incomingNeighborNodesIterator(Graph::NodeId node)
391 {
392  return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::INCOMINGNEIGHBORITER, false>(*this, node));
393 }
394 
395 std::unique_ptr<Graph::NodeIterator> GlobalGraph::outgoingNeighborNodesIterator(Graph::NodeId node) const
396 {
397  return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::OUTGOINGNEIGHBORITER, true>(*this, node));
398 }
399 
400 
401 std::unique_ptr<Graph::NodeIterator> GlobalGraph::incomingNeighborNodesIterator(Graph::NodeId node) const
402 {
403  return std::unique_ptr<Graph::NodeIterator>(new NodesIteratorClass<Graph::INCOMINGNEIGHBORITER, true>(*this, node));
404 }
405 
406 
408 {
409  return nodeStructure_.size();
410 }
411 
412 
414 {
415  return edgeStructure_.size();
416 }
417 
418 
419 size_t GlobalGraph::getDegree(const Graph::NodeId node) const
420 {
421  nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
422  if (foundNode == nodeStructure_.end())
423  throw Exception("GlobalGraph::getDegree : Node " + TextTools::toString(node) + " does not exist.");
424 
425  return isDirected() ? foundNode->second.first.size() + foundNode->second.second.size() : foundNode->second.first.size();
426 }
427 
428 
429 bool GlobalGraph::isLeaf(const Graph::NodeId node) const
430 {
431  nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
432  if (foundNode == nodeStructure_.end())
433  throw Exception("GlobalGraph::isLeaf : Node " + TextTools::toString(node) + " does not exist.");
434 
435  const auto& assoc = foundNode->second;
436  return (!isDirected() && (assoc.first.size() <= 1))
437  || (isDirected() && (
438  (assoc.first.size() + assoc.second.size() <= 1)
439  || (assoc.first.size() == 1 && assoc.second.size() == 1 &&
440  assoc.first.begin()->first == assoc.second.begin()->first)));
441 }
442 
443 
445 {
446  nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
447  if (foundNode == nodeStructure_.end())
448  throw (Exception("The requested node is not in the structure."));
449 
450  if (isDirected())
451  return foundNode->second.first.size() + foundNode->second.second.size();
452  else
453  return foundNode->second.first.size();
454 }
455 
457 {
458  nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
459  if (foundNode == nodeStructure_.end())
460  throw (Exception("The requested node is not in the structure."));
461  return foundNode->second.first.size();
462 }
463 
465 {
466  nodeStructureType::const_iterator foundNode = nodeStructure_.find(node);
467  if (foundNode == nodeStructure_.end())
468  throw (Exception("The requested node is not in the structure."));
469  return foundNode->second.second.size();
470 }
471 
472 vector< Graph::NodeId > GlobalGraph::getNeighbors(const Graph::NodeId node) const
473 {
474  vector<Graph::NodeId> result;
475  vector<Graph::NodeId> neighborsToInsert;
476  neighborsToInsert = getNeighbors_(node, false);
477  result.insert(result.end(), neighborsToInsert.begin(), neighborsToInsert.end());
478  neighborsToInsert = getNeighbors_(node, true);
479  result.insert(result.end(), neighborsToInsert.begin(), neighborsToInsert.end());
480  return result;
481 }
482 
483 std::pair<Graph::NodeId, Graph::NodeId> GlobalGraph::getNodes(Graph::EdgeId edge) const
484 {
485  edgeMustExist_(edge);
486  edgeStructureType::const_iterator found = edgeStructure_.find(edge);
487  return found->second;
488 }
489 
491 {
492  return std::get<0>(getNodes(edge));
493 }
494 
496 {
497  return std::get<1>(getNodes(edge));
498 }
499 
501 {
502  // checking the node
503  nodeMustExist_(node, "node to delete");
504  isolate_(node);
505 
506  nodeStructureType::iterator found = nodeStructure_.find(node);
507  if (found == nodeStructure_.end())
508  throw Exception("GlobalGraph::deleteNode : no node to erase " + TextTools::toString(node));
509 
510  nodeStructure_.erase(found);
511 
512  this->topologyHasChanged_();
513 }
514 
516 {
517  vector<Graph::NodeId> oneighbors = getOutgoingNeighbors(node);
518  for (auto& currNeighbor : oneighbors)
519  {
520  unlink(node, currNeighbor);
521  }
522 
523  vector<Graph::NodeId> ineighbors = getIncomingNeighbors(node);
524  for (auto& currNeighbor : ineighbors)
525  {
526  unlink(currNeighbor, node);
527  }
528 }
529 
530 vector<Graph::EdgeId> GlobalGraph::getAllEdges() const
531 {
532  vector<Graph::EdgeId> listOfEdges;
533  for (const auto& it : edgeStructure_)
534  {
535  listOfEdges.push_back(it.first);
536  }
537 
538  return listOfEdges;
539 }
540 
542 {
543  try
544  {
545  // trying in the given order A->B
546  return getEdge(nodeA, nodeB);
547  }
548  catch (Exception& e)
549  {
550  // didn’t work, hence trying in the opposite order B->A
551  return getEdge(nodeB, nodeA);
552  }
553 }
554 
555 vector<Graph::NodeId> GlobalGraph::getAllLeaves() const
556 {
557  vector<Graph::NodeId> listOfLeaves;
558  for (const auto& it : nodeStructure_)
559  {
560  if (this->isLeaf(it.first))
561  listOfLeaves.push_back(it.first);
562  }
563 
564  return listOfLeaves;
565 }
566 
567 set<Graph::NodeId> GlobalGraph::getSetOfAllLeaves() const
568 {
569  set<Graph::NodeId> listOfLeaves;
570  for (const auto& it : nodeStructure_)
571  {
572  if (this->isLeaf(it.first))
573  listOfLeaves.insert(it.first);
574  }
575 
576  return listOfLeaves;
577 }
578 
579 vector<Graph::NodeId> GlobalGraph::getAllNodes() const
580 {
581  vector<Graph::NodeId> listOfNodes;
582  for (const auto& it : nodeStructure_)
583  {
584  listOfNodes.push_back(it.first);
585  }
586 
587  return listOfNodes;
588 }
589 
590 vector<Graph::NodeId> GlobalGraph::getAllInnerNodes() const
591 {
592  vector<Graph::NodeId> listOfInNodes;
593  for (const auto& it : nodeStructure_)
594  {
595  if (this->getNumberOfOutgoingNeighbors(it.first) >= 1)
596  listOfInNodes.push_back(it.first);
597  }
598  return listOfInNodes;
599 }
600 
601 
602 void GlobalGraph::fillListOfLeaves_(const GlobalGraph::Node& startingNode, vector<GlobalGraph::Node>& foundLeaves, const GlobalGraph::Node& originNode, unsigned int maxRecursions) const
603 {
604  const vector<Graph::NodeId> neighbors = getNeighbors(startingNode);
605  if (neighbors.size() > 1)
606  {
607  if (maxRecursions > 0)
608  for (const auto& currNeighbor : neighbors)
609  {
610  if (currNeighbor != originNode)
611  fillListOfLeaves_(currNeighbor, foundLeaves, startingNode, maxRecursions - 1);
612  }
613  }
614  else
615  foundLeaves.push_back(startingNode);
616 }
617 
618 
619 std::vector<Graph::NodeId> GlobalGraph::getLeavesFromNode(const Graph::NodeId node, unsigned int maxDepth) const
620 {
621  vector<Graph::NodeId> listOfLeaves;
622  fillListOfLeaves_(node, listOfLeaves, node, maxDepth);
623  return listOfLeaves;
624 }
625 
626 void GlobalGraph::nodeToDot_(const GlobalGraph::Node& node, ostream& out, std::set<std::pair<Node, Node> >& alreadyFigured) const
627 {
628  out << node;
629  const std::map<Node, Edge>& children = nodeStructure_.at(node).first;
630  bool flag(false);
631  for (const auto& currChild : children)
632  {
633  if (alreadyFigured.find(pair<Node, Node>(node, currChild.first)) != alreadyFigured.end() || (!directed_ && alreadyFigured.find(pair<Node, Node>(currChild.first, node)) != alreadyFigured.end()))
634  continue;
635  alreadyFigured.insert(pair<Node, Node>(node, currChild.first));
636  if (flag)
637  out << node;
638  out << (directed_ ? " -> " : " -- ");
639  nodeToDot_(currChild.first, out, alreadyFigured);
640  flag = true;
641  }
642  if (!flag)
643  out << ";\n ";
644 }
645 
647 {
648  set<GlobalGraph::Node> metNodes;
649  bool nodesAreMetOnlyOnce = nodesAreMetOnlyOnce_(root_, metNodes, root_);
650 
651  if (!nodesAreMetOnlyOnce)
652  return false;
653 
654  // now they have only been met at most once, they have to be met at least once
655  for (const auto& currNode:nodeStructure_)
656  {
657  if (metNodes.find(currNode.first) == metNodes.end())
658  return false;
659  }
660 
661  return true;
662 }
663 
664 
665 bool GlobalGraph::nodesAreMetOnlyOnce_(const GlobalGraph::Node& node, set< GlobalGraph::Node >& metNodes, const GlobalGraph::Node& originNode) const
666 {
667  // insert().second <=> not yet in the set
668  if (!metNodes.insert(node).second)
669  return false;
670 
671  vector<Graph::NodeId> neighbors = getOutgoingNeighbors(node);
672  for (auto currNeighbor:neighbors)
673  {
674  if (currNeighbor == originNode)
675  continue;
676  if (!nodesAreMetOnlyOnce_(currNeighbor, metNodes, node))
677  return false;
678  }
679  return true;
680 }
681 
682 bool GlobalGraph::isDA() const
683 {
684  GlobalGraph gg(*this);
685 
686  gg.observers_.clear();
687  // Algo: remove recursively all nodes with no sons from graph
688 
689  std::vector<Graph::NodeId> vL;
690 
691  std::unique_ptr<Graph::NodeIterator> it = gg.allNodesIterator();
692  for ( ; !it->end(); it->next())
693  {
694  if (gg.getNumberOfOutgoingNeighbors(**it) == 0)
695  vL.push_back(**it);
696  }
697 
698  while (vL.size() != 0)
699  {
700  for (auto& it2 : vL)
701  {
702  gg.deleteNode(it2);
703  }
704 
705  if (gg.getNumberOfNodes() == 0)
706  return true;
707 
708  vL.clear();
709 
710  it = gg.allNodesIterator();
711  for ( ; !it->end(); it->next())
712  {
713  if (gg.getNumberOfOutgoingNeighbors(**it) == 0)
714  vL.push_back(**it);
715  }
716  }
717 
718  return false;
719 }
720 
721 
723 {
724  if (!isDirected())
725  makeDirected();
726 
727  GlobalGraph gg(*this);
728  gg.observers_.clear();
729 
730  // Algo: remove recursively all nodes from graph, starting with
731  // root_
732 
733  Graph::NodeId node = root_;
734  std::set<Graph::NodeId> nextNodes;
735  nextNodes.insert(node);
736 
737  while (gg.getNumberOfNodes() != 0)
738  {
739  // look for the next node to be treated
740  Graph::NodeId nbgg = 0;
741 
742  // first node with one neighbor (ie no choice on orientation)
743 
744  std::set<Graph::NodeId>::iterator it = nextNodes.begin();
745  for ( ; it != nextNodes.end(); it++)
746  {
747  if (gg.getNumberOfNeighbors(*it) <= 1)
748  break;
749  }
750 
751  // if none, look for node wih minimum number of fathers
752  if (it == nextNodes.end())
753  {
754  size_t nbF = numeric_limits<size_t>::infinity();
755  it = nextNodes.begin();
756 
757  for ( ; it != nextNodes.end(); it++)
758  {
759  size_t nbFi = gg.getNumberOfIncomingNeighbors(*it);
760  if (nbF == 0)
761  {
762  nbgg = *it;
763  break;
764  }
765  else
766  {
767  if (nbFi < nbF)
768  {
769  nbgg = *it;
770  nbF = nbFi;
771  }
772  }
773  }
774  }
775  else
776  nbgg = *it;
777 
778  // next orient edges from this node and catch neighbors
779  std::vector<Graph::NodeId> vL = gg.getIncomingNeighbors(nbgg);
780  for (auto& it2:vL)
781  {
782  switchNodes(nbgg, it2);
783  nextNodes.insert(it2);
784  }
785 
786  vL = gg.getOutgoingNeighbors(nbgg);
787  for (auto& it2:vL)
788  {
789  nextNodes.insert(it2);
790  }
791 
792  gg.deleteNode(nbgg);
793  nextNodes.erase(nbgg);
794  }
795 }
796 
798 {
799  nodeMustExist_(newRoot, "new root");
800  root_ = newRoot;
801 }
802 
804 {
805  return root_;
806 }
807 
809 {
810  return directed_;
811 }
812 
814 {
815  if (directed_)
816  return;
817  // save and clean the undirectedStructure
818  nodeStructureType undirectedStructure = nodeStructure_;
819  for (auto& it : nodeStructure_)
820  {
821  it.second = std::pair<std::map<Node, Edge>, std::map<Node, Edge> >();
822  }
823 
824  // copy each relation once, without the reciprocal link
825  // (first met, first kept)
826  // eg: A - B in undirected is represented as A->B and B->A
827  // in directed, becomes A->B only
828  std::set<pair<Node, Node> > alreadyConvertedRelations;
829  for (auto& currNodeRow : undirectedStructure)
830  {
831  Node nodeA = currNodeRow.first;
832 
833  for (auto& currRelation : currNodeRow.second.first)
834  {
835  Node nodeB = currRelation.first;
836  Edge edge = currRelation.second;
837  if (alreadyConvertedRelations.insert(pair<Node, Node>(min(nodeA, nodeB), max(nodeA, nodeB))).second)
838  linkInNodeStructure_(nodeA, nodeB, edge);
839  }
840  }
841  directed_ = true;
842  this->topologyHasChanged_();
843 }
844 
846 {
847  if (!directed_)
848  return;
850  throw Exception("Cannot make an undirected graph from a directed one containing reciprocal relations.");
851  // save and clean the undirectedStructure
852  nodeStructureType directedStructure = nodeStructure_;
853  for (auto& it : nodeStructure_)
854  {
855  it.second = std::pair<std::map<Node, Edge>, std::map<Node, Edge> >();
856  }
857 
858  // copy each relation twice, making the reciprocal link
859  // eg: A - B in directed is represented as A->B
860  // in undirected, becomes A->B and B->A
861  for (auto& currNodeRow : directedStructure)
862  {
863  Node nodeA = currNodeRow.first;
864  for (auto currRelation : currNodeRow.second.first)
865  {
866  Node nodeB = currRelation.first;
867  Edge edge = currRelation.second;
868  linkInNodeStructure_(nodeA, nodeB, edge);
869  linkInNodeStructure_(nodeB, nodeA, edge);
870  }
871  }
872  directed_ = false;
873  this->topologyHasChanged_();
874 }
875 
877 {
878  if (!directed_)
879  throw Exception("Cannot state reciprocal link in an undirected graph.");
880  std::set<pair<Node, Node> > alreadyMetRelations;
881  for (const auto& currNodeRow : nodeStructure_)
882  {
883  Node nodeA = currNodeRow.first;
884  for (const auto& currRelation : currNodeRow.second.first)
885  {
886  Node nodeB = currRelation.first;
887  if (!alreadyMetRelations.insert(pair<Node, Node>(min(nodeA, nodeB), max(nodeA, nodeB))).second)
888  return true;
889  }
890  }
891  return false;
892 }
893 
894 std::unique_ptr<Graph::EdgeIterator> GlobalGraph::allEdgesIterator()
895 {
896  return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::ALLGRAPHITER, false>(*this));
897 }
898 
899 std::unique_ptr<Graph::EdgeIterator> GlobalGraph::outgoingEdgesIterator(Graph::NodeId node)
900 {
901  return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::OUTGOINGNEIGHBORITER, false>(*this, node));
902 }
903 
904 std::unique_ptr<Graph::EdgeIterator> GlobalGraph::incomingEdgesIterator(Graph::NodeId node)
905 {
906  return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::INCOMINGNEIGHBORITER, false>(*this, node));
907 }
908 
909 std::unique_ptr<Graph::EdgeIterator> GlobalGraph::allEdgesIterator() const
910 {
911  return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::ALLGRAPHITER, true>(*this));
912 }
913 
914 std::unique_ptr<Graph::EdgeIterator> GlobalGraph::outgoingEdgesIterator(Graph::NodeId node) const
915 {
916  return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::OUTGOINGNEIGHBORITER, true>(*this, node));
917 }
918 
919 std::unique_ptr<Graph::EdgeIterator> GlobalGraph::incomingEdgesIterator(Graph::NodeId node) const
920 {
921  return std::unique_ptr<Graph::EdgeIterator>(new EdgesIteratorClass<Graph::INCOMINGNEIGHBORITER, true>(*this, node));
922 }
923 
925 {
926  nodeStructureType::const_iterator firstNodeFound = nodeStructure_.find(nodeA);
927  if (firstNodeFound == nodeStructure_.end())
928  throw (Exception("The fist node was not the origin of an edge."));
929  map<Node, Edge>::const_iterator secondNodeFound = firstNodeFound->second.first.find(nodeB);
930  if (secondNodeFound == firstNodeFound->second.first.end())
931  throw (Exception("The second node was not in a relation with the first one."));
932  return secondNodeFound->second;
933 }
934 
935 vector<Graph::EdgeId> GlobalGraph::getEdges(Graph::NodeId node) const
936 {
937  vector<Graph::EdgeId> result;
938  vector<Graph::EdgeId> edgesToInsert;
939  edgesToInsert = getEdges_(node, false);
940  result.insert(result.end(), edgesToInsert.begin(), edgesToInsert.end());
941  edgesToInsert = getEdges_(node, true);
942  result.insert(result.end(), edgesToInsert.begin(), edgesToInsert.end());
943  return result;
944 }
945 
946 void GlobalGraph::outputToDot(ostream& out, const std::string& name) const
947 {
948  out << (directed_ ? "digraph" : "graph") << " " << name << " {\n ";
949  set<pair<Node, Node> > alreadyFigured;
950  nodeToDot_(root_, out, alreadyFigured);
951  for (const auto& node: nodeStructure_)
952  {
953  if (node.first != root_)
954  nodeToDot_(node.first, out, alreadyFigured);
955  }
956  out << "\r}" << endl;
957 }
958 
959 void GlobalGraph::notifyDeletedEdges(const vector<Graph::EdgeId>& edgesToDelete) const
960 {
961  for (auto& currObserver : observers_)
962  {
963  currObserver->deletedEdgesUpdate(edgesToDelete);
964  }
965 }
966 
967 void GlobalGraph::notifyDeletedNodes(const vector<Graph::NodeId>& nodesToDelete) const
968 {
969  for (auto& currObserver : observers_)
970  {
971  currObserver->deletedNodesUpdate(nodesToDelete);
972  }
973 }
Exception base class. Overload exception constructor (to control the exceptions mechanism)....
Definition: Exceptions.h:59
Graph::EdgeId getAnyEdge(Graph::NodeId nodeA, Graph::NodeId nodeB) const
bool isDA() const
bool isTree() const
size_t getNumberOfIncomingNeighbors(Graph::NodeId node) const
std::unique_ptr< Graph::NodeIterator > outgoingNeighborNodesIterator(NodeId node)
std::vector< Graph::NodeId > getNeighbors(Graph::NodeId node) const
GlobalGraph & operator=(const GlobalGraph &gg)
Definition: GlobalGraph.cpp:75
bool isDirected() const
std::vector< Graph::EdgeId > getEdges(Graph::NodeId node) const
void fillListOfLeaves_(const Node &startingNode, std::vector< Node > &foundLeaves, const Node &originNode, unsigned int maxRecursions) const
void deleteNode(Graph::NodeId node)
void edgeMustExist_(const Edge &edge, std::string name="") const
Definition: GlobalGraph.cpp:95
bool nodesAreMetOnlyOnce_(const Node &node, std::set< Node > &metNodes, const Node &originNode) const
Graph::EdgeId link(Graph::NodeId nodeA, Graph::NodeId nodeB)
std::unique_ptr< EdgeIterator > allEdgesIterator()
size_t getNumberOfOutgoingNeighbors(Graph::NodeId node) const
std::set< NodeId > getSetOfAllLeaves() const
std::vector< Graph::NodeId > getLeavesFromNode(Graph::NodeId node, unsigned int maxDepth) const
bool containsReciprocalRelations() const
void nodeToDot_(const Node &node, std::ostream &out, std::set< std::pair< Node, Node > > &alreadyFigured) const
edgeStructureType edgeStructure_
Definition: GlobalGraph.h:115
Graph::NodeId Node
Definition: GlobalGraph.h:60
Graph::EdgeId getEdge(Graph::NodeId nodeA, Graph::NodeId nodeB) const
Graph::NodeId createNodeFromNode(Graph::NodeId origin)
void switchNodes(Graph::NodeId nodeA, Graph::NodeId nodeB)
void unregisterObserver(GraphObserver *observer)
std::unique_ptr< Graph::NodeIterator > incomingNeighborNodesIterator(NodeId node)
Graph::NodeId createNodeOnEdge(Graph::EdgeId edge)
std::pair< Graph::NodeId, Graph::NodeId > getNodes(Graph::EdgeId edge) const
size_t getNumberOfNodes() const
size_t getNumberOfNeighbors(Graph::NodeId node) const
Graph::NodeId getRoot() const
std::unique_ptr< EdgeIterator > incomingEdgesIterator(NodeId node)
std::vector< Edge > getEdges_(const Node &node, bool outgoing=true) const
std::vector< Graph::NodeId > getAllNodes() const
std::vector< Node > getNeighbors_(const Node &node, bool outgoing=true) const
std::map< Node, std::pair< std::map< Node, Edge >, std::map< Node, Edge > > > nodeStructureType
Definition: GlobalGraph.h:75
Graph::NodeId createNodeFromEdge(Graph::NodeId origin)
nodeStructureType nodeStructure_
Definition: GlobalGraph.h:109
std::vector< Graph::EdgeId > unlink(Graph::NodeId nodeA, Graph::NodeId nodeB)
void linkInEdgeStructure_(const Node &nodeA, const Node &nodeB, const Edge &edge)
std::set< GraphObserver * > observers_
Definition: GlobalGraph.h:93
bool isLeaf(Graph::NodeId node) const
size_t getNumberOfEdges() const
void linkInNodeStructure_(const Node &nodeA, const Node &nodeB, const Edge &edge)
std::vector< Graph::NodeId > getAllInnerNodes() const
std::unique_ptr< Graph::NodeIterator > allNodesIterator()
std::vector< Graph::NodeId > getIncomingNeighbors(Graph::NodeId node) const
Graph::NodeId getTop(Graph::EdgeId edge) const
Edge unlinkInNodeStructure_(const Node &nodeA, const Node &nodeB)
void unlinkInEdgeStructure_(const Edge &edge)
std::vector< Graph::EdgeId > getIncomingEdges(Graph::NodeId node) const
void isolate_(Node &node)
std::unique_ptr< EdgeIterator > outgoingEdgesIterator(NodeId node)
void registerObserver(GraphObserver *observer)
virtual void topologyHasChanged_() const
Definition: GlobalGraph.h:126
std::vector< Graph::EdgeId > getOutgoingEdges(Graph::NodeId node) const
Graph::EdgeId Edge
Definition: GlobalGraph.h:61
void outputToDot(std::ostream &out, const std::string &name) const
std::map< Edge, std::pair< Node, Node > > edgeStructureType
Definition: GlobalGraph.h:82
size_t getDegree(Graph::NodeId node) const
std::vector< Graph::EdgeId > getAllEdges() const
std::vector< Graph::NodeId > getAllLeaves() const
void notifyDeletedNodes(const std::vector< Graph::NodeId > &nodesToDelete) const
Graph::NodeId createNode()
GlobalGraph(bool directed=false)
Definition: GlobalGraph.cpp:54
void nodeMustExist_(const Node &node, std::string name="") const
Definition: GlobalGraph.cpp:89
Graph::NodeId getBottom(Graph::EdgeId edge) const
std::vector< Graph::NodeId > getOutgoingNeighbors(Graph::NodeId node) const
void setRoot(Graph::NodeId newRoot)
void notifyDeletedEdges(const std::vector< Graph::EdgeId > &edgesToDelete) const
Defines a Graph Observer. It is a template which follows (subscribed to) a Graph. The graph and the g...
Definition: GraphObserver.h:69
unsigned int NodeId
Definition: Graph.h:66
unsigned int EdgeId
Definition: Graph.h:67
std::string toString(T t)
General template method to convert to a string.
Definition: TextTools.h:153