dominator_tree.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. //=======================================================================
  2. // Copyright (C) 2005-2009 Jongsoo Park <jongsoo.park -at- gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //=======================================================================
  8. #ifndef BOOST_GRAPH_DOMINATOR_HPP
  9. #define BOOST_GRAPH_DOMINATOR_HPP
  10. #include <boost/config.hpp>
  11. #include <deque>
  12. #include <set>
  13. #include <boost/graph/depth_first_search.hpp>
  14. #include <boost/concept/assert.hpp>
  15. // Dominator tree computation
  16. namespace boost {
  17. namespace detail {
  18. /**
  19. * An extended time_stamper which also records vertices for each dfs number
  20. */
  21. template<class TimeMap, class VertexVector, class TimeT, class Tag>
  22. class time_stamper_with_vertex_vector
  23. : public base_visitor<
  24. time_stamper_with_vertex_vector<TimeMap, VertexVector, TimeT, Tag> >
  25. {
  26. public :
  27. typedef Tag event_filter;
  28. time_stamper_with_vertex_vector(TimeMap timeMap, VertexVector& v,
  29. TimeT& t)
  30. : timeStamper_(timeMap, t), v_(v) { }
  31. template<class Graph>
  32. void
  33. operator()(const typename property_traits<TimeMap>::key_type& v,
  34. const Graph& g)
  35. {
  36. timeStamper_(v, g);
  37. v_[timeStamper_.m_time] = v;
  38. }
  39. private :
  40. time_stamper<TimeMap, TimeT, Tag> timeStamper_;
  41. VertexVector& v_;
  42. };
  43. /**
  44. * A convenient way to create a time_stamper_with_vertex_vector
  45. */
  46. template<class TimeMap, class VertexVector, class TimeT, class Tag>
  47. time_stamper_with_vertex_vector<TimeMap, VertexVector, TimeT, Tag>
  48. stamp_times_with_vertex_vector(TimeMap timeMap, VertexVector& v, TimeT& t,
  49. Tag)
  50. {
  51. return time_stamper_with_vertex_vector<TimeMap, VertexVector, TimeT,
  52. Tag>(timeMap, v, t);
  53. }
  54. template<class Graph, class IndexMap, class TimeMap, class PredMap,
  55. class DomTreePredMap>
  56. class dominator_visitor
  57. {
  58. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  59. typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
  60. public :
  61. /**
  62. * @param g [in] the target graph of the dominator tree
  63. * @param entry [in] the entry node of g
  64. * @param indexMap [in] the vertex index map for g
  65. * @param domTreePredMap [out] the immediate dominator map
  66. * (parent map in dominator tree)
  67. */
  68. dominator_visitor(const Graph& g, const Vertex& entry,
  69. const IndexMap& indexMap,
  70. DomTreePredMap domTreePredMap)
  71. : semi_(num_vertices(g)),
  72. ancestor_(num_vertices(g), graph_traits<Graph>::null_vertex()),
  73. samedom_(ancestor_),
  74. best_(semi_),
  75. semiMap_(make_iterator_property_map(semi_.begin(),
  76. indexMap)),
  77. ancestorMap_(make_iterator_property_map(ancestor_.begin(),
  78. indexMap)),
  79. bestMap_(make_iterator_property_map(best_.begin(),
  80. indexMap)),
  81. buckets_(num_vertices(g)),
  82. bucketMap_(make_iterator_property_map(buckets_.begin(),
  83. indexMap)),
  84. entry_(entry),
  85. domTreePredMap_(domTreePredMap),
  86. numOfVertices_(num_vertices(g)),
  87. samedomMap(make_iterator_property_map(samedom_.begin(),
  88. indexMap))
  89. {
  90. }
  91. void
  92. operator()(const Vertex& n, const TimeMap& dfnumMap,
  93. const PredMap& parentMap, const Graph& g)
  94. {
  95. if (n == entry_) return;
  96. const Vertex p(get(parentMap, n));
  97. Vertex s(p);
  98. // 1. Calculate the semidominator of n,
  99. // based on the semidominator thm.
  100. // * Semidominator thm. : To find the semidominator of a node n,
  101. // consider all predecessors v of n in the CFG (Control Flow Graph).
  102. // - If v is a proper ancestor of n in the spanning tree
  103. // (so dfnum(v) < dfnum(n)), then v is a candidate for semi(n)
  104. // - If v is a non-ancestor of n (so dfnum(v) > dfnum(n))
  105. // then for each u that is an ancestor of v (or u = v),
  106. // Let semi(u) be a candidate for semi(n)
  107. // of all these candidates, the one with lowest dfnum is
  108. // the semidominator of n.
  109. // For each predecessor of n
  110. typename graph_traits<Graph>::in_edge_iterator inItr, inEnd;
  111. for (boost::tie(inItr, inEnd) = in_edges(n, g); inItr != inEnd; ++inItr)
  112. {
  113. const Vertex v = source(*inItr, g);
  114. // To deal with unreachable nodes
  115. if (get(dfnumMap, v) < 0 || get(dfnumMap, v) >= numOfVertices_)
  116. continue;
  117. Vertex s2;
  118. if (get(dfnumMap, v) <= get(dfnumMap, n))
  119. s2 = v;
  120. else
  121. s2 = get(semiMap_, ancestor_with_lowest_semi_(v, dfnumMap));
  122. if (get(dfnumMap, s2) < get(dfnumMap, s))
  123. s = s2;
  124. }
  125. put(semiMap_, n, s);
  126. // 2. Calculation of n's dominator is deferred until
  127. // the path from s to n has been linked into the forest
  128. get(bucketMap_, s).push_back(n);
  129. get(ancestorMap_, n) = p;
  130. get(bestMap_, n) = n;
  131. // 3. Now that the path from p to v has been linked into
  132. // the spanning forest, these lines calculate the dominator of v,
  133. // based on the dominator thm., or else defer the calculation
  134. // until y's dominator is known
  135. // * Dominator thm. : On the spanning-tree path below semi(n) and
  136. // above or including n, let y be the node
  137. // with the smallest-numbered semidominator. Then,
  138. //
  139. // idom(n) = semi(n) if semi(y)=semi(n) or
  140. // idom(y) if semi(y) != semi(n)
  141. typename std::deque<Vertex>::iterator buckItr;
  142. for (buckItr = get(bucketMap_, p).begin();
  143. buckItr != get(bucketMap_, p).end();
  144. ++buckItr)
  145. {
  146. const Vertex v(*buckItr);
  147. const Vertex y(ancestor_with_lowest_semi_(v, dfnumMap));
  148. if (get(semiMap_, y) == get(semiMap_, v))
  149. put(domTreePredMap_, v, p);
  150. else
  151. put(samedomMap, v, y);
  152. }
  153. get(bucketMap_, p).clear();
  154. }
  155. protected :
  156. /**
  157. * Evaluate function in Tarjan's path compression
  158. */
  159. const Vertex
  160. ancestor_with_lowest_semi_(const Vertex& v, const TimeMap& dfnumMap)
  161. {
  162. const Vertex a(get(ancestorMap_, v));
  163. if (get(ancestorMap_, a) != graph_traits<Graph>::null_vertex())
  164. {
  165. const Vertex b(ancestor_with_lowest_semi_(a, dfnumMap));
  166. put(ancestorMap_, v, get(ancestorMap_, a));
  167. if (get(dfnumMap, get(semiMap_, b)) <
  168. get(dfnumMap, get(semiMap_, get(bestMap_, v))))
  169. put(bestMap_, v, b);
  170. }
  171. return get(bestMap_, v);
  172. }
  173. std::vector<Vertex> semi_, ancestor_, samedom_, best_;
  174. PredMap semiMap_, ancestorMap_, bestMap_;
  175. std::vector< std::deque<Vertex> > buckets_;
  176. iterator_property_map<typename std::vector<std::deque<Vertex> >::iterator,
  177. IndexMap> bucketMap_;
  178. const Vertex& entry_;
  179. DomTreePredMap domTreePredMap_;
  180. const VerticesSizeType numOfVertices_;
  181. public :
  182. PredMap samedomMap;
  183. };
  184. } // namespace detail
  185. /**
  186. * @brief Build dominator tree using Lengauer-Tarjan algorithm.
  187. * It takes O((V+E)log(V+E)) time.
  188. *
  189. * @pre dfnumMap, parentMap and verticesByDFNum have dfs results corresponding
  190. * indexMap.
  191. * If dfs has already run before,
  192. * this function would be good for saving computations.
  193. * @pre Unreachable nodes must be masked as
  194. * graph_traits<Graph>::null_vertex in parentMap.
  195. * @pre Unreachable nodes must be masked as
  196. * (std::numeric_limits<VerticesSizeType>::max)() in dfnumMap.
  197. *
  198. * @param domTreePredMap [out] : immediate dominator map (parent map
  199. * in dom. tree)
  200. *
  201. * @note reference Appel. p. 452~453. algorithm 19.9, 19.10.
  202. *
  203. * @todo : Optimization in Finding Dominators in Practice, Loukas Georgiadis
  204. */
  205. template<class Graph, class IndexMap, class TimeMap, class PredMap,
  206. class VertexVector, class DomTreePredMap>
  207. void
  208. lengauer_tarjan_dominator_tree_without_dfs
  209. (const Graph& g,
  210. const typename graph_traits<Graph>::vertex_descriptor& entry,
  211. const IndexMap& indexMap,
  212. TimeMap dfnumMap, PredMap parentMap, VertexVector& verticesByDFNum,
  213. DomTreePredMap domTreePredMap)
  214. {
  215. // Typedefs and concept check
  216. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  217. typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
  218. BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> ));
  219. const VerticesSizeType numOfVertices = num_vertices(g);
  220. if (numOfVertices == 0) return;
  221. // 1. Visit each vertex in reverse post order and calculate sdom.
  222. detail::dominator_visitor<Graph, IndexMap, TimeMap, PredMap, DomTreePredMap>
  223. visitor(g, entry, indexMap, domTreePredMap);
  224. VerticesSizeType i;
  225. for (i = 0; i < numOfVertices; ++i)
  226. {
  227. const Vertex u(verticesByDFNum[numOfVertices - 1 - i]);
  228. if (u != graph_traits<Graph>::null_vertex())
  229. visitor(u, dfnumMap, parentMap, g);
  230. }
  231. // 2. Now all the deferred dominator calculations,
  232. // based on the second clause of the dominator thm., are performed
  233. for (i = 0; i < numOfVertices; ++i)
  234. {
  235. const Vertex n(verticesByDFNum[i]);
  236. if (n == entry || n == graph_traits<Graph>::null_vertex())
  237. continue;
  238. Vertex u = get(visitor.samedomMap, n);
  239. if (u != graph_traits<Graph>::null_vertex())
  240. {
  241. put(domTreePredMap, n, get(domTreePredMap, u));
  242. }
  243. }
  244. }
  245. /**
  246. * Unlike lengauer_tarjan_dominator_tree_without_dfs,
  247. * dfs is run in this function and
  248. * the result is written to dfnumMap, parentMap, vertices.
  249. *
  250. * If the result of dfs required after this algorithm,
  251. * this function can eliminate the need of rerunning dfs.
  252. */
  253. template<class Graph, class IndexMap, class TimeMap, class PredMap,
  254. class VertexVector, class DomTreePredMap>
  255. void
  256. lengauer_tarjan_dominator_tree
  257. (const Graph& g,
  258. const typename graph_traits<Graph>::vertex_descriptor& entry,
  259. const IndexMap& indexMap,
  260. TimeMap dfnumMap, PredMap parentMap, VertexVector& verticesByDFNum,
  261. DomTreePredMap domTreePredMap)
  262. {
  263. // Typedefs and concept check
  264. typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
  265. BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> ));
  266. // 1. Depth first visit
  267. const VerticesSizeType numOfVertices = num_vertices(g);
  268. if (numOfVertices == 0) return;
  269. VerticesSizeType time =
  270. (std::numeric_limits<VerticesSizeType>::max)();
  271. std::vector<default_color_type>
  272. colors(numOfVertices, color_traits<default_color_type>::white());
  273. depth_first_visit
  274. (g, entry,
  275. make_dfs_visitor
  276. (make_pair(record_predecessors(parentMap, on_tree_edge()),
  277. detail::stamp_times_with_vertex_vector
  278. (dfnumMap, verticesByDFNum, time, on_discover_vertex()))),
  279. make_iterator_property_map(colors.begin(), indexMap));
  280. // 2. Run main algorithm.
  281. lengauer_tarjan_dominator_tree_without_dfs(g, entry, indexMap, dfnumMap,
  282. parentMap, verticesByDFNum,
  283. domTreePredMap);
  284. }
  285. /**
  286. * Use vertex_index as IndexMap and make dfnumMap, parentMap, verticesByDFNum
  287. * internally.
  288. * If we don't need the result of dfs (dfnumMap, parentMap, verticesByDFNum),
  289. * this function would be more convenient one.
  290. */
  291. template<class Graph, class DomTreePredMap>
  292. void
  293. lengauer_tarjan_dominator_tree
  294. (const Graph& g,
  295. const typename graph_traits<Graph>::vertex_descriptor& entry,
  296. DomTreePredMap domTreePredMap)
  297. {
  298. // typedefs
  299. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  300. typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
  301. typedef typename property_map<Graph, vertex_index_t>::const_type IndexMap;
  302. typedef
  303. iterator_property_map<typename std::vector<VerticesSizeType>::iterator,
  304. IndexMap> TimeMap;
  305. typedef
  306. iterator_property_map<typename std::vector<Vertex>::iterator, IndexMap>
  307. PredMap;
  308. // Make property maps
  309. const VerticesSizeType numOfVertices = num_vertices(g);
  310. if (numOfVertices == 0) return;
  311. const IndexMap indexMap = get(vertex_index, g);
  312. std::vector<VerticesSizeType> dfnum(numOfVertices, 0);
  313. TimeMap dfnumMap(make_iterator_property_map(dfnum.begin(), indexMap));
  314. std::vector<Vertex> parent(numOfVertices,
  315. graph_traits<Graph>::null_vertex());
  316. PredMap parentMap(make_iterator_property_map(parent.begin(), indexMap));
  317. std::vector<Vertex> verticesByDFNum(parent);
  318. // Run main algorithm
  319. lengauer_tarjan_dominator_tree(g, entry,
  320. indexMap, dfnumMap, parentMap,
  321. verticesByDFNum, domTreePredMap);
  322. }
  323. /**
  324. * Muchnick. p. 182, 184
  325. *
  326. * using iterative bit vector analysis
  327. */
  328. template<class Graph, class IndexMap, class DomTreePredMap>
  329. void
  330. iterative_bit_vector_dominator_tree
  331. (const Graph& g,
  332. const typename graph_traits<Graph>::vertex_descriptor& entry,
  333. const IndexMap& indexMap,
  334. DomTreePredMap domTreePredMap)
  335. {
  336. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  337. typedef typename graph_traits<Graph>::vertex_iterator vertexItr;
  338. typedef typename graph_traits<Graph>::vertices_size_type VerticesSizeType;
  339. typedef
  340. iterator_property_map<typename std::vector< std::set<Vertex> >::iterator,
  341. IndexMap> vertexSetMap;
  342. BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph> ));
  343. // 1. Finding dominator
  344. // 1.1. Initialize
  345. const VerticesSizeType numOfVertices = num_vertices(g);
  346. if (numOfVertices == 0) return;
  347. vertexItr vi, viend;
  348. boost::tie(vi, viend) = vertices(g);
  349. const std::set<Vertex> N(vi, viend);
  350. bool change = true;
  351. std::vector< std::set<Vertex> > dom(numOfVertices, N);
  352. vertexSetMap domMap(make_iterator_property_map(dom.begin(), indexMap));
  353. get(domMap, entry).clear();
  354. get(domMap, entry).insert(entry);
  355. while (change)
  356. {
  357. change = false;
  358. for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi)
  359. {
  360. if (*vi == entry) continue;
  361. std::set<Vertex> T(N);
  362. typename graph_traits<Graph>::in_edge_iterator inItr, inEnd;
  363. for (boost::tie(inItr, inEnd) = in_edges(*vi, g); inItr != inEnd; ++inItr)
  364. {
  365. const Vertex p = source(*inItr, g);
  366. std::set<Vertex> tempSet;
  367. std::set_intersection(T.begin(), T.end(),
  368. get(domMap, p).begin(),
  369. get(domMap, p).end(),
  370. std::inserter(tempSet, tempSet.begin()));
  371. T.swap(tempSet);
  372. }
  373. T.insert(*vi);
  374. if (T != get(domMap, *vi))
  375. {
  376. change = true;
  377. get(domMap, *vi).swap(T);
  378. }
  379. } // end of for (boost::tie(vi, viend) = vertices(g)
  380. } // end of while(change)
  381. // 2. Build dominator tree
  382. for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi)
  383. get(domMap, *vi).erase(*vi);
  384. Graph domTree(numOfVertices);
  385. for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi)
  386. {
  387. if (*vi == entry) continue;
  388. // We have to iterate through copied dominator set
  389. const std::set<Vertex> tempSet(get(domMap, *vi));
  390. typename std::set<Vertex>::const_iterator s;
  391. for (s = tempSet.begin(); s != tempSet.end(); ++s)
  392. {
  393. typename std::set<Vertex>::iterator t;
  394. for (t = get(domMap, *vi).begin(); t != get(domMap, *vi).end(); )
  395. {
  396. typename std::set<Vertex>::iterator old_t = t;
  397. ++t; // Done early because t may become invalid
  398. if (*old_t == *s) continue;
  399. if (get(domMap, *s).find(*old_t) != get(domMap, *s).end())
  400. get(domMap, *vi).erase(old_t);
  401. }
  402. }
  403. }
  404. for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi)
  405. {
  406. if (*vi != entry && get(domMap, *vi).size() == 1)
  407. {
  408. Vertex temp = *get(domMap, *vi).begin();
  409. put(domTreePredMap, *vi, temp);
  410. }
  411. }
  412. }
  413. template<class Graph, class DomTreePredMap>
  414. void
  415. iterative_bit_vector_dominator_tree
  416. (const Graph& g,
  417. const typename graph_traits<Graph>::vertex_descriptor& entry,
  418. DomTreePredMap domTreePredMap)
  419. {
  420. typename property_map<Graph, vertex_index_t>::const_type
  421. indexMap = get(vertex_index, g);
  422. iterative_bit_vector_dominator_tree(g, entry, indexMap, domTreePredMap);
  423. }
  424. } // namespace boost
  425. #endif // BOOST_GRAPH_DOMINATOR_HPP