ctkDependencyGraph.cpp 13 KB

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