tgbagraph: add a merge_transitions() method.

* src/graph/graph.hh: Add some framework to erase transitions, and
defrag the resulting transitions_ vector on demand.  Also remove
the nb_states() and nb_transitions() because num_states() and
num_transitions() already exist.
* src/graphtest/graph.cc, src/graphtest/ngraph.cc: Adjust to
use num_states().
* src/tgba/tgbagraph.hh (merge_transitions): New method.
* src/misc/hash.hh: Add a pair_hash class, needed by
merge_transitions().
* src/graphtest/tgbagraph.cc, src/graphtest/tgbagraph.test: Add states
for transitions removal and merge_transitions().
This commit is contained in:
Alexandre Duret-Lutz 2014-05-21 19:16:50 +02:00
parent 9909699c63
commit 424de90385
7 changed files with 286 additions and 10 deletions

View file

@ -233,7 +233,7 @@ namespace spot
{
auto s = down_cast<const typename graph_t::state_storage_t*>(st);
assert(s);
assert(s->succ < g_.num_transitions());
assert(!s->succ || g_.valid_trans(s->succ));
if (this->iter_cache_)
{
@ -308,6 +308,47 @@ namespace spot
{
return bddtrue;
}
/// Iterate over all transitions, and merge those with compatible
/// extremities and acceptance.
void merge_transitions()
{
for (auto& s: g_.states())
{
// Map a pair (dest state, acc) to the first transition seen
// with such characteristic.
typedef std::pair<graph_t::state, int> key_t;
std::unordered_map<key_t, graph_t::transition, pair_hash> trmap;
auto t = g_.out_iteraser(s);
while (t)
{
// Simply skip false transitions.
if (t->cond == bddfalse)
{
t.erase();
continue;
}
key_t k(t->dst, t->acc.id());
auto p = trmap.insert(make_pair(k, t.trans()));
if (!p.second)
{
// A previous transitions exist for k, merge the
// condition, and schedule the transition for
// removal.
g_.trans_data(p.first->second).cond |= t->cond;
t.erase();
}
else
{
++t;
}
}
}
g_.defrag();
}
};
}