parseaut: preliminary support for reading alternating automata
Currently this only reads universal branches. The parser (and the automaton code) do not support universal initial states. * spot/parseaut/parseaut.yy: Read universal branches. Deal with the no-univ-branch/!univ-branch change in HOA 1.1. * tests/python/alternating.py: Read the output of print_hoa. * tests/core/parseaut.test: Adjust test output, and add more tests.
This commit is contained in:
parent
56df459c75
commit
e620368696
3 changed files with 314 additions and 18 deletions
|
|
@ -157,6 +157,14 @@ extern "C" int strverscmp(const char *s1, const char *s2);
|
||||||
return i->second;
|
return i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prop_info prop_is_false(const std::string& p)
|
||||||
|
{
|
||||||
|
auto i = props.find(p);
|
||||||
|
if (i == props.end())
|
||||||
|
return prop_info{spot::location(), false};
|
||||||
|
return prop_info{i->second.loc, !i->second.val};
|
||||||
|
}
|
||||||
|
|
||||||
~result_()
|
~result_()
|
||||||
{
|
{
|
||||||
delete namer;
|
delete namer;
|
||||||
|
|
@ -180,6 +188,7 @@ extern "C" int strverscmp(const char *s1, const char *s2);
|
||||||
pair* p;
|
pair* p;
|
||||||
std::list<pair>* list;
|
std::list<pair>* list;
|
||||||
spot::acc_cond::acc_code* code;
|
spot::acc_cond::acc_code* code;
|
||||||
|
std::vector<unsigned>* states;
|
||||||
}
|
}
|
||||||
|
|
||||||
%code
|
%code
|
||||||
|
|
@ -230,6 +239,7 @@ extern "C" int strverscmp(const char *s1, const char *s2);
|
||||||
%left '&'
|
%left '&'
|
||||||
%nonassoc '!'
|
%nonassoc '!'
|
||||||
|
|
||||||
|
%type <states> state-conj-2 state-conj-checked
|
||||||
%type <num> checked-state-num state-num acc-set sign
|
%type <num> checked-state-num state-num acc-set sign
|
||||||
%type <b> label-expr
|
%type <b> label-expr
|
||||||
%type <mark> acc-sig acc-sets trans-acc_opt state-acc_opt
|
%type <mark> acc-sig acc-sets trans-acc_opt state-acc_opt
|
||||||
|
|
@ -274,9 +284,23 @@ extern "C" int strverscmp(const char *s1, const char *s2);
|
||||||
%destructor { bdd_delref($$); } <b>
|
%destructor { bdd_delref($$); } <b>
|
||||||
%destructor { bdd_delref($$->first); delete $$->second; delete $$; } <p>
|
%destructor { bdd_delref($$->first); delete $$->second; delete $$; } <p>
|
||||||
%destructor { delete $$; } <code>
|
%destructor { delete $$; } <code>
|
||||||
|
%destructor { delete $$; } <states>
|
||||||
|
%printer {
|
||||||
|
auto& os = debug_stream();
|
||||||
|
os << '{';
|
||||||
|
bool notfirst = false;
|
||||||
|
for (auto i: *$$)
|
||||||
|
{
|
||||||
|
if (notfirst)
|
||||||
|
os << ", ";
|
||||||
|
else
|
||||||
|
notfirst = true;
|
||||||
|
os << i;
|
||||||
|
}
|
||||||
|
os << '}';
|
||||||
|
} <states>
|
||||||
%destructor {
|
%destructor {
|
||||||
for (std::list<pair>::iterator i = $$->begin();
|
for (auto i = $$->begin(); i != $$->end(); ++i)
|
||||||
i != $$->end(); ++i)
|
|
||||||
{
|
{
|
||||||
bdd_delref(i->first);
|
bdd_delref(i->first);
|
||||||
delete i->second;
|
delete i->second;
|
||||||
|
|
@ -374,7 +398,7 @@ header: format-version header-items
|
||||||
{
|
{
|
||||||
if (res.opts.want_kripke)
|
if (res.opts.want_kripke)
|
||||||
error(trans_labels.loc,
|
error(trans_labels.loc,
|
||||||
"Kripke structure may not use transition labels");
|
"Kripke structures may not use transition labels");
|
||||||
|
|
||||||
if (state_labels)
|
if (state_labels)
|
||||||
{
|
{
|
||||||
|
|
@ -406,7 +430,7 @@ header: format-version header-items
|
||||||
|
|
||||||
if (res.opts.want_kripke && res.label_style != State_Labels)
|
if (res.opts.want_kripke && res.label_style != State_Labels)
|
||||||
error(@$,
|
error(@$,
|
||||||
"Kripke structure should use 'properties: state-labels'");
|
"Kripke structures should use 'properties: state-labels'");
|
||||||
|
|
||||||
auto state_acc = res.prop_is_true("state-acc");
|
auto state_acc = res.prop_is_true("state-acc");
|
||||||
auto trans_acc = res.prop_is_true("trans-acc");
|
auto trans_acc = res.prop_is_true("trans-acc");
|
||||||
|
|
@ -428,7 +452,12 @@ header: format-version header-items
|
||||||
{
|
{
|
||||||
res.acc_style = State_Acc;
|
res.acc_style = State_Acc;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
auto univ_branch = res.prop_is_true("univ-branch");
|
||||||
|
if (res.opts.want_kripke && univ_branch)
|
||||||
|
error(univ_branch.loc,
|
||||||
|
"Kripke structures may not use 'properties: univ-branch'");
|
||||||
|
}
|
||||||
{
|
{
|
||||||
unsigned ss = res.start.size();
|
unsigned ss = res.start.size();
|
||||||
auto det = res.prop_is_true("deterministic");
|
auto det = res.prop_is_true("deterministic");
|
||||||
|
|
@ -602,7 +631,7 @@ header-item: "States:" INT
|
||||||
}
|
}
|
||||||
| "Start:" init-state-conj-2
|
| "Start:" init-state-conj-2
|
||||||
{
|
{
|
||||||
error(@2, "alternation is not yet supported");
|
error(@2, "alternation is not yet supported for initial states");
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
| "Start:" state-num
|
| "Start:" state-num
|
||||||
|
|
@ -723,14 +752,22 @@ acc-spec: | acc-spec BOOLEAN
|
||||||
}
|
}
|
||||||
properties: | properties IDENTIFIER
|
properties: | properties IDENTIFIER
|
||||||
{
|
{
|
||||||
auto pos = res.props.emplace(*$2, result_::prop_info{@2, true});
|
bool val = true;
|
||||||
if (!pos.first->second.val)
|
// no-univ-branch was replaced by !univ-branch in HOA 1.1
|
||||||
|
if (*$2 == "no-univ-branch")
|
||||||
|
{
|
||||||
|
*$2 = "univ-branch";
|
||||||
|
val = false;
|
||||||
|
}
|
||||||
|
auto pos = res.props.emplace(*$2, result_::prop_info{@2, val});
|
||||||
|
if (pos.first->second.val != val)
|
||||||
{
|
{
|
||||||
std::ostringstream out(std::ios_base::ate);
|
std::ostringstream out(std::ios_base::ate);
|
||||||
error(@2, std::string("'properties: ")
|
error(@2, std::string("'properties: ")
|
||||||
+ *$2 + "' contradicts...");
|
+ (val ? "" : "!") + *$2 + "' contradicts...");
|
||||||
error(pos.first->second.loc,
|
error(pos.first->second.loc,
|
||||||
std::string("... 'properties: !") + *$2
|
std::string("... 'properties: ")
|
||||||
|
+ (val ? "!" : "") + *$2
|
||||||
+ "' previously given here.");
|
+ "' previously given here.");
|
||||||
}
|
}
|
||||||
delete $2;
|
delete $2;
|
||||||
|
|
@ -773,10 +810,17 @@ header-spec: | header-spec BOOLEAN
|
||||||
}
|
}
|
||||||
|
|
||||||
state-conj-2: checked-state-num '&' checked-state-num
|
state-conj-2: checked-state-num '&' checked-state-num
|
||||||
|
{
|
||||||
|
$$ = new std::vector<unsigned>{$1, $3};
|
||||||
|
}
|
||||||
| state-conj-2 '&' checked-state-num
|
| state-conj-2 '&' checked-state-num
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
$$->emplace_back($3);
|
||||||
|
}
|
||||||
|
|
||||||
// Currently we do not check the number of these states
|
// Currently we do not check the number of these states
|
||||||
// since we do not support alternation.
|
// since we do not support alternation for initial states.
|
||||||
init-state-conj-2: state-num '&' state-num
|
init-state-conj-2: state-num '&' state-num
|
||||||
| init-state-conj-2 '&' state-num
|
| init-state-conj-2 '&' state-num
|
||||||
|
|
||||||
|
|
@ -1262,12 +1306,30 @@ labeled-edge: trans-label checked-state-num trans-acc_opt
|
||||||
res.cur_label, $3 | res.acc_state);
|
res.cur_label, $3 | res.acc_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| trans-label state-conj-2 trans-acc_opt
|
| trans-label state-conj-checked trans-acc_opt
|
||||||
{
|
{
|
||||||
error(@2, "alternation is not yet supported");
|
if (res.cur_label != bddfalse)
|
||||||
YYABORT;
|
{
|
||||||
|
assert(!res.opts.want_kripke);
|
||||||
|
res.h->aut->new_univ_edge(res.cur_state,
|
||||||
|
$2->begin(), $2->end(),
|
||||||
|
res.cur_label,
|
||||||
|
$3 | res.acc_state);
|
||||||
|
}
|
||||||
|
delete $2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state-conj-checked: state-conj-2
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
if (auto ub = res.prop_is_false("univ-branch"))
|
||||||
|
{
|
||||||
|
error(@1, "universal branch used despite"
|
||||||
|
" previous declaration...");
|
||||||
|
error(ub.loc, "... here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Block of unlabeled edge, with occasional (incorrect) labeled
|
/* Block of unlabeled edge, with occasional (incorrect) labeled
|
||||||
edge. We never have zero unlabeled edges, these are considered as
|
edge. We never have zero unlabeled edges, these are considered as
|
||||||
zero labeled edges. */
|
zero labeled edges. */
|
||||||
|
|
@ -1305,10 +1367,36 @@ unlabeled-edge: checked-state-num trans-acc_opt
|
||||||
cond, $2 | res.acc_state);
|
cond, $2 | res.acc_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| state-conj-2 trans-acc_opt
|
| state-conj-checked trans-acc_opt
|
||||||
{
|
{
|
||||||
error(@1, "alternation is not yet supported");
|
bdd cond;
|
||||||
YYABORT;
|
if (res.has_state_label)
|
||||||
|
{
|
||||||
|
cond = res.state_label;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (res.guards.empty())
|
||||||
|
fill_guards(res);
|
||||||
|
if (res.cur_guard == res.guards.end())
|
||||||
|
{
|
||||||
|
error(@$, "too many transitions for this state, "
|
||||||
|
"ignoring this one");
|
||||||
|
cond = bddfalse;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cond = *res.cur_guard++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cond != bddfalse)
|
||||||
|
{
|
||||||
|
assert(!res.opts.want_kripke);
|
||||||
|
res.h->aut->new_univ_edge(res.cur_state,
|
||||||
|
$1->begin(), $1->end(),
|
||||||
|
cond, $2 | res.acc_state);
|
||||||
|
}
|
||||||
|
delete $1;
|
||||||
}
|
}
|
||||||
incorrectly-labeled-edge: trans-label unlabeled-edge
|
incorrectly-labeled-edge: trans-label unlabeled-edge
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1921,10 +1921,61 @@ State: 11 "t"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
expecterr input <<EOF
|
expecterr input <<EOF
|
||||||
input:4.8-12: alternation is not yet supported
|
input:4.8-12: alternation is not yet supported for initial states
|
||||||
autfilt: failed to read automaton from input
|
autfilt: failed to read automaton from input
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Some alternation errors
|
||||||
|
cat >input <<EOF
|
||||||
|
HOA: v1
|
||||||
|
States: 3
|
||||||
|
Start: 0
|
||||||
|
AP: 2 "a" "b"
|
||||||
|
acc-name: co-Buchi
|
||||||
|
Acceptance: 1 Fin(0)
|
||||||
|
properties: no-univ-branch trans-labels explicit-labels state-acc
|
||||||
|
properties: complete deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[!0&!1] 0&1
|
||||||
|
[0&!1] 1
|
||||||
|
[!0&1] 2
|
||||||
|
[0&1] 0&1
|
||||||
|
--END--
|
||||||
|
HOA: v1.1
|
||||||
|
States: 3
|
||||||
|
Start: 0
|
||||||
|
AP: 2 "a" "b"
|
||||||
|
acc-name: co-Buchi
|
||||||
|
Acceptance: 1 Fin(0)
|
||||||
|
properties: !univ-branch trans-labels explicit-labels state-acc
|
||||||
|
properties: complete deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[!0&!1] 0&1
|
||||||
|
[0&!1] 1
|
||||||
|
[!0&1] 2
|
||||||
|
[0&1] 0&1
|
||||||
|
--END--
|
||||||
|
EOF
|
||||||
|
|
||||||
|
err1="this might cause the following errors"
|
||||||
|
expecterr input<<EOF
|
||||||
|
input:11.9-11: universal branch used despite previous declaration...
|
||||||
|
input:7.13-26: ... here
|
||||||
|
input:14.7-9: universal branch used despite previous declaration...
|
||||||
|
input:7.13-26: ... here
|
||||||
|
input:11.11: state 1 has no definition
|
||||||
|
input:13.8: state 2 has no definition
|
||||||
|
input:16.6-9: we can read HOA v1 but this file uses v1.1; $err1
|
||||||
|
input:26.9-11: universal branch used despite previous declaration...
|
||||||
|
input:22.13-24: ... here
|
||||||
|
input:29.7-9: universal branch used despite previous declaration...
|
||||||
|
input:22.13-24: ... here
|
||||||
|
input:26.11: state 1 has no definition
|
||||||
|
input:28.8: state 2 has no definition
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
HOA: v1
|
HOA: v1
|
||||||
|
|
@ -2056,6 +2107,50 @@ State: 0
|
||||||
[!0&1] 0 {2}
|
[!0&1] 0 {2}
|
||||||
[0&1] 0 {}
|
[0&1] 0 {}
|
||||||
--END--
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
tool: "ltl3ba" "1.1.3"
|
||||||
|
name: "VWAA for (a U b) && G(F(b)) && F(G(a))"
|
||||||
|
States: 7
|
||||||
|
Start: 0
|
||||||
|
acc-name: co-Buchi
|
||||||
|
Acceptance: 1 Fin(0)
|
||||||
|
AP: 2 "b" "a"
|
||||||
|
properties: trans-labels explicit-labels state-acc univ-branch very-weak
|
||||||
|
--BODY--
|
||||||
|
State: 0 "((((a) U (b)) && GF(b)) && FG(a))"
|
||||||
|
[(0)] 3&1
|
||||||
|
[(!0 & 1)] 5&3&1
|
||||||
|
State: 1 "FG(a)" {0}
|
||||||
|
[(1)] 2
|
||||||
|
[t] 1
|
||||||
|
State: 2 "G(a)"
|
||||||
|
[(1)] 2
|
||||||
|
State: 3 "GF(b)"
|
||||||
|
[(0)] 3
|
||||||
|
[(!0)] 4&3
|
||||||
|
State: 4 "F(b)" {0}
|
||||||
|
[(0)] 6
|
||||||
|
[(!0)] 4
|
||||||
|
State: 5 "((a) U (b))" {0}
|
||||||
|
[(0)] 6
|
||||||
|
[(!0 & 1)] 5
|
||||||
|
State: 6 "t"
|
||||||
|
[t] 6
|
||||||
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
States: 3
|
||||||
|
Start: 0
|
||||||
|
acc-name: co-Buchi
|
||||||
|
Acceptance: 1 Fin(0)
|
||||||
|
AP: 2 "a" "b"
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
0&1 1 0& 2&1 0&1 /* weird spacing on purpose */
|
||||||
|
State: 2
|
||||||
|
0 & 1 2 & 1 2 0 & 2 & 1
|
||||||
|
State: 1
|
||||||
|
0&1 2&1 2 1&1 /* should we warn about duplicate destinations for univ edges? */
|
||||||
|
--END--
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
expectok input <<EOF
|
expectok input <<EOF
|
||||||
|
|
@ -2209,6 +2304,60 @@ State: 0
|
||||||
[!0&1] 0 {2}
|
[!0&1] 0 {2}
|
||||||
[0&1] 0
|
[0&1] 0
|
||||||
--END--
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
name: "VWAA for (a U b) && G(F(b)) && F(G(a))"
|
||||||
|
States: 7
|
||||||
|
Start: 0
|
||||||
|
AP: 2 "b" "a"
|
||||||
|
acc-name: co-Buchi
|
||||||
|
Acceptance: 1 Fin(0)
|
||||||
|
properties: univ-branch trans-labels explicit-labels state-acc
|
||||||
|
--BODY--
|
||||||
|
State: 0 "((((a) U (b)) && GF(b)) && FG(a))"
|
||||||
|
[0] 3&1
|
||||||
|
[!0&1] 5&3&1
|
||||||
|
State: 1 "FG(a)" {0}
|
||||||
|
[1] 2
|
||||||
|
[t] 1
|
||||||
|
State: 2 "G(a)"
|
||||||
|
[1] 2
|
||||||
|
State: 3 "GF(b)"
|
||||||
|
[0] 3
|
||||||
|
[!0] 4&3
|
||||||
|
State: 4 "F(b)" {0}
|
||||||
|
[0] 6
|
||||||
|
[!0] 4
|
||||||
|
State: 5 "((a) U (b))" {0}
|
||||||
|
[0] 6
|
||||||
|
[!0&1] 5
|
||||||
|
State: 6 "t"
|
||||||
|
[t] 6
|
||||||
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
States: 3
|
||||||
|
Start: 0
|
||||||
|
AP: 2 "a" "b"
|
||||||
|
acc-name: co-Buchi
|
||||||
|
Acceptance: 1 Fin(0)
|
||||||
|
properties: univ-branch trans-labels explicit-labels state-acc complete
|
||||||
|
properties: deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[!0&!1] 0&1
|
||||||
|
[0&!1] 1
|
||||||
|
[!0&1] 0&2&1
|
||||||
|
[0&1] 0&1
|
||||||
|
State: 1
|
||||||
|
[!0&!1] 0&1
|
||||||
|
[0&!1] 2&1
|
||||||
|
[!0&1] 2
|
||||||
|
[0&1] 1&1
|
||||||
|
State: 2
|
||||||
|
[!0&!1] 0&1
|
||||||
|
[0&!1] 2&1
|
||||||
|
[!0&1] 2
|
||||||
|
[0&1] 0&2&1
|
||||||
|
--END--
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# The complements are Streett and Rabin, but the acceptance set are
|
# The complements are Streett and Rabin, but the acceptance set are
|
||||||
|
|
@ -2360,6 +2509,60 @@ State: 0
|
||||||
[!0&1] 0 {2}
|
[!0&1] 0 {2}
|
||||||
[0&1] 0
|
[0&1] 0
|
||||||
--END--
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
name: "VWAA for (a U b) && G(F(b)) && F(G(a))"
|
||||||
|
States: 7
|
||||||
|
Start: 0
|
||||||
|
AP: 2 "b" "a"
|
||||||
|
acc-name: Buchi
|
||||||
|
Acceptance: 1 Inf(0)
|
||||||
|
properties: univ-branch trans-labels explicit-labels state-acc
|
||||||
|
--BODY--
|
||||||
|
State: 0 "((((a) U (b)) && GF(b)) && FG(a))"
|
||||||
|
[0] 3&1
|
||||||
|
[!0&1] 5&3&1
|
||||||
|
State: 1 "FG(a)" {0}
|
||||||
|
[1] 2
|
||||||
|
[t] 1
|
||||||
|
State: 2 "G(a)"
|
||||||
|
[1] 2
|
||||||
|
State: 3 "GF(b)"
|
||||||
|
[0] 3
|
||||||
|
[!0] 4&3
|
||||||
|
State: 4 "F(b)" {0}
|
||||||
|
[0] 6
|
||||||
|
[!0] 4
|
||||||
|
State: 5 "((a) U (b))" {0}
|
||||||
|
[0] 6
|
||||||
|
[!0&1] 5
|
||||||
|
State: 6 "t"
|
||||||
|
[t] 6
|
||||||
|
--END--
|
||||||
|
HOA: v1
|
||||||
|
States: 3
|
||||||
|
Start: 0
|
||||||
|
AP: 2 "a" "b"
|
||||||
|
acc-name: Buchi
|
||||||
|
Acceptance: 1 Inf(0)
|
||||||
|
properties: univ-branch trans-labels explicit-labels state-acc complete
|
||||||
|
properties: deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
[!0&!1] 0&1
|
||||||
|
[0&!1] 1
|
||||||
|
[!0&1] 0&2&1
|
||||||
|
[0&1] 0&1
|
||||||
|
State: 1
|
||||||
|
[!0&!1] 0&1
|
||||||
|
[0&!1] 2&1
|
||||||
|
[!0&1] 2
|
||||||
|
[0&1] 1&1
|
||||||
|
State: 2
|
||||||
|
[!0&!1] 0&1
|
||||||
|
[0&!1] 2&1
|
||||||
|
[!0&1] 2
|
||||||
|
[0&1] 0&2&1
|
||||||
|
--END--
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat >input <<EOF
|
cat >input <<EOF
|
||||||
|
|
|
||||||
|
|
@ -69,3 +69,8 @@ State: 1
|
||||||
State: 2
|
State: 2
|
||||||
[0 | 1] 2
|
[0 | 1] 2
|
||||||
--END--"""
|
--END--"""
|
||||||
|
|
||||||
|
aut2 = spot.automaton(h)
|
||||||
|
h2 = aut2.to_str('hoa')
|
||||||
|
print(h2)
|
||||||
|
assert h == h2
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue