safra: Ensure parity min even acceptance

* src/tests/safra.cc, src/tests/safra.test:  Use HOA format in tests.
* src/twaalgos/safra.cc:  Make sure the number of sets are always odd so
that cycles without any acceptance set are rejected.
This commit is contained in:
Alexandre Lewkowicz 2015-05-27 16:42:19 +02:00 committed by Alexandre Duret-Lutz
parent d0d42f86f9
commit 8362bf3a5f
3 changed files with 91 additions and 54 deletions

View file

@ -26,6 +26,7 @@
#include "hoaparse/public.hh" #include "hoaparse/public.hh"
#include "ltlparse/public.hh" #include "ltlparse/public.hh"
#include "twaalgos/dotty.hh" #include "twaalgos/dotty.hh"
#include "twaalgos/hoa.hh"
int main(int argc, char* argv[]) int main(int argc, char* argv[])
@ -57,5 +58,11 @@ int main(int argc, char* argv[])
} }
res->merge_transitions(); res->merge_transitions();
if (argc >= 4 && !strncmp(argv[3], "-H", 2))
{
spot::hoa_reachable(std::cout, res, "t");
std::cout << std::endl;
}
else
spot::dotty_reachable(std::cout, res); spot::dotty_reachable(std::cout, res);
} }

View file

@ -41,28 +41,31 @@ State: 1
EOF EOF
cat >out.exp << EOF cat >out.exp << EOF
digraph G { HOA: v1
rankdir=LR States: 4
node [shape="circle"] Start: 0
I [label="", style=invis, width=0] AP: 2 "a" "b"
I -> 0 acc-name: Buchi
0 [label="0"] Acceptance: 1 Inf(0)
0 -> 1 [label="a"] properties: trans-labels explicit-labels trans-acc deterministic
1 [label="1"] --BODY--
1 -> 2 [label="a\n{0}"] State: 0
1 -> 3 [label="!a & b\n{3}"] [0] 1
2 [label="2"] State: 1
2 -> 1 [label="a"] [0] 2 {0}
2 -> 3 [label="!a & b"] [!0&1] 3
3 [label="3"] State: 2
3 -> 0 [label="a & !b"] [0] 1
3 -> 2 [label="a & b"] [!0&1] 3
3 -> 3 [label="!a & b"] State: 3
} [0&!1] 0
[0&1] 2
[!0&1] 3
--END--
EOF EOF
run 0 ../safra --hoa double_a.hoa > out.dot run 0 ../safra --hoa double_a.hoa -H > out.hoa
diff out.dot out.exp diff out.hoa out.exp
cat >double_b.hoa << EOF cat >double_b.hoa << EOF
HOA: v1 HOA: v1
@ -83,33 +86,36 @@ State: 1
EOF EOF
cat >out.exp << EOF cat >out.exp << EOF
digraph G { HOA: v1
rankdir=LR States: 6
node [shape="circle"] Start: 0
I [label="", style=invis, width=0] AP: 2 "a" "b"
I -> 0 acc-name: Buchi
0 [label="0"] Acceptance: 1 Inf(0)
0 -> 1 [label="a"] properties: trans-labels explicit-labels trans-acc deterministic
1 [label="1"] --BODY--
1 -> 1 [label="a & !b"] State: 0
1 -> 2 [label="a & b"] [0] 1
1 -> 3 [label="!a & b\n{0}"] State: 1
2 [label="2"] [0&!1] 1
2 -> 3 [label="!a & b\n{0}"] [0&1] 2
2 -> 4 [label="a & !b"] [!0&1] 3 {0}
2 -> 5 [label="a & b"] State: 2
3 [label="3"] [!0&1] 3 {0}
3 -> 0 [label="a & !b"] [0&!1] 4
3 -> 2 [label="a & b"] [0&1] 5
3 -> 3 [label="!a & b\n{0}"] State: 3
4 [label="4"] [0&!1] 0
4 -> 1 [label="a\n{0}"] [0&1] 2
4 -> 3 [label="!a & b\n{0}"] [!0&1] 3 {0}
5 [label="5"] State: 4
5 -> 1 [label="a\n{0}"] [0] 1 {0}
5 -> 3 [label="!a & b\n{0}"] [!0&1] 3 {0}
} State: 5
[0] 1 {0}
[!0&1] 3 {0}
--END--
EOF EOF
run 0 ../safra --hoa double_b.hoa > out.dot run 0 ../safra --hoa double_b.hoa -H > out.hoa
diff out.dot out.exp diff out.hoa out.exp

View file

@ -26,6 +26,19 @@
namespace spot namespace spot
{ {
namespace
{
// Used to remove all acceptance whos value is above max_acc
void remove_dead_acc(twa_graph_ptr& aut, unsigned max_acc)
{
assert(max_acc < 32);
unsigned mask = (1 << max_acc) - 1;
for (auto& t: aut->transitions())
{
t.acc &= mask;
}
}
}
auto auto
safra_state::compute_succs(const const_twa_graph_ptr& aut, safra_state::compute_succs(const const_twa_graph_ptr& aut,
const std::vector<unsigned>& bddnums, const std::vector<unsigned>& bddnums,
@ -293,10 +306,10 @@ namespace spot
auto res = make_twa_graph(aut->get_dict()); auto res = make_twa_graph(aut->get_dict());
res->copy_ap_of(aut); res->copy_ap_of(aut);
res->prop_copy(aut, res->prop_copy(aut,
{ true, // state based { false, // state based
true, // inherently_weak true, // inherently_weak
true, // deterministic false, // deterministic
false // stutter inv true // stutter inv
}); });
// Given a safra_state get its associated state in output automata. // Given a safra_state get its associated state in output automata.
@ -309,6 +322,7 @@ namespace spot
seen.insert(std::make_pair(init, num)); seen.insert(std::make_pair(init, num));
std::deque<safra_state> todo; std::deque<safra_state> todo;
todo.push_back(init); todo.push_back(init);
unsigned sets = 0;
while (!todo.empty()) while (!todo.empty())
{ {
using succs_t = safra_state::succs_t; using succs_t = safra_state::succs_t;
@ -332,12 +346,22 @@ namespace spot
seen.insert(std::make_pair(s.first, dst_num)); seen.insert(std::make_pair(s.first, dst_num));
} }
if (s.first.color_ != -1U) if (s.first.color_ != -1U)
{
res->new_transition(src_num, dst_num, num2bdd[s.second], res->new_transition(src_num, dst_num, num2bdd[s.second],
{s.first.color_}); {s.first.color_});
// We only care about green acc
if (s.first.color_ % 2 == 0)
sets = std::max(s.first.color_ + 1, sets);
}
else else
res->new_transition(src_num, dst_num, num2bdd[s.second]); res->new_transition(src_num, dst_num, num2bdd[s.second]);
} }
} }
//
remove_dead_acc(res, sets);
res->set_acceptance(sets, acc_cond::acc_code::parity(false, false, sets));
res->prop_deterministic(true);
res->prop_state_based_acc(false);
return res; return res;
} }
} }