stutter: Improve sl2.

* src/tgbaalgos/stutter.cc (sl2): Detect selfloops, and merge
intermediate states when possible.
This commit is contained in:
Alexandre Duret-Lutz 2015-02-07 12:59:55 +01:00
parent bd414d4d4c
commit 204af40b09

View file

@ -377,21 +377,45 @@ namespace spot
atomic_propositions = get_all_ap(a); atomic_propositions = get_all_ap(a);
unsigned num_states = a->num_states(); unsigned num_states = a->num_states();
unsigned num_transitions = a->num_transitions(); unsigned num_transitions = a->num_transitions();
for (unsigned src = 0; src < num_states; ++src) std::vector<bdd> selfloops(num_states, bddfalse);
std::map<std::pair<unsigned, int>, unsigned> newstates;
// Record all the conditions for which we can selfloop on each
// state.
for (auto& t: a->transitions())
if (t.src == t.dst)
selfloops[t.src] |= t.cond;
for (unsigned t = 1; t <= num_transitions; ++t)
{ {
auto trans = a->out(src); auto& td = a->trans_storage(t);
if (a->is_dead_transition(td))
continue;
for (auto it = trans.begin(); it != trans.end() unsigned src = td.src;
&& it.trans() <= num_transitions; ++it) unsigned dst = td.dst;
if (it->dst != src) if (src != dst)
{ {
bdd all = it->cond; bdd all = td.cond;
// If there is a self-loop with the whole condition on
// either end of the transition, do not bother with it.
if (bdd_implies(all, selfloops[src])
|| bdd_implies(all, selfloops[dst]))
continue;
// Do not use td in the loop because the new_transition()
// might invalidate it.
auto acc = td.acc;
while (all != bddfalse) while (all != bddfalse)
{ {
unsigned dst = it->dst;
bdd one = bdd_satoneset(all, atomic_propositions, bddtrue); bdd one = bdd_satoneset(all, atomic_propositions, bddtrue);
unsigned tmp = a->new_state(); all -= one;
unsigned i = a->new_transition(src, tmp, one, it->acc); // Skip if there is a loop for this particular letter.
if (bdd_implies(one, selfloops[src])
|| bdd_implies(one, selfloops[dst]))
continue;
auto p = newstates.emplace(std::make_pair(dst, one.id()), 0);
if (p.second)
p.first->second = a->new_state();
unsigned tmp = p.first->second; // intermediate state
unsigned i = a->new_transition(src, tmp, one, acc);
assert(i > num_transitions); assert(i > num_transitions);
i = a->new_transition(tmp, tmp, one, 0U); i = a->new_transition(tmp, tmp, one, 0U);
assert(i > num_transitions); assert(i > num_transitions);
@ -399,7 +423,6 @@ namespace spot
i = a->new_transition(tmp, dst, one, 0U); i = a->new_transition(tmp, dst, one, 0U);
assert(i > num_transitions); assert(i > num_transitions);
(void)i; (void)i;
all -= one;
} }
} }
} }