ctkDependencyGraph.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. All rights reserved.
  5. Distributed under a BSD License. See LICENSE.txt file.
  6. This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even
  7. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the above copyright notice for more information.
  9. =========================================================================*/
  10. // Qt includes
  11. #include <QQueue>
  12. #include <QVarLengthArray>
  13. #include <QDebug>
  14. // CTK includes
  15. #include "ctkDependencyGraph.h"
  16. // STD includes
  17. #include <iostream>
  18. #define MAXV 100
  19. #define MAXDEGREE 50
  20. //----------------------------------------------------------------------------
  21. class ctkDependencyGraph::ctkInternal
  22. {
  23. public:
  24. ctkInternal(ctkDependencyGraph* p);
  25. /// Compute indegree
  26. void computeIndegrees(QVarLengthArray<int, MAXV>& computedIndegrees);
  27. /// Traverse tree using Depth-first_search
  28. void traverseUsingDFS(int v);
  29. /// Called each time an edge is visited
  30. void processEdge(int from, int to);
  31. /// Called each time a vertex is processed
  32. void processVertex(int v);
  33. /// Retrieve the path between two vertices
  34. void findPathDFS(int from, int to, QList<int>& path);
  35. /// Recursive function used by findPaths to retrieve the path between two vertices
  36. void findPathsRec(int from, int to, QList<int>* path, QList<QList<int>* >& paths);
  37. void setEdge(int vertice, int degree, int value);
  38. int edge(int vertice, int degree);
  39. /// See http://en.wikipedia.org/wiki/Adjacency_list
  40. QVarLengthArray<QVarLengthArray<int,MAXDEGREE>*, MAXV+1> Edges;
  41. QVarLengthArray<int, MAXV+1> Degree;
  42. int NVertices;
  43. int NEdges;
  44. /// Structure used by DFS
  45. /// See http://en.wikipedia.org/wiki/Depth-first_search
  46. QVarLengthArray<bool, MAXV> Processed; // processed vertices
  47. QVarLengthArray<bool, MAXV> Discovered; // discovered vertices
  48. QVarLengthArray<int, MAXV> Parent; // relation discovered
  49. bool Abort; // Flag indicating if traverse should be aborted
  50. bool Verbose;
  51. bool CycleDetected;
  52. int CycleOrigin;
  53. int CycleEnd;
  54. QList<int> ListOfEdgeToExclude;
  55. /// Pointer to the public API
  56. ctkDependencyGraph* P;
  57. };
  58. //----------------------------------------------------------------------------
  59. // ctkInternal methods
  60. //----------------------------------------------------------------------------
  61. ctkDependencyGraph::ctkInternal::ctkInternal(ctkDependencyGraph* p)
  62. {
  63. Q_ASSERT(p);
  64. this->P = p;
  65. this->NVertices = 0;
  66. this->NEdges = 0;
  67. this->Abort = false;
  68. this->Verbose = false;
  69. this->CycleDetected = false;
  70. this->CycleOrigin = 0;
  71. this->CycleEnd = 0;
  72. }
  73. //----------------------------------------------------------------------------
  74. void ctkDependencyGraph::ctkInternal::computeIndegrees(QVarLengthArray<int, MAXV>& computedIndegrees)
  75. {
  76. for (int i=1; i <= this->NVertices; i++)
  77. {
  78. computedIndegrees[i] = 0;
  79. }
  80. for (int i=1; i <= this->NVertices; i++)
  81. {
  82. for (int j=0; j < this->Degree[i]; j++)
  83. {
  84. computedIndegrees[ this->edge(i,j) ] ++;
  85. }
  86. }
  87. }
  88. //----------------------------------------------------------------------------
  89. void ctkDependencyGraph::ctkInternal::traverseUsingDFS(int v)
  90. {
  91. // allow for search termination
  92. if (this->Abort)
  93. {
  94. return;
  95. }
  96. this->Discovered[v] = true;
  97. this->processVertex(v);
  98. int y; // successor vertex
  99. for (int i=0; i<this->Degree[v]; i++)
  100. {
  101. y = this->edge(v, i);
  102. if (this->P->shouldExcludeEdge(this->edge(v, i)) == false)
  103. {
  104. if (this->Discovered[y] == false)
  105. {
  106. this->Parent[y] = v;
  107. this->traverseUsingDFS(y);
  108. }
  109. else
  110. {
  111. if (this->Processed[y] == false)
  112. {
  113. this->processEdge(v,y);
  114. }
  115. }
  116. }
  117. if (this->Abort)
  118. {
  119. return;
  120. }
  121. }
  122. this->Processed[v] = true;
  123. }
  124. //----------------------------------------------------------------------------
  125. void ctkDependencyGraph::ctkInternal::processEdge(int from, int to)
  126. {
  127. if (this->Parent[from] != to)
  128. {
  129. this->CycleDetected = true;
  130. this->CycleOrigin = to;
  131. this->CycleEnd = from;
  132. if (this->Verbose)
  133. {
  134. QList<int> path;
  135. this->findPathDFS(from, to, path);
  136. qWarning() << "Cycle detected from " << to << " to " << from;
  137. qWarning() << " " << path;
  138. path.clear();
  139. this->findPathDFS(to, from, path);
  140. qWarning() << " " << path;
  141. }
  142. this->Abort = true;
  143. }
  144. }
  145. //----------------------------------------------------------------------------
  146. void ctkDependencyGraph::ctkInternal::processVertex(int v)
  147. {
  148. if (this->Verbose)
  149. {
  150. qDebug() << "processed vertex " << v;
  151. }
  152. }
  153. //----------------------------------------------------------------------------
  154. void ctkDependencyGraph::ctkInternal::setEdge(int vertice, int degree, int value)
  155. {
  156. Q_ASSERT(vertice <= this->NVertices);
  157. Q_ASSERT(degree < MAXDEGREE);
  158. (*this->Edges[vertice])[degree] = value;
  159. }
  160. //----------------------------------------------------------------------------
  161. int ctkDependencyGraph::ctkInternal::edge(int vertice, int degree)
  162. {
  163. Q_ASSERT(vertice <= this->NVertices);
  164. Q_ASSERT(degree < MAXDEGREE);
  165. return (*this->Edges[vertice])[degree];
  166. }
  167. //----------------------------------------------------------------------------
  168. void ctkDependencyGraph::ctkInternal::findPathDFS(int from, int to, QList<int>& path)
  169. {
  170. if ((from == to) || (to == -1))
  171. {
  172. path << from;
  173. }
  174. else
  175. {
  176. this->findPathDFS(from, this->Parent[to], path);
  177. path << to;
  178. }
  179. }
  180. //----------------------------------------------------------------------------
  181. void ctkDependencyGraph::ctkInternal::findPathsRec(
  182. int from, int to, QList<int>* path, QList<QList<int>* >& paths)
  183. {
  184. if (from == to)
  185. {
  186. return;
  187. }
  188. QList<int> branch(*path);
  189. int child = from;
  190. for (int j=0; j < this->Degree[child]; j++)
  191. {
  192. if (j == 0)
  193. {
  194. int parent = this->edge(child, j);
  195. *path << parent;
  196. this->findPathsRec(parent, to, path, paths);
  197. }
  198. else
  199. {
  200. int parent = this->edge(child, j);
  201. // Copy path and add it to the list
  202. QList<int>* pathCopy = new QList<int>(branch);
  203. paths << pathCopy;
  204. *pathCopy << parent;
  205. this->findPathsRec(parent, to, pathCopy, paths);
  206. }
  207. }
  208. }
  209. //----------------------------------------------------------------------------
  210. // ctkDependencyGraph methods
  211. //----------------------------------------------------------------------------
  212. ctkDependencyGraph::ctkDependencyGraph(int nvertices)
  213. {
  214. this->Internal = new ctkInternal(this);
  215. this->Internal->NVertices = nvertices;
  216. // Resize internal array
  217. this->Internal->Processed.resize(nvertices + 1);
  218. this->Internal->Discovered.resize(nvertices + 1);
  219. this->Internal->Parent.resize(nvertices + 1);
  220. this->Internal->Edges.resize(nvertices + 1);
  221. this->Internal->Degree.resize(nvertices + 1);
  222. for (int i=1; i <= nvertices; i++)
  223. {
  224. this->Internal->Degree[i] = 0;
  225. }
  226. // initialize Edge adjacency list
  227. for (int i=0; i <= nvertices; i++)
  228. {
  229. this->Internal->Edges[i] = new QVarLengthArray<int, MAXDEGREE>();
  230. this->Internal->Edges[i]->resize(MAXDEGREE);
  231. }
  232. // initialize search
  233. for (int i=1; i <= nvertices; i++)
  234. {
  235. this->Internal->Processed[i] = false;
  236. this->Internal->Discovered[i] = false;
  237. this->Internal->Parent[i] = -1;
  238. }
  239. }
  240. //----------------------------------------------------------------------------
  241. ctkDependencyGraph::~ctkDependencyGraph()
  242. {
  243. // Clean memory
  244. for (int i=0; i <= this->Internal->NVertices; i++)
  245. {
  246. delete this->Internal->Edges[i];
  247. }
  248. delete this->Internal;
  249. }
  250. //----------------------------------------------------------------------------
  251. void ctkDependencyGraph::printAdditionalInfo()
  252. {
  253. qDebug() << "ctkDependencyGraph (" << this << ")" << endl
  254. << " NVertices:" << this->numberOfVertices() << endl
  255. << " NEdges:" << this->numberOfEdges() << endl
  256. << " Abort:" << this->Internal->Abort;
  257. qDebug() << " [Processed]";
  258. for(int i=1; i < this->Internal->Processed.size(); i++)
  259. {
  260. qDebug() << i << "->" << this->Internal->Processed[i];
  261. }
  262. qDebug() << " [Discovered]";
  263. for(int i=1; i < this->Internal->Discovered.size(); i++)
  264. {
  265. qDebug() << i << "->" << this->Internal->Discovered[i];
  266. }
  267. qDebug() << " [Parent]";
  268. for(int i=1; i < this->Internal->Parent.size(); i++)
  269. {
  270. qDebug() << i << "->" << this->Internal->Parent[i];
  271. }
  272. qDebug() << " [Graph]";
  273. this->printGraph();
  274. }
  275. //----------------------------------------------------------------------------
  276. void ctkDependencyGraph::printGraph()
  277. {
  278. for(int i=1; i <= this->Internal->NVertices; i++)
  279. {
  280. std::cout << i << ":";
  281. for (int j=0; j < this->Internal->Degree[i]; j++)
  282. {
  283. std::cout << " " << this->Internal->edge(i, j);
  284. }
  285. std::cout << std::endl;
  286. }
  287. }
  288. //----------------------------------------------------------------------------
  289. int ctkDependencyGraph::numberOfVertices()
  290. {
  291. return this->Internal->NVertices;
  292. }
  293. //----------------------------------------------------------------------------
  294. int ctkDependencyGraph::numberOfEdges()
  295. {
  296. return this->Internal->NEdges;
  297. }
  298. //----------------------------------------------------------------------------
  299. void ctkDependencyGraph::setVerbose(bool verbose)
  300. {
  301. this->Internal->Verbose = verbose;
  302. }
  303. //----------------------------------------------------------------------------
  304. void ctkDependencyGraph::setEdgeListToExclude(const QList<int>& list)
  305. {
  306. this->Internal->ListOfEdgeToExclude = list;
  307. }
  308. //----------------------------------------------------------------------------
  309. bool ctkDependencyGraph::shouldExcludeEdge(int edge)
  310. {
  311. return this->Internal->ListOfEdgeToExclude.contains(edge);
  312. }
  313. //----------------------------------------------------------------------------
  314. bool ctkDependencyGraph::checkForCycle()
  315. {
  316. if (this->Internal->NEdges > 0)
  317. {
  318. // get a valid vertice Id
  319. int verticeId = 1;
  320. this->Internal->traverseUsingDFS(verticeId);
  321. }
  322. return this->cycleDetected();
  323. }
  324. //----------------------------------------------------------------------------
  325. bool ctkDependencyGraph::cycleDetected()
  326. {
  327. return this->Internal->CycleDetected;
  328. }
  329. //----------------------------------------------------------------------------
  330. int ctkDependencyGraph::cycleOrigin()
  331. {
  332. return this->Internal->CycleOrigin;
  333. }
  334. //----------------------------------------------------------------------------
  335. int ctkDependencyGraph::cycleEnd()
  336. {
  337. return this->Internal->CycleEnd;
  338. }
  339. //----------------------------------------------------------------------------
  340. void ctkDependencyGraph::insertEdge(int from, int to)
  341. {
  342. Q_ASSERT(from > 0 && from <= this->Internal->NVertices);
  343. Q_ASSERT(to > 0 && to <= this->Internal->NVertices);
  344. // resize if needed
  345. int capacity = this->Internal->Edges[from]->capacity();
  346. if (this->Internal->Degree[from] > capacity)
  347. {
  348. this->Internal->Edges[from]->resize(capacity + capacity * 0.3);
  349. }
  350. this->Internal->setEdge(from, this->Internal->Degree[from], to);
  351. this->Internal->Degree[from]++;
  352. this->Internal->NEdges++;
  353. }
  354. //----------------------------------------------------------------------------
  355. void ctkDependencyGraph::findPaths(int from, int to, QList<QList<int>* >& paths)
  356. {
  357. QList<int>* path = new QList<int>;
  358. *path << from;
  359. paths << path;
  360. this->Internal->findPathsRec(from, to, path, paths);
  361. QList<int> pathToRemove;
  362. // Remove list no ending with the requested element
  363. int i = 0;
  364. while (!paths.isEmpty() && i < paths.size())
  365. {
  366. QList<int>* p = paths[i];
  367. Q_ASSERT(p);
  368. if (p->last() != to)
  369. {
  370. paths.removeAt(i);
  371. delete p;
  372. }
  373. else
  374. {
  375. i++;
  376. }
  377. }
  378. }
  379. //----------------------------------------------------------------------------
  380. void ctkDependencyGraph::findPath(int from, int to, QList<int>& path)
  381. {
  382. int child = from;
  383. int parent = this->Internal->edge(child, 0);
  384. path << child;
  385. while (parent > 0)
  386. {
  387. path << parent;
  388. if (parent == to)
  389. {
  390. break;
  391. }
  392. child = parent;
  393. parent = this->Internal->edge(child, 0);
  394. }
  395. }
  396. //----------------------------------------------------------------------------
  397. bool ctkDependencyGraph::topologicalSort(QList<int>& sorted)
  398. {
  399. QVarLengthArray<int, MAXV> indegree; // indegree of each vertex
  400. QQueue<int> zeroin; // vertices of indegree 0
  401. int x, y; // current and next vertex
  402. indegree.resize(this->Internal->NVertices + 1);
  403. // resize if needed
  404. if (this->Internal->NVertices > MAXV)
  405. {
  406. indegree.resize(this->Internal->NVertices);
  407. }
  408. this->Internal->computeIndegrees(indegree);
  409. for (int i=1; i <= this->Internal->NVertices; i++)
  410. {
  411. if (indegree[i] == 0)
  412. {
  413. zeroin.enqueue(i);
  414. }
  415. }
  416. int j=0;
  417. while (zeroin.empty() == false)
  418. {
  419. j = j+1;
  420. x = zeroin.dequeue();
  421. sorted << x;
  422. for (int i=0; i < this->Internal->Degree[x]; i++)
  423. {
  424. y = this->Internal->edge(x, i);
  425. indegree[y] --;
  426. if (indegree[y] == 0)
  427. {
  428. zeroin.enqueue(y);
  429. }
  430. }
  431. }
  432. if (j != this->Internal->NVertices)
  433. {
  434. return false;
  435. }
  436. return true;
  437. }