support for semi-deterministic property
* spot/twa/twa.hh (prop_semi_deterministic): New methods. * spot/parseaut/parseaut.yy, spot/twaalgos/hoa.cc: Add support for the semi-deterministic property. * doc/org/concepts.org, doc/org/hoa.org: Document it. * spot/twaalgos/isdet.cc, spot/twaalgos/isdet.hh (is_semi_deterministic): New function. * bin/autfilt.cc: Add --is-semi-deterministic. * bin/common_aoutput.cc: Add --check=semi-deterministic. * tests/core/semidet.test: New file. * tests/Makefile.am: Add it. * tests/core/parseaut.test, tests/core/readsave.test: Adjust.
This commit is contained in:
parent
db5d9780f1
commit
4b01387817
14 changed files with 265 additions and 50 deletions
|
|
@ -590,6 +590,19 @@ header: format-version header-items
|
|||
"... 'properties: !unambiguous' given here");
|
||||
}
|
||||
}
|
||||
auto sd = p.find("semi-deterministic");
|
||||
if (sd != e)
|
||||
{
|
||||
a->prop_semi_deterministic(sd->second.val);
|
||||
auto d = p.find("deterministic");
|
||||
if (d != e && !sd->second.val && d->second.val)
|
||||
{
|
||||
error(d->second.loc,
|
||||
"'properties: deterministic' contradicts...");
|
||||
error(sd->second.loc,
|
||||
"... 'properties: !semi-deterministic' given here");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -991,6 +991,7 @@ namespace spot
|
|||
trival::repr_t unambiguous:2; // Unambiguous automaton.
|
||||
trival::repr_t stutter_invariant:2; // Stutter invariant language.
|
||||
trival::repr_t very_weak:2; // very-weak, or 1-weak
|
||||
trival::repr_t semi_deterministic:2; // semi-deterministic automaton.
|
||||
};
|
||||
union
|
||||
{
|
||||
|
|
@ -1285,16 +1286,17 @@ namespace spot
|
|||
|
||||
/// \brief Set the deterministic property.
|
||||
///
|
||||
/// Setting the "deterministic" property automatically
|
||||
/// sets the "unambiguous" property.
|
||||
/// Setting the "deterministic" property automatically sets the
|
||||
/// "unambiguous" and "semi-deterministic" properties.
|
||||
///
|
||||
/// \see prop_unambiguous()
|
||||
/// \see prop_semi_deterministic()
|
||||
void prop_deterministic(trival val)
|
||||
{
|
||||
is.deterministic = val.val();
|
||||
if (val)
|
||||
// deterministic implies unambiguous
|
||||
is.unambiguous = val.val();
|
||||
// deterministic implies unambiguous and semi-deterministic
|
||||
is.unambiguous = is.semi_deterministic = val.val();
|
||||
}
|
||||
|
||||
/// \brief Whether the automaton is unambiguous
|
||||
|
|
@ -1328,6 +1330,36 @@ namespace spot
|
|||
is.deterministic = val.val();
|
||||
}
|
||||
|
||||
/// \brief Whether the automaton is semi-deterministic
|
||||
///
|
||||
/// An automaton is semi-deterministic if the sub-automaton
|
||||
/// reachable from any accepting SCC is deterministic.
|
||||
///
|
||||
/// Note that this method may return trival::maybe() when it is
|
||||
/// unknown whether the automaton is semi-deterministic or not.
|
||||
/// If you need a true/false answer, prefer the
|
||||
/// is_semi_deterministic() function.
|
||||
///
|
||||
/// \see prop_deterministic()
|
||||
/// \see is_semi_deterministic()
|
||||
trival prop_semi_deterministic() const
|
||||
{
|
||||
return is.semi_deterministic;
|
||||
}
|
||||
|
||||
/// \brief Sets the semi-deterministic property
|
||||
///
|
||||
/// Marking an automaton as "non semi-deterministic" automatically
|
||||
/// marks it as "non deterministic".
|
||||
///
|
||||
/// \see prop_deterministic()
|
||||
void prop_semi_deterministic(trival val)
|
||||
{
|
||||
is.semi_deterministic = val.val();
|
||||
if (!val)
|
||||
is.deterministic = val.val();
|
||||
}
|
||||
|
||||
/// \brief Whether the automaton is stutter-invariant.
|
||||
///
|
||||
/// An automaton is stutter-invariant iff any accepted word
|
||||
|
|
@ -1436,6 +1468,7 @@ namespace spot
|
|||
if (p.deterministic)
|
||||
{
|
||||
prop_deterministic(other->prop_deterministic());
|
||||
prop_semi_deterministic(other->prop_semi_deterministic());
|
||||
prop_unambiguous(other->prop_unambiguous());
|
||||
}
|
||||
if (p.stutter_inv)
|
||||
|
|
@ -1455,11 +1488,13 @@ namespace spot
|
|||
{
|
||||
prop_terminal(trival::maybe());
|
||||
prop_weak(trival::maybe());
|
||||
prop_very_weak(trival::maybe());
|
||||
prop_inherently_weak(trival::maybe());
|
||||
}
|
||||
if (!p.deterministic)
|
||||
{
|
||||
prop_deterministic(trival::maybe());
|
||||
prop_semi_deterministic(trival::maybe());
|
||||
prop_unambiguous(trival::maybe());
|
||||
}
|
||||
if (!p.stutter_inv)
|
||||
|
|
|
|||
|
|
@ -489,6 +489,10 @@ namespace spot
|
|||
prop(" unambiguous");
|
||||
else if (v1_1 && !aut->prop_unambiguous())
|
||||
prop(" !unambiguous");
|
||||
if (aut->prop_semi_deterministic() && (verbose || !md.is_deterministic))
|
||||
prop(" semi-deterministic");
|
||||
else if (v1_1 && !aut->prop_semi_deterministic())
|
||||
prop(" !semi-deterministic");
|
||||
if (aut->prop_stutter_invariant())
|
||||
prop(" stutter-invariant");
|
||||
if (!aut->prop_stutter_invariant())
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <spot/twaalgos/isdet.hh>
|
||||
#include <set>
|
||||
#include <deque>
|
||||
#include <spot/twaalgos/sccinfo.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -148,4 +147,48 @@ namespace spot
|
|||
// initial state.
|
||||
return ns > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
is_semi_deterministic(const const_twa_graph_ptr& aut)
|
||||
{
|
||||
trival sd = aut->prop_semi_deterministic();
|
||||
if (sd.is_known())
|
||||
return sd.is_true();
|
||||
scc_info si(aut);
|
||||
si.determine_unknown_acceptance();
|
||||
unsigned nscc = si.scc_count();
|
||||
assert(nscc);
|
||||
std::vector<bool> reachable_from_acc(nscc);
|
||||
bool semi_det = true;
|
||||
do // iterator of SCCs in reverse topological order
|
||||
{
|
||||
--nscc;
|
||||
if (si.is_accepting_scc(nscc) || reachable_from_acc[nscc])
|
||||
{
|
||||
for (unsigned succ: si.succ(nscc))
|
||||
reachable_from_acc[succ] = true;
|
||||
for (unsigned src: si.states_of(nscc))
|
||||
{
|
||||
bdd available = bddtrue;
|
||||
for (auto& t: aut->out(src))
|
||||
if (!bdd_implies(t.cond, available))
|
||||
{
|
||||
semi_det = false;
|
||||
std::cerr << "Failed on state " << src << '\n';
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
{
|
||||
available -= t.cond;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (nscc);
|
||||
done:
|
||||
std::const_pointer_cast<twa_graph>(aut)
|
||||
->prop_semi_deterministic(semi_det);
|
||||
return semi_det;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,4 +74,13 @@ namespace spot
|
|||
/// i.e., each state as a successor for any possible configuration.
|
||||
SPOT_API bool
|
||||
is_complete(const const_twa_graph_ptr& aut);
|
||||
|
||||
/// \brief Return true iff \a aut is semi-deterministic.
|
||||
///
|
||||
/// An automaton is semi-deterministic if the sub-automaton
|
||||
/// reachable from any accepting SCC is deterministic.
|
||||
SPOT_API bool
|
||||
is_semi_deterministic(const const_twa_graph_ptr& aut);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue