autfilt: Add --is-terminal and --is-weak.

Fixes #47.

* src/twaalgos/strength.cc, src/twaalgos/strength.hh
(is_weak_automaton): New function.
(is_terminal_automaton): Generalize slightly.
* src/bin/autfilt.cc: Add options --is-terminal and --is-weak.
* src/tests/readsave.test: Add a test.
* NEWS: Update.
This commit is contained in:
Alexandre Duret-Lutz 2015-11-07 15:30:51 +01:00
parent 81cfa05aef
commit f4cf0f4078
5 changed files with 103 additions and 38 deletions

View file

@ -19,49 +19,68 @@
#include "strength.hh"
#include "misc/hash.hh"
#include "isweakscc.hh"
#include <deque>
namespace spot
{
namespace
{
template <bool terminal>
bool is_type_automaton(const const_twa_graph_ptr& aut, scc_info* si)
{
// Create an scc_info if the user did not give one to us.
bool need_si = !si;
if (need_si)
si = new scc_info(aut);
si->determine_unknown_acceptance();
bool result = true;
unsigned n = si->scc_count();
for (unsigned i = 0; i < n; ++i)
{
if (si->is_trivial(i))
continue;
bool first = true;
acc_cond::mark_t m = 0U;
for (auto src: si->states_of(i))
for (auto& t: aut->out(src))
if (si->scc_of(t.dst) == i)
{
if (first)
{
first = false;
m = t.acc;
}
else if (m != t.acc)
{
result = false;
goto exit;
}
}
if (terminal && si->is_accepting_scc(i) && !is_complete_scc(*si, i))
{
result = false;
break;
}
}
exit:
if (need_si)
delete si;
return result;
}
}
bool
is_terminal_automaton(const const_twa_graph_ptr& aut, scc_info* si)
{
if (aut->prop_terminal())
return true;
// Create an scc_info if the user did not give one to us.
bool need_si = !si;
if (need_si)
si = new scc_info(aut);
si->determine_unknown_acceptance();
return aut->prop_terminal() || is_type_automaton<true>(aut, si);
}
bool result = true;
for (auto& scc: *si)
{
if (scc.is_rejecting())
continue;
// Accepting SCCs should have only one state.
auto& st = scc.states();
if (st.size() != 1)
{
result = false;
break;
}
// The state should have only one edge that is a
// self-loop labelled by true.
auto src = st.front();
auto out = aut->out(src);
auto it = out.begin();
assert(it != out.end());
result =
(it->cond == bddtrue) && (it->dst == src) && (++it == out.end());
if (!result)
break;
}
if (need_si)
delete si;
return result;
bool
is_weak_automaton(const const_twa_graph_ptr& aut, scc_info* si)
{
return aut->prop_weak() || is_type_automaton<false>(aut, si);
}
bool is_safety_mwdba(const const_twa_graph_ptr& aut)

View file

@ -25,9 +25,8 @@ namespace spot
{
/// \brief Whether an automaton is terminal.
///
/// An automaton is terminal if any accepting path ends on an
/// accepting state with only one transition that is a self-loop
/// labelled by true.
/// An automaton is terminal if it is weak, and all accepting SCCs
/// are complete.
///
/// \param aut the automaton to check
///
@ -36,6 +35,19 @@ namespace spot
SPOT_API bool
is_terminal_automaton(const const_twa_graph_ptr& aut, scc_info* sm = nullptr);
/// \brief Whether an automaton is weak.
///
/// An automaton is weak if if any given SCC, all transitions belong
/// to the same acceptance sets.
///
/// \param aut the automaton to check
///
/// \param sm an scc_info object for the automaton if available (it
/// will be built otherwise).
SPOT_API bool
is_weak_automaton(const const_twa_graph_ptr& aut, scc_info* sm = nullptr);
/// \brief Whether a minimized WDBA represents a safety property.
///
/// A minimized WDBA (as returned by a successful run of