AudioManager  7.5.11
Native Application Runtime Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
CAmGraph.h
Go to the documentation of this file.
1 
24 #ifndef GRAPH_H
25 #define GRAPH_H
26 
27 #include <functional>
28 #include <iostream>
29 #include <vector>
30 #include <map>
31 #include <list>
32 #include <stack>
33 #include <queue>
34 #include <algorithm>
35 #include <limits.h>
36 #include <iomanip>
37 #include <cstring>
38 #include <set>
39 
40 
41 namespace am
42 {
46  typedef enum:uint8_t
47  {
48  GES_NOT_VISITED,
50  GES_VISITED
52 
56  typedef enum:uint8_t
57  {
58  GRAPH_PATH_START, //at the beginning of the path
59  GRAPH_PATH_MIDDLE, //in middle of the path
60  GRAPH_PATH_END //at the end of the path
62 
63 
68  {
69  am_GraphElementStatus_e mStatus;
70  public:
71  CAmGraphElement(): mStatus(GES_NOT_VISITED) { };
76  void setStatus(const am_GraphElementStatus_e s) { mStatus = s; };
77  am_GraphElementStatus_e getStatus() const { return mStatus; };
78  };
79 
80  template <class NodeData> class CAmNode : public CAmGraphElement
81  {
82  uint16_t mIndex;
83  NodeData mData;
84  public:
85  CAmNode(const NodeData & in):CAmGraphElement(), mIndex(0), mData(in) { };
86  CAmNode(const NodeData & in, const uint16_t index):CAmGraphElement(), mIndex(index), mData(in) { };
87  ~CAmNode() { };
91  NodeData & getData() { return mData; }
92  uint16_t getIndex() const { return mIndex; }
93  void setIndex(uint16_t index) { mIndex = index; }
94  };
95 
96  template <class NodeData, class VertexData> class CAmVertex : public CAmGraphElement
97  {
98  CAmNode<NodeData>* mpNode;
99  VertexData mVertexData;
100  uint16_t mWeight;
101  public:
102  CAmVertex(CAmNode<NodeData> *aNode, const VertexData & vertexData, const uint16_t weight):CAmGraphElement(),
103  mpNode(aNode), mVertexData(vertexData), mWeight(weight) { };
104  ~CAmVertex() { };
108  CAmNode<NodeData>* getNode() const { return mpNode; }
109  VertexData & getData() { return mVertexData; }
110  uint16_t getWeight() const { return mWeight; }
111  void setWeight(const uint16_t weight) { mWeight=weight; }
112  };
113 
118  template <class T, class V> class CAmGraph
119  {
120  typedef typename std::vector<CAmNode<T>*> CAmListNodePtrs;
121  typedef typename std::list<CAmVertex<T,V>> CAmListVertices;
122  typedef typename std::list<CAmVertex<T,V>>::iterator CAmListVerticesItr;
123  typedef typename std::list<CAmVertex<T,V>>::const_iterator CAmListVerticesItrConst;
124  typedef typename std::list<CAmListVertices> CAmNodesAdjList;
125  typedef typename std::list<CAmListVertices>::iterator CAmNodesAdjListItr;
126  typedef typename std::list<CAmListVertices>::const_iterator CAmNodesAdjListItrConst;
127  typedef typename std::list<CAmNode<T>> CAmListNodes;
128  typedef typename std::list<CAmNode<T>>::iterator CAmListNodesItr;
129  typedef typename std::list<CAmNode<T>>::const_iterator CAmListNodesItrConst;
130  typedef typename std::vector<CAmNode<T>*> CAmNodeReferenceList;
131  typedef typename std::vector<CAmListVertices*> CAmVertexReferenceList;
132 
133  CAmListNodes mStoreNodes;
134  CAmNodesAdjList mStoreAdjList;
135  CAmNodeReferenceList mPointersNodes;
136  CAmVertexReferenceList mPointersAdjList;
137  bool mIsCyclic;
138 
144  void updateIndexes(const int16_t fromIndex)
145  {
146  if( fromIndex<mPointersNodes.size() )
147  {
148  for(auto iter = mPointersNodes.begin()+fromIndex; iter!=mPointersNodes.end(); iter++)
149  (*iter)->setIndex(iter-mPointersNodes.begin());
150  }
151  }
152 
153 
162  typedef uint16_t vertex_t;
163  typedef uint16_t weight_t;
164 
165  void findShortestsPathsFromNode(const CAmNode<T> & node, std::vector<weight_t> &minDistance, std::vector<CAmNode<T> *> &previous)
166  {
167  typename CAmListVertices::const_iterator nIter;
168  CAmListVertices * neighbors;
169  weight_t dist, weight, v, distanceThroughU;
170  CAmNode<T>* pU;
171  CAmVertex<T,V> * pVertex;
172  CAmNode<T> *pDstNode;
173 
174  size_t n = mPointersAdjList.size();
175  std::set<std::pair<weight_t, CAmNode<T>*> > vertexQueue;
176 
177  minDistance.clear();
178  minDistance.resize(n, std::numeric_limits<weight_t>::max());
179  minDistance[node.getIndex()] = 0;
180  previous.clear();
181  previous.resize(n, NULL);
182 
183  vertexQueue.insert(std::make_pair(minDistance[node.getIndex()], (CAmNode<T>*)&node));
184 
185  while (!vertexQueue.empty())
186  {
187  dist = vertexQueue.begin()->first;
188  pU = vertexQueue.begin()->second;
189  vertexQueue.erase(vertexQueue.begin());
190  //todo: terminate the search at this position if you want the path to a target node ( if(pU==target)break; )
191 
192  // Visit each edge exiting u
193  neighbors = mPointersAdjList[pU->getIndex()];
194  nIter = neighbors->begin();
195  for (; nIter != neighbors->end(); nIter++)
196  {
197  pVertex = (CAmVertex<T,V> *)&(*nIter);
198  pDstNode = pVertex->getNode();
199 
200  v = pDstNode->getIndex();
201  weight = pVertex->getWeight();
202  distanceThroughU = dist + weight;
203  if (distanceThroughU < minDistance[pDstNode->getIndex()])
204  {
205  vertexQueue.erase(std::make_pair(minDistance[v], pDstNode));
206  minDistance[v] = distanceThroughU;
207  previous[v] = pU;
208  vertexQueue.insert(std::make_pair(minDistance[v], pDstNode));
209  }
210  }
211  }
212  }
213 
221  void constructShortestPathTo(const CAmNode<T> & node, const std::vector<CAmNode<T> *> &previous, CAmListNodePtrs & result)
222  {
223  CAmNode<T> * vertex = (CAmNode<T> *)&node;
224 
225  int i=0;
226  while ( (vertex = previous[vertex->getIndex()])!=NULL )
227  {
228  result.insert(result.begin(), vertex);
229  i++;
230  }
231  if(i)
232  result.push_back((CAmNode<T> *)&node);
233  }
234 
243  void constructShortestPathTo(const CAmNode<T> & node, const std::vector<CAmNode<T> *> &previous, std::function<void(const am_GraphPathPosition_e pos, CAmNode<T> &)> cb)
244  {
245  CAmNode<T> * vertex = (CAmNode<T> *)&node;
246  CAmNode<T> * prev = vertex;
247  int i=0;
248  while ( (vertex = previous[vertex->getIndex()])!=NULL )
249  {
250  cb(i==0?GRAPH_PATH_START:GRAPH_PATH_MIDDLE, *prev);
251  prev = vertex;
252  i++;
253  }
254  if(i)
255  cb(GRAPH_PATH_END, *prev);
256  }
257 
266  void goThroughAllPaths(const CAmNode<T> & dst, std::vector<CAmNode<T>*> & visited, std::function<void(const CAmNodeReferenceList & path)> cb)
267  {
268  CAmListVertices * nodes = mPointersAdjList[visited.back()->getIndex()];
269  CAmListVerticesItrConst vItr(nodes->begin());
270  for (; vItr != nodes->end(); ++vItr)
271  {
272  const CAmVertex<T,V> & vertex = (*vItr);
273  if(vertex.getNode()->getStatus()!=GES_NOT_VISITED)
274  continue;
275  if (vertex.getNode()==&dst)
276  {
277  vertex.getNode()->setStatus(GES_IN_PROGRESS);
278  visited.push_back(vertex.getNode());
279  //notify observer
280  cb(visited);
281  //remove last node from the list
282  auto last = visited.end()-1;
283  visited.erase(last);
284  vertex.getNode()->setStatus(GES_NOT_VISITED);
285  break;
286  }
287  }
288  vItr = nodes->begin();
289  //bfs like loop
290  for (; vItr != nodes->end(); ++vItr)
291  {
292  const CAmVertex<T,V> & vertex = (*vItr);
293  if(vertex.getNode()->getStatus()!=GES_NOT_VISITED||vertex.getNode()==&dst)
294  continue;
295  vertex.getNode()->setStatus(GES_IN_PROGRESS);
296  visited.push_back(vertex.getNode());
297  goThroughAllPaths(dst, visited, cb);
298  //remove last node from the list
299  auto last = visited.end()-1;
300  visited.erase(last);
301  vertex.getNode()->setStatus(GES_NOT_VISITED);
302  }
303  }
304 
305  public:
306  explicit CAmGraph(const std::vector<T> &v):mStoreNodes(), mStoreAdjList(), mPointersNodes(), mPointersAdjList()
307  {
308  typedef typename std::vector<T>::const_iterator inItr;
309  inItr itr(v.begin());
310 
311  for (; itr != v.end(); ++itr)
312  {
313  addNode(*itr);
314  }
315 
316  mIsCyclic = false;
317  };
318  CAmGraph():mStoreNodes(), mStoreAdjList(), mPointersNodes(), mPointersAdjList(), mIsCyclic(false){};
320 
321  const CAmListNodes & getNodes() const
322  {
323  return mStoreNodes;
324  }
325 
326  const CAmVertexReferenceList & getVertexList() const
327  {
328  return mPointersAdjList;
329  }
330 
335  const CAmNode<T>* findNode(const T & in)
336  {
337  typename CAmNodeReferenceList::const_iterator itr (mPointersNodes.begin());
338 
339  for (; itr != mPointersNodes.end(); ++itr)
340  {
341  if ((*itr)->getData() == in) {
342  return (*itr);
343  }
344  }
345  return NULL;
346  }
347 
352  const CAmVertex<T,V>* findVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2) const
353  {
354  const CAmNode<T> * pEdge2 = (CAmNode<T> *)&edge2;
355  const CAmListVertices * list = mPointersAdjList[edge1.getIndex()];
356  CAmListVerticesItrConst result = std::find_if(list->begin(), list->end(), [&](const CAmVertex<T,V> & refObject){
357  return refObject.getNode()==pEdge2;
358  });
359  if(result!=list->end())
360  return (CAmVertex<T,V>*)&(*result);
361 
362  return NULL;
363  }
364 
365  bool hasCycles() const
366  {
367  return mIsCyclic;
368  }
369 
370 
375  CAmNode<T> & addNode(const T & in)
376  {
377  size_t index = mStoreNodes.size();
378  mStoreNodes.emplace_back(in, index);
379  mStoreAdjList.emplace_back();
380  mPointersNodes.push_back(&mStoreNodes.back());
381  mPointersAdjList.push_back(&mStoreAdjList.back());
382  return mStoreNodes.back();
383  }
384 
388  void removeVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2)
389  {
390  const CAmListVertices * list = mPointersAdjList[edge1.getIndex()];
391  CAmListVerticesItr iter = std::find_if(list->begin(), list->end(), [&edge2](const CAmVertex<T,V> & refVertex){
392  return (refVertex.getNode()==&edge2);
393  });
394  if(iter!=list->end())
395  list->erase(iter);
396  }
397 
402  {
403  auto comparator = [&node](const CAmVertex<T,V> & refVertex){
404  return (refVertex.getNode()==&node);
405  };
406  auto itr = mPointersAdjList.begin();
407  for(;itr!=mPointersAdjList.end();itr++)
408  {
409  CAmListVertices * vertices = *itr;
410  auto iterVert = std::find_if(vertices->begin(), vertices->end(), comparator);
411  if(iterVert!=vertices->end())
412  vertices->erase(iterVert);
413  }
414  }
415 
419  void removeNode(const T & in)
420  {
421  CAmNode<T> * node = findNode(in);
422  if(node!=NULL)
423  removeNode(*node);
424  }
425 
429  void removeNode(const CAmNode<T> & node)
430  {
431  uint16_t index = node.getIndex();
433  mPointersAdjList.erase(mPointersAdjList.begin()+index);
434  mPointersNodes.erase(mPointersNodes.begin()+index);
435  auto iter = std::find_if(mStoreNodes.begin(), mStoreNodes.end(), [&node](const CAmNode<T> & otherNode){
436  return &otherNode==&node;
437  });
438  if(iter!=mStoreNodes.end())
439  mStoreNodes.erase(iter);
440  updateIndexes(index);
441  }
442 
446  void connectNodes(const CAmNode<T> & first, const CAmNode<T> & last, const V & vertexData, const int16_t weight = 1)
447  {
448  CAmListVertices * list = mPointersAdjList[first.getIndex()];
449  CAmNode<T> * node = mPointersNodes[last.getIndex()];
450  list->emplace_back(node, vertexData, weight);
451  }
452 
457  bool isAnyVertex(const CAmNode<T> & edge1, const CAmNode<T> & edge2) const
458  {
459  return findVertex(edge1, edge2)!=NULL;
460  }
461 
465  void reset()
466  {
467  // set all nodes to GES_NOT_VISITED
468  std::for_each(mPointersNodes.begin(), mPointersNodes.end(), [](CAmNode<T> * refNode){
469  if(refNode->getStatus()!= GES_NOT_VISITED)
470  refNode->setStatus(GES_NOT_VISITED);
471  });
472  // set all vertices to GES_NOT_VISITED
473  auto action = [](CAmVertex<T,V> & refVertex){
474  if(refVertex.getStatus()!= GES_NOT_VISITED)
475  refVertex.setStatus(GES_NOT_VISITED);
476  };
477  auto itr1(mPointersAdjList.begin());
478  for (; itr1 != mPointersAdjList.end(); ++itr1)
479  {
480  CAmListVertices * vertices = *itr1;
481  std::for_each(vertices->begin(), vertices->end(), action);
482  }
483  }
484 
488  void clear()
489  {
490  mStoreNodes.clear();
491  mStoreAdjList.clear();
492  mPointersAdjList.clear();
493  mPointersNodes.clear();
494  mPointersAdjList.clear();
495  }
496 
500  void trace(std::function<void(const CAmNode<T> &, const std::vector<CAmVertex<T,V>*> &)> cb)
501  {
502  std::for_each(mPointersNodes.begin(), mPointersNodes.end(), [&](CAmNode<T> * refNode){
503  CAmListVertices * vertices = this->mPointersAdjList[refNode->getIndex()];
504  std::vector<CAmVertex<T,V>*> list;
505  std::for_each(vertices->begin(), vertices->end(), [&list](CAmVertex<T,V> & refVertex){
506  list.push_back(&refVertex);
507  });
508  cb(*refNode, list);
509  });
510  }
511 
519  void getShortestPath(const CAmNode<T> & source, const CAmListNodePtrs & listTargets, std::vector<CAmListNodePtrs> & resultPath )
520  {
521  const size_t numberOfNodes = mPointersNodes.size();
522  if(numberOfNodes==0)
523  return;
524 
525  std::vector<weight_t> min_distance;
526  std::vector<CAmNode<T>*> previous;
527  findShortestsPathsFromNode(source, min_distance, previous);
528 
529  for(auto it=listTargets.begin(); it!=listTargets.end(); it++)
530  {
531  CAmNode<T> *node = *it;
532  resultPath.emplace_back();
533  CAmListNodePtrs & path = resultPath.back();
534  constructShortestPathTo(*node, previous, path);
535  if(path.empty())
536  {
537  typename std::vector<CAmListNodePtrs>::iterator iter = resultPath.end();
538  resultPath.erase(--iter);
539  }
540  }
541  }
542 
550  void getShortestPath(const CAmNode<T> & source, const CAmNode<T> & destination, CAmListNodePtrs & resultPath )
551  {
552  const size_t numberOfNodes = mPointersNodes.size();
553  if(numberOfNodes==0)
554  return;
555  std::vector<weight_t> min_distance;
556  std::vector<CAmNode<T>*> previous;
557  findShortestsPathsFromNode(source, min_distance, previous);
558  constructShortestPathTo(destination, previous, resultPath);
559  }
560 
569  void getShortestPath(const CAmNode<T> & source,
570  const CAmListNodePtrs & listTargets,
571  std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> cb )
572  {
573  const size_t numberOfNodes = mPointersNodes.size();
574  if(numberOfNodes==0)
575  return;
576 
577  std::vector<weight_t> min_distance;
578  std::vector<CAmNode<T>*> previous;
579  findShortestsPathsFromNode(source, min_distance, previous);
580 
581  for(auto it=listTargets.begin(); it!=listTargets.end(); it++)
582  {
583  CAmNode<T>* node = *it;
584  constructShortestPathTo(*node, previous, cb);
585  }
586  }
587 
596  void getShortestPath(const CAmNode<T> & source,
597  const CAmNode<T> & destination,
598  std::function<void(const am_GraphPathPosition_e, CAmNode<T> &)> cb )
599  {
600  const size_t numberOfNodes = mPointersNodes.size();
601  if(numberOfNodes==0)
602  return;
603 
604  std::vector<weight_t> min_distance;
605  std::vector<CAmNode<T>*> previous;
606  findShortestsPathsFromNode(source, min_distance, previous);
607  constructShortestPathTo(destination, previous, cb);
608  }
609 
618  void getAllPaths(const CAmNode<T> & src, const CAmNode<T> & dst, std::function<void(const CAmNodeReferenceList & path)> cb)
619  {
620  CAmNodeReferenceList visited;
621  visited.push_back((CAmNode<T>*)&src);
622  ((CAmNode<T>*)&src)->setStatus(GES_VISITED);
623  goThroughAllPaths(dst, visited, cb);
624  reset();
625  }
626  };
627 
628 }
629 
630 #endif
void removeNode(const CAmNode< T > &node)
Removes the given node from the graph .
Definition: CAmGraph.h:429
void setWeight(const uint16_t weight)
Definition: CAmGraph.h:111
const CAmNode< T > * findNode(const T &in)
Returns pointer to a node which data is equal to the given.
Definition: CAmGraph.h:335
bool hasCycles() const
Definition: CAmGraph.h:365
void getShortestPath(const CAmNode< T > &source, const CAmListNodePtrs &listTargets, std::vector< CAmListNodePtrs > &resultPath)
Finds the shortest path from given node to all nodes in listTargets.
Definition: CAmGraph.h:519
void connectNodes(const CAmNode< T > &first, const CAmNode< T > &last, const V &vertexData, const int16_t weight=1)
Connect first with last node and set user data and weight to the vertex.
Definition: CAmGraph.h:446
NodeData & getData()
Setters and getters.
Definition: CAmGraph.h:91
const CAmVertex< T, V > * findVertex(const CAmNode< T > &edge1, const CAmNode< T > &edge2) const
Returns pointer to a vertex which two ends are equal to the given nodes.
Definition: CAmGraph.h:352
CAmNode< T > & addNode(const T &in)
Adds a new node to the graph with given user data.
Definition: CAmGraph.h:375
Class representing a directed or undirected graph.
Definition: CAmGraph.h:118
CAmVertex(CAmNode< NodeData > *aNode, const VertexData &vertexData, const uint16_t weight)
Definition: CAmGraph.h:102
bool isAnyVertex(const CAmNode< T > &edge1, const CAmNode< T > &edge2) const
Exists any vertex with two given ends.
Definition: CAmGraph.h:457
CAmGraph(const std::vector< T > &v)
Definition: CAmGraph.h:306
void setStatus(const am_GraphElementStatus_e s)
Setter and getter.
Definition: CAmGraph.h:76
VertexData & getData()
Definition: CAmGraph.h:109
CAmNode< NodeData > * getNode() const
Setters and getters.
Definition: CAmGraph.h:108
typedef GES_IN_PROGRESS
Definition: CAmGraph.h:48
GRAPH_PATH_END am_GraphPathPosition_e
Definition: CAmGraph.h:58
am_GraphElementStatus_e getStatus() const
Definition: CAmGraph.h:77
GES_VISITED am_GraphElementStatus_e
Definition: CAmGraph.h:48
CAmNode(const NodeData &in)
Definition: CAmGraph.h:85
This class is base class for nodes and vertices.
Definition: CAmGraph.h:67
void trace(std::function< void(const CAmNode< T > &, const std::vector< CAmVertex< T, V > * > &)> cb)
Goes through all nodes and vertices and calls the callback.
Definition: CAmGraph.h:500
void getShortestPath(const CAmNode< T > &source, const CAmListNodePtrs &listTargets, std::function< void(const am_GraphPathPosition_e, CAmNode< T > &)> cb)
Finds the shortest path from given node to all nodes in listTargets.
Definition: CAmGraph.h:569
const CAmListNodes & getNodes() const
Definition: CAmGraph.h:321
void getShortestPath(const CAmNode< T > &source, const CAmNode< T > &destination, std::function< void(const am_GraphPathPosition_e, CAmNode< T > &)> cb)
Finds the shortest path between two given nodes.
Definition: CAmGraph.h:596
typedef GRAPH_PATH_MIDDLE
Definition: CAmGraph.h:58
void clear()
Clears all nodes and vertices.
Definition: CAmGraph.h:488
void reset()
Sets the status of all nodes and vertices to GES_NOT_VISITED.
Definition: CAmGraph.h:465
void removeNode(const T &in)
Removes a node with given user data .
Definition: CAmGraph.h:419
uint16_t getIndex() const
Definition: CAmGraph.h:92
void getAllPaths(const CAmNode< T > &src, const CAmNode< T > &dst, std::function< void(const CAmNodeReferenceList &path)> cb)
Finds all possible paths between two given nodes.
Definition: CAmGraph.h:618
uint16_t getWeight() const
Definition: CAmGraph.h:110
void getShortestPath(const CAmNode< T > &source, const CAmNode< T > &destination, CAmListNodePtrs &resultPath)
Finds the shortest path between two nodes.
Definition: CAmGraph.h:550
const CAmVertexReferenceList & getVertexList() const
Definition: CAmGraph.h:326
void removeVertex(const CAmNode< T > &edge1, const CAmNode< T > &edge2)
Removes a vertex with two ends equal to the given nodes .
Definition: CAmGraph.h:388
void removeAllVerticesToNode(const CAmNode< T > &node)
Removes all vertices to given node .
Definition: CAmGraph.h:401
void setIndex(uint16_t index)
Definition: CAmGraph.h:93
CAmNode(const NodeData &in, const uint16_t index)
Definition: CAmGraph.h:86