ctkDependencyGraph.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  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 outdegree
  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. int subgraphSize(int rootId);
  45. void subgraphSizeRec(int rootId, QSet<int>& uniqueVertices);
  46. void subgraphInsert(ctkDependencyGraph& subgraph, int rootId,
  47. QHash<int,int>& subgraphIdToGlobal, QHash<int,int>& globalIdToSubgraph);
  48. int getOrGenerateSubgraphId(QHash<int, int>& subgraphIdToGlobal,
  49. QHash<int, int>& globalIdToSubgraph,
  50. int globalId);
  51. /// See http://en.wikipedia.org/wiki/Adjacency_list
  52. QVarLengthArray<QVarLengthArray<int,MAXDEGREE>*, MAXV+1> Edges;
  53. QVarLengthArray<int, MAXV+1> OutDegree;
  54. QVarLengthArray<int, MAXV+1> InDegree;
  55. int NVertices;
  56. int NEdges;
  57. /// Structure used by DFS
  58. /// See http://en.wikipedia.org/wiki/Depth-first_search
  59. QVarLengthArray<bool, MAXV> Processed; // processed vertices
  60. QVarLengthArray<bool, MAXV> Discovered; // discovered vertices
  61. QVarLengthArray<int, MAXV> Parent; // relation discovered
  62. bool Abort; // Flag indicating if traverse should be aborted
  63. bool Verbose;
  64. bool CycleDetected;
  65. int CycleOrigin;
  66. int CycleEnd;
  67. QList<int> ListOfEdgeToExclude;
  68. /// Pointer to the public API
  69. ctkDependencyGraph* P;
  70. };
  71. //----------------------------------------------------------------------------
  72. // ctkInternal methods
  73. //----------------------------------------------------------------------------
  74. ctkDependencyGraph::ctkInternal::ctkInternal(ctkDependencyGraph* p)
  75. {
  76. Q_ASSERT(p);
  77. this->P = p;
  78. this->NVertices = 0;
  79. this->NEdges = 0;
  80. this->Abort = false;
  81. this->Verbose = false;
  82. this->CycleDetected = false;
  83. this->CycleOrigin = 0;
  84. this->CycleEnd = 0;
  85. }
  86. //----------------------------------------------------------------------------
  87. void ctkDependencyGraph::ctkInternal::computeOutdegrees(QVarLengthArray<int, MAXV>& computedOutdegrees)
  88. {
  89. for (int i=1; i <= this->NVertices; i++)
  90. {
  91. computedOutdegrees[i] = 0;
  92. }
  93. for (int i=1; i <= this->NVertices; i++)
  94. {
  95. for (int j=0; j < this->OutDegree[i]; j++)
  96. {
  97. computedOutdegrees[ this->edge(i,j) ] ++;
  98. }
  99. }
  100. }
  101. //----------------------------------------------------------------------------
  102. void ctkDependencyGraph::ctkInternal::traverseUsingDFS(int v)
  103. {
  104. // allow for search termination
  105. if (this->Abort)
  106. {
  107. return;
  108. }
  109. this->Discovered[v] = true;
  110. this->processVertex(v);
  111. int y; // successor vertex
  112. for (int i=0; i<this->OutDegree[v]; i++)
  113. {
  114. y = this->edge(v, i);
  115. if (this->P->shouldExcludeEdge(this->edge(v, i)) == false)
  116. {
  117. this->Parent[y] = v;
  118. if (this->Discovered[y] == false)
  119. {
  120. this->traverseUsingDFS(y);
  121. }
  122. else
  123. {
  124. if (this->Processed[y] == false)
  125. {
  126. this->processEdge(v,y);
  127. }
  128. }
  129. }
  130. if (this->Abort)
  131. {
  132. return;
  133. }
  134. }
  135. this->Processed[v] = true;
  136. }
  137. //----------------------------------------------------------------------------
  138. void ctkDependencyGraph::ctkInternal::processEdge(int from, int to)
  139. {
  140. if (this->Discovered[to] == true)
  141. {
  142. this->CycleDetected = true;
  143. this->CycleOrigin = to;
  144. this->CycleEnd = from;
  145. if (this->Verbose)
  146. {
  147. QList<int> path;
  148. this->findPathDFS(from, to, path);
  149. qWarning() << "Cycle detected from " << to << " to " << from;
  150. qWarning() << " " << path;
  151. path.clear();
  152. this->findPathDFS(to, from, path);
  153. qWarning() << " " << path;
  154. }
  155. this->Abort = true;
  156. }
  157. }
  158. //----------------------------------------------------------------------------
  159. void ctkDependencyGraph::ctkInternal::processVertex(int v)
  160. {
  161. if (this->Verbose)
  162. {
  163. qDebug() << "processed vertex " << v;
  164. }
  165. }
  166. //----------------------------------------------------------------------------
  167. void ctkDependencyGraph::ctkInternal::setEdge(int vertice, int degree, int value)
  168. {
  169. Q_ASSERT(vertice <= this->NVertices);
  170. Q_ASSERT(degree < MAXDEGREE);
  171. (*this->Edges[vertice])[degree] = value;
  172. }
  173. //----------------------------------------------------------------------------
  174. int ctkDependencyGraph::ctkInternal::edge(int vertice, int degree)
  175. {
  176. Q_ASSERT(vertice <= this->NVertices);
  177. Q_ASSERT(degree < MAXDEGREE);
  178. return (*this->Edges[vertice])[degree];
  179. }
  180. //----------------------------------------------------------------------------
  181. void ctkDependencyGraph::ctkInternal::findPathDFS(int from, int to, QList<int>& path)
  182. {
  183. if ((from == to) || (to == -1))
  184. {
  185. path << from;
  186. }
  187. else
  188. {
  189. this->findPathDFS(from, this->Parent[to], path);
  190. path << to;
  191. }
  192. }
  193. //----------------------------------------------------------------------------
  194. void ctkDependencyGraph::ctkInternal::findPathsRec(
  195. int from, int to, QList<int>* path, QList<QList<int>* >& paths)
  196. {
  197. if (from == to)
  198. {
  199. return;
  200. }
  201. QList<int> branch(*path);
  202. int child = from;
  203. for (int j=0; j < this->OutDegree[child]; j++)
  204. {
  205. if (j == 0)
  206. {
  207. int parent = this->edge(child, j);
  208. *path << parent;
  209. this->findPathsRec(parent, to, path, paths);
  210. }
  211. else
  212. {
  213. int parent = this->edge(child, j);
  214. // Copy path and add it to the list
  215. QList<int>* pathCopy = new QList<int>(branch);
  216. paths << pathCopy;
  217. *pathCopy << parent;
  218. this->findPathsRec(parent, to, pathCopy, paths);
  219. }
  220. }
  221. }
  222. void ctkDependencyGraph::ctkInternal::verticesWithIndegree(int indegree, QList<int>& list)
  223. {
  224. Q_ASSERT(indegree >= 0);
  225. for (int i=1; i <= this->NVertices; i++)
  226. {
  227. if (this->InDegree[i] == indegree)
  228. {
  229. list << i;
  230. }
  231. }
  232. }
  233. void ctkDependencyGraph::ctkInternal::subgraphSizeRec(int rootId, QSet<int>& uniqueVertices)
  234. {
  235. Q_ASSERT(rootId > 0);
  236. for (int i = 0; i < this->OutDegree[rootId]; ++i)
  237. {
  238. int child = this->edge(rootId, i);
  239. uniqueVertices << child;
  240. subgraphSizeRec(child, uniqueVertices);
  241. }
  242. }
  243. int ctkDependencyGraph::ctkInternal::subgraphSize(int rootId)
  244. {
  245. Q_ASSERT(rootId > 0);
  246. QSet<int> vertices;
  247. vertices << rootId;
  248. this->subgraphSizeRec(rootId, vertices);
  249. return vertices.size();
  250. }
  251. void ctkDependencyGraph::ctkInternal::subgraphInsert(
  252. ctkDependencyGraph& subgraph, int rootId,
  253. QHash<int,int>& subgraphIdToGlobal, QHash<int,int>& globalIdToSubgraph)
  254. {
  255. int from = this->getOrGenerateSubgraphId(subgraphIdToGlobal, globalIdToSubgraph, rootId);
  256. for (int i = 0; i < this->OutDegree[rootId]; ++i)
  257. {
  258. int childId = this->edge(rootId, i);
  259. int to = this->getOrGenerateSubgraphId(subgraphIdToGlobal, globalIdToSubgraph,
  260. childId);
  261. subgraph.insertEdge(from, to);
  262. this->subgraphInsert(subgraph, childId, subgraphIdToGlobal, globalIdToSubgraph);
  263. }
  264. }
  265. int ctkDependencyGraph::ctkInternal::getOrGenerateSubgraphId(
  266. QHash<int, int>& subgraphIdToGlobal,
  267. QHash<int, int>& globalIdToSubgraph,
  268. int globalId)
  269. {
  270. // If needed, generate vertex id
  271. int subgraphId = -1;
  272. if (!globalIdToSubgraph.keys().contains(globalId))
  273. {
  274. subgraphId = globalIdToSubgraph.keys().size() + 1;
  275. globalIdToSubgraph[globalId] = subgraphId;
  276. subgraphIdToGlobal[subgraphId] = globalId;
  277. }
  278. else
  279. {
  280. subgraphId = globalIdToSubgraph[globalId];
  281. }
  282. return subgraphId;
  283. }
  284. //----------------------------------------------------------------------------
  285. // ctkDependencyGraph methods
  286. //----------------------------------------------------------------------------
  287. ctkDependencyGraph::ctkDependencyGraph(int nvertices)
  288. {
  289. this->Internal = new ctkInternal(this);
  290. this->Internal->NVertices = nvertices;
  291. // Resize internal array
  292. this->Internal->Processed.resize(nvertices + 1);
  293. this->Internal->Discovered.resize(nvertices + 1);
  294. this->Internal->Parent.resize(nvertices + 1);
  295. this->Internal->Edges.resize(nvertices + 1);
  296. this->Internal->OutDegree.resize(nvertices + 1);
  297. this->Internal->InDegree.resize(nvertices + 1);
  298. for (int i=1; i <= nvertices; i++)
  299. {
  300. this->Internal->OutDegree[i] = 0;
  301. this->Internal->InDegree[i] = 0;
  302. }
  303. // initialize Edge adjacency list
  304. for (int i=0; i <= nvertices; i++)
  305. {
  306. this->Internal->Edges[i] = new QVarLengthArray<int, MAXDEGREE>();
  307. this->Internal->Edges[i]->resize(MAXDEGREE);
  308. }
  309. // initialize search
  310. for (int i=1; i <= nvertices; i++)
  311. {
  312. this->Internal->Processed[i] = false;
  313. this->Internal->Discovered[i] = false;
  314. this->Internal->Parent[i] = -1;
  315. }
  316. }
  317. //----------------------------------------------------------------------------
  318. ctkDependencyGraph::~ctkDependencyGraph()
  319. {
  320. // Clean memory
  321. for (int i=0; i <= this->Internal->NVertices; i++)
  322. {
  323. delete this->Internal->Edges[i];
  324. }
  325. delete this->Internal;
  326. }
  327. //----------------------------------------------------------------------------
  328. void ctkDependencyGraph::printAdditionalInfo()
  329. {
  330. qDebug() << "ctkDependencyGraph (" << this << ")" << endl
  331. << " NVertices:" << this->numberOfVertices() << endl
  332. << " NEdges:" << this->numberOfEdges() << endl
  333. << " Abort:" << this->Internal->Abort;
  334. qDebug() << " [Processed]";
  335. for(int i=1; i < this->Internal->Processed.size(); i++)
  336. {
  337. qDebug() << i << "->" << this->Internal->Processed[i];
  338. }
  339. qDebug() << " [Discovered]";
  340. for(int i=1; i < this->Internal->Discovered.size(); i++)
  341. {
  342. qDebug() << i << "->" << this->Internal->Discovered[i];
  343. }
  344. qDebug() << " [Parent]";
  345. for(int i=1; i < this->Internal->Parent.size(); i++)
  346. {
  347. qDebug() << i << "->" << this->Internal->Parent[i];
  348. }
  349. qDebug() << " [Graph]";
  350. this->printGraph();
  351. }
  352. //----------------------------------------------------------------------------
  353. void ctkDependencyGraph::printGraph()
  354. {
  355. for(int i=1; i <= this->Internal->NVertices; i++)
  356. {
  357. std::cout << i << ":";
  358. for (int j=0; j < this->Internal->OutDegree[i]; j++)
  359. {
  360. std::cout << " " << this->Internal->edge(i, j);
  361. }
  362. std::cout << std::endl;
  363. }
  364. }
  365. //----------------------------------------------------------------------------
  366. int ctkDependencyGraph::numberOfVertices()
  367. {
  368. return this->Internal->NVertices;
  369. }
  370. //----------------------------------------------------------------------------
  371. int ctkDependencyGraph::numberOfEdges()
  372. {
  373. return this->Internal->NEdges;
  374. }
  375. //----------------------------------------------------------------------------
  376. void ctkDependencyGraph::setVerbose(bool verbose)
  377. {
  378. this->Internal->Verbose = verbose;
  379. }
  380. //----------------------------------------------------------------------------
  381. void ctkDependencyGraph::setEdgeListToExclude(const QList<int>& list)
  382. {
  383. this->Internal->ListOfEdgeToExclude = list;
  384. }
  385. //----------------------------------------------------------------------------
  386. bool ctkDependencyGraph::shouldExcludeEdge(int edge)
  387. {
  388. return this->Internal->ListOfEdgeToExclude.contains(edge);
  389. }
  390. //----------------------------------------------------------------------------
  391. bool ctkDependencyGraph::checkForCycle()
  392. {
  393. if (this->Internal->NEdges > 0)
  394. {
  395. // Store unprocessed vertex ids
  396. QList<int> uncheckedVertices;
  397. for (int i = 1; i <= this->Internal->NVertices; ++i)
  398. {
  399. uncheckedVertices << i;
  400. }
  401. // Start the cycle detection on the source vertices
  402. QList<int> sources;
  403. this->sourceVertices(sources);
  404. foreach(int sourceId, sources)
  405. {
  406. this->Internal->traverseUsingDFS(sourceId);
  407. if (this->cycleDetected()) return true;
  408. for (int i=0; i < this->Internal->Processed.size(); i++)
  409. {
  410. if (this->Internal->Processed[i] == true)
  411. {
  412. uncheckedVertices.removeOne(i);
  413. }
  414. this->Internal->Discovered[i] = false;
  415. this->Internal->Processed[i] = false;
  416. }
  417. }
  418. // If a component does not have a source vertex,
  419. // i.e. it is a cycle a -> b -> a, check all non
  420. // processed vertices.
  421. while (!uncheckedVertices.empty())
  422. {
  423. this->Internal->traverseUsingDFS(uncheckedVertices.last());
  424. if (this->cycleDetected()) return true;
  425. for (int i=0; i < this->Internal->Processed.size(); i++)
  426. {
  427. if (this->Internal->Processed[i] == true)
  428. {
  429. uncheckedVertices.removeOne(i);
  430. }
  431. this->Internal->Discovered[i] = false;
  432. this->Internal->Processed[i] = false;
  433. }
  434. }
  435. }
  436. return this->cycleDetected();
  437. }
  438. //----------------------------------------------------------------------------
  439. bool ctkDependencyGraph::cycleDetected()
  440. {
  441. return this->Internal->CycleDetected;
  442. }
  443. //----------------------------------------------------------------------------
  444. int ctkDependencyGraph::cycleOrigin()
  445. {
  446. return this->Internal->CycleOrigin;
  447. }
  448. //----------------------------------------------------------------------------
  449. int ctkDependencyGraph::cycleEnd()
  450. {
  451. return this->Internal->CycleEnd;
  452. }
  453. //----------------------------------------------------------------------------
  454. void ctkDependencyGraph::insertEdge(int from, int to)
  455. {
  456. Q_ASSERT(from > 0 && from <= this->Internal->NVertices);
  457. Q_ASSERT(to > 0 && to <= this->Internal->NVertices);
  458. // resize if needed
  459. int capacity = this->Internal->Edges[from]->capacity();
  460. if (this->Internal->OutDegree[from] > capacity)
  461. {
  462. this->Internal->Edges[from]->resize(capacity + capacity * 0.3);
  463. }
  464. this->Internal->setEdge(from, this->Internal->OutDegree[from], to);
  465. this->Internal->OutDegree[from]++;
  466. this->Internal->InDegree[to]++;
  467. this->Internal->NEdges++;
  468. }
  469. //----------------------------------------------------------------------------
  470. void ctkDependencyGraph::findPaths(int from, int to, QList<QList<int>* >& paths)
  471. {
  472. QList<int>* path = new QList<int>;
  473. *path << from;
  474. paths << path;
  475. this->Internal->findPathsRec(from, to, path, paths);
  476. QList<int> pathToRemove;
  477. // Remove list no ending with the requested element
  478. int i = 0;
  479. while (!paths.isEmpty() && i < paths.size())
  480. {
  481. QList<int>* p = paths[i];
  482. Q_ASSERT(p);
  483. if (p->last() != to)
  484. {
  485. paths.removeAt(i);
  486. delete p;
  487. }
  488. else
  489. {
  490. i++;
  491. }
  492. }
  493. }
  494. //----------------------------------------------------------------------------
  495. void ctkDependencyGraph::findPath(int from, int to, QList<int>& path)
  496. {
  497. QList<QList<int>* > paths;
  498. this->findPaths(from, to, paths);
  499. if (!paths.empty())
  500. {
  501. path << *(paths.first());
  502. }
  503. qDeleteAll(paths);
  504. }
  505. //----------------------------------------------------------------------------
  506. bool ctkDependencyGraph::topologicalSort(QList<int>& sorted, int rootId)
  507. {
  508. if (rootId > 0)
  509. {
  510. ctkDependencyGraph subgraph(this->Internal->subgraphSize(rootId));
  511. QHash<int,int> subgraphIdToGlobal;
  512. QHash<int,int> globalIdToSubgraph;
  513. this->Internal->subgraphInsert(subgraph, rootId, subgraphIdToGlobal, globalIdToSubgraph);
  514. QList<int> subgraphSorted;
  515. bool result = subgraph.topologicalSort(subgraphSorted);
  516. foreach(int subgraphId, subgraphSorted)
  517. {
  518. sorted << subgraphIdToGlobal[subgraphId];
  519. }
  520. return result;
  521. }
  522. QVarLengthArray<int, MAXV> outdegree; // outdegree of each vertex
  523. QQueue<int> zeroout; // vertices of outdegree 0
  524. int x, y; // current and next vertex
  525. outdegree.resize(this->Internal->NVertices + 1);
  526. // resize if needed
  527. if (this->Internal->NVertices > MAXV)
  528. {
  529. outdegree.resize(this->Internal->NVertices);
  530. }
  531. this->Internal->computeOutdegrees(outdegree);
  532. for (int i=1; i <= this->Internal->NVertices; i++)
  533. {
  534. if (outdegree[i] == 0)
  535. {
  536. zeroout.enqueue(i);
  537. }
  538. }
  539. int j=0;
  540. while (zeroout.empty() == false)
  541. {
  542. j = j+1;
  543. x = zeroout.dequeue();
  544. sorted << x;
  545. for (int i=0; i < this->Internal->OutDegree[x]; i++)
  546. {
  547. y = this->Internal->edge(x, i);
  548. outdegree[y] --;
  549. if (outdegree[y] == 0)
  550. {
  551. zeroout.enqueue(y);
  552. }
  553. }
  554. }
  555. if (j != this->Internal->NVertices)
  556. {
  557. return false;
  558. }
  559. return true;
  560. }
  561. void ctkDependencyGraph::sourceVertices(QList<int>& sources)
  562. {
  563. this->Internal->verticesWithIndegree(0, sources);
  564. }