ctkDependencyGraph.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  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. // CTK includes
  15. #include "ctkDependencyGraph.h"
  16. // STD includes
  17. #include <iostream>
  18. #include <sstream>
  19. #include <algorithm>
  20. #include <vector>
  21. #include <set>
  22. #include <map>
  23. #include <list>
  24. #include <queue>
  25. #include <cassert>
  26. #define MAXV 100
  27. #define MAXDEGREE 50
  28. //----------------------------------------------------------------------------
  29. class ctkDependencyGraphPrivate
  30. {
  31. public:
  32. ctkDependencyGraph* const q_ptr;
  33. ctkDependencyGraphPrivate(ctkDependencyGraph& p);
  34. ~ctkDependencyGraphPrivate();
  35. /// Compute outdegree
  36. void computeOutdegrees(std::vector<int>& computedOutdegrees);
  37. /// Traverse tree using Depth-first_search
  38. void traverseUsingDFS(int v);
  39. /// Called each time an edge is visited
  40. void processEdge(int from, int to);
  41. /// Called each time a vertex is processed
  42. void processVertex(int v);
  43. /// Retrieve the path between two vertices
  44. void findPathDFS(int from, int to, std::list<int>& path);
  45. /// Recursive function used by findPaths to retrieve the path between two vertices
  46. void findPathsRec(int from, int to, std::list<int>* path, std::list<std::list<int>* >& paths);
  47. void setEdge(int vertice, int degree, int value);
  48. int edge(int vertice, int degree)const;
  49. void verticesWithIndegree(int indegree, std::list<int>& list);
  50. int subgraphSize(int rootId);
  51. void subgraphSizeRec(int rootId, std::set<int>& uniqueVertices);
  52. void subgraphInsert(ctkDependencyGraph& subgraph, int rootId,
  53. std::map<int,int>& subgraphIdToGlobal, std::map<int,int>& globalIdToSubgraph);
  54. int getOrGenerateSubgraphId(std::map<int, int>& subgraphIdToGlobal,
  55. std::map<int, int>& globalIdToSubgraph,
  56. int globalId);
  57. /// See http://en.wikipedia.org/wiki/Adjacency_list
  58. std::vector<std::vector<int>* > Edges;
  59. std::vector<int> OutDegree;
  60. std::vector<int> InDegree;
  61. int NVertices;
  62. int NEdges;
  63. /// Structure used by DFS
  64. /// See http://en.wikipedia.org/wiki/Depth-first_search
  65. std::vector<bool> Processed; // processed vertices
  66. std::vector<bool> Discovered; // discovered vertices
  67. std::vector<int> Parent; // relation discovered
  68. bool Abort; // Flag indicating if traverse should be aborted
  69. bool Verbose;
  70. bool CycleDetected;
  71. int CycleOrigin;
  72. int CycleEnd;
  73. std::list<int> ListOfEdgeToExclude;
  74. };
  75. //----------------------------------------------------------------------------
  76. // Returns a space separated string of T.
  77. template<class T>
  78. std::string listToString(const std::list<T>& list)
  79. {
  80. std::stringstream outputString;
  81. typename std::list<T>::const_iterator iter;
  82. for (iter = list.begin(); iter != list.end(); iter++)
  83. {
  84. outputString << *iter << " ";
  85. }
  86. return outputString.str();
  87. }
  88. //----------------------------------------------------------------------------
  89. // Returns true if the map contains the key and false otherwise.
  90. template<class T1, class T2>
  91. bool mapContainsKey(const std::map<T1, T2>& map, const T1& key)
  92. {
  93. bool result = false;
  94. if (map.find(key) != map.end())
  95. {
  96. result = true;
  97. }
  98. return result;
  99. }
  100. //----------------------------------------------------------------------------
  101. // Returns true if the list contains the value and false otherwise.
  102. template<class T>
  103. bool listContainsValue(const std::list<T>& list, const T& value)
  104. {
  105. bool result = false;
  106. typename std::list<T>::const_iterator iter;
  107. for (iter = list.begin(); iter != list.end(); iter++)
  108. {
  109. if ((*iter) == value)
  110. {
  111. result = true;
  112. break;
  113. }
  114. }
  115. return result;
  116. }
  117. //----------------------------------------------------------------------------
  118. // ctkInternal methods
  119. //----------------------------------------------------------------------------
  120. ctkDependencyGraphPrivate::ctkDependencyGraphPrivate(ctkDependencyGraph& object)
  121. :q_ptr(&object)
  122. {
  123. this->NVertices = 0;
  124. this->NEdges = 0;
  125. this->Abort = false;
  126. this->Verbose = false;
  127. this->CycleDetected = false;
  128. this->CycleOrigin = 0;
  129. this->CycleEnd = 0;
  130. }
  131. ctkDependencyGraphPrivate::~ctkDependencyGraphPrivate()
  132. {
  133. std::vector<std::vector<int>* >::iterator edgesIterator;
  134. for (edgesIterator = this->Edges.begin(); edgesIterator != this->Edges.end(); edgesIterator++)
  135. {
  136. if (*edgesIterator != NULL)
  137. {
  138. delete *edgesIterator;
  139. }
  140. }
  141. }
  142. //----------------------------------------------------------------------------
  143. void ctkDependencyGraphPrivate::computeOutdegrees(std::vector<int>& computedOutdegrees)
  144. {
  145. for (int i=1; i <= this->NVertices; i++)
  146. {
  147. computedOutdegrees[i] = 0;
  148. }
  149. for (int i=1; i <= this->NVertices; i++)
  150. {
  151. for (int j=0; j < this->OutDegree[i]; j++)
  152. {
  153. computedOutdegrees[ this->edge(i,j) ] ++;
  154. }
  155. }
  156. }
  157. //----------------------------------------------------------------------------
  158. void ctkDependencyGraphPrivate::traverseUsingDFS(int v)
  159. {
  160. // allow for search termination
  161. if (this->Abort)
  162. {
  163. return;
  164. }
  165. this->Discovered[v] = true;
  166. this->processVertex(v);
  167. int y; // successor vertex
  168. for (int i=0; i<this->OutDegree[v]; i++)
  169. {
  170. y = this->edge(v, i);
  171. if (q_ptr->shouldExcludeEdge(this->edge(v, i)) == false)
  172. {
  173. this->Parent[y] = v;
  174. if (this->Discovered[y] == false)
  175. {
  176. this->traverseUsingDFS(y);
  177. }
  178. else
  179. {
  180. if (this->Processed[y] == false)
  181. {
  182. this->processEdge(v,y);
  183. }
  184. }
  185. }
  186. if (this->Abort)
  187. {
  188. return;
  189. }
  190. }
  191. this->Processed[v] = true;
  192. }
  193. //----------------------------------------------------------------------------
  194. void ctkDependencyGraphPrivate::processEdge(int from, int to)
  195. {
  196. if (this->Discovered[to] == true)
  197. {
  198. this->CycleDetected = true;
  199. this->CycleOrigin = to;
  200. this->CycleEnd = from;
  201. if (this->Verbose)
  202. {
  203. std::list<int> path;
  204. this->findPathDFS(from, to, path);
  205. std::cerr << "ERROR: Cycle detected from " << to << " to " << from << std::endl;
  206. std::cerr << " " << listToString<int>(path) << std::endl;
  207. path.clear();
  208. this->findPathDFS(to, from, path);
  209. std::cerr << " " << listToString<int>(path) << std::endl;
  210. }
  211. this->Abort = true;
  212. }
  213. }
  214. //----------------------------------------------------------------------------
  215. void ctkDependencyGraphPrivate::processVertex(int v)
  216. {
  217. if (this->Verbose)
  218. {
  219. std::cout << "processed vertex " << v << std::endl;
  220. }
  221. }
  222. //----------------------------------------------------------------------------
  223. void ctkDependencyGraphPrivate::setEdge(int vertice, int degree, int value)
  224. {
  225. assert(vertice <= this->NVertices);
  226. assert(degree < MAXDEGREE);
  227. (*this->Edges[vertice])[degree] = value;
  228. }
  229. //----------------------------------------------------------------------------
  230. int ctkDependencyGraphPrivate::edge(int vertice, int degree)const
  231. {
  232. assert(vertice <= this->NVertices);
  233. assert(degree < MAXDEGREE);
  234. return (*this->Edges[vertice])[degree];
  235. }
  236. //----------------------------------------------------------------------------
  237. void ctkDependencyGraphPrivate::findPathDFS(int from, int to, std::list<int>& path)
  238. {
  239. if ((from == to) || (to == -1))
  240. {
  241. path.push_back(from);
  242. }
  243. else
  244. {
  245. this->findPathDFS(from, this->Parent[to], path);
  246. path.push_back(to);
  247. }
  248. }
  249. //----------------------------------------------------------------------------
  250. void ctkDependencyGraphPrivate::findPathsRec(
  251. int from, int to, std::list<int>* path, std::list<std::list<int>* >& paths)
  252. {
  253. if (from == to)
  254. {
  255. return;
  256. }
  257. std::list<int> branch;
  258. branch = *path;
  259. int child = from;
  260. for (int j=0; j < this->OutDegree[child]; j++)
  261. {
  262. if (j == 0)
  263. {
  264. int parent = this->edge(child, j);
  265. (*path).push_back(parent);
  266. this->findPathsRec(parent, to, path, paths);
  267. }
  268. else
  269. {
  270. int parent = this->edge(child, j);
  271. // Copy path and add it to the list
  272. std::list<int>* pathCopy = new std::list<int>();
  273. *pathCopy = branch;
  274. paths.push_back(pathCopy);
  275. (*pathCopy).push_back(parent);
  276. this->findPathsRec(parent, to, pathCopy, paths);
  277. }
  278. }
  279. }
  280. //----------------------------------------------------------------------------
  281. void ctkDependencyGraphPrivate::verticesWithIndegree(int indegree, std::list<int>& list)
  282. {
  283. assert(indegree >= 0);
  284. for (int i=1; i <= this->NVertices; i++)
  285. {
  286. if (this->InDegree[i] == indegree)
  287. {
  288. list.push_back(i);
  289. }
  290. }
  291. }
  292. //----------------------------------------------------------------------------
  293. void ctkDependencyGraphPrivate::subgraphSizeRec(int rootId, std::set<int>& uniqueVertices)
  294. {
  295. assert(rootId > 0);
  296. for (int i = 0; i < this->OutDegree[rootId]; ++i)
  297. {
  298. int child = this->edge(rootId, i);
  299. uniqueVertices.insert(child);
  300. subgraphSizeRec(child, uniqueVertices);
  301. }
  302. }
  303. //----------------------------------------------------------------------------
  304. int ctkDependencyGraphPrivate::subgraphSize(int rootId)
  305. {
  306. assert(rootId > 0);
  307. std::set<int> vertices;
  308. vertices.insert(rootId);
  309. this->subgraphSizeRec(rootId, vertices);
  310. return vertices.size();
  311. }
  312. void ctkDependencyGraphPrivate::subgraphInsert(
  313. ctkDependencyGraph& subgraph, int rootId,
  314. std::map<int,int>& subgraphIdToGlobal, std::map<int,int>& globalIdToSubgraph)
  315. {
  316. int from = this->getOrGenerateSubgraphId(subgraphIdToGlobal, globalIdToSubgraph, rootId);
  317. for (int i = 0; i < this->OutDegree[rootId]; ++i)
  318. {
  319. int childId = this->edge(rootId, i);
  320. int to = this->getOrGenerateSubgraphId(subgraphIdToGlobal, globalIdToSubgraph,
  321. childId);
  322. subgraph.insertEdge(from, to);
  323. this->subgraphInsert(subgraph, childId, subgraphIdToGlobal, globalIdToSubgraph);
  324. }
  325. }
  326. //----------------------------------------------------------------------------
  327. int ctkDependencyGraphPrivate::getOrGenerateSubgraphId(
  328. std::map<int, int>& subgraphIdToGlobal,
  329. std::map<int, int>& globalIdToSubgraph,
  330. int globalId)
  331. {
  332. // If needed, generate vertex id
  333. int subgraphId = -1;
  334. if (!mapContainsKey<int, int>(globalIdToSubgraph,globalId))
  335. {
  336. subgraphId = globalIdToSubgraph.size() + 1;
  337. globalIdToSubgraph[globalId] = subgraphId;
  338. subgraphIdToGlobal[subgraphId] = globalId;
  339. }
  340. else
  341. {
  342. subgraphId = globalIdToSubgraph[globalId];
  343. }
  344. return subgraphId;
  345. }
  346. //----------------------------------------------------------------------------
  347. // ctkDependencyGraph methods
  348. //----------------------------------------------------------------------------
  349. ctkDependencyGraph::ctkDependencyGraph(int nvertices)
  350. :d_ptr(new ctkDependencyGraphPrivate(*this))
  351. {
  352. d_ptr->NVertices = nvertices;
  353. // Resize internal array
  354. d_ptr->Processed.resize(nvertices + 1);
  355. d_ptr->Discovered.resize(nvertices + 1);
  356. d_ptr->Parent.resize(nvertices + 1);
  357. d_ptr->Edges.resize(nvertices + 1);
  358. d_ptr->OutDegree.resize(nvertices + 1);
  359. d_ptr->InDegree.resize(nvertices + 1);
  360. for (int i=1; i <= nvertices; i++)
  361. {
  362. d_ptr->OutDegree[i] = 0;
  363. d_ptr->InDegree[i] = 0;
  364. }
  365. // initialize Edge adjacency list
  366. for (int i=0; i <= nvertices; i++)
  367. {
  368. d_ptr->Edges[i] = new std::vector<int>();
  369. d_ptr->Edges[i]->resize(MAXDEGREE);
  370. }
  371. // initialize search
  372. for (int i=1; i <= nvertices; i++)
  373. {
  374. d_ptr->Processed[i] = false;
  375. d_ptr->Discovered[i] = false;
  376. d_ptr->Parent[i] = -1;
  377. }
  378. }
  379. //----------------------------------------------------------------------------
  380. ctkDependencyGraph::~ctkDependencyGraph()
  381. {
  382. if (d_ptr != NULL)
  383. {
  384. delete d_ptr;
  385. }
  386. }
  387. //----------------------------------------------------------------------------
  388. void ctkDependencyGraph::printAdditionalInfo()const
  389. {
  390. std::cout << "ctkDependencyGraph (" << this << ")" << std::endl
  391. << " NVertices:" << this->numberOfVertices() << std::endl
  392. << " NEdges:" << this->numberOfEdges() << std::endl
  393. << " Abort:" << d_ptr->Abort << std::endl;
  394. std::cout << " [Processed]" << std::endl;
  395. for(unsigned int i=1; i < d_ptr->Processed.size(); i++)
  396. {
  397. std::cout << i << "->" << d_ptr->Processed[i] << std::endl;
  398. }
  399. std::cout << " [Discovered]" << std::endl;
  400. for(unsigned int i=1; i < d_ptr->Discovered.size(); i++)
  401. {
  402. std::cout << i << "->" << d_ptr->Discovered[i] << std::endl;
  403. }
  404. std::cout << " [Parent]" << std::endl;
  405. for(unsigned int i=1; i < d_ptr->Parent.size(); i++)
  406. {
  407. std::cout << i << "->" << d_ptr->Parent[i] << std::endl;
  408. }
  409. std::cout << " [Graph]" << std::endl;
  410. this->printGraph();
  411. }
  412. //----------------------------------------------------------------------------
  413. void ctkDependencyGraph::printGraph()const
  414. {
  415. for(int i=1; i <= d_ptr->NVertices; i++)
  416. {
  417. std::cout << i << ":";
  418. for (int j=0; j < d_ptr->OutDegree[i]; j++)
  419. {
  420. std::cout << " " << d_ptr->edge(i, j);
  421. }
  422. std::cout << std::endl;
  423. }
  424. }
  425. //----------------------------------------------------------------------------
  426. int ctkDependencyGraph::numberOfVertices()const
  427. {
  428. return d_ptr->NVertices;
  429. }
  430. //----------------------------------------------------------------------------
  431. int ctkDependencyGraph::numberOfEdges()const
  432. {
  433. return d_ptr->NEdges;
  434. }
  435. //----------------------------------------------------------------------------
  436. void ctkDependencyGraph::setVerbose(bool verbose)
  437. {
  438. d_ptr->Verbose = verbose;
  439. }
  440. //----------------------------------------------------------------------------
  441. void ctkDependencyGraph::setEdgeListToExclude(const std::list<int>& list)
  442. {
  443. d_ptr->ListOfEdgeToExclude = list;
  444. }
  445. //----------------------------------------------------------------------------
  446. bool ctkDependencyGraph::shouldExcludeEdge(int edge)const
  447. {
  448. return listContainsValue(d_ptr->ListOfEdgeToExclude, edge);
  449. }
  450. //----------------------------------------------------------------------------
  451. bool ctkDependencyGraph::checkForCycle()
  452. {
  453. if (d_ptr->NEdges > 0)
  454. {
  455. // Store unprocessed vertex ids
  456. std::list<int> uncheckedVertices;
  457. for (int i = 1; i <= d_ptr->NVertices; ++i)
  458. {
  459. uncheckedVertices.push_back(i);
  460. }
  461. // Start the cycle detection on the source vertices
  462. std::list<int> sources;
  463. this->sourceVertices(sources);
  464. std::list<int>::const_iterator sourcesIterator;
  465. for (sourcesIterator = sources.begin(); sourcesIterator != sources.end(); sourcesIterator++)
  466. {
  467. d_ptr->traverseUsingDFS(*sourcesIterator);
  468. if (this->cycleDetected()) return true;
  469. for (unsigned int i=0; i < d_ptr->Processed.size(); i++)
  470. {
  471. if (d_ptr->Processed[i] == true)
  472. {
  473. uncheckedVertices.remove(i);
  474. }
  475. d_ptr->Discovered[i] = false;
  476. d_ptr->Processed[i] = false;
  477. }
  478. }
  479. // If a component does not have a source vertex,
  480. // i.e. it is a cycle a -> b -> a, check all non
  481. // processed vertices.
  482. while (!uncheckedVertices.empty())
  483. {
  484. d_ptr->traverseUsingDFS((*uncheckedVertices.rbegin()));
  485. if (this->cycleDetected()) return true;
  486. for (unsigned int i=0; i < d_ptr->Processed.size(); i++)
  487. {
  488. if (d_ptr->Processed[i] == true)
  489. {
  490. uncheckedVertices.remove(i);
  491. }
  492. d_ptr->Discovered[i] = false;
  493. d_ptr->Processed[i] = false;
  494. }
  495. }
  496. }
  497. return this->cycleDetected();
  498. }
  499. //----------------------------------------------------------------------------
  500. bool ctkDependencyGraph::cycleDetected()const
  501. {
  502. return d_ptr->CycleDetected;
  503. }
  504. //----------------------------------------------------------------------------
  505. int ctkDependencyGraph::cycleOrigin()const
  506. {
  507. return d_ptr->CycleOrigin;
  508. }
  509. //----------------------------------------------------------------------------
  510. int ctkDependencyGraph::cycleEnd()const
  511. {
  512. return d_ptr->CycleEnd;
  513. }
  514. //----------------------------------------------------------------------------
  515. void ctkDependencyGraph::insertEdge(int from, int to)
  516. {
  517. assert(from > 0 && from <= d_ptr->NVertices);
  518. assert(to > 0 && to <= d_ptr->NVertices);
  519. // resize if needed
  520. int capacity = d_ptr->Edges[from]->capacity();
  521. if (d_ptr->OutDegree[from] > capacity)
  522. {
  523. d_ptr->Edges[from]->resize(capacity + capacity * 0.3);
  524. }
  525. d_ptr->setEdge(from, d_ptr->OutDegree[from], to);
  526. d_ptr->OutDegree[from]++;
  527. d_ptr->InDegree[to]++;
  528. d_ptr->NEdges++;
  529. }
  530. //----------------------------------------------------------------------------
  531. void ctkDependencyGraph::findPaths(int from, int to, std::list<std::list<int>* >& paths)
  532. {
  533. std::list<int>* path = new std::list<int>;
  534. (*path).push_back(from);
  535. (paths).push_back(path);
  536. d_ptr->findPathsRec(from, to, path, paths);
  537. // Remove lists not ending with the requested element
  538. std::list<std::list<int>* >::iterator pathsIterator;
  539. pathsIterator = paths.begin();
  540. while (paths.size() > 0 && pathsIterator != paths.end())
  541. {
  542. std::list<int>* pathToCheck = (*pathsIterator);
  543. assert(pathToCheck);
  544. if (*(pathToCheck->rbegin()) != to)
  545. {
  546. pathsIterator = paths.erase(pathsIterator);
  547. }
  548. else
  549. {
  550. pathsIterator++;
  551. }
  552. }
  553. }
  554. //----------------------------------------------------------------------------
  555. void ctkDependencyGraph::findPath(int from, int to, std::list<int>& path)
  556. {
  557. std::list<std::list<int>* > paths;
  558. this->findPaths(from, to, paths);
  559. if (!paths.empty())
  560. {
  561. std::list<int>::iterator pathIterator;
  562. for (pathIterator = (*(paths.begin()))->begin(); pathIterator != (*(paths.begin()))->end(); pathIterator++)
  563. {
  564. path.push_back(*pathIterator);
  565. }
  566. }
  567. std::list<std::list<int>* >::iterator pathsIterator;
  568. for(pathsIterator = paths.begin(); pathsIterator != paths.end(); pathsIterator++)
  569. {
  570. if (*pathsIterator != NULL)
  571. {
  572. delete *pathsIterator;
  573. }
  574. }
  575. }
  576. //----------------------------------------------------------------------------
  577. bool ctkDependencyGraph::topologicalSort(std::list<int>& sorted, int rootId)
  578. {
  579. if (rootId > 0)
  580. {
  581. ctkDependencyGraph subgraph(d_ptr->subgraphSize(rootId));
  582. std::map<int,int> subgraphIdToGlobal;
  583. std::map<int,int> globalIdToSubgraph;
  584. d_ptr->subgraphInsert(subgraph, rootId, subgraphIdToGlobal, globalIdToSubgraph);
  585. std::list<int> subgraphSorted;
  586. bool result = subgraph.topologicalSort(subgraphSorted);
  587. std::list<int>::const_iterator subgraphSortedIterator;
  588. for (subgraphSortedIterator = subgraphSorted.begin(); subgraphSortedIterator != subgraphSorted.end(); subgraphSortedIterator++)
  589. {
  590. sorted.push_back(subgraphIdToGlobal[*subgraphSortedIterator]);
  591. }
  592. return result;
  593. }
  594. std::vector<int> outdegree; // outdegree of each vertex
  595. outdegree.resize(MAXV);
  596. std::queue<int> zeroout; // vertices of outdegree 0
  597. int x, y; // current and next vertex
  598. outdegree.resize(d_ptr->NVertices + 1);
  599. // resize if needed
  600. if (d_ptr->NVertices > MAXV)
  601. {
  602. outdegree.resize(d_ptr->NVertices);
  603. }
  604. d_ptr->computeOutdegrees(outdegree);
  605. for (int i=1; i <= d_ptr->NVertices; i++)
  606. {
  607. if (outdegree[i] == 0)
  608. {
  609. zeroout.push(i);
  610. }
  611. }
  612. int j=0;
  613. while (zeroout.empty() == false)
  614. {
  615. j = j+1;
  616. x = zeroout.front();
  617. zeroout.pop();
  618. sorted.push_back(x);
  619. for (int i=0; i < d_ptr->OutDegree[x]; i++)
  620. {
  621. y = d_ptr->edge(x, i);
  622. outdegree[y] --;
  623. if (outdegree[y] == 0)
  624. {
  625. zeroout.push(y);
  626. }
  627. }
  628. }
  629. if (j != d_ptr->NVertices)
  630. {
  631. return false;
  632. }
  633. return true;
  634. }
  635. //----------------------------------------------------------------------------
  636. void ctkDependencyGraph::sourceVertices(std::list<int>& sources)
  637. {
  638. d_ptr->verticesWithIndegree(0, sources);
  639. }