genem: fix removal of unsatisfied Fin(x) sets

Fixes #360.

* spot/twa/acc.cc, spot/twa/acc.hh (force_inf): New method.
* spot/twaalgos/genem.cc: Fix the emptiness check using force_inf.
* tests/python/genem.py: Add test case and adjust the python
version of the emptiness check.
This commit is contained in:
Alexandre Duret-Lutz 2018-07-26 15:14:28 +02:00
parent 9f81df2cd4
commit 469d2b4ef4
4 changed files with 88 additions and 3 deletions

View file

@ -1481,6 +1481,51 @@ namespace spot
SPOT_UNREACHABLE();
return {};
}
static acc_cond::acc_code
force_inf_rec(const acc_cond::acc_word* pos, acc_cond::mark_t rem)
{
auto start = pos - pos->sub.size;
switch (pos->sub.op)
{
case acc_cond::acc_op::And:
{
--pos;
auto res = acc_cond::acc_code::t();
do
{
auto tmp = force_inf_rec(pos, rem) & std::move(res);
std::swap(tmp, res);
pos -= pos->sub.size + 1;
}
while (pos > start);
return res;
}
case acc_cond::acc_op::Or:
{
--pos;
auto res = acc_cond::acc_code::f();
do
{
auto tmp = force_inf_rec(pos, rem) | std::move(res);
std::swap(tmp, res);
pos -= pos->sub.size + 1;
}
while (pos > start);
return res;
}
case acc_cond::acc_op::Fin:
return acc_cond::acc_code::fin(pos[-1].mark - rem);
case acc_cond::acc_op::Inf:
return acc_cond::acc_code::inf(pos[-1].mark);
case acc_cond::acc_op::FinNeg:
case acc_cond::acc_op::InfNeg:
SPOT_UNREACHABLE();
return {};
}
SPOT_UNREACHABLE();
return {};
}
}
acc_cond::acc_code
@ -1499,6 +1544,14 @@ namespace spot
return strip_rec(&back(), rem, missing, false);
}
acc_cond::acc_code
acc_cond::acc_code::force_inf(mark_t rem) const
{
if (is_t() || is_f())
return *this;
return force_inf_rec(&back(), rem);
}
acc_cond::mark_t
acc_cond::acc_code::used_sets() const
{

View file

@ -921,6 +921,8 @@ namespace spot
acc_code remove(acc_cond::mark_t rem, bool missing) const;
// Same as remove, but also shift numbers
acc_code strip(acc_cond::mark_t rem, bool missing) const;
// for all x in m, this replaces Fin(x) by false.
acc_code force_inf(mark_t m) const;
// Return the set of sets appearing in the condition.
acc_cond::mark_t used_sets() const;
@ -1388,6 +1390,12 @@ namespace spot
{ num_sets() - (all_sets() & rem).count(), code_.strip(rem, missing) };
}
// For all x in m, this replaces Fin(x) by false.
acc_cond force_inf(mark_t m) const
{
return {num_sets(), code_.force_inf(m)};
}
// Restrict an acceptance condition to a subset of set numbers
// that are occurring at some point.
acc_cond restrict_to(mark_t rem) const

View file

@ -175,7 +175,7 @@ namespace spot
<deal_with_disjunct>))
return false;
// Try to accept when Fin(fo) == false
tmp.set(acc.remove({(unsigned) fo}, false));
tmp.set(acc.force_inf({(unsigned) fo}));
return generic_emptiness_check_for_scc_nocopy
<deal_with_disjunct>(si, scc, tocut);
return true;