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:
Alexandre Duret-Lutz 2016-11-24 21:49:30 +01:00
parent 56df459c75
commit e620368696
3 changed files with 314 additions and 18 deletions

View file

@ -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,6 +452,11 @@ 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();
@ -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,10 +1306,28 @@ 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
@ -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
{ {

View file

@ -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

View file

@ -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