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