From b66a6cc77e7d3a8e67452d75c0c0b3ffc8b45571 Mon Sep 17 00:00:00 2001 From: Pavel Samolysov Date: Sat, 21 Dec 2024 07:43:50 +0300 Subject: [PATCH 1/2] Use vector-of-structs of preds/semi for Lengauer-Tarjan Closes #383 --- include/boost/graph/dominator_tree.hpp | 75 ++++++++++++++++++-------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/include/boost/graph/dominator_tree.hpp b/include/boost/graph/dominator_tree.hpp index 8a9e7afde..cd7e7f9e9 100644 --- a/include/boost/graph/dominator_tree.hpp +++ b/include/boost/graph/dominator_tree.hpp @@ -62,6 +62,33 @@ namespace detail Tag >(timeMap, v, t); } + // Auxiliary structure of different kinds of predecessors are used to + // calculate the semidominators: ancestor, semidominator, and the ancestor + // with the lowest semidominator (`best`). Placing these predecessors in a + // structure let us organize a "vector of structs" what improves cache + // efficiency. + template < class Graph > struct preds + { + preds() + : semi(graph_traits< Graph >::null_vertex()) + , ancestor(graph_traits< Graph >::null_vertex()) + , best(graph_traits< Graph >::null_vertex()) + { + } + + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + void set_ancestor(const preds& pr) { ancestor = pr.ancestor; } + + void set_ancestor(const Vertex& v) { ancestor = v; } + + void set_best(const Vertex& v) { best = v; } + + void set_semi(const Vertex& v) { semi = v; } + + Vertex semi, ancestor, best; + }; + template < class Graph, class IndexMap, class TimeMap, class PredMap, class DomTreePredMap > class dominator_visitor @@ -80,13 +107,9 @@ namespace detail */ dominator_visitor(const Graph& g, const Vertex& entry, const IndexMap& indexMap, DomTreePredMap domTreePredMap) - : semi_(num_vertices(g)) - , ancestor_(num_vertices(g), graph_traits< Graph >::null_vertex()) - , samedom_(ancestor_) - , best_(semi_) - , semiMap_(make_iterator_property_map(semi_.begin(), indexMap)) - , ancestorMap_(make_iterator_property_map(ancestor_.begin(), indexMap)) - , bestMap_(make_iterator_property_map(best_.begin(), indexMap)) + : preds_(num_vertices(g)) + , predsMap_(make_iterator_property_map(preds_.begin(), indexMap)) + , samedom_(num_vertices(g), graph_traits< Graph >::null_vertex()) , buckets_(num_vertices(g)) , bucketMap_(make_iterator_property_map(buckets_.begin(), indexMap)) , entry_(entry) @@ -132,18 +155,20 @@ namespace detail if (get(dfnumMap, v) <= get(dfnumMap, n)) s2 = v; else - s2 = get(semiMap_, ancestor_with_lowest_semi_(v, dfnumMap)); + s2 = get(predsMap_, ancestor_with_lowest_semi_(v, dfnumMap)) + .semi; if (get(dfnumMap, s2) < get(dfnumMap, s)) s = s2; } - put(semiMap_, n, s); + preds< Graph >& preds_of_n = get(predsMap_, n); + preds_of_n.set_semi(s); // 2. Calculation of n's dominator is deferred until // the path from s to n has been linked into the forest get(bucketMap_, s).push_back(n); - get(ancestorMap_, n) = p; - get(bestMap_, n) = n; + preds_of_n.set_ancestor(p); + preds_of_n.set_best(n); // 3. Now that the path from p to v has been linked into // the spanning forest, these lines calculate the dominator of v, @@ -161,7 +186,7 @@ namespace detail { const Vertex v(*buckItr); const Vertex y(ancestor_with_lowest_semi_(v, dfnumMap)); - if (get(semiMap_, y) == get(semiMap_, v)) + if (get(predsMap_, y).semi == get(predsMap_, v).semi) put(domTreePredMap_, v, p); else put(samedomMap, v, y); @@ -177,24 +202,32 @@ namespace detail const Vertex ancestor_with_lowest_semi_( const Vertex& v, const TimeMap& dfnumMap) { - const Vertex a(get(ancestorMap_, v)); + const Vertex a(get(predsMap_, v).ancestor); + const preds< Graph >& preds_of_a = get(predsMap_, a); + + preds< Graph >& preds_of_v = get(predsMap_, v); - if (get(ancestorMap_, a) != graph_traits< Graph >::null_vertex()) + if (preds_of_a.ancestor != graph_traits< Graph >::null_vertex()) { const Vertex b(ancestor_with_lowest_semi_(a, dfnumMap)); + const preds< Graph >& preds_of_b = get(predsMap_, b); - put(ancestorMap_, v, get(ancestorMap_, a)); + preds_of_v.set_ancestor(preds_of_a); - if (get(dfnumMap, get(semiMap_, b)) - < get(dfnumMap, get(semiMap_, get(bestMap_, v)))) - put(bestMap_, v, b); + if (get(dfnumMap, preds_of_b.semi) + < get(dfnumMap, get(predsMap_, preds_of_v.best).semi)) + preds_of_v.set_best(b); } - return get(bestMap_, v); + return preds_of_v.best; } - std::vector< Vertex > semi_, ancestor_, samedom_, best_; - PredMap semiMap_, ancestorMap_, bestMap_; + std::vector< preds< Graph > > preds_; + iterator_property_map< typename std::vector< preds< Graph > >::iterator, + IndexMap > + predsMap_; + + std::vector< Vertex > samedom_; std::vector< std::vector< Vertex > > buckets_; iterator_property_map< From 7c27b395f1cddc1d8e1ec07d521e53cf61c4d597 Mon Sep 17 00:00:00 2001 From: Pavel Samolysov Date: Sun, 29 Dec 2024 12:57:14 +0300 Subject: [PATCH 2/2] Remove the 'set_' members from 'preds' struct --- include/boost/graph/dominator_tree.hpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/include/boost/graph/dominator_tree.hpp b/include/boost/graph/dominator_tree.hpp index cd7e7f9e9..8f9b048c4 100644 --- a/include/boost/graph/dominator_tree.hpp +++ b/include/boost/graph/dominator_tree.hpp @@ -78,14 +78,6 @@ namespace detail typedef typename graph_traits< Graph >::vertex_descriptor Vertex; - void set_ancestor(const preds& pr) { ancestor = pr.ancestor; } - - void set_ancestor(const Vertex& v) { ancestor = v; } - - void set_best(const Vertex& v) { best = v; } - - void set_semi(const Vertex& v) { semi = v; } - Vertex semi, ancestor, best; }; @@ -162,13 +154,13 @@ namespace detail s = s2; } preds< Graph >& preds_of_n = get(predsMap_, n); - preds_of_n.set_semi(s); + preds_of_n.semi = s; // 2. Calculation of n's dominator is deferred until // the path from s to n has been linked into the forest get(bucketMap_, s).push_back(n); - preds_of_n.set_ancestor(p); - preds_of_n.set_best(n); + preds_of_n.ancestor = p; + preds_of_n.best = n; // 3. Now that the path from p to v has been linked into // the spanning forest, these lines calculate the dominator of v, @@ -212,11 +204,11 @@ namespace detail const Vertex b(ancestor_with_lowest_semi_(a, dfnumMap)); const preds< Graph >& preds_of_b = get(predsMap_, b); - preds_of_v.set_ancestor(preds_of_a); + preds_of_v.ancestor = preds_of_a.ancestor; if (get(dfnumMap, preds_of_b.semi) < get(dfnumMap, get(predsMap_, preds_of_v.best).semi)) - preds_of_v.set_best(b); + preds_of_v.best = b; } return preds_of_v.best;