minimize_wdba: improve handling of terminal automata

Part of #444.

* spot/twaalgos/minimize.cc (minimize_wdba): Terminal automata do not
need a product to decide which states are accepting in the DBA.  This
is faster, and also determinize more formulas of #443.
* tests/core/ltl2tgba2.test: Adjust the expected iteration where
determinization will be aborted.
This commit is contained in:
Alexandre Duret-Lutz 2020-12-08 20:02:33 +01:00
parent 48edfd80c2
commit 2d6c7ac045
2 changed files with 32 additions and 16 deletions

View file

@ -384,7 +384,7 @@ namespace spot
hash_set* non_final; hash_set* non_final;
twa_graph_ptr det_a; twa_graph_ptr det_a;
bool has_sinks = false;
{ {
bool input_is_det = is_deterministic(a); bool input_is_det = is_deterministic(a);
if (input_is_det) if (input_is_det)
@ -396,21 +396,30 @@ namespace spot
// Find any accepting sink state, to speed up the // Find any accepting sink state, to speed up the
// determinization by merging all states containing a sink // determinization by merging all states containing a sink
// state. // state.
//
// We only as consider as "accepting sink" any state
// that have an accepting self-loop labeled by true.
std::vector<unsigned> acc_sinks; std::vector<unsigned> acc_sinks;
unsigned ns = a->num_states(); unsigned ns = a->num_states();
for (unsigned n = 0; n < ns; ++n) if (!a->prop_terminal().is_true())
{ {
for (auto& e: a->out(n)) // We only consider as "accepting sink" any state
if (e.dst == n && e.cond == bddtrue // that has an accepting self-loop labeled by true.
&& a->acc().accepting(e.acc)) for (unsigned n = 0; n < ns; ++n)
{ for (auto& e: a->out(n))
acc_sinks.push_back(n); if (e.dst == n && e.cond == bddtrue
break; && a->acc().accepting(e.acc))
} {
acc_sinks.push_back(n);
break;
}
} }
else
{
// All accepting SCCs are terminal.
scc_info si(a, scc_info_options::NONE);
for (unsigned n = 0; n < ns; ++n)
if (si.is_accepting_scc(si.scc_of(n)))
acc_sinks.push_back(n);
}
has_sinks = !acc_sinks.empty();
det_a = tgba_powerset(a, aborter, &acc_sinks); det_a = tgba_powerset(a, aborter, &acc_sinks);
if (!det_a) if (!det_a)
return nullptr; return nullptr;
@ -441,6 +450,13 @@ namespace spot
for (unsigned m = 0; m < scc_count; ++m) for (unsigned m = 0; m < scc_count; ++m)
is_accepting_scc[m] = sm.is_accepting_scc(m); is_accepting_scc[m] = sm.is_accepting_scc(m);
} }
else if (a->prop_terminal())
{
// tgba_powerset has gathered all terminal states on
// powerstate 0.
if (has_sinks)
is_accepting_scc[sm.scc_of(0)] = true;
}
else else
{ {
twa_graph_ptr prod = spot::product(a, det_a, aborter); twa_graph_ptr prod = spot::product(a, det_a, aborter);

View file

@ -481,7 +481,7 @@ test 34,0 = `ltl2tgba -B --stats=%s,%d "$f"`
# Issue #444. Because WDBA-minimization disables itself for large # Issue #444. Because WDBA-minimization disables itself for large
# automata, the output is only deterministic up to a certain point, # automata, the output is only deterministic up to a certain point,
# and the goal is to raise that point. # and the goal is to raise that point.
f='(!(G({(a)} |=> {(b)[*9]})))' f='(!(G({(a)} |=> {(b)[*12]})))'
test 11,1 = `ltl2tgba -B --stats=%s,%d "$f"` test 14,1 = `ltl2tgba -B --stats=%s,%d "$f"`
f='(!(G({(a)} |=> {(b)[*10]})))' f='(!(G({(a)} |=> {(b)[*13]})))'
test 12,0 = `ltl2tgba -B --stats=%s,%d "$f"` test 15,0 = `ltl2tgba -B --stats=%s,%d "$f"`