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