stutter: Improve sl2.
* src/tgbaalgos/stutter.cc (sl2): Detect selfloops, and merge intermediate states when possible.
This commit is contained in:
parent
bd414d4d4c
commit
204af40b09
1 changed files with 46 additions and 23 deletions
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue