ctkDependencyGraph.cpp 11 KB

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