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;
|
||||
}
|
||||
|
||||
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
|
||||
acc_cond::has_parity_prefix(acc_cond& new_cond,
|
||||
std::vector<unsigned>& colors) const
|
||||
|
|
@ -1082,18 +1136,6 @@ namespace spot
|
|||
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
|
||||
{
|
||||
unsigned sets = num_;
|
||||
|
|
@ -2520,6 +2562,124 @@ namespace spot
|
|||
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
|
||||
{
|
||||
mark_t res = {};
|
||||
|
|
|
|||
254
spot/twa/acc.hh
254
spot/twa/acc.hh
|
|
@ -70,12 +70,6 @@ namespace spot
|
|||
#endif
|
||||
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
|
||||
///
|
||||
/// This type is used to represent a set of acceptance sets. It
|
||||
|
|
@ -469,250 +463,12 @@ namespace spot
|
|||
/// provided methods instead.
|
||||
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();
|
||||
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;
|
||||
}
|
||||
unit_propagation();
|
||||
|
||||
bool
|
||||
has_parity_prefix_aux(spot::acc_cond& new_cond,
|
||||
std::vector<unsigned>& colors, std::vector<acc_code> elements,
|
||||
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;
|
||||
}
|
||||
has_parity_prefix(acc_cond& new_cond,
|
||||
std::vector<unsigned>& colors) const;
|
||||
|
||||
bool
|
||||
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
|
||||
/// we can rewrite it as Fin(0)|Fin(1).
|
||||
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
|
||||
|
|
|
|||
|
|
@ -620,7 +620,7 @@ namespace spot
|
|||
fuse_marks_here(aut);
|
||||
}
|
||||
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())
|
||||
{
|
||||
aut->set_acceptance(prop_cond);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue