Move several functions from acc.hh to acc.h
* spot/twa/acc.hh: Remove colors_inf_conj and colors_fin_disj (unused) and moved get_alone_mark (now find_unit_clause), propagate_fin_inf (now unit_propagation) and has_parity_prefix to acc.cc. * spot/twa/acc.cc: Use a new implementation of unit_propagation and find_unit_clause. * spot/twaalgos/cleanacc.cc: Use the new name of propagate_fin_inf.
This commit is contained in:
parent
630b8333fe
commit
b4db34995f
3 changed files with 178 additions and 262 deletions
184
spot/twa/acc.cc
184
spot/twa/acc.cc
|
|
@ -1060,6 +1060,60 @@ namespace spot
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool
|
||||||
|
has_parity_prefix_aux(acc_cond original,
|
||||||
|
acc_cond &new_cond,
|
||||||
|
std::vector<unsigned> &colors,
|
||||||
|
std::vector<acc_cond::acc_code> elements,
|
||||||
|
acc_cond::acc_op op)
|
||||||
|
{
|
||||||
|
acc_cond::mark_t empty_m = {};
|
||||||
|
if (elements.size() > 2)
|
||||||
|
{
|
||||||
|
new_cond = original;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (elements.size() == 2)
|
||||||
|
{
|
||||||
|
unsigned pos = elements[1].back().sub.op == op &&
|
||||||
|
elements[1][0].mark.count() == 1;
|
||||||
|
if (!(elements[0].back().sub.op == op || pos))
|
||||||
|
{
|
||||||
|
new_cond = original;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((elements[1 - pos].used_sets() & elements[pos][0].mark) != empty_m)
|
||||||
|
{
|
||||||
|
new_cond = original;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (elements[pos][0].mark.count() != 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
colors.push_back(elements[pos][0].mark.min_set() - 1);
|
||||||
|
elements[1 - pos].has_parity_prefix(new_cond, colors);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
acc_cond::acc_code::has_parity_prefix(acc_cond &new_cond,
|
||||||
|
std::vector<unsigned> &colors) const
|
||||||
|
{
|
||||||
|
auto disj = top_disjuncts();
|
||||||
|
if (!(has_parity_prefix_aux((*this), new_cond, colors,
|
||||||
|
disj, acc_cond::acc_op::Inf) ||
|
||||||
|
has_parity_prefix_aux((*this), new_cond, colors,
|
||||||
|
top_conjuncts(), acc_cond::acc_op::Fin)))
|
||||||
|
new_cond = acc_cond((*this));
|
||||||
|
return disj.size() == 2;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
acc_cond::has_parity_prefix(acc_cond& new_cond,
|
acc_cond::has_parity_prefix(acc_cond& new_cond,
|
||||||
std::vector<unsigned>& colors) const
|
std::vector<unsigned>& colors) const
|
||||||
|
|
@ -1082,18 +1136,6 @@ namespace spot
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned>
|
|
||||||
acc_cond::colors_inf_conj(unsigned min_nb_colors)
|
|
||||||
{
|
|
||||||
return code_.colors_inf_conj(min_nb_colors);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned>
|
|
||||||
acc_cond::colors_fin_disj(unsigned min_nb_colors)
|
|
||||||
{
|
|
||||||
return code_.colors_fin_disj(min_nb_colors);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool acc_cond::is_parity(bool& max, bool& odd, bool equiv) const
|
bool acc_cond::is_parity(bool& max, bool& odd, bool equiv) const
|
||||||
{
|
{
|
||||||
unsigned sets = num_;
|
unsigned sets = num_;
|
||||||
|
|
@ -2520,6 +2562,124 @@ namespace spot
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool
|
||||||
|
find_unit_clause(acc_cond::acc_code code, bool& conj, bool& fin,
|
||||||
|
acc_cond::mark_t& res)
|
||||||
|
{
|
||||||
|
res = {};
|
||||||
|
acc_cond::mark_t possibles = ~code.used_once_sets();
|
||||||
|
bool found_one = false;
|
||||||
|
conj = false;
|
||||||
|
fin = false;
|
||||||
|
if (code.empty() || code.is_f())
|
||||||
|
return false;
|
||||||
|
const acc_cond::acc_word* pos = &code.back();
|
||||||
|
conj = (pos->sub.op == acc_cond::acc_op::And);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
switch (pos->sub.op)
|
||||||
|
{
|
||||||
|
case acc_cond::acc_op::And:
|
||||||
|
if (!conj)
|
||||||
|
pos -= pos->sub.size + 1;
|
||||||
|
else
|
||||||
|
--pos;
|
||||||
|
break;
|
||||||
|
case acc_cond::acc_op::Or:
|
||||||
|
if (conj)
|
||||||
|
pos -= pos->sub.size + 1;
|
||||||
|
else
|
||||||
|
--pos;
|
||||||
|
break;
|
||||||
|
case acc_cond::acc_op::Inf:
|
||||||
|
case acc_cond::acc_op::InfNeg:
|
||||||
|
case acc_cond::acc_op::FinNeg:
|
||||||
|
if (!fin)
|
||||||
|
{
|
||||||
|
auto m = pos[-1].mark & possibles;
|
||||||
|
if (m.count() == 1 || conj)
|
||||||
|
{
|
||||||
|
found_one = true;
|
||||||
|
res |= m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos -= 2;
|
||||||
|
break;
|
||||||
|
case acc_cond::acc_op::Fin:
|
||||||
|
if (!found_one || fin)
|
||||||
|
{
|
||||||
|
auto m = pos[-1].mark & possibles;
|
||||||
|
if (m.count() == 1 || !conj)
|
||||||
|
{
|
||||||
|
found_one = true;
|
||||||
|
fin = true;
|
||||||
|
res |= m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos -= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (pos >= &code.front());
|
||||||
|
return res != acc_cond::mark_t {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
acc_cond::acc_code
|
||||||
|
acc_cond::acc_code::unit_propagation()
|
||||||
|
{
|
||||||
|
bool fin, conj;
|
||||||
|
acc_cond::mark_t mark;
|
||||||
|
acc_code result = (*this);
|
||||||
|
acc_code code;
|
||||||
|
if (result.size() > 1 &&
|
||||||
|
(result.back().sub.op == acc_cond::acc_op::And
|
||||||
|
|| result.back().sub.op == acc_cond::acc_op::Or))
|
||||||
|
{
|
||||||
|
while (find_unit_clause(result, conj, fin, mark))
|
||||||
|
{
|
||||||
|
acc_code init_code;
|
||||||
|
if (fin)
|
||||||
|
init_code = acc_code::fin(mark);
|
||||||
|
else
|
||||||
|
init_code = acc_code::inf(mark);
|
||||||
|
if (conj)
|
||||||
|
result = init_code & result.remove(mark, fin == conj);
|
||||||
|
else
|
||||||
|
result = init_code | result.remove(mark, fin == conj);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pos = &result.back();
|
||||||
|
auto fo = pos->sub.op;
|
||||||
|
bool is_and = (fo == acc_cond::acc_op::And);
|
||||||
|
std::vector<acc_cond::acc_code> propagated;
|
||||||
|
acc_cond::acc_code res;
|
||||||
|
if (is_and)
|
||||||
|
res = acc_cond::acc_code::t();
|
||||||
|
else
|
||||||
|
res = acc_cond::acc_code::f();
|
||||||
|
if (is_and || fo == acc_cond::acc_op::Or)
|
||||||
|
{
|
||||||
|
--pos;
|
||||||
|
while (pos >= &result.front())
|
||||||
|
{
|
||||||
|
propagated.push_back(acc_code(pos).unit_propagation());
|
||||||
|
pos -= pos->sub.size + 1;
|
||||||
|
}
|
||||||
|
result = std::accumulate(propagated.rbegin(), propagated.rend(), res,
|
||||||
|
[&](acc_cond::acc_code c1, acc_cond::acc_code c2)
|
||||||
|
{
|
||||||
|
if (is_and)
|
||||||
|
return c1 & c2;
|
||||||
|
return c1 | c2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
acc_cond::mark_t acc_cond::acc_code::fin_unit() const
|
acc_cond::mark_t acc_cond::acc_code::fin_unit() const
|
||||||
{
|
{
|
||||||
mark_t res = {};
|
mark_t res = {};
|
||||||
|
|
|
||||||
254
spot/twa/acc.hh
254
spot/twa/acc.hh
|
|
@ -70,12 +70,6 @@ namespace spot
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
|
|
||||||
std::vector<unsigned>
|
|
||||||
colors_inf_conj(unsigned min_nb_colors);
|
|
||||||
|
|
||||||
std::vector<unsigned>
|
|
||||||
colors_fin_disj(unsigned min_nb_colors);
|
|
||||||
|
|
||||||
/// \brief An acceptance mark
|
/// \brief An acceptance mark
|
||||||
///
|
///
|
||||||
/// This type is used to represent a set of acceptance sets. It
|
/// This type is used to represent a set of acceptance sets. It
|
||||||
|
|
@ -469,250 +463,12 @@ 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
|
acc_code
|
||||||
propagate_fin_inf()
|
unit_propagation();
|
||||||
{
|
|
||||||
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();
|
|
||||||
acc_code init_code;
|
|
||||||
if (conj)
|
|
||||||
init_code = acc_code::t();
|
|
||||||
else
|
|
||||||
init_code = acc_code::f();
|
|
||||||
bool keeped_code = false;
|
|
||||||
result = std::accumulate(elements.rbegin(), elements.rend(),
|
|
||||||
init_code,
|
|
||||||
[&](acc_code a, acc_code b)
|
|
||||||
{
|
|
||||||
if (b != code || keeped_code)
|
|
||||||
b = b.remove(mark, fin == conj);
|
|
||||||
if (b == code)
|
|
||||||
keeped_code = true;
|
|
||||||
if (conj)
|
|
||||||
return a & b;
|
|
||||||
else
|
|
||||||
return a | b;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
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.rbegin(), elements.rend(),
|
|
||||||
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>
|
|
||||||
colors_inf_conj(unsigned min_nb_colors = 2)
|
|
||||||
{
|
|
||||||
auto result = std::vector<unsigned>();
|
|
||||||
auto conj = top_conjuncts();
|
|
||||||
if (conj.size() != 1)
|
|
||||||
{
|
|
||||||
std::sort(conj.begin(), conj.end(),
|
|
||||||
[](acc_code c1, acc_code c2)
|
|
||||||
{
|
|
||||||
(void)c2;
|
|
||||||
return c1.back().sub.op == acc_cond::acc_op::Inf;
|
|
||||||
});
|
|
||||||
unsigned i = 0;
|
|
||||||
while (i < conj.size())
|
|
||||||
{
|
|
||||||
acc_cond::acc_code elem = conj[i];
|
|
||||||
if (elem.back().sub.op == acc_cond::acc_op::Inf)
|
|
||||||
{
|
|
||||||
if (elem[0].mark.count() == 1)
|
|
||||||
result.insert(result.end(), elem[0].mark.min_set() - 1);
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if (result.size() >= min_nb_colors)
|
|
||||||
return result;
|
|
||||||
while (i < conj.size())
|
|
||||||
{
|
|
||||||
result = conj[i].colors_inf_conj();
|
|
||||||
if (result.size() >= min_nb_colors)
|
|
||||||
return result;
|
|
||||||
result.clear();
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto disj = top_disjuncts();
|
|
||||||
if (disj.size() > 1)
|
|
||||||
{
|
|
||||||
for (auto elem : disj)
|
|
||||||
{
|
|
||||||
result = elem.colors_inf_conj();
|
|
||||||
if (result.size() >= min_nb_colors)
|
|
||||||
return result;
|
|
||||||
result.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned>
|
|
||||||
colors_fin_disj(unsigned min_nb_colors = 2)
|
|
||||||
{
|
|
||||||
auto result = std::vector<unsigned>();
|
|
||||||
auto disj = top_disjuncts();
|
|
||||||
if (disj.size() != 1)
|
|
||||||
{
|
|
||||||
std::sort(disj.begin(), disj.end(),
|
|
||||||
[](acc_code c1, acc_code c2)
|
|
||||||
{
|
|
||||||
(void) c2;
|
|
||||||
return c1.back().sub.op == acc_cond::acc_op::Fin;
|
|
||||||
});
|
|
||||||
unsigned i = 0;
|
|
||||||
while (i < disj.size())
|
|
||||||
{
|
|
||||||
acc_cond::acc_code elem = disj[i];
|
|
||||||
if (elem.back().sub.op == acc_cond::acc_op::Fin)
|
|
||||||
{
|
|
||||||
if (elem[0].mark.count() == 1)
|
|
||||||
result.insert(result.end(), elem[0].mark.min_set() - 1);
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if (result.size() >= min_nb_colors)
|
|
||||||
return result;
|
|
||||||
while (i < disj.size())
|
|
||||||
{
|
|
||||||
result = disj[i].colors_fin_disj();
|
|
||||||
if (result.size() >= min_nb_colors)
|
|
||||||
return result;
|
|
||||||
result.clear();
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto disj = top_conjuncts();
|
|
||||||
if (disj.size() > 1)
|
|
||||||
{
|
|
||||||
for (auto elem : disj)
|
|
||||||
{
|
|
||||||
result = elem.colors_fin_disj();
|
|
||||||
if (result.size() >= min_nb_colors)
|
|
||||||
return result;
|
|
||||||
result.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
has_parity_prefix_aux(spot::acc_cond& new_cond,
|
has_parity_prefix(acc_cond& new_cond,
|
||||||
std::vector<unsigned>& colors, std::vector<acc_code> elements,
|
std::vector<unsigned>& colors) const;
|
||||||
acc_cond::acc_op op) const
|
|
||||||
{
|
|
||||||
mark_t empty_m = { };
|
|
||||||
if (elements.size() > 2)
|
|
||||||
{
|
|
||||||
new_cond = (*this);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (elements.size() == 2)
|
|
||||||
{
|
|
||||||
unsigned pos = elements[1].back().sub.op == op
|
|
||||||
&& elements[1][0].mark.count() == 1;
|
|
||||||
if (!(elements[0].back().sub.op == op || pos))
|
|
||||||
{
|
|
||||||
new_cond = (*this);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((elements[1 - pos].used_sets() & elements[pos][0].mark)
|
|
||||||
!= empty_m)
|
|
||||||
{
|
|
||||||
new_cond = (*this);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (elements[pos][0].mark.count() != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
colors.push_back(elements[pos][0].mark.min_set() - 1);
|
|
||||||
elements[1 - pos].has_parity_prefix(new_cond, colors);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_parity_prefix(spot::acc_cond& new_cond,
|
|
||||||
std::vector<unsigned>& colors) const
|
|
||||||
{
|
|
||||||
auto disj = top_disjuncts();
|
|
||||||
if (!
|
|
||||||
(has_parity_prefix_aux(new_cond, colors,
|
|
||||||
top_conjuncts(), acc_cond::acc_op::Fin) ||
|
|
||||||
has_parity_prefix_aux(new_cond, colors,
|
|
||||||
disj, acc_cond::acc_op::Inf)))
|
|
||||||
new_cond = spot::acc_cond(*this);
|
|
||||||
return disj.size() == 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_parity_max_equiv(std::vector<int>& permut,
|
is_parity_max_equiv(std::vector<int>& permut,
|
||||||
|
|
@ -1951,9 +1707,9 @@ namespace spot
|
||||||
/// Fin(0)|(Inf(0) & Fin(1)), Inf(0) is true iff Fin(0) is false so
|
/// 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).
|
/// we can rewrite it as Fin(0)|Fin(1).
|
||||||
acc_cond
|
acc_cond
|
||||||
propagate_fin_inf()
|
unit_propagation()
|
||||||
{
|
{
|
||||||
return acc_cond(code_.propagate_fin_inf());
|
return acc_cond(code_.unit_propagation());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return (true, m) if there exist some acceptance mark m that
|
// Return (true, m) if there exist some acceptance mark m that
|
||||||
|
|
|
||||||
|
|
@ -620,7 +620,7 @@ namespace spot
|
||||||
fuse_marks_here(aut);
|
fuse_marks_here(aut);
|
||||||
}
|
}
|
||||||
cleanup_acceptance_here(aut, true);
|
cleanup_acceptance_here(aut, true);
|
||||||
auto prop_cond = aut->acc().propagate_fin_inf();
|
auto prop_cond = aut->acc().unit_propagation();
|
||||||
if (prop_cond != aut->acc())
|
if (prop_cond != aut->acc())
|
||||||
{
|
{
|
||||||
aut->set_acceptance(prop_cond);
|
aut->set_acceptance(prop_cond);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue