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  longestDownstreamPathsCache.clear();
74 }
75 
80 {
81  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
82  if (i->first->key() == key)
83  return i->first;
84 
85  return NULL;
86 }
87 
94 void VuoDirectedAcyclicGraph::addEdge(Vertex *fromVertex, Vertex *toVertex)
95 {
96  if (find(edges[fromVertex].begin(), edges[fromVertex].end(), toVertex) == edges[fromVertex].end())
97  {
98  edges[fromVertex].push_back(toVertex);
99  edges[toVertex];
100  }
101 
102  downstreamVerticesCache.clear();
103  upstreamVerticesCache.clear();
104  cycleVerticesCacheReady = false;
105  longestDownstreamPathsCache.clear();
106 }
107 
114 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getDownstreamVertices(Vertex *vertex)
115 {
116  map< Vertex *, vector<Vertex *> >::iterator iter = downstreamVerticesCache.find(vertex);
117  if (iter != downstreamVerticesCache.end())
118  return iter->second;
119 
120  set<Vertex *> unused;
121  vector<Vertex *> downstreamVertices = getReachableVertices(vertex, edges, unused);
122 
123  downstreamVerticesCache[vertex] = downstreamVertices;
124 
125  return downstreamVertices;
126 }
127 
134 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getUpstreamVertices(Vertex *vertex)
135 {
136  map< Vertex *, vector<Vertex *> >::iterator iter = upstreamVerticesCache.find(vertex);
137  if (iter != upstreamVerticesCache.end())
138  return iter->second;
139 
140  map< Vertex *, vector<Vertex *> > backEdges;
141  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
142  {
143  for (vector<Vertex *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
144  if (find(backEdges[*j].begin(), backEdges[*j].end(), i->first) == backEdges[*j].end())
145  backEdges[*j].push_back(i->first);
146 
147  backEdges[i->first];
148  }
149 
150  set<Vertex *> unused;
151  vector<Vertex *> upstreamVertices = getReachableVertices(vertex, backEdges, unused);
152 
153  upstreamVerticesCache[vertex] = upstreamVertices;
154 
155  return upstreamVertices;
156 }
157 
161 set<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getCycleVertices(void)
162 {
163  if (cycleVerticesCacheReady)
164  return cycleVerticesCache;
165 
166  set<Vertex *> cycleVertices;
167  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
168  {
169  set<Vertex *> c;
170  getReachableVertices(i->first, edges, c);
171  cycleVertices.insert(c.begin(), c.end());
172  }
173 
174  cycleVerticesCacheReady = true;
175  cycleVerticesCache = cycleVertices;
176 
177  return cycleVertices;
178 }
179 
184 {
185  auto iter = longestDownstreamPathsCache.find(vertex);
186  if (iter != longestDownstreamPathsCache.end())
187  return iter->second;
188 
189  int longest = -1;
190  for (Vertex *v : getDownstreamVertices(vertex))
191  {
192  int curr = getLongestDownstreamPath(v);
193  longest = std::max(longest, curr);
194  }
195 
196  return longest + 1;
197 }
198 
202 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getReachableVertices(Vertex *vertex,
203  const map< Vertex *, vector<Vertex *> > &edges,
204  set<Vertex *> &cycleVertices)
205 {
206  map<Vertex *, vector<Vertex *> > reachableVertices;
207 
208  if (edges.find(vertex) == edges.end())
209  return vector<Vertex *>();
210 
211  list<Vertex *> toVisit; // Used as a stack, except for a call to find().
212  toVisit.push_back(vertex);
213 
214  while (! toVisit.empty())
215  {
216  // Visit the vertex at the top of the stack.
217  Vertex *currVertex = toVisit.back();
218 
219  set<Vertex *> nextVertices;
220  bool areCurrVerticesComplete = true;
221 
222  // Consider each vertex immediately downstream of this vertex.
223  map< Vertex *, vector<Vertex *> >::const_iterator edgesIter = edges.find(currVertex);
224  if (edgesIter != edges.end())
225  {
226  for (vector<Vertex *>::const_iterator j = edgesIter->second.begin(); j != edgesIter->second.end(); ++j)
227  {
228  Vertex *nextVertex = *j;
229  nextVertices.insert(nextVertex);
230 
231  map<Vertex *, vector<Vertex *> >::iterator nextNextVerticesIter = reachableVertices.find(nextVertex);
232  if (nextNextVerticesIter != reachableVertices.end())
233  {
234  // The downstream vertex has already been visited, so add its downstream vertices to this vertex's.
235  nextVertices.insert( nextNextVerticesIter->second.begin(), nextNextVerticesIter->second.end() );
236  }
237  else
238  {
239  if (find(toVisit.begin(), toVisit.end(), nextVertex) != toVisit.end())
240  {
241  // The downstream vertex is already on the stack, so there's a cycle.
242  cycleVertices.insert(nextVertex);
243  }
244  else
245  {
246  // The downstream vertex has not yet been visited, so add it to the stack.
247  toVisit.push_back(nextVertex);
248  areCurrVerticesComplete = false;
249  }
250  }
251  }
252  }
253 
254  if (areCurrVerticesComplete)
255  {
256  reachableVertices[currVertex].insert(reachableVertices[currVertex].end(), nextVertices.begin(), nextVertices.end());
257  toVisit.pop_back();
258  }
259  }
260 
261  return reachableVertices[vertex];
262 }
263 
267 string VuoDirectedAcyclicGraph::toString(bool showVertexPointers)
268 {
269  ostringstream ss;
270 
271  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
272  {
273  ss << i->first->key();
274  if (showVertexPointers)
275  ss << " (" << i->first << ")";
276  ss << " ->";
277 
278  for (Vertex *vertex : i->second)
279  {
280  ss << " " << vertex->key();
281  if (showVertexPointers)
282  ss << " (" << vertex << ")";
283  }
284 
285  ss << "\n";
286  }
287 
288  return ss.str();
289 }
290 
294 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::findVertex(const string &key)
295 {
296  vector<VuoDirectedAcyclicGraph::Vertex *> foundVertices;
297 
298  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator i = edges.begin(); i != edges.end(); ++i)
299  {
300  VuoDirectedAcyclicGraph::Vertex *vertex = i->first->findVertex(key);
301  if (vertex)
302  foundVertices.push_back(vertex);
303  }
304 
305  return foundVertices;
306 }
307 
314 {
315  if (find(edges[fromGraph].begin(), edges[fromGraph].end(), toGraph) == edges[fromGraph].end())
316  {
317  edges[fromGraph].push_back(toGraph);
318  edges[toGraph];
319  }
320 }
321 
333 {
334  return getReachableVertices(vertex, edges, true);
335 }
336 
347 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::getUpstreamVertices(VuoDirectedAcyclicGraph::Vertex *vertex)
348 {
349  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> > backEdges;
350  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
351  {
352  for (vector<VuoDirectedAcyclicGraph *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
353  if (find(backEdges[*j].begin(), backEdges[*j].end(), i->first) == backEdges[*j].end())
354  backEdges[*j].push_back(i->first);
355 
356  backEdges[i->first];
357  }
358 
359  return getReachableVertices(vertex, backEdges, false);
360 }
361 
365 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::getReachableVertices(VuoDirectedAcyclicGraph::Vertex *vertex,
366  const map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> > &edges,
367  bool isDownstream)
368 {
369  vector<VuoDirectedAcyclicGraph::Vertex *> reachableVertices;
370 
371  VuoDirectedAcyclicGraph *containingGraph = NULL;
372  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator i = edges.begin(); i != edges.end(); ++i)
373  {
374  if (i->first->edges.find(vertex) != i->first->edges.end())
375  {
376  containingGraph = i->first;
377  break;
378  }
379  }
380 
381  if (! containingGraph)
382  return reachableVertices;
383 
384  list< pair< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> > > toVisit;
385  toVisit.push_back( make_pair(containingGraph, vector<VuoDirectedAcyclicGraph::Vertex *>(1, vertex)) );
386 
387  while (! toVisit.empty())
388  {
389  VuoDirectedAcyclicGraph *currGraph = toVisit.front().first;
390  vector<VuoDirectedAcyclicGraph::Vertex *> currVertices = toVisit.front().second;
391  toVisit.pop_front();
392 
393  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator edgesIter = edges.find(currGraph);
394  if (edgesIter != edges.end())
395  {
396  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> > moreToVisit;
397 
398  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator i = currVertices.begin(); i != currVertices.end(); ++i)
399  {
400  VuoDirectedAcyclicGraph::Vertex *currVertex = *i;
401  vector<VuoDirectedAcyclicGraph::Vertex *> currReachableVertices = (isDownstream ?
402  currGraph->getDownstreamVertices(currVertex) :
403  currGraph->getUpstreamVertices(currVertex));
404 
405  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = currReachableVertices.begin(); j != currReachableVertices.end(); ++j)
406  {
407  VuoDirectedAcyclicGraph::Vertex *currReachableVertex = *j;
408 
409  if (find(reachableVertices.begin(), reachableVertices.end(), currReachableVertex) == reachableVertices.end())
410  reachableVertices.push_back(currReachableVertex);
411  }
412 
413  vector<VuoDirectedAcyclicGraph::Vertex *> candidateVertices;
414  candidateVertices.push_back(currVertex);
415  candidateVertices.insert(candidateVertices.end(), currReachableVertices.begin(), currReachableVertices.end());
416 
417  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = candidateVertices.begin(); j != candidateVertices.end(); ++j)
418  {
419  VuoDirectedAcyclicGraph::Vertex *candidateVertex = *j;
420 
421  for (vector<VuoDirectedAcyclicGraph *>::const_iterator k = edgesIter->second.begin(); k != edgesIter->second.end(); ++k)
422  {
423  VuoDirectedAcyclicGraph *otherGraph = *k;
424 
425  VuoDirectedAcyclicGraph::Vertex *matchingVertexInOtherGraph = otherGraph->findVertex(candidateVertex->key());
426  if (matchingVertexInOtherGraph)
427  {
428  moreToVisit[otherGraph].push_back(matchingVertexInOtherGraph);
429 
430  if (find(reachableVertices.begin(), reachableVertices.end(), matchingVertexInOtherGraph) == reachableVertices.end())
431  reachableVertices.push_back(matchingVertexInOtherGraph);
432  }
433  }
434  }
435  }
436 
437  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> >::iterator i = moreToVisit.begin(); i != moreToVisit.end(); ++i)
438  toVisit.push_back( make_pair(i->first, i->second) );
439  }
440  }
441 
442  return reachableVertices;
443 }
444 
448 string VuoDirectedAcyclicNetwork::toString(bool showVertexAddresses)
449 {
450  ostringstream ss;
451 
452  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
453  {
454  ss << i->first << " ->";
455  for (VuoDirectedAcyclicGraph *graph : i->second)
456  ss << " " << graph;
457  ss << "\n";
458  }
459 
460  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
461  {
462  string graphString = i->first->toString(showVertexAddresses);
463  if (! graphString.empty())
464  ss << "\n" << i->first << ":\n" << graphString << "\n";
465  }
466 
467  return ss.str();
468 }