Use vector-of-structs of preds/semi for Lengauer-Tarjan

Closes #383
This commit is contained in:
Pavel Samolysov 2024-12-21 07:43:50 +03:00
parent 9237081239
commit 8119d0e169

View File

@ -62,6 +62,33 @@ namespace detail
Tag >(timeMap, v, t); 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, template < class Graph, class IndexMap, class TimeMap, class PredMap,
class DomTreePredMap > class DomTreePredMap >
class dominator_visitor class dominator_visitor
@ -80,13 +107,9 @@ namespace detail
*/ */
dominator_visitor(const Graph& g, const Vertex& entry, dominator_visitor(const Graph& g, const Vertex& entry,
const IndexMap& indexMap, DomTreePredMap domTreePredMap) const IndexMap& indexMap, DomTreePredMap domTreePredMap)
: semi_(num_vertices(g)) : preds_(num_vertices(g))
, ancestor_(num_vertices(g), graph_traits< Graph >::null_vertex()) , predsMap_(make_iterator_property_map(preds_.begin(), indexMap))
, samedom_(ancestor_) , samedom_(num_vertices(g), graph_traits< Graph >::null_vertex())
, 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))
, buckets_(num_vertices(g)) , buckets_(num_vertices(g))
, bucketMap_(make_iterator_property_map(buckets_.begin(), indexMap)) , bucketMap_(make_iterator_property_map(buckets_.begin(), indexMap))
, entry_(entry) , entry_(entry)
@ -132,18 +155,20 @@ namespace detail
if (get(dfnumMap, v) <= get(dfnumMap, n)) if (get(dfnumMap, v) <= get(dfnumMap, n))
s2 = v; s2 = v;
else 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)) if (get(dfnumMap, s2) < get(dfnumMap, s))
s = s2; 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 // 2. Calculation of n's dominator is deferred until
// the path from s to n has been linked into the forest // the path from s to n has been linked into the forest
get(bucketMap_, s).push_back(n); get(bucketMap_, s).push_back(n);
get(ancestorMap_, n) = p; preds_of_n.set_ancestor(p);
get(bestMap_, n) = n; preds_of_n.set_best(n);
// 3. Now that the path from p to v has been linked into // 3. Now that the path from p to v has been linked into
// the spanning forest, these lines calculate the dominator of v, // the spanning forest, these lines calculate the dominator of v,
@ -161,7 +186,7 @@ namespace detail
{ {
const Vertex v(*buckItr); const Vertex v(*buckItr);
const Vertex y(ancestor_with_lowest_semi_(v, dfnumMap)); 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); put(domTreePredMap_, v, p);
else else
put(samedomMap, v, y); put(samedomMap, v, y);
@ -177,24 +202,32 @@ namespace detail
const Vertex ancestor_with_lowest_semi_( const Vertex ancestor_with_lowest_semi_(
const Vertex& v, const TimeMap& dfnumMap) 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);
if (get(ancestorMap_, a) != graph_traits< Graph >::null_vertex()) preds< Graph >& preds_of_v = get(predsMap_, v);
if (preds_of_a.ancestor != graph_traits< Graph >::null_vertex())
{ {
const Vertex b(ancestor_with_lowest_semi_(a, dfnumMap)); 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)) if (get(dfnumMap, preds_of_b.semi)
< get(dfnumMap, get(semiMap_, get(bestMap_, v)))) < get(dfnumMap, get(predsMap_, preds_of_v.best).semi))
put(bestMap_, v, b); preds_of_v.set_best(b);
} }
return get(bestMap_, v); return preds_of_v.best;
} }
std::vector< Vertex > semi_, ancestor_, samedom_, best_; std::vector< preds< Graph > > preds_;
PredMap semiMap_, ancestorMap_, bestMap_; iterator_property_map< typename std::vector< preds< Graph > >::iterator,
IndexMap >
predsMap_;
std::vector< Vertex > samedom_;
std::vector< std::vector< Vertex > > buckets_; std::vector< std::vector< Vertex > > buckets_;
iterator_property_map< iterator_property_map<