ctkDependencyGraph.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  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. void setEdge(int vertice, int degree, int value);
  34. int edge(int vertice, int degree);
  35. /// See http://en.wikipedia.org/wiki/Adjacency_list
  36. QVarLengthArray<QVarLengthArray<int,MAXDEGREE>*, MAXV+1> Edges;
  37. QVarLengthArray<int, MAXV+1> Degree;
  38. int NVertices;
  39. int NEdges;
  40. /// Structure used by DFS
  41. /// See http://en.wikipedia.org/wiki/Depth-first_search
  42. QVarLengthArray<bool, MAXV> Processed; // processed vertices
  43. QVarLengthArray<bool, MAXV> Discovered; // discovered vertices
  44. QVarLengthArray<int, MAXV> Parent; // relation discovered
  45. bool Abort; // Flag indicating if traverse should be aborted
  46. bool Verbose;
  47. bool CycleDetected;
  48. int CycleOrigin;
  49. int CycleEnd;
  50. QList<int> ListOfEdgeToExclude;
  51. /// Pointer to the public API
  52. ctkDependencyGraph* P;
  53. };
  54. //----------------------------------------------------------------------------
  55. // ctkInternal methods
  56. //----------------------------------------------------------------------------
  57. ctkDependencyGraph::ctkInternal::ctkInternal(ctkDependencyGraph* p)
  58. {
  59. Q_ASSERT(p);
  60. this->P = p;
  61. this->NVertices = 0;
  62. this->NEdges = 0;
  63. this->Abort = false;
  64. this->Verbose = false;
  65. this->CycleDetected = false;
  66. this->CycleOrigin = 0;
  67. this->CycleEnd = 0;
  68. }
  69. //----------------------------------------------------------------------------
  70. void ctkDependencyGraph::ctkInternal::computeIndegrees(QVarLengthArray<int, MAXV>& computedIndegrees)
  71. {
  72. for (int i=1; i <= this->NVertices; i++)
  73. {
  74. computedIndegrees[i] = 0;
  75. }
  76. for (int i=1; i <= this->NVertices; i++)
  77. {
  78. for (int j=0; j < this->Degree[i]; j++)
  79. {
  80. computedIndegrees[ this->edge(i,j) ] ++;
  81. }
  82. }
  83. }
  84. //----------------------------------------------------------------------------
  85. void ctkDependencyGraph::ctkInternal::traverseUsingDFS(int v)
  86. {
  87. // allow for search termination
  88. if (this->Abort)
  89. {
  90. return;
  91. }
  92. this->Discovered[v] = true;
  93. this->processVertex(v);
  94. int y; // successor vertex
  95. for (int i=0; i<this->Degree[v]; i++)
  96. {
  97. y = this->edge(v, i);
  98. if (this->P->shouldExcludeEdge(this->edge(v, i)) == false)
  99. {
  100. if (this->Discovered[y] == false)
  101. {
  102. this->Parent[y] = v;
  103. this->traverseUsingDFS(y);
  104. }
  105. else
  106. {
  107. if (this->Processed[y] == false)
  108. {
  109. this->processEdge(v,y);
  110. }
  111. }
  112. }
  113. if (this->Abort)
  114. {
  115. return;
  116. }
  117. }
  118. this->Processed[v] = true;
  119. }
  120. //----------------------------------------------------------------------------
  121. void ctkDependencyGraph::ctkInternal::processEdge(int from, int to)
  122. {
  123. if (this->Parent[from] != to)
  124. {
  125. this->CycleDetected = true;
  126. this->CycleOrigin = to;
  127. this->CycleEnd = from;
  128. if (this->Verbose)
  129. {
  130. QList<int> path;
  131. this->P->findPath(from, to, path);
  132. qWarning() << "Cycle detected from " << to << " to " << from;
  133. qWarning() << " " << path;
  134. path.clear();
  135. this->P->findPath(to, from, path);
  136. qWarning() << " " << path;
  137. }
  138. this->Abort = true;
  139. }
  140. }
  141. //----------------------------------------------------------------------------
  142. void ctkDependencyGraph::ctkInternal::processVertex(int v)
  143. {
  144. if (this->Verbose)
  145. {
  146. qDebug() << "processed vertex " << v;
  147. }
  148. }
  149. //----------------------------------------------------------------------------
  150. void ctkDependencyGraph::ctkInternal::setEdge(int vertice, int degree, int value)
  151. {
  152. Q_ASSERT(vertice <= this->NVertices);
  153. Q_ASSERT(degree < MAXDEGREE);
  154. (*this->Edges[vertice])[degree] = value;
  155. }
  156. //----------------------------------------------------------------------------
  157. int ctkDependencyGraph::ctkInternal::edge(int vertice, int degree)
  158. {
  159. Q_ASSERT(vertice <= this->NVertices);
  160. Q_ASSERT(degree < MAXDEGREE);
  161. return (*this->Edges[vertice])[degree];
  162. }
  163. //----------------------------------------------------------------------------
  164. // ctkDependencyGraph methods
  165. //----------------------------------------------------------------------------
  166. ctkDependencyGraph::ctkDependencyGraph(int nvertices, int nedges)
  167. {
  168. this->Internal = new ctkInternal(this);
  169. this->Internal->NVertices = nvertices;
  170. this->Internal->NEdges = nedges;
  171. // Resize internal array
  172. this->Internal->Processed.resize(nvertices + 1);
  173. this->Internal->Discovered.resize(nvertices + 1);
  174. this->Internal->Parent.resize(nvertices + 1);
  175. this->Internal->Edges.resize(nvertices + 1);
  176. this->Internal->Degree.resize(nvertices + 1);
  177. for (int i=1; i <= nvertices; i++)
  178. {
  179. this->Internal->Degree[i] = 0;
  180. }
  181. // initialize Edge adjacency list
  182. for (int i=0; i <= nvertices; i++)
  183. {
  184. this->Internal->Edges[i] = new QVarLengthArray<int, MAXDEGREE>();
  185. this->Internal->Edges[i]->resize(MAXDEGREE);
  186. }
  187. // initialize search
  188. for (int i=1; i <= nvertices; i++)
  189. {
  190. this->Internal->Processed[i] = false;
  191. this->Internal->Discovered[i] = false;
  192. this->Internal->Parent[i] = -1;
  193. }
  194. }
  195. //----------------------------------------------------------------------------
  196. ctkDependencyGraph::~ctkDependencyGraph()
  197. {
  198. // Clean memory
  199. for (int i=0; i <= this->Internal->NVertices; i++)
  200. {
  201. delete this->Internal->Edges[i];
  202. }
  203. delete this->Internal;
  204. }
  205. //----------------------------------------------------------------------------
  206. void ctkDependencyGraph::printAdditionalInfo()
  207. {
  208. qDebug() << "ctkDependencyGraph (" << this << ")" << endl
  209. << " NVertices:" << this->numberOfVertices() << endl
  210. << " NEdges:" << this->numberOfEdges() << endl
  211. << " Abort:" << this->Internal->Abort;
  212. qDebug() << " [Processed]";
  213. for(int i=1; i < this->Internal->Processed.size(); i++)
  214. {
  215. qDebug() << i << "->" << this->Internal->Processed[i];
  216. }
  217. qDebug() << " [Discovered]";
  218. for(int i=1; i < this->Internal->Discovered.size(); i++)
  219. {
  220. qDebug() << i << "->" << this->Internal->Discovered[i];
  221. }
  222. qDebug() << " [Parent]";
  223. for(int i=1; i < this->Internal->Parent.size(); i++)
  224. {
  225. qDebug() << i << "->" << this->Internal->Parent[i];
  226. }
  227. qDebug() << " [Graph]";
  228. this->printGraph();
  229. }
  230. //----------------------------------------------------------------------------
  231. void ctkDependencyGraph::printGraph()
  232. {
  233. for(int i=1; i <= this->Internal->NVertices; i++)
  234. {
  235. std::cout << i << ":";
  236. for (int j=0; j < this->Internal->Degree[i]; j++)
  237. {
  238. std::cout << " " << this->Internal->edge(i, j);
  239. }
  240. std::cout << std::endl;
  241. }
  242. }
  243. //----------------------------------------------------------------------------
  244. int ctkDependencyGraph::numberOfVertices()
  245. {
  246. return this->Internal->NVertices;
  247. }
  248. //----------------------------------------------------------------------------
  249. int ctkDependencyGraph::numberOfEdges()
  250. {
  251. return this->Internal->NEdges;
  252. }
  253. //----------------------------------------------------------------------------
  254. void ctkDependencyGraph::setVerbose(bool verbose)
  255. {
  256. this->Internal->Verbose = verbose;
  257. }
  258. //----------------------------------------------------------------------------
  259. void ctkDependencyGraph::setEdgeListToExclude(const QList<int>& list)
  260. {
  261. this->Internal->ListOfEdgeToExclude = list;
  262. }
  263. //----------------------------------------------------------------------------
  264. bool ctkDependencyGraph::shouldExcludeEdge(int edge)
  265. {
  266. return this->Internal->ListOfEdgeToExclude.contains(edge);
  267. }
  268. //----------------------------------------------------------------------------
  269. bool ctkDependencyGraph::checkForCycle()
  270. {
  271. if (this->Internal->NEdges > 0)
  272. {
  273. // get a valid vertice Id
  274. int verticeId = 1;
  275. this->Internal->traverseUsingDFS(verticeId);
  276. }
  277. return this->cycleDetected();
  278. }
  279. //----------------------------------------------------------------------------
  280. bool ctkDependencyGraph::cycleDetected()
  281. {
  282. return this->Internal->CycleDetected;
  283. }
  284. //----------------------------------------------------------------------------
  285. int ctkDependencyGraph::cycleOrigin()
  286. {
  287. return this->Internal->CycleOrigin;
  288. }
  289. //----------------------------------------------------------------------------
  290. int ctkDependencyGraph::cycleEnd()
  291. {
  292. return this->Internal->CycleEnd;
  293. }
  294. //----------------------------------------------------------------------------
  295. void ctkDependencyGraph::insertEdge(int from, int to)
  296. {
  297. Q_ASSERT(from > 0 && from <= this->Internal->NVertices);
  298. Q_ASSERT(to > 0 && to <= this->Internal->NVertices);
  299. // resize if needed
  300. int capacity = this->Internal->Edges[from]->capacity();
  301. if (this->Internal->Degree[from] > capacity)
  302. {
  303. this->Internal->Edges[from]->resize(capacity + capacity * 0.3);
  304. }
  305. this->Internal->setEdge(from, this->Internal->Degree[from], to);
  306. this->Internal->Degree[from]++;
  307. this->Internal->NEdges++;
  308. }
  309. //----------------------------------------------------------------------------
  310. void ctkDependencyGraph::findPath(int from, int to, QList<int>& path)
  311. {
  312. if ((from == to) || (to == -1))
  313. {
  314. path << from;
  315. }
  316. else
  317. {
  318. this->findPath(from, this->Internal->Parent[to], path);
  319. path << to;
  320. }
  321. }
  322. //----------------------------------------------------------------------------
  323. bool ctkDependencyGraph::topologicalSort(QList<int>& sorted)
  324. {
  325. QVarLengthArray<int, MAXV> indegree; // indegree of each vertex
  326. QQueue<int> zeroin; // vertices of indegree 0
  327. int x, y; // current and next vertex
  328. indegree.resize(this->Internal->NVertices + 1);
  329. // resize if needed
  330. if (this->Internal->NVertices > MAXV)
  331. {
  332. indegree.resize(this->Internal->NVertices);
  333. }
  334. this->Internal->computeIndegrees(indegree);
  335. for (int i=1; i <= this->Internal->NVertices; i++)
  336. {
  337. if (indegree[i] == 0)
  338. {
  339. zeroin.enqueue(i);
  340. }
  341. }
  342. int j=0;
  343. while (zeroin.empty() == false)
  344. {
  345. j = j+1;
  346. x = zeroin.dequeue();
  347. sorted << x;
  348. for (int i=0; i < this->Internal->Degree[x]; i++)
  349. {
  350. y = this->Internal->edge(x, i);
  351. indegree[y] --;
  352. if (indegree[y] == 0)
  353. {
  354. zeroin.enqueue(y);
  355. }
  356. }
  357. }
  358. if (j != this->Internal->NVertices)
  359. {
  360. return false;
  361. }
  362. return true;
  363. }