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:
parent
d0d42f86f9
commit
8362bf3a5f
3 changed files with 91 additions and 54 deletions
|
|
@ -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();
|
||||||
|
|
||||||
spot::dotty_reachable(std::cout, res);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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],
|
{
|
||||||
{s.first.color_});
|
res->new_transition(src_num, dst_num, num2bdd[s.second],
|
||||||
|
{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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue