autfilt add support for --partial-degeneralize

* bin/autfilt.cc: Add a --partial-degeneralize option.
* NEWS: Mention it.
* spot/twaalgos/degen.cc: Do not restrict partial_degeneralize() to
deterministic automata.
* spot/twaalgos/degen.hh: Adjust documentation.
* tests/core/pdegen.test: New test case.
* tests/Makefile.am: Add it.
* tests/python/pdegen.py: Adjust.
This commit is contained in:
Alexandre Duret-Lutz 2020-02-15 10:07:59 +01:00
parent bf42b19eff
commit b5e464e05a
7 changed files with 94 additions and 45 deletions

View file

@ -750,8 +750,7 @@ namespace spot
namespace
{
static acc_cond::mark_t
to_strip(const acc_cond::acc_code& code, acc_cond::mark_t todegen,
bool also_fin)
to_strip(const acc_cond::acc_code& code, acc_cond::mark_t todegen)
{
if (code.empty())
return todegen;
@ -768,14 +767,6 @@ namespace spot
break;
case acc_cond::acc_op::Fin:
case acc_cond::acc_op::FinNeg:
if (!also_fin)
{
pos -= 2;
tostrip -= code[pos].mark;
break;
}
// Handle Fin and Inf in the same way
SPOT_FALLTHROUGH;
case acc_cond::acc_op::Inf:
case acc_cond::acc_op::InfNeg:
{
@ -796,8 +787,7 @@ namespace spot
update_acc_for_partial_degen(acc_cond::acc_code& code,
acc_cond::mark_t todegen,
acc_cond::mark_t tostrip,
acc_cond::mark_t accmark,
bool also_fin)
acc_cond::mark_t accmark)
{
if (!todegen || code.empty())
{
@ -817,14 +807,6 @@ namespace spot
break;
case acc_cond::acc_op::Fin:
case acc_cond::acc_op::FinNeg:
if (!also_fin)
{
pos -= 2;
code[pos].mark = code[pos].mark.strip(tostrip);
break;
}
// Handle Fin and Inf in the same way
SPOT_FALLTHROUGH;
case acc_cond::acc_op::Inf:
case acc_cond::acc_op::InfNeg:
{
@ -869,9 +851,6 @@ namespace spot
if (code.empty())
return {};
if (allow_fin)
allow_fin = is_deterministic(aut);
acc_cond::mark_t res = {};
unsigned res_sz = -1U;
auto update = [&](const acc_cond::mark_t& m)
@ -926,16 +905,11 @@ namespace spot
res->copy_ap_of(a);
acc_cond::acc_code acc = a->get_acceptance();
// We can also degeneralize disjunctions of Fin if the input is
// deterministic.
bool also_fin = a->acc().uses_fin_acceptance() && is_deterministic(a);
acc_cond::mark_t tostrip = to_strip(acc, todegen, also_fin);
acc_cond::mark_t tostrip = to_strip(acc, todegen);
acc_cond::mark_t keep = a->acc().all_sets() - tostrip;
acc_cond::mark_t degenmark = {keep.count()};
if (!update_acc_for_partial_degen(acc, todegen, tostrip, degenmark,
also_fin))
if (!update_acc_for_partial_degen(acc, todegen, tostrip, degenmark))
report_invalid_partial_degen_arg(todegen, acc);
res->set_acceptance(acc);

View file

@ -107,13 +107,12 @@ namespace spot
///
/// Cases where the sets listed in \a todegen also occur outside
/// of the Inf-conjunction are also supported. Subformulas that
/// are disjunctions of Fin(.) terms (e.g., Fin(1)|Fin(2)) can
/// also be degeneralized if the input automaton is deterministic.
/// are disjunctions of Fin(.) terms (e.g., Fin(1)|Fin(2)) will
/// be degeneralized as well.
///
/// If this functions is called with a value of \a todegen that does
/// not match a conjunction of Inf(.), or in a deterministic
/// automaton a disjunction of Fin(.), an std::runtime_error
/// exception is thrown.
/// not match a conjunction of Inf(.), or a disjunction of Fin(.),
/// an std::runtime_error exception is thrown.
///
/// The version of the function that has no \a todegen argument will
/// perform all possible partial degeneralizations, and may return
@ -132,10 +131,9 @@ namespace spot
/// \brief Is the automaton partially degeneralizable?
///
/// Return a mark `M={m₁, m₂, ..., mₙ}` such that either (1)
/// `Inf(m₁)&Inf(m₂)&...&Inf(mₙ)` appears in the acceptance
/// condition of \a aut, or (2) \a aut is deterministic and
/// `Inf(m₁)|Inf(m₂)|...|Fin(mₙ)` appear in its conditions.
/// Return a mark `M={m₁, m₂, ..., mₙ}` such that either
/// `Inf(m₁)&Inf(m₂)&...&Inf(mₙ)` or `Fin(m₁)|Fin(m₂)|...|Fin(mₙ)`
/// appears in the acceptance condition of \a aut.
///
/// If multiple such marks exist the smallest such mark is returned.
/// (This is important in case of overlapping options. E.g., in the