ctkDependencyGraph.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) 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.apache.org/licenses/LICENSE-2.0.txt
  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 ctkDependencyGraphPrivate
  26. {
  27. Q_DECLARE_PUBLIC(ctkDependencyGraph);
  28. public:
  29. ctkDependencyGraph* const q_ptr;
  30. ctkDependencyGraphPrivate(ctkDependencyGraph& p);
  31. /// Compute outdegree
  32. void computeOutdegrees(QVarLengthArray<int, MAXV>& computedOutdegrees);
  33. /// Traverse tree using Depth-first_search
  34. void traverseUsingDFS(int v);
  35. /// Called each time an edge is visited
  36. void processEdge(int from, int to);
  37. /// Called each time a vertex is processed
  38. void processVertex(int v);
  39. /// Retrieve the path between two vertices
  40. void findPathDFS(int from, int to, QList<int>& path);
  41. /// Recursive function used by findPaths to retrieve the path between two vertices
  42. void findPathsRec(int from, int to, QList<int>* path, QList<QList<int>* >& paths);
  43. void setEdge(int vertice, int degree, int value);
  44. int edge(int vertice, int degree)const;
  45. void verticesWithIndegree(int indegree, QList<int>& list);
  46. int subgraphSize(int rootId);
  47. void subgraphSizeRec(int rootId, QSet<int>& uniqueVertices);
  48. void subgraphInsert(ctkDependencyGraph& subgraph, int rootId,
  49. QHash<int,int>& subgraphIdToGlobal, QHash<int,int>& globalIdToSubgraph);
  50. int getOrGenerateSubgraphId(QHash<int, int>& subgraphIdToGlobal,
  51. QHash<int, int>& globalIdToSubgraph,
  52. int globalId);
  53. /// See http://en.wikipedia.org/wiki/Adjacency_list
  54. QVarLengthArray<QVarLengthArray<int,MAXDEGREE>*, MAXV+1> Edges;
  55. QVarLengthArray<int, MAXV+1> OutDegree;
  56. QVarLengthArray<int, MAXV+1> InDegree;
  57. int NVertices;
  58. int NEdges;
  59. /// Structure used by DFS
  60. /// See http://en.wikipedia.org/wiki/Depth-first_search
  61. QVarLengthArray<bool, MAXV> Processed; // processed vertices
  62. QVarLengthArray<bool, MAXV> Discovered; // discovered vertices
  63. QVarLengthArray<int, MAXV> Parent; // relation discovered
  64. bool Abort; // Flag indicating if traverse should be aborted
  65. bool Verbose;
  66. bool CycleDetected;
  67. int CycleOrigin;
  68. int CycleEnd;
  69. QList<int> ListOfEdgeToExclude;
  70. };
  71. //----------------------------------------------------------------------------
  72. // ctkInternal methods
  73. //----------------------------------------------------------------------------
  74. ctkDependencyGraphPrivate::ctkDependencyGraphPrivate(ctkDependencyGraph& object)
  75. :q_ptr(&object)
  76. {
  77. this->NVertices = 0;
  78. this->NEdges = 0;
  79. this->Abort = false;
  80. this->Verbose = false;
  81. this->CycleDetected = false;
  82. this->CycleOrigin = 0;
  83. this->CycleEnd = 0;
  84. }
  85. //----------------------------------------------------------------------------
  86. void ctkDependencyGraphPrivate::computeOutdegrees(QVarLengthArray<int, MAXV>& computedOutdegrees)
  87. {
  88. for (int i=1; i <= this->NVertices; i++)
  89. {
  90. computedOutdegrees[i] = 0;
  91. }
  92. for (int i=1; i <= this->NVertices; i++)
  93. {
  94. for (int j=0; j < this->OutDegree[i]; j++)
  95. {
  96. computedOutdegrees[ this->edge(i,j) ] ++;
  97. }
  98. }
  99. }
  100. //----------------------------------------------------------------------------
  101. void ctkDependencyGraphPrivate::traverseUsingDFS(int v)
  102. {
  103. Q_Q(ctkDependencyGraph);
  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 (q->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 ctkDependencyGraphPrivate::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 ctkDependencyGraphPrivate::processVertex(int v)
  160. {
  161. if (this->Verbose)
  162. {
  163. qDebug() << "processed vertex " << v;
  164. }
  165. }
  166. //----------------------------------------------------------------------------
  167. void ctkDependencyGraphPrivate::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 ctkDependencyGraphPrivate::edge(int vertice, int degree)const
  175. {
  176. Q_ASSERT(vertice <= this->NVertices);
  177. Q_ASSERT(degree < MAXDEGREE);
  178. return (*this->Edges[vertice])[degree];
  179. }
  180. //----------------------------------------------------------------------------
  181. void ctkDependencyGraphPrivate::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 ctkDependencyGraphPrivate::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 ctkDependencyGraphPrivate::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 ctkDependencyGraphPrivate::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 ctkDependencyGraphPrivate::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 ctkDependencyGraphPrivate::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 ctkDependencyGraphPrivate::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. :d_ptr(new ctkDependencyGraphPrivate(*this))
  289. {
  290. Q_D(ctkDependencyGraph);
  291. d->NVertices = nvertices;
  292. // Resize internal array
  293. d->Processed.resize(nvertices + 1);
  294. d->Discovered.resize(nvertices + 1);
  295. d->Parent.resize(nvertices + 1);
  296. d->Edges.resize(nvertices + 1);
  297. d->OutDegree.resize(nvertices + 1);
  298. d->InDegree.resize(nvertices + 1);
  299. for (int i=1; i <= nvertices; i++)
  300. {
  301. d->OutDegree[i] = 0;
  302. d->InDegree[i] = 0;
  303. }
  304. // initialize Edge adjacency list
  305. for (int i=0; i <= nvertices; i++)
  306. {
  307. d->Edges[i] = new QVarLengthArray<int, MAXDEGREE>();
  308. d->Edges[i]->resize(MAXDEGREE);
  309. }
  310. // initialize search
  311. for (int i=1; i <= nvertices; i++)
  312. {
  313. d->Processed[i] = false;
  314. d->Discovered[i] = false;
  315. d->Parent[i] = -1;
  316. }
  317. }
  318. //----------------------------------------------------------------------------
  319. ctkDependencyGraph::~ctkDependencyGraph()
  320. {
  321. Q_D(ctkDependencyGraph);
  322. // Clean memory
  323. for (int i=0; i <= d->NVertices; i++)
  324. {
  325. delete d->Edges[i];
  326. }
  327. }
  328. //----------------------------------------------------------------------------
  329. void ctkDependencyGraph::printAdditionalInfo()const
  330. {
  331. Q_D(const ctkDependencyGraph);
  332. qDebug() << "ctkDependencyGraph (" << this << ")" << endl
  333. << " NVertices:" << this->numberOfVertices() << endl
  334. << " NEdges:" << this->numberOfEdges() << endl
  335. << " Abort:" << d->Abort;
  336. qDebug() << " [Processed]";
  337. for(int i=1; i < d->Processed.size(); i++)
  338. {
  339. qDebug() << i << "->" << d->Processed[i];
  340. }
  341. qDebug() << " [Discovered]";
  342. for(int i=1; i < d->Discovered.size(); i++)
  343. {
  344. qDebug() << i << "->" << d->Discovered[i];
  345. }
  346. qDebug() << " [Parent]";
  347. for(int i=1; i < d->Parent.size(); i++)
  348. {
  349. qDebug() << i << "->" << d->Parent[i];
  350. }
  351. qDebug() << " [Graph]";
  352. this->printGraph();
  353. }
  354. //----------------------------------------------------------------------------
  355. void ctkDependencyGraph::printGraph()const
  356. {
  357. Q_D(const ctkDependencyGraph);
  358. for(int i=1; i <= d->NVertices; i++)
  359. {
  360. std::cout << i << ":";
  361. for (int j=0; j < d->OutDegree[i]; j++)
  362. {
  363. std::cout << " " << d->edge(i, j);
  364. }
  365. std::cout << std::endl;
  366. }
  367. }
  368. //----------------------------------------------------------------------------
  369. int ctkDependencyGraph::numberOfVertices()const
  370. {
  371. Q_D(const ctkDependencyGraph);
  372. return d->NVertices;
  373. }
  374. //----------------------------------------------------------------------------
  375. int ctkDependencyGraph::numberOfEdges()const
  376. {
  377. Q_D(const ctkDependencyGraph);
  378. return d->NEdges;
  379. }
  380. //----------------------------------------------------------------------------
  381. void ctkDependencyGraph::setVerbose(bool verbose)
  382. {
  383. Q_D(ctkDependencyGraph);
  384. d->Verbose = verbose;
  385. }
  386. //----------------------------------------------------------------------------
  387. void ctkDependencyGraph::setEdgeListToExclude(const QList<int>& list)
  388. {
  389. Q_D(ctkDependencyGraph);
  390. d->ListOfEdgeToExclude = list;
  391. }
  392. //----------------------------------------------------------------------------
  393. bool ctkDependencyGraph::shouldExcludeEdge(int edge)const
  394. {
  395. Q_D(const ctkDependencyGraph);
  396. return d->ListOfEdgeToExclude.contains(edge);
  397. }
  398. //----------------------------------------------------------------------------
  399. bool ctkDependencyGraph::checkForCycle()
  400. {
  401. Q_D(ctkDependencyGraph);
  402. if (d->NEdges > 0)
  403. {
  404. // Store unprocessed vertex ids
  405. QList<int> uncheckedVertices;
  406. for (int i = 1; i <= d->NVertices; ++i)
  407. {
  408. uncheckedVertices << i;
  409. }
  410. // Start the cycle detection on the source vertices
  411. QList<int> sources;
  412. this->sourceVertices(sources);
  413. foreach(int sourceId, sources)
  414. {
  415. d->traverseUsingDFS(sourceId);
  416. if (this->cycleDetected()) return true;
  417. for (int i=0; i < d->Processed.size(); i++)
  418. {
  419. if (d->Processed[i] == true)
  420. {
  421. uncheckedVertices.removeOne(i);
  422. }
  423. d->Discovered[i] = false;
  424. d->Processed[i] = false;
  425. }
  426. }
  427. // If a component does not have a source vertex,
  428. // i.e. it is a cycle a -> b -> a, check all non
  429. // processed vertices.
  430. while (!uncheckedVertices.empty())
  431. {
  432. d->traverseUsingDFS(uncheckedVertices.last());
  433. if (this->cycleDetected()) return true;
  434. for (int i=0; i < d->Processed.size(); i++)
  435. {
  436. if (d->Processed[i] == true)
  437. {
  438. uncheckedVertices.removeOne(i);
  439. }
  440. d->Discovered[i] = false;
  441. d->Processed[i] = false;
  442. }
  443. }
  444. }
  445. return this->cycleDetected();
  446. }
  447. //----------------------------------------------------------------------------
  448. bool ctkDependencyGraph::cycleDetected()const
  449. {
  450. Q_D(const ctkDependencyGraph);
  451. return d->CycleDetected;
  452. }
  453. //----------------------------------------------------------------------------
  454. int ctkDependencyGraph::cycleOrigin()const
  455. {
  456. Q_D(const ctkDependencyGraph);
  457. return d->CycleOrigin;
  458. }
  459. //----------------------------------------------------------------------------
  460. int ctkDependencyGraph::cycleEnd()const
  461. {
  462. Q_D(const ctkDependencyGraph);
  463. return d->CycleEnd;
  464. }
  465. //----------------------------------------------------------------------------
  466. void ctkDependencyGraph::insertEdge(int from, int to)
  467. {
  468. Q_D(ctkDependencyGraph);
  469. Q_ASSERT(from > 0 && from <= d->NVertices);
  470. Q_ASSERT(to > 0 && to <= d->NVertices);
  471. // resize if needed
  472. int capacity = d->Edges[from]->capacity();
  473. if (d->OutDegree[from] > capacity)
  474. {
  475. d->Edges[from]->resize(capacity + capacity * 0.3);
  476. }
  477. d->setEdge(from, d->OutDegree[from], to);
  478. d->OutDegree[from]++;
  479. d->InDegree[to]++;
  480. d->NEdges++;
  481. }
  482. //----------------------------------------------------------------------------
  483. void ctkDependencyGraph::findPaths(int from, int to, QList<QList<int>* >& paths)
  484. {
  485. Q_D(ctkDependencyGraph);
  486. QList<int>* path = new QList<int>;
  487. *path << from;
  488. paths << path;
  489. d->findPathsRec(from, to, path, paths);
  490. QList<int> pathToRemove;
  491. // Remove list no ending with the requested element
  492. int i = 0;
  493. while (!paths.isEmpty() && i < paths.size())
  494. {
  495. QList<int>* path = paths[i];
  496. Q_ASSERT(path);
  497. if (path->last() != to)
  498. {
  499. paths.removeAt(i);
  500. delete path;
  501. }
  502. else
  503. {
  504. i++;
  505. }
  506. }
  507. }
  508. //----------------------------------------------------------------------------
  509. void ctkDependencyGraph::findPath(int from, int to, QList<int>& path)
  510. {
  511. QList<QList<int>* > paths;
  512. this->findPaths(from, to, paths);
  513. if (!paths.empty())
  514. {
  515. path << *(paths.first());
  516. }
  517. qDeleteAll(paths);
  518. }
  519. //----------------------------------------------------------------------------
  520. bool ctkDependencyGraph::topologicalSort(QList<int>& sorted, int rootId)
  521. {
  522. Q_D(ctkDependencyGraph);
  523. if (rootId > 0)
  524. {
  525. ctkDependencyGraph subgraph(d->subgraphSize(rootId));
  526. QHash<int,int> subgraphIdToGlobal;
  527. QHash<int,int> globalIdToSubgraph;
  528. d->subgraphInsert(subgraph, rootId, subgraphIdToGlobal, globalIdToSubgraph);
  529. QList<int> subgraphSorted;
  530. bool result = subgraph.topologicalSort(subgraphSorted);
  531. foreach(int subgraphId, subgraphSorted)
  532. {
  533. sorted << subgraphIdToGlobal[subgraphId];
  534. }
  535. return result;
  536. }
  537. QVarLengthArray<int, MAXV> outdegree; // outdegree of each vertex
  538. QQueue<int> zeroout; // vertices of outdegree 0
  539. int x, y; // current and next vertex
  540. outdegree.resize(d->NVertices + 1);
  541. // resize if needed
  542. if (d->NVertices > MAXV)
  543. {
  544. outdegree.resize(d->NVertices);
  545. }
  546. d->computeOutdegrees(outdegree);
  547. for (int i=1; i <= d->NVertices; i++)
  548. {
  549. if (outdegree[i] == 0)
  550. {
  551. zeroout.enqueue(i);
  552. }
  553. }
  554. int j=0;
  555. while (zeroout.empty() == false)
  556. {
  557. j = j+1;
  558. x = zeroout.dequeue();
  559. sorted << x;
  560. for (int i=0; i < d->OutDegree[x]; i++)
  561. {
  562. y = d->edge(x, i);
  563. outdegree[y] --;
  564. if (outdegree[y] == 0)
  565. {
  566. zeroout.enqueue(y);
  567. }
  568. }
  569. }
  570. if (j != d->NVertices)
  571. {
  572. return false;
  573. }
  574. return true;
  575. }
  576. void ctkDependencyGraph::sourceVertices(QList<int>& sources)
  577. {
  578. Q_D(ctkDependencyGraph);
  579. d->verticesWithIndegree(0, sources);
  580. }