hoa: add support for multiple initial states

* src/hoaparse/hoaparse.yy: Here.
* src/tgbatest/hoaparse.test: Add tests.
This commit is contained in:
Alexandre Duret-Lutz 2014-11-21 16:05:28 +01:00
parent 63abfed108
commit 8004dca157
2 changed files with 126 additions and 29 deletions

View file

@ -33,6 +33,7 @@
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <unordered_map> #include <unordered_map>
#include <algorithm>
#include "ltlast/constant.hh" #include "ltlast/constant.hh"
#include "public.hh" #include "public.hh"
@ -49,17 +50,16 @@
std::vector<bdd> guards; std::vector<bdd> guards;
std::vector<bdd>::const_iterator cur_guard; std::vector<bdd>::const_iterator cur_guard;
std::vector<bool> declared_states; // States that have been declared. std::vector<bool> declared_states; // States that have been declared.
std::vector<std::pair<spot::location, unsigned>> start; // Initial states;
std::unordered_map<std::string, bdd> alias; std::unordered_map<std::string, bdd> alias;
spot::location states_loc; spot::location states_loc;
spot::location ap_loc; spot::location ap_loc;
spot::location state_label_loc; spot::location state_label_loc;
spot::location start_loc;
spot::location accset_loc; spot::location accset_loc;
spot::acc_cond::mark_t acc_state; spot::acc_cond::mark_t acc_state;
spot::acc_cond::mark_t neg_acc_sets = 0U; spot::acc_cond::mark_t neg_acc_sets = 0U;
spot::acc_cond::mark_t pos_acc_sets = 0U; spot::acc_cond::mark_t pos_acc_sets = 0U;
unsigned cur_state; unsigned cur_state;
int start = -1;
int states = -1; int states = -1;
int ap_count = -1; int ap_count = -1;
int accset = -1; int accset = -1;
@ -152,16 +152,16 @@ BOOLEAN: 't' | 'f'
header: format-version header-items header: format-version header-items
{ {
// Preallocate the states if we know their number. // Preallocate the states if we know their number.
if (res.states != -1) if (res.states >= 0)
{ {
unsigned states = res.states; unsigned states = res.states;
if (res.start != -1 && for (auto& p : res.start)
res.states <= res.start) if ((unsigned) res.states <= p.second)
{ {
error(res.start_loc, error(p.first,
"initial state number is larger than state count..."); "initial state number is larger than state count...");
error(res.states_loc, "... declared here."); error(res.states_loc, "... declared here.");
states = res.start + 1; states = std::max(states, p.second + 1);
} }
res.h->aut->new_states(states); res.h->aut->new_states(states);
res.declared_states.resize(states); res.declared_states.resize(states);
@ -201,19 +201,12 @@ header-item: "States:" INT
} }
| "Start:" state-conj-2 | "Start:" state-conj-2
{ {
res.start_loc = @$;
error(@2, "alternation is not yet supported"); error(@2, "alternation is not yet supported");
YYABORT; YYABORT;
} }
| "Start:" state-num | "Start:" state-num
{ {
if (res.start >= 0) res.start.emplace_back(@$, $2);
{
error(@$, "multiple initial states are not yet supported");
YYABORT;
}
res.start = $2;
res.start_loc = @$;
} }
| "AP:" INT { | "AP:" INT {
if (res.ignore_more_ap) if (res.ignore_more_ap)
@ -658,6 +651,42 @@ static void fix_acceptance(result_& r)
} }
} }
static void fix_initial_state(result_& r)
{
if (r.start.empty())
{
// If no initial state has been declared, add one, because
// Spot will not work without one.
r.h->aut->set_init_state(r.h->aut->new_state());
return;
}
// Remove any duplicate initial state.
std::vector<unsigned> start;
start.reserve(r.start.size());
for (auto& p : r.start)
start.push_back(p.second);
std::sort(start.begin(), start.end());
auto res = std::unique(start.begin(), start.end());
start.resize(std::distance(start.begin(), res));
assert(start.size() >= 1);
if (start.size() == 1)
{
r.h->aut->set_init_state(start.front());
}
else
{
// Multiple initial states. Add a fake one.
auto& aut = r.h->aut;
unsigned i = aut->new_state();
aut->set_init_state(i);
for (auto p : start)
for (auto& t: aut->out(p))
aut->new_transition(i, t.dst, t.cond);
}
}
namespace spot namespace spot
{ {
hoa_stream_parser::hoa_stream_parser(const std::string& name) hoa_stream_parser::hoa_stream_parser(const std::string& name)
@ -703,16 +732,7 @@ namespace spot
return nullptr; return nullptr;
if (r.neg_acc_sets) if (r.neg_acc_sets)
fix_acceptance(r); fix_acceptance(r);
if (r.start != -1) fix_initial_state(r);
{
r.h->aut->set_init_state(r.start);
}
else
{
// If no initial state has been declared, add one, because
// Spot will not work without one.
r.h->aut->set_init_state(r.h->aut->new_state());
}
return r.h; return r.h;
}; };
} }

View file

@ -446,3 +446,80 @@ State: 1
EOF EOF
diff expected input.out diff expected input.out
cat >input <<EOF
HOA: v1
States: 2
Start: 0
Start: 1
Start: 0 /* duplicate */
AP: 2 "a" "b"
Acceptance: 1 Inf(0)
--BODY--
State: 0 {0}
[1] 1
[!1] 0
State: 1
[!0] 1
[0] 0
--END--
EOF
expectok input <<EOF
HOA: v1
States: 3
Start: 0
AP: 2 "a" "b"
acc-name: Buchi
Acceptance: 1 Inf(0)
properties: trans-labels explicit-labels state-acc complete
--BODY--
State: 0
[1] 1
[!1] 2
[!0] 1
[0] 2
State: 1
[!0] 1
[0] 2
State: 2 {0}
[1] 1
[!1] 2
--END--
EOF
cat >input <<EOF
HOA: v1
States: 2
Start: 0
Start: 0 /* duplicate */
AP: 2 "a" "b"
Acceptance: 1 Inf(0)
--BODY--
State: 0 {0}
[1] 1
[!1] 0
State: 1
[!0] 1
[0] 0
--END--
EOF
expectok input <<EOF
HOA: v1
States: 2
Start: 0
AP: 2 "a" "b"
acc-name: Buchi
Acceptance: 1 Inf(0)
properties: trans-labels explicit-labels state-acc complete deterministic
--BODY--
State: 0 {0}
[1] 1
[!1] 0
State: 1
[!0] 1
[0] 0
--END--
EOF