Vuo  2.3.2
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  std::lock_guard<std::mutex> lock(graphMutex);
42 
43  edges[vertex];
44 }
45 
50 {
51  std::lock_guard<std::mutex> lock(graphMutex);
52 
53  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
54  {
55  for (vector<Vertex *>::iterator j = i->second.begin(); j != i->second.end(); )
56  {
57  if (*j == vertex)
58  j = i->second.erase(j);
59  else
60  ++j;
61  }
62  }
63 
64  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); )
65  {
66  if (i->first == vertex)
67  edges.erase(i++);
68  else
69  ++i;
70  }
71 
72  delete vertex;
73 
74  downstreamVerticesCache.clear();
75  upstreamVerticesCache.clear();
76  cycleVerticesCacheReady = false;
77  longestDownstreamPathsCache.clear();
78 }
79 
84 {
85  std::lock_guard<std::mutex> lock(graphMutex);
86 
87  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
88  if (i->first->key() == key)
89  return i->first;
90 
91  return NULL;
92 }
93 
100 void VuoDirectedAcyclicGraph::addEdge(Vertex *fromVertex, Vertex *toVertex)
101 {
102  std::lock_guard<std::mutex> lock(graphMutex);
103 
104  if (find(edges[fromVertex].begin(), edges[fromVertex].end(), toVertex) == edges[fromVertex].end())
105  {
106  edges[fromVertex].push_back(toVertex);
107  edges[toVertex];
108  }
109 
110  downstreamVerticesCache.clear();
111  upstreamVerticesCache.clear();
112  cycleVerticesCacheReady = false;
113  longestDownstreamPathsCache.clear();
114 }
115 
122 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getDownstreamVertices(Vertex *vertex)
123 {
124  std::lock_guard<std::mutex> lock(graphMutex);
125 
126  return getDownstreamVerticesInternal(vertex);
127 }
128 
132 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getDownstreamVerticesInternal(Vertex *vertex)
133 {
134  map< Vertex *, vector<Vertex *> >::iterator iter = downstreamVerticesCache.find(vertex);
135  if (iter != downstreamVerticesCache.end())
136  return iter->second;
137 
138  set<Vertex *> unused;
139  vector<Vertex *> downstreamVertices = getReachableVertices(vertex, edges, unused);
140 
141  downstreamVerticesCache[vertex] = downstreamVertices;
142 
143  return downstreamVertices;
144 }
145 
152 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getUpstreamVertices(Vertex *vertex)
153 {
154  std::lock_guard<std::mutex> lock(graphMutex);
155 
156  map< Vertex *, vector<Vertex *> >::iterator iter = upstreamVerticesCache.find(vertex);
157  if (iter != upstreamVerticesCache.end())
158  return iter->second;
159 
160  map< Vertex *, vector<Vertex *> > backEdges;
161  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
162  {
163  for (vector<Vertex *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
164  if (find(backEdges[*j].begin(), backEdges[*j].end(), i->first) == backEdges[*j].end())
165  backEdges[*j].push_back(i->first);
166 
167  backEdges[i->first];
168  }
169 
170  set<Vertex *> unused;
171  vector<Vertex *> upstreamVertices = getReachableVertices(vertex, backEdges, unused);
172 
173  upstreamVerticesCache[vertex] = upstreamVertices;
174 
175  return upstreamVertices;
176 }
177 
181 set<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getCycleVertices(void)
182 {
183  std::lock_guard<std::mutex> lock(graphMutex);
184 
185  if (cycleVerticesCacheReady)
186  return cycleVerticesCache;
187 
188  set<Vertex *> cycleVertices;
189  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
190  {
191  set<Vertex *> c;
192  getReachableVertices(i->first, edges, c);
193  cycleVertices.insert(c.begin(), c.end());
194  }
195 
196  cycleVerticesCacheReady = true;
197  cycleVerticesCache = cycleVertices;
198 
199  return cycleVertices;
200 }
201 
206 {
207  std::lock_guard<std::mutex> lock(graphMutex);
208 
209  return getLongestDownstreamPathInternal(vertex);
210 }
211 
215 int VuoDirectedAcyclicGraph::getLongestDownstreamPathInternal(Vertex *vertex)
216 {
217  auto iter = longestDownstreamPathsCache.find(vertex);
218  if (iter != longestDownstreamPathsCache.end())
219  return iter->second;
220 
221  int longest = -1;
222  for (Vertex *v : getDownstreamVerticesInternal(vertex))
223  {
224  int curr = getLongestDownstreamPathInternal(v);
225  longest = std::max(longest, curr);
226  }
227 
228  return longest + 1;
229 }
230 
234 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicGraph::getReachableVertices(Vertex *vertex,
235  const map< Vertex *, vector<Vertex *> > &edges,
236  set<Vertex *> &cycleVertices)
237 {
238  map<Vertex *, vector<Vertex *> > reachableVertices;
239 
240  if (edges.find(vertex) == edges.end())
241  return vector<Vertex *>();
242 
243  list<Vertex *> toVisit; // Used as a stack, except for a call to find().
244  toVisit.push_back(vertex);
245 
246  while (! toVisit.empty())
247  {
248  // Visit the vertex at the top of the stack.
249  Vertex *currVertex = toVisit.back();
250 
251  set<Vertex *> nextVertices;
252  bool areCurrVerticesComplete = true;
253 
254  // Consider each vertex immediately downstream of this vertex.
255  map< Vertex *, vector<Vertex *> >::const_iterator edgesIter = edges.find(currVertex);
256  if (edgesIter != edges.end())
257  {
258  for (vector<Vertex *>::const_iterator j = edgesIter->second.begin(); j != edgesIter->second.end(); ++j)
259  {
260  Vertex *nextVertex = *j;
261  nextVertices.insert(nextVertex);
262 
263  map<Vertex *, vector<Vertex *> >::iterator nextNextVerticesIter = reachableVertices.find(nextVertex);
264  if (nextNextVerticesIter != reachableVertices.end())
265  {
266  // The downstream vertex has already been visited, so add its downstream vertices to this vertex's.
267  nextVertices.insert( nextNextVerticesIter->second.begin(), nextNextVerticesIter->second.end() );
268  }
269  else
270  {
271  if (find(toVisit.begin(), toVisit.end(), nextVertex) != toVisit.end())
272  {
273  // The downstream vertex is already on the stack, so there's a cycle.
274  cycleVertices.insert(nextVertex);
275  }
276  else
277  {
278  // The downstream vertex has not yet been visited, so add it to the stack.
279  toVisit.push_back(nextVertex);
280  areCurrVerticesComplete = false;
281  }
282  }
283  }
284  }
285 
286  if (areCurrVerticesComplete)
287  {
288  reachableVertices[currVertex].insert(reachableVertices[currVertex].end(), nextVertices.begin(), nextVertices.end());
289  toVisit.pop_back();
290  }
291  }
292 
293  return reachableVertices[vertex];
294 }
295 
299 string VuoDirectedAcyclicGraph::toString(bool showVertexPointers)
300 {
301  std::lock_guard<std::mutex> lock(graphMutex);
302 
303  ostringstream ss;
304 
305  for (map< Vertex *, vector<Vertex *> >::iterator i = edges.begin(); i != edges.end(); ++i)
306  {
307  ss << i->first->key();
308  if (showVertexPointers)
309  ss << " (" << i->first << ")";
310  ss << " ->";
311 
312  for (Vertex *vertex : i->second)
313  {
314  ss << " " << vertex->key();
315  if (showVertexPointers)
316  ss << " (" << vertex << ")";
317  }
318 
319  ss << "\n";
320  }
321 
322  return ss.str();
323 }
324 
328 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::findVertex(const string &key)
329 {
330  vector<VuoDirectedAcyclicGraph::Vertex *> foundVertices;
331 
332  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator i = edges.begin(); i != edges.end(); ++i)
333  {
334  VuoDirectedAcyclicGraph::Vertex *vertex = i->first->findVertex(key);
335  if (vertex)
336  foundVertices.push_back(vertex);
337  }
338 
339  return foundVertices;
340 }
341 
348 {
349  if (find(edges[fromGraph].begin(), edges[fromGraph].end(), toGraph) == edges[fromGraph].end())
350  {
351  edges[fromGraph].push_back(toGraph);
352  edges[toGraph];
353  }
354 }
355 
367 {
368  return getReachableVertices(vertex, edges, true);
369 }
370 
381 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::getUpstreamVertices(VuoDirectedAcyclicGraph::Vertex *vertex)
382 {
383  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> > backEdges;
384  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
385  {
386  for (vector<VuoDirectedAcyclicGraph *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
387  if (find(backEdges[*j].begin(), backEdges[*j].end(), i->first) == backEdges[*j].end())
388  backEdges[*j].push_back(i->first);
389 
390  backEdges[i->first];
391  }
392 
393  return getReachableVertices(vertex, backEdges, false);
394 }
395 
399 vector<VuoDirectedAcyclicGraph::Vertex *> VuoDirectedAcyclicNetwork::getReachableVertices(VuoDirectedAcyclicGraph::Vertex *vertex,
400  const map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> > &edges,
401  bool isDownstream)
402 {
403  vector<VuoDirectedAcyclicGraph::Vertex *> reachableVertices;
404 
405  VuoDirectedAcyclicGraph *containingGraph = NULL;
406  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator i = edges.begin(); i != edges.end(); ++i)
407  {
408  if (i->first->edges.find(vertex) != i->first->edges.end())
409  {
410  containingGraph = i->first;
411  break;
412  }
413  }
414 
415  if (! containingGraph)
416  return reachableVertices;
417 
418  list< pair< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> > > toVisit;
419  toVisit.push_back( make_pair(containingGraph, vector<VuoDirectedAcyclicGraph::Vertex *>(1, vertex)) );
420 
421  while (! toVisit.empty())
422  {
423  VuoDirectedAcyclicGraph *currGraph = toVisit.front().first;
424  vector<VuoDirectedAcyclicGraph::Vertex *> currVertices = toVisit.front().second;
425  toVisit.pop_front();
426 
427  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::const_iterator edgesIter = edges.find(currGraph);
428  if (edgesIter != edges.end())
429  {
430  map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> > moreToVisit;
431 
432  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator i = currVertices.begin(); i != currVertices.end(); ++i)
433  {
434  VuoDirectedAcyclicGraph::Vertex *currVertex = *i;
435  vector<VuoDirectedAcyclicGraph::Vertex *> currReachableVertices = (isDownstream ?
436  currGraph->getDownstreamVertices(currVertex) :
437  currGraph->getUpstreamVertices(currVertex));
438 
439  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = currReachableVertices.begin(); j != currReachableVertices.end(); ++j)
440  {
441  VuoDirectedAcyclicGraph::Vertex *currReachableVertex = *j;
442 
443  if (find(reachableVertices.begin(), reachableVertices.end(), currReachableVertex) == reachableVertices.end())
444  reachableVertices.push_back(currReachableVertex);
445  }
446 
447  vector<VuoDirectedAcyclicGraph::Vertex *> candidateVertices;
448  candidateVertices.push_back(currVertex);
449  candidateVertices.insert(candidateVertices.end(), currReachableVertices.begin(), currReachableVertices.end());
450 
451  for (vector<VuoDirectedAcyclicGraph::Vertex *>::iterator j = candidateVertices.begin(); j != candidateVertices.end(); ++j)
452  {
453  VuoDirectedAcyclicGraph::Vertex *candidateVertex = *j;
454 
455  for (vector<VuoDirectedAcyclicGraph *>::const_iterator k = edgesIter->second.begin(); k != edgesIter->second.end(); ++k)
456  {
457  VuoDirectedAcyclicGraph *otherGraph = *k;
458 
459  VuoDirectedAcyclicGraph::Vertex *matchingVertexInOtherGraph = otherGraph->findVertex(candidateVertex->key());
460  if (matchingVertexInOtherGraph)
461  {
462  moreToVisit[otherGraph].push_back(matchingVertexInOtherGraph);
463 
464  if (find(reachableVertices.begin(), reachableVertices.end(), matchingVertexInOtherGraph) == reachableVertices.end())
465  reachableVertices.push_back(matchingVertexInOtherGraph);
466  }
467  }
468  }
469  }
470 
471  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph::Vertex *> >::iterator i = moreToVisit.begin(); i != moreToVisit.end(); ++i)
472  toVisit.push_back( make_pair(i->first, i->second) );
473  }
474  }
475 
476  return reachableVertices;
477 }
478 
482 string VuoDirectedAcyclicNetwork::toString(bool showVertexAddresses)
483 {
484  ostringstream ss;
485 
486  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
487  {
488  ss << i->first << " ->";
489  for (VuoDirectedAcyclicGraph *graph : i->second)
490  ss << " " << graph;
491  ss << "\n";
492  }
493 
494  for (map< VuoDirectedAcyclicGraph *, vector<VuoDirectedAcyclicGraph *> >::iterator i = edges.begin(); i != edges.end(); ++i)
495  {
496  string graphString = i->first->toString(showVertexAddresses);
497  if (! graphString.empty())
498  ss << "\n" << i->first << ":\n" << graphString << "\n";
499  }
500 
501  return ss.str();
502 }