Make it easy to complement an acceptance condition

* src/tgba/acc.cc, src/tgba/acc.hh (complement): New method.
* src/bin/autfilt.cc: Add a --complement-acceptance option.
* src/tgbatest/acc2.test: Test it.
This commit is contained in:
Alexandre Duret-Lutz 2015-02-24 21:50:00 +01:00
parent 659107a000
commit d597050f6d
4 changed files with 123 additions and 11 deletions

View file

@ -353,6 +353,84 @@ namespace spot
return true;
}
namespace
{
acc_cond::acc_code complement_rec(const acc_cond::acc_word* pos)
{
auto start = pos - pos->size;
acc_cond::acc_code res;
res.resize(2);
res[0].mark = 0U;
res[1].size = 1;
switch (pos->op)
{
case acc_cond::acc_op::And:
{
--pos;
res[1].op = acc_cond::acc_op::Fin; // f
do
{
auto tmp = complement_rec(pos);
tmp.append_or(std::move(res));
std::swap(tmp, res);
pos -= pos->size + 1;
}
while (pos > start);
return res;
}
case acc_cond::acc_op::Or:
{
--pos;
res[1].op = acc_cond::acc_op::Inf; // t
do
{
auto tmp = complement_rec(pos);
tmp.append_and(std::move(res));
std::swap(tmp, res);
pos -= pos->size + 1;
}
while (pos > start);
return res;
}
case acc_cond::acc_op::Fin:
res[0].mark = pos[-1].mark;
res[1].op = acc_cond::acc_op::Inf;
return res;
case acc_cond::acc_op::Inf:
res[0].mark = pos[-1].mark;
res[1].op = acc_cond::acc_op::Fin;
return res;
case acc_cond::acc_op::FinNeg:
res[0].mark = pos[-1].mark;
res[1].op = acc_cond::acc_op::InfNeg;
return res;
case acc_cond::acc_op::InfNeg:
res[0].mark = pos[-1].mark;
res[1].op = acc_cond::acc_op::FinNeg;
return res;
}
SPOT_UNREACHABLE();
return acc_cond::acc_code{};
}
}
acc_cond::acc_code acc_cond::acc_code::complement() const
{
if (empty())
{
acc_cond::acc_code res;
res.resize(2);
res[0].mark = 0U;
res[1].op = acc_cond::acc_op::Fin;
res[1].size = 1;
return res;
}
return complement_rec(&back());
}
std::ostream& operator<<(std::ostream& os,
const spot::acc_cond::acc_code& code)