ctkDependencyGraph.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  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 computeOutdegrees(QVarLengthArray<int, MAXV>& computedOutdegrees);
  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. void verticesWithIndegree(int indegree, QList<int>& list);
  44. /// See http://en.wikipedia.org/wiki/Adjacency_list
  45. QVarLengthArray<QVarLengthArray<int,MAXDEGREE>*, MAXV+1> Edges;
  46. QVarLengthArray<int, MAXV+1> OutDegree;
  47. QVarLengthArray<int, MAXV+1> InDegree;
  48. int NVertices;
  49. int NEdges;
  50. /// Structure used by DFS
  51. /// See http://en.wikipedia.org/wiki/Depth-first_search
  52. QVarLengthArray<bool, MAXV> Processed; // processed vertices
  53. QVarLengthArray<bool, MAXV> Discovered; // discovered vertices
  54. QVarLengthArray<int, MAXV> Parent; // relation discovered
  55. bool Abort; // Flag indicating if traverse should be aborted
  56. bool Verbose;
  57. bool CycleDetected;
  58. int CycleOrigin;
  59. int CycleEnd;
  60. QList<int> ListOfEdgeToExclude;
  61. /// Pointer to the public API
  62. ctkDependencyGraph* P;
  63. };
  64. //----------------------------------------------------------------------------
  65. // ctkInternal methods
  66. //----------------------------------------------------------------------------
  67. ctkDependencyGraph::ctkInternal::ctkInternal(ctkDependencyGraph* p)
  68. {
  69. Q_ASSERT(p);
  70. this->P = p;
  71. this->NVertices = 0;
  72. this->NEdges = 0;
  73. this->Abort = false;
  74. this->Verbose = false;
  75. this->CycleDetected = false;
  76. this->CycleOrigin = 0;
  77. this->CycleEnd = 0;
  78. }
  79. //----------------------------------------------------------------------------
  80. void ctkDependencyGraph::ctkInternal::computeOutdegrees(QVarLengthArray<int, MAXV>& computedOutdegrees)
  81. {
  82. for (int i=1; i <= this->NVertices; i++)
  83. {
  84. computedOutdegrees[i] = 0;
  85. }
  86. for (int i=1; i <= this->NVertices; i++)
  87. {
  88. for (int j=0; j < this->OutDegree[i]; j++)
  89. {
  90. computedOutdegrees[ this->edge(i,j) ] ++;
  91. }
  92. }
  93. }
  94. //----------------------------------------------------------------------------
  95. void ctkDependencyGraph::ctkInternal::traverseUsingDFS(int v)
  96. {
  97. // allow for search termination
  98. if (this->Abort)
  99. {
  100. return;
  101. }
  102. this->Discovered[v] = true;
  103. this->processVertex(v);
  104. int y; // successor vertex
  105. for (int i=0; i<this->OutDegree[v]; i++)
  106. {
  107. y = this->edge(v, i);
  108. if (this->P->shouldExcludeEdge(this->edge(v, i)) == false)
  109. {
  110. this->Parent[y] = v;
  111. if (this->Discovered[y] == false)
  112. {
  113. this->traverseUsingDFS(y);
  114. }
  115. else
  116. {
  117. if (this->Processed[y] == false)
  118. {
  119. this->processEdge(v,y);
  120. }
  121. }
  122. }
  123. if (this->Abort)
  124. {
  125. return;
  126. }
  127. }
  128. this->Processed[v] = true;
  129. }
  130. //----------------------------------------------------------------------------
  131. void ctkDependencyGraph::ctkInternal::processEdge(int from, int to)
  132. {
  133. if (this->Discovered[to] == true)
  134. {
  135. this->CycleDetected = true;
  136. this->CycleOrigin = to;
  137. this->CycleEnd = from;
  138. if (this->Verbose)
  139. {
  140. QList<int> path;
  141. this->findPathDFS(from, to, path);
  142. qWarning() << "Cycle detected from " << to << " to " << from;
  143. qWarning() << " " << path;
  144. path.clear();
  145. this->findPathDFS(to, from, path);
  146. qWarning() << " " << path;
  147. }
  148. this->Abort = true;
  149. }
  150. }
  151. //----------------------------------------------------------------------------
  152. void ctkDependencyGraph::ctkInternal::processVertex(int v)
  153. {
  154. if (this->Verbose)
  155. {
  156. qDebug() << "processed vertex " << v;
  157. }
  158. }
  159. //----------------------------------------------------------------------------
  160. void ctkDependencyGraph::ctkInternal::setEdge(int vertice, int degree, int value)
  161. {
  162. Q_ASSERT(vertice <= this->NVertices);
  163. Q_ASSERT(degree < MAXDEGREE);
  164. (*this->Edges[vertice])[degree] = value;
  165. }
  166. //----------------------------------------------------------------------------
  167. int ctkDependencyGraph::ctkInternal::edge(int vertice, int degree)
  168. {
  169. Q_ASSERT(vertice <= this->NVertices);
  170. Q_ASSERT(degree < MAXDEGREE);
  171. return (*this->Edges[vertice])[degree];
  172. }
  173. //----------------------------------------------------------------------------
  174. void ctkDependencyGraph::ctkInternal::findPathDFS(int from, int to, QList<int>& path)
  175. {
  176. if ((from == to) || (to == -1))
  177. {
  178. path << from;
  179. }
  180. else
  181. {
  182. this->findPathDFS(from, this->Parent[to], path);
  183. path << to;
  184. }
  185. }
  186. //----------------------------------------------------------------------------
  187. void ctkDependencyGraph::ctkInternal::findPathsRec(
  188. int from, int to, QList<int>* path, QList<QList<int>* >& paths)
  189. {
  190. if (from == to)
  191. {
  192. return;
  193. }
  194. QList<int> branch(*path);
  195. int child = from;
  196. for (int j=0; j < this->OutDegree[child]; j++)
  197. {
  198. if (j == 0)
  199. {
  200. int parent = this->edge(child, j);
  201. *path << parent;
  202. this->findPathsRec(parent, to, path, paths);
  203. }
  204. else
  205. {
  206. int parent = this->edge(child, j);
  207. // Copy path and add it to the list
  208. QList<int>* pathCopy = new QList<int>(branch);
  209. paths << pathCopy;
  210. *pathCopy << parent;
  211. this->findPathsRec(parent, to, pathCopy, paths);
  212. }
  213. }
  214. }
  215. void ctkDependencyGraph::ctkInternal::verticesWithIndegree(int indegree, QList<int>& list)
  216. {
  217. Q_ASSERT(indegree >= 0);
  218. for (int i=1; i <= this->NVertices; i++)
  219. {
  220. if (this->InDegree[i] == indegree)
  221. {
  222. list << i;
  223. }
  224. }
  225. }
  226. //----------------------------------------------------------------------------
  227. // ctkDependencyGraph methods
  228. //----------------------------------------------------------------------------
  229. ctkDependencyGraph::ctkDependencyGraph(int nvertices)
  230. {
  231. this->Internal = new ctkInternal(this);
  232. this->Internal->NVertices = nvertices;
  233. // Resize internal array
  234. this->Internal->Processed.resize(nvertices + 1);
  235. this->Internal->Discovered.resize(nvertices + 1);
  236. this->Internal->Parent.resize(nvertices + 1);
  237. this->Internal->Edges.resize(nvertices + 1);
  238. this->Internal->OutDegree.resize(nvertices + 1);
  239. this->Internal->InDegree.resize(nvertices + 1);
  240. for (int i=1; i <= nvertices; i++)
  241. {
  242. this->Internal->OutDegree[i] = 0;
  243. this->Internal->InDegree[i] = 0;
  244. }
  245. // initialize Edge adjacency list
  246. for (int i=0; i <= nvertices; i++)
  247. {
  248. this->Internal->Edges[i] = new QVarLengthArray<int, MAXDEGREE>();
  249. this->Internal->Edges[i]->resize(MAXDEGREE);
  250. }
  251. // initialize search
  252. for (int i=1; i <= nvertices; i++)
  253. {
  254. this->Internal->Processed[i] = false;
  255. this->Internal->Discovered[i] = false;
  256. this->Internal->Parent[i] = -1;
  257. }
  258. }
  259. //----------------------------------------------------------------------------
  260. ctkDependencyGraph::~ctkDependencyGraph()
  261. {
  262. // Clean memory
  263. for (int i=0; i <= this->Internal->NVertices; i++)
  264. {
  265. delete this->Internal->Edges[i];
  266. }
  267. delete this->Internal;
  268. }
  269. //----------------------------------------------------------------------------
  270. void ctkDependencyGraph::printAdditionalInfo()
  271. {
  272. qDebug() << "ctkDependencyGraph (" << this << ")" << endl
  273. << " NVertices:" << this->numberOfVertices() << endl
  274. << " NEdges:" << this->numberOfEdges() << endl
  275. << " Abort:" << this->Internal->Abort;
  276. qDebug() << " [Processed]";
  277. for(int i=1; i < this->Internal->Processed.size(); i++)
  278. {
  279. qDebug() << i << "->" << this->Internal->Processed[i];
  280. }
  281. qDebug() << " [Discovered]";
  282. for(int i=1; i < this->Internal->Discovered.size(); i++)
  283. {
  284. qDebug() << i << "->" << this->Internal->Discovered[i];
  285. }
  286. qDebug() << " [Parent]";
  287. for(int i=1; i < this->Internal->Parent.size(); i++)
  288. {
  289. qDebug() << i << "->" << this->Internal->Parent[i];
  290. }
  291. qDebug() << " [Graph]";
  292. this->printGraph();
  293. }
  294. //----------------------------------------------------------------------------
  295. void ctkDependencyGraph::printGraph()
  296. {
  297. for(int i=1; i <= this->Internal->NVertices; i++)
  298. {
  299. std::cout << i << ":";
  300. for (int j=0; j < this->Internal->OutDegree[i]; j++)
  301. {
  302. std::cout << " " << this->Internal->edge(i, j);
  303. }
  304. std::cout << std::endl;
  305. }
  306. }
  307. //----------------------------------------------------------------------------
  308. int ctkDependencyGraph::numberOfVertices()
  309. {
  310. return this->Internal->NVertices;
  311. }
  312. //----------------------------------------------------------------------------
  313. int ctkDependencyGraph::numberOfEdges()
  314. {
  315. return this->Internal->NEdges;
  316. }
  317. //----------------------------------------------------------------------------
  318. void ctkDependencyGraph::setVerbose(bool verbose)
  319. {
  320. this->Internal->Verbose = verbose;
  321. }
  322. //----------------------------------------------------------------------------
  323. void ctkDependencyGraph::setEdgeListToExclude(const QList<int>& list)
  324. {
  325. this->Internal->ListOfEdgeToExclude = list;
  326. }
  327. //----------------------------------------------------------------------------
  328. bool ctkDependencyGraph::shouldExcludeEdge(int edge)
  329. {
  330. return this->Internal->ListOfEdgeToExclude.contains(edge);
  331. }
  332. //----------------------------------------------------------------------------
  333. bool ctkDependencyGraph::checkForCycle()
  334. {
  335. if (this->Internal->NEdges > 0)
  336. {
  337. // get a valid vertice Id
  338. int verticeId = 1;
  339. this->Internal->traverseUsingDFS(verticeId);
  340. }
  341. return this->cycleDetected();
  342. }
  343. //----------------------------------------------------------------------------
  344. bool ctkDependencyGraph::cycleDetected()
  345. {
  346. return this->Internal->CycleDetected;
  347. }
  348. //----------------------------------------------------------------------------
  349. int ctkDependencyGraph::cycleOrigin()
  350. {
  351. return this->Internal->CycleOrigin;
  352. }
  353. //----------------------------------------------------------------------------
  354. int ctkDependencyGraph::cycleEnd()
  355. {
  356. return this->Internal->CycleEnd;
  357. }
  358. //----------------------------------------------------------------------------
  359. void ctkDependencyGraph::insertEdge(int from, int to)
  360. {
  361. Q_ASSERT(from > 0 && from <= this->Internal->NVertices);
  362. Q_ASSERT(to > 0 && to <= this->Internal->NVertices);
  363. // resize if needed
  364. int capacity = this->Internal->Edges[from]->capacity();
  365. if (this->Internal->OutDegree[from] > capacity)
  366. {
  367. this->Internal->Edges[from]->resize(capacity + capacity * 0.3);
  368. }
  369. this->Internal->setEdge(from, this->Internal->OutDegree[from], to);
  370. this->Internal->OutDegree[from]++;
  371. this->Internal->InDegree[to]++;
  372. this->Internal->NEdges++;
  373. }
  374. //----------------------------------------------------------------------------
  375. void ctkDependencyGraph::findPaths(int from, int to, QList<QList<int>* >& paths)
  376. {
  377. QList<int>* path = new QList<int>;
  378. *path << from;
  379. paths << path;
  380. this->Internal->findPathsRec(from, to, path, paths);
  381. QList<int> pathToRemove;
  382. // Remove list no ending with the requested element
  383. int i = 0;
  384. while (!paths.isEmpty() && i < paths.size())
  385. {
  386. QList<int>* p = paths[i];
  387. Q_ASSERT(p);
  388. if (p->last() != to)
  389. {
  390. paths.removeAt(i);
  391. delete p;
  392. }
  393. else
  394. {
  395. i++;
  396. }
  397. }
  398. }
  399. //----------------------------------------------------------------------------
  400. void ctkDependencyGraph::findPath(int from, int to, QList<int>& path)
  401. {
  402. int child = from;
  403. int parent = this->Internal->edge(child, 0);
  404. path << child;
  405. while (parent > 0)
  406. {
  407. path << parent;
  408. if (parent == to)
  409. {
  410. break;
  411. }
  412. child = parent;
  413. parent = this->Internal->edge(child, 0);
  414. }
  415. }
  416. //----------------------------------------------------------------------------
  417. bool ctkDependencyGraph::topologicalSort(QList<int>& sorted)
  418. {
  419. QVarLengthArray<int, MAXV> outdegree; // outdegree of each vertex
  420. QQueue<int> zeroout; // vertices of outdegree 0
  421. int x, y; // current and next vertex
  422. outdegree.resize(this->Internal->NVertices + 1);
  423. // resize if needed
  424. if (this->Internal->NVertices > MAXV)
  425. {
  426. outdegree.resize(this->Internal->NVertices);
  427. }
  428. this->Internal->computeOutdegrees(outdegree);
  429. for (int i=1; i <= this->Internal->NVertices; i++)
  430. {
  431. if (outdegree[i] == 0)
  432. {
  433. zeroout.enqueue(i);
  434. }
  435. }
  436. int j=0;
  437. while (zeroout.empty() == false)
  438. {
  439. j = j+1;
  440. x = zeroout.dequeue();
  441. sorted << x;
  442. for (int i=0; i < this->Internal->OutDegree[x]; i++)
  443. {
  444. y = this->Internal->edge(x, i);
  445. outdegree[y] --;
  446. if (outdegree[y] == 0)
  447. {
  448. zeroout.enqueue(y);
  449. }
  450. }
  451. }
  452. if (j != this->Internal->NVertices)
  453. {
  454. return false;
  455. }
  456. return true;
  457. }
  458. void ctkDependencyGraph::sourceVertices(QList<int>& sources)
  459. {
  460. this->Internal->verticesWithIndegree(0, sources);
  461. }