Remove redundant Fin and Inf with simplify_acceptance

* spot/twa/acc.hh: Add simplification like
Fin(0)|(Inf(0) & Fin(1)) to Fin(0)|Fin(1).
* spot/twaalgos/cleanacc.cc: Use this simplification.
This commit is contained in:
Florian Renkin 2020-04-02 18:50:09 +02:00 committed by Alexandre Duret-Lutz
parent 502778f83f
commit 37897e89e8
2 changed files with 87 additions and 0 deletions

View file

@ -110,6 +110,7 @@ namespace spot
mark_t mark_t
apply_permutation(std::vector<unsigned> permut); apply_permutation(std::vector<unsigned> permut);
#ifndef SWIG #ifndef SWIG
/// Create a mark_t from a range of set numbers. /// Create a mark_t from a range of set numbers.
template<class iterator> template<class iterator>
@ -468,6 +469,82 @@ namespace spot
/// provided methods instead. /// provided methods instead.
struct SPOT_API acc_code: public std::vector<acc_word> struct SPOT_API acc_code: public std::vector<acc_word>
{ {
private:
bool
get_alone_mark(bool& fin, acc_cond::mark_t& mark, bool& conj, acc_code& code)
{
auto elements = top_conjuncts();
conj = (elements.size() > 1);
if (!conj)
{
elements = top_disjuncts();
if (elements.size() < 2)
return false;
}
for (auto c : elements)
{
auto op = c.back().sub.op;
fin = (op == acc_cond::acc_op::Fin);
if ((fin || op == acc_cond::acc_op::Inf) && c[0].mark.count() == 1
&& (used_once_sets() & c[0].mark) == acc_cond::mark_t {})
{
mark = c[0].mark;
code = c;
return true;
}
}
return false;
}
public:
acc_code
propagate_fin_inf()
{
bool fin = false, conj;
acc_cond::mark_t mark;
acc_code result = (*this);
acc_code code;
while (result.get_alone_mark(fin, mark, conj, code))
{
auto elements = result.top_disjuncts();
if (elements.size() < 2)
elements = result.top_conjuncts();
result = std::accumulate(elements.begin(), elements.end(), code,
[&](acc_code a, acc_code b)
{
if (b != code)
{
b = b.remove(mark, !fin);
if (conj)
return a & b;
else
return a | b;
}
return a;
});
}
std::vector<acc_code> elements = result.top_disjuncts();
if (elements.size() < 2)
elements = result.top_conjuncts();
if (elements.size() > 1)
{
acc_code init_code;
if (conj)
init_code = acc_code::t();
else
init_code = acc_code::f();
result = std::accumulate(elements.begin(), elements.end(), init_code,
[&](acc_code a, acc_code b)
{
if (conj)
return a & b.propagate_fin_inf();
else
return a | b.propagate_fin_inf();
});
}
return result;
}
std::vector<unsigned> std::vector<unsigned>
colors_inf_conj(unsigned min_nb_colors = 2) colors_inf_conj(unsigned min_nb_colors = 2)
@ -1862,6 +1939,15 @@ namespace spot
return is_parity(max, odd); return is_parity(max, odd);
} }
/// \brief Remove redundant Fin and Inf. For example in
/// Fin(0)|(Inf(0) & Fin(1)), Inf(0) is true iff Fin(0) is false so
/// we can rewrite it as Fin(0)|Fin(1).
acc_cond
propagate_fin_inf()
{
return acc_cond(code_.propagate_fin_inf());
}
// Return (true, m) if there exist some acceptance mark m that // Return (true, m) if there exist some acceptance mark m that
// does not satisfy the acceptance condition. Return (false, 0U) // does not satisfy the acceptance condition. Return (false, 0U)
// otherwise. // otherwise.

View file

@ -619,6 +619,7 @@ namespace spot
simplify_complementary_marks_here(aut); simplify_complementary_marks_here(aut);
fuse_marks_here(aut); fuse_marks_here(aut);
} }
aut->set_acceptance(aut->acc().propagate_fin_inf());
cleanup_acceptance_here(aut, true); cleanup_acceptance_here(aut, true);
return aut; return aut;
} }