Vuo  2.0.0
VuoDirectedAcyclicGraph.cc
Go to the documentation of this file.
1 
11 #include <sstream>
12 
13 VuoDirectedAcyclicGraph::Vertex::~Vertex(void)
14 {
15 }
16 
21 {
22  cycleVerticesCacheReady = false;
23 }
24 
29 {
30  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
31  delete i->first;
32 }
33 
40 {
41  edges[vertex];
42 }
43 
48 {
49  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
50  {
51  for (vector<Vertex *>::iterator j = i->second.begin(); j != i->second.end(); )
52  {
53  if (*j == vertex)
54  j = i->second.erase(j);
55  else
56  ++j;
57  }
58  }
59 
60  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); )
61  {
62  if (i->first == vertex)
63  edges.erase(i++);
64  else
65  ++i;
66  }
67 
68  delete vertex;
69 
70  downstreamVerticesCache.clear();
71  upstreamVerticesCache.clear();
72  cycleVerticesCacheReady = false;
73 }
74 
79 {
80  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
81  if (i->first->key() == key)
82  return i->first;
83 
84  return NULL;
85 }
86 
93 void VuoDirectedAcyclicGraph::addEdge(Vertex *fromVertex, Vertex *toVertex)
94 {
95  if (find(edges[fromVertex].begin(), edges[fromVertex].end(), toVertex) == edges[fromVertex].end())
96  {
97  edges[fromVertex].push_back(toVertex);
98  edges[toVertex];
99  }
100 
101  downstreamVerticesCache.clear();
102  upstreamVerticesCache.clear();
103  cycleVerticesCacheReady = false;
104 }
105 
112 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getDownstreamVertices(Vertex *vertex)
113 {
114  map< Vertex *, vector<Vertex *> >::iterator iter = downstreamVerticesCache.find(vertex);
115  if (iter != downstreamVerticesCache.end())
116  return iter->second;
117 
118  set<Vertex *> unused;
119  vector<Vertex *> downstreamVertices = getReachableVertices(vertex, edges, unused);
120 
121  downstreamVerticesCache[vertex] = downstreamVertices;
122 
123  return downstreamVertices;
124 }
125 
132 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getUpstreamVertices(Vertex *vertex)
133 {
134  map< Vertex *, vector<Vertex *> >::iterator iter = upstreamVerticesCache.find(vertex);
135  if (iter != upstreamVerticesCache.end())
136  return iter->second;
137 
138  map< Vertex *, vector<Vertex *> > backEdges;
139  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
140  {
141  for (vector<Vertex *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
142  if (find(backEdges[*j].begin(), backEdges[*j].end(), i->first) == backEdges[*j].end())
143  backEdges[*j].push_back(i->first);
144 
145  backEdges[i->first];
146  }
147 
148  set<Vertex *> unused;
149  vector<Vertex *> upstreamVertices = getReachableVertices(vertex, backEdges, unused);
150 
151  upstreamVerticesCache[vertex] = upstreamVertices;
152 
153  return upstreamVertices;
154 }
155 
159 set<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getCycleVertices(void)
160 {
161  if (cycleVerticesCacheReady)
162  return cycleVerticesCache;
163 
164  set<Vertex *> cycleVertices;
165  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
166  {
167  set<Vertex *> c;
168  getReachableVertices(i->first, edges, c);
169  cycleVertices.insert(c.begin(), c.end());
170  }
171 
172  cycleVerticesCacheReady = true;
173  cycleVerticesCache = cycleVertices;
174 
175  return cycleVertices;
176 }
177 
181 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getReachableVertices(Vertex *vertex,
182  const map< Vertex *, vector<Vertex *> > &edges,
183  set<Vertex *> &cycleVertices)
184 {
185  map<Vertex *, vector<Vertex *> > reachableVertices;
186 
187  if (edges.find(vertex) == edges.end())
188  return vector<Vertex *>();
189 
190  list<Vertex *> toVisit; // Used as a stack, except for a call to find().
191  toVisit.push_back(vertex);
192 
193  while (! toVisit.empty())
194  {
195  // Visit the vertex at the top of the stack.
196  Vertex *currVertex = toVisit.back();
197 
198  set<Vertex *> nextVertices;
199  bool areCurrVerticesComplete = true;
200 
201  // Consider each vertex immediately downstream of this vertex.
202  map< Vertex *, vector<Vertex *> >::const_iterator edgesIter = edges.find(currVertex);
203  if (edgesIter != edges.end())
204  {
205  for (vector<Vertex *>::const_iterator j = edgesIter->second.begin(); j != edgesIter->second.end(); ++j)
206  {
207  Vertex *nextVertex = *j;
208  nextVertices.insert(nextVertex);
209 
210  map<Vertex *, vector<Vertex *> >::iterator nextNextVerticesIter = reachableVertices.find(nextVertex);
211  if (nextNextVerticesIter != reachableVertices.end())
212  {
213  // The downstream vertex has already been visited, so add its downstream vertices to this vertex's.
214  nextVertices.insert( nextNextVerticesIter->second.begin(), nextNextVerticesIter->second.end() );
215  }
216  else
217  {
218  if (find(toVisit.begin(), toVisit.end(), nextVertex) != toVisit.end())
219  {
220  // The downstream vertex is already on the stack, so there's a cycle.
221  cycleVertices.insert(nextVertex);
222  }
223  else
224  {
225  // The downstream vertex has not yet been visited, so add it to the stack.
226  toVisit.push_back(nextVertex);
227  areCurrVerticesComplete = false;
228  }
229  }
230  }
231  }
232 
233  if (areCurrVerticesComplete)
234  {
235  reachableVertices[currVertex].insert(reachableVertices[currVertex].end(), nextVertices.begin(), nextVertices.end());
236  toVisit.pop_back();
237  }
238  }
239 
240  return reachableVertices[vertex];
241 }
242 
246 string VuoDirectedAcyclicGraph::toString(bool showVertexPointers)
247 {
248  ostringstream ss;
249 
250  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
251  {
252  ss << i->first->key();
253  if (showVertexPointers)
254  ss << " (" << i->first << ")";
255  ss << " ->";
256 
257  for (Vertex *vertex : i->second)
258  {
259  ss << " " << vertex->key();
260  if (showVertexPointers)
261  ss << " (" << vertex << ")";
262  }
263 
264  ss << "\n";
265  }
266 
267  return ss.str();
268 }
269 
273 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::findVertex(const string &key)
274 {
275  vector<VuoDirectedAcyclicGraph::Vertex *> foundVertices;
276 
277  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator i = edges.begin(); i != edges.end(); ++i)
278  {
279  VuoDirectedAcyclicGraph::Vertex *vertex = i->first->findVertex(key);
280  if (vertex)
281  foundVertices.push_back(vertex);
282  }
283 
284  return foundVertices;
285 }
286 
293 {
294  if (find(edges[fromGraph].begin(), edges[fromGraph].end(), toGraph) == edges[fromGraph].end())
295  {
296  edges[fromGraph].push_back(toGraph);
297  edges[toGraph];
298  }
299 }
300 
312 {
313  return getReachableVertices(vertex, edges, true);
314 }
315 
326 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::getUpstreamVertices(VuoDirectedAcyclicGraph::Vertex *vertex)
327 {
328  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> > backEdges;
329  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
330  {
331  for (vector<VuoDirectedAcyclicGraph *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
332  if (find(backEdges[*j].begin(), backEdges[*j].end(), i->first) == backEdges[*j].end())
333  backEdges[*j].push_back(i->first);
334 
335  backEdges[i->first];
336  }
337 
338  return getReachableVertices(vertex, backEdges, false);
339 }
340 
344 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::getReachableVertices(VuoDirectedAcyclicGraph::Vertex *vertex,
345  const map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> > &edges,
346  bool isDownstream)
347 {
348  vector<VuoDirectedAcyclicGraph::Vertex *> reachableVertices;
349 
350  VuoDirectedAcyclicGraph *containingGraph = NULL;
351  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator i = edges.begin(); i != edges.end(); ++i)
352  {
353  if (i->first->edges.find(vertex) != i->first->edges.end())
354  {
355  containingGraph = i->first;
356  break;
357  }
358  }
359 
360  if (! containingGraph)
361  return reachableVertices;
362 
363  list< pair< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> > > toVisit;
364  toVisit.push_back( make_pair(containingGraph, vector<VuoDirectedAcyclicGraph::Vertex *>(1, vertex)) );
365 
366  while (! toVisit.empty())
367  {
368  VuoDirectedAcyclicGraph *currGraph = toVisit.front().first;
369  vector<VuoDirectedAcyclicGraph::Vertex *> currVertices = toVisit.front().second;
370  toVisit.pop_front();
371 
372  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator edgesIter = edges.find(currGraph);
373  if (edgesIter != edges.end())
374  {
375  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> > moreToVisit;
376 
377  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator i = currVertices.begin(); i != currVertices.end(); ++i)
378  {
379  VuoDirectedAcyclicGraph::Vertex *currVertex = *i;
380  vector<VuoDirectedAcyclicGraph::Vertex *> currReachableVertices = (isDownstream ?
381  currGraph->getDownstreamVertices(currVertex) :
382  currGraph->getUpstreamVertices(currVertex));
383 
384  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = currReachableVertices.begin(); j != currReachableVertices.end(); ++j)
385  {
386  VuoDirectedAcyclicGraph::Vertex *currReachableVertex = *j;
387 
388  if (find(reachableVertices.begin(), reachableVertices.end(), currReachableVertex) == reachableVertices.end())
389  reachableVertices.push_back(currReachableVertex);
390  }
391 
392  vector<VuoDirectedAcyclicGraph::Vertex *> candidateVertices;
393  candidateVertices.push_back(currVertex);
394  candidateVertices.insert(candidateVertices.end(), currReachableVertices.begin(), currReachableVertices.end());
395 
396  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = candidateVertices.begin(); j != candidateVertices.end(); ++j)
397  {
398  VuoDirectedAcyclicGraph::Vertex *candidateVertex = *j;
399 
400  for (vector<VuoDirectedAcyclicGraph *>::const_iterator k = edgesIter->second.begin(); k != edgesIter->second.end(); ++k)
401  {
402  VuoDirectedAcyclicGraph *otherGraph = *k;
403 
404  VuoDirectedAcyclicGraph::Vertex *matchingVertexInOtherGraph = otherGraph->findVertex(candidateVertex->key());
405  if (matchingVertexInOtherGraph)
406  {
407  moreToVisit[otherGraph].push_back(matchingVertexInOtherGraph);
408 
409  if (find(reachableVertices.begin(), reachableVertices.end(), matchingVertexInOtherGraph) == reachableVertices.end())
410  reachableVertices.push_back(matchingVertexInOtherGraph);
411  }
412  }
413  }
414  }
415 
416  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> >::iterator i = moreToVisit.begin(); i != moreToVisit.end(); ++i)
417  toVisit.push_back( make_pair(i->first, i->second) );
418  }
419  }
420 
421  return reachableVertices;
422 }
423 
427 string VuoDirectedAcyclicNetwork::toString(bool showVertexAddresses)
428 {
429  ostringstream ss;
430 
431  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
432  {
433  ss << i->first << " ->";
434  for (VuoDirectedAcyclicGraph *graph : i->second)
435  ss << " " << graph;
436  ss << "\n";
437  }
438 
439  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
440  {
441  string graphString = i->first->toString(showVertexAddresses);
442  if (! graphString.empty())
443  ss << "\n" << i->first << ":\n" << graphString << "\n";
444  }
445 
446  return ss.str();
447 }