hoa: add option to output implicit labels
Fixes #59. * src/tgbaalgos/hoa.cc: Add option i. * src/bin/common_aoutput.cc, src/bin/dstar2tgba.cc, src/tgbaalgos/hoa.hh: Document it. * src/tgbatest/hoaparse.test: Test it.
This commit is contained in:
parent
5749fe6f7c
commit
566118a5be
5 changed files with 220 additions and 45 deletions
|
|
@ -49,13 +49,14 @@ static const argp_option options[] =
|
||||||
{
|
{
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
{ 0, 0, 0, 0, "Output format:", 3 },
|
{ 0, 0, 0, 0, "Output format:", 3 },
|
||||||
{ "dot", OPT_DOT, "c|h|n|N|s|t|v", OPTION_ARG_OPTIONAL,
|
{ "dot", OPT_DOT, "a|c|h|n|N|s|t|v", OPTION_ARG_OPTIONAL,
|
||||||
"GraphViz's format (default). Add letters for "
|
"GraphViz's format (default). Add letters for "
|
||||||
"(a) acceptance display, (c) circular nodes, (h) horizontal layout, "
|
"(a) acceptance display, (c) circular nodes, (h) horizontal layout, "
|
||||||
"(v) vertical layout, (n) with name, (N) without name, (s) with SCCs, "
|
"(v) vertical layout, (n) with name, (N) without name, (s) with SCCs, "
|
||||||
"(t) force transition-based acceptance.", 0 },
|
"(t) force transition-based acceptance.", 0 },
|
||||||
{ "hoaf", 'H', "s|t|m|l", OPTION_ARG_OPTIONAL,
|
{ "hoaf", 'H', "i|s|t|m|l", OPTION_ARG_OPTIONAL,
|
||||||
"Output the automaton in HOA format. Add letters to select "
|
"Output the automaton in HOA format. Add letters to select "
|
||||||
|
"(i) use implicit labels for complete deterministic automata, "
|
||||||
"(s) prefer state-based acceptance when possible [default], "
|
"(s) prefer state-based acceptance when possible [default], "
|
||||||
"(t) force transition-based acceptance, "
|
"(t) force transition-based acceptance, "
|
||||||
"(m) mix state and transition-based acceptance, "
|
"(m) mix state and transition-based acceptance, "
|
||||||
|
|
|
||||||
|
|
@ -71,13 +71,14 @@ static const argp_option options[] =
|
||||||
"of the given property)", 0 },
|
"of the given property)", 0 },
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
{ 0, 0, 0, 0, "Output format:", 3 },
|
{ 0, 0, 0, 0, "Output format:", 3 },
|
||||||
{ "dot", OPT_DOT, "c|h|n|N|s|t|v", OPTION_ARG_OPTIONAL,
|
{ "dot", OPT_DOT, "a|c|h|n|N|s|t|v", OPTION_ARG_OPTIONAL,
|
||||||
"GraphViz's format (default). Add letters for (a) acceptance display, "
|
"GraphViz's format (default). Add letters for (a) acceptance display, "
|
||||||
"(c) circular nodes, (h) horizontal layout, (v) vertical layout, "
|
"(c) circular nodes, (h) horizontal layout, (v) vertical layout, "
|
||||||
"(n) with name, (N) without name, (s) with SCCs, "
|
"(n) with name, (N) without name, (s) with SCCs, "
|
||||||
"(t) force transition-based acceptance.", 0 },
|
"(t) force transition-based acceptance.", 0 },
|
||||||
{ "hoaf", 'H', "s|t|m|l", OPTION_ARG_OPTIONAL,
|
{ "hoaf", 'H', "i|s|t|m|l", OPTION_ARG_OPTIONAL,
|
||||||
"Output the automaton in HOA format. Add letters to select "
|
"Output the automaton in HOA format. Add letters to select "
|
||||||
|
"(i) use implicit labels for complete deterministic automata, "
|
||||||
"(s) prefer state-based acceptance when possible [default], "
|
"(s) prefer state-based acceptance when possible [default], "
|
||||||
"(t) force transition-based acceptance, "
|
"(t) force transition-based acceptance, "
|
||||||
"(m) mix state and transition-based acceptance, "
|
"(m) mix state and transition-based acceptance, "
|
||||||
|
|
|
||||||
|
|
@ -49,15 +49,18 @@ namespace spot
|
||||||
bool has_state_acc;
|
bool has_state_acc;
|
||||||
bool is_complete;
|
bool is_complete;
|
||||||
bool is_deterministic;
|
bool is_deterministic;
|
||||||
|
bool use_implicit_labels;
|
||||||
|
bdd all_ap;
|
||||||
|
|
||||||
// Label support: the set of all conditions occurring in the
|
// Label support: the set of all conditions occurring in the
|
||||||
// automaton.
|
// automaton.
|
||||||
typedef std::map<bdd, std::string, bdd_less_than> sup_map;
|
typedef std::map<bdd, std::string, bdd_less_than> sup_map;
|
||||||
sup_map sup;
|
sup_map sup;
|
||||||
|
|
||||||
metadata(const const_tgba_digraph_ptr& aut)
|
metadata(const const_tgba_digraph_ptr& aut, bool implicit)
|
||||||
{
|
{
|
||||||
check_det_and_comp(aut);
|
check_det_and_comp(aut);
|
||||||
|
use_implicit_labels = implicit && is_deterministic && is_complete;
|
||||||
number_all_ap();
|
number_all_ap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,6 +147,7 @@ namespace spot
|
||||||
bdd all = bddtrue;
|
bdd all = bddtrue;
|
||||||
for (auto& i: sup)
|
for (auto& i: sup)
|
||||||
all &= bdd_support(i.first);
|
all &= bdd_support(i.first);
|
||||||
|
all_ap = all;
|
||||||
|
|
||||||
while (all != bddtrue)
|
while (all != bddtrue)
|
||||||
{
|
{
|
||||||
|
|
@ -153,6 +157,9 @@ namespace spot
|
||||||
vap.push_back(v);
|
vap.push_back(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_implicit_labels)
|
||||||
|
return;
|
||||||
|
|
||||||
for (auto& i: sup)
|
for (auto& i: sup)
|
||||||
{
|
{
|
||||||
bdd cond = i.first;
|
bdd cond = i.first;
|
||||||
|
|
@ -199,12 +206,10 @@ namespace spot
|
||||||
i.second = s.str();
|
i.second = s.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum hoa_alias { Hoa_Alias_None, Hoa_Alias_Ap, Hoa_Alias_Cond };
|
|
||||||
enum hoa_acceptance
|
enum hoa_acceptance
|
||||||
{
|
{
|
||||||
Hoa_Acceptance_States, /// state-based acceptance if
|
Hoa_Acceptance_States, /// state-based acceptance if
|
||||||
|
|
@ -218,17 +223,40 @@ namespace spot
|
||||||
static std::ostream&
|
static std::ostream&
|
||||||
hoa_reachable(std::ostream& os,
|
hoa_reachable(std::ostream& os,
|
||||||
const const_tgba_digraph_ptr& aut,
|
const const_tgba_digraph_ptr& aut,
|
||||||
hoa_acceptance acceptance,
|
const char* opt)
|
||||||
hoa_alias alias,
|
|
||||||
bool newline)
|
|
||||||
{
|
{
|
||||||
(void) alias;
|
bool newline = true;
|
||||||
|
hoa_acceptance acceptance = Hoa_Acceptance_States;
|
||||||
|
bool implicit_labels = false;
|
||||||
|
|
||||||
|
if (opt)
|
||||||
|
while (*opt)
|
||||||
|
{
|
||||||
|
switch (*opt++)
|
||||||
|
{
|
||||||
|
case 'i':
|
||||||
|
implicit_labels = true;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
newline = false;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
acceptance = Hoa_Acceptance_Mixed;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
acceptance = Hoa_Acceptance_States;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
acceptance = Hoa_Acceptance_Transitions;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calling get_init_state_number() may add a state to empty
|
// Calling get_init_state_number() may add a state to empty
|
||||||
// automata, so it has to be done first.
|
// automata, so it has to be done first.
|
||||||
unsigned init = aut->get_init_state_number();
|
unsigned init = aut->get_init_state_number();
|
||||||
|
|
||||||
metadata md(aut);
|
metadata md(aut, implicit_labels);
|
||||||
|
|
||||||
if (acceptance == Hoa_Acceptance_States && !md.has_state_acc)
|
if (acceptance == Hoa_Acceptance_States && !md.has_state_acc)
|
||||||
acceptance = Hoa_Acceptance_Transitions;
|
acceptance = Hoa_Acceptance_Transitions;
|
||||||
|
|
@ -240,9 +268,10 @@ namespace spot
|
||||||
auto n = aut->get_named_prop<std::string>("automaton-name");
|
auto n = aut->get_named_prop<std::string>("automaton-name");
|
||||||
if (n)
|
if (n)
|
||||||
escape_str(os << "name: \"", *n) << '"' << nl;
|
escape_str(os << "name: \"", *n) << '"' << nl;
|
||||||
|
unsigned nap = md.vap.size();
|
||||||
os << "States: " << num_states << nl
|
os << "States: " << num_states << nl
|
||||||
<< "Start: " << init << nl
|
<< "Start: " << init << nl
|
||||||
<< "AP: " << md.vap.size();
|
<< "AP: " << nap;
|
||||||
auto d = aut->get_dict();
|
auto d = aut->get_dict();
|
||||||
for (auto& i: md.vap)
|
for (auto& i: md.vap)
|
||||||
{
|
{
|
||||||
|
|
@ -251,6 +280,7 @@ namespace spot
|
||||||
escape_str(os << " \"", f->name()) << '"';
|
escape_str(os << " \"", f->name()) << '"';
|
||||||
}
|
}
|
||||||
os << nl;
|
os << nl;
|
||||||
|
|
||||||
unsigned num_acc = aut->acc().num_sets();
|
unsigned num_acc = aut->acc().num_sets();
|
||||||
if (aut->acc().is_generalized_buchi())
|
if (aut->acc().is_generalized_buchi())
|
||||||
{
|
{
|
||||||
|
|
@ -265,7 +295,12 @@ namespace spot
|
||||||
os << "Acceptance: " << num_acc << ' ';
|
os << "Acceptance: " << num_acc << ' ';
|
||||||
os << aut->acc().get_acceptance();
|
os << aut->acc().get_acceptance();
|
||||||
os << nl;
|
os << nl;
|
||||||
os << "properties: trans-labels explicit-labels";
|
os << "properties:";
|
||||||
|
implicit_labels = md.use_implicit_labels;
|
||||||
|
if (implicit_labels)
|
||||||
|
os << " implicit-labels";
|
||||||
|
else
|
||||||
|
os << " trans-labels explicit-labels";
|
||||||
if (acceptance == Hoa_Acceptance_States)
|
if (acceptance == Hoa_Acceptance_States)
|
||||||
os << " state-acc";
|
os << " state-acc";
|
||||||
else if (acceptance == Hoa_Acceptance_Transitions)
|
else if (acceptance == Hoa_Acceptance_Transitions)
|
||||||
|
|
@ -275,6 +310,18 @@ namespace spot
|
||||||
if (md.is_deterministic)
|
if (md.is_deterministic)
|
||||||
os << " deterministic";
|
os << " deterministic";
|
||||||
os << nl;
|
os << nl;
|
||||||
|
|
||||||
|
// If we want to output implicit labels, we have to
|
||||||
|
// fill a vector with all destinations in order.
|
||||||
|
std::vector<unsigned> out;
|
||||||
|
std::vector<acc_cond::mark_t> outm;
|
||||||
|
if (implicit_labels)
|
||||||
|
{
|
||||||
|
out.resize(1UL << nap);
|
||||||
|
if (acceptance != Hoa_Acceptance_States)
|
||||||
|
outm.resize(1UL << nap);
|
||||||
|
}
|
||||||
|
|
||||||
os << "--BODY--" << nl;
|
os << "--BODY--" << nl;
|
||||||
auto sn = aut->get_named_prop<std::vector<std::string>>("state-names");
|
auto sn = aut->get_named_prop<std::vector<std::string>>("state-names");
|
||||||
for (unsigned i = 0; i < num_states; ++i)
|
for (unsigned i = 0; i < num_states; ++i)
|
||||||
|
|
@ -299,12 +346,61 @@ namespace spot
|
||||||
}
|
}
|
||||||
os << nl;
|
os << nl;
|
||||||
|
|
||||||
for (auto& t: aut->out(i))
|
if (!implicit_labels)
|
||||||
{
|
{
|
||||||
os << '[' << md.sup[t.cond] << "] " << t.dst;
|
for (auto& t: aut->out(i))
|
||||||
if (this_acc == Hoa_Acceptance_Transitions)
|
{
|
||||||
md.emit_acc(os, aut, t.acc);
|
os << '[' << md.sup[t.cond] << "] " << t.dst;
|
||||||
os << nl;
|
if (this_acc == Hoa_Acceptance_Transitions)
|
||||||
|
md.emit_acc(os, aut, t.acc);
|
||||||
|
os << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto& t: aut->out(i))
|
||||||
|
{
|
||||||
|
bdd cond = t.cond;
|
||||||
|
while (cond != bddfalse)
|
||||||
|
{
|
||||||
|
bdd one = bdd_satoneset(cond, md.all_ap, bddfalse);
|
||||||
|
cond -= one;
|
||||||
|
unsigned level = 1;
|
||||||
|
unsigned pos = 0U;
|
||||||
|
while (one != bddtrue)
|
||||||
|
{
|
||||||
|
bdd h = bdd_high(one);
|
||||||
|
if (h == bddfalse)
|
||||||
|
{
|
||||||
|
one = bdd_low(one);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos |= level;
|
||||||
|
one = h;
|
||||||
|
}
|
||||||
|
level <<= 1;
|
||||||
|
}
|
||||||
|
out[pos] = t.dst;
|
||||||
|
if (this_acc != Hoa_Acceptance_States)
|
||||||
|
outm[pos] = t.acc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsigned n = out.size();
|
||||||
|
for (unsigned i = 0; i < n;)
|
||||||
|
{
|
||||||
|
os << out[i];
|
||||||
|
if (this_acc != Hoa_Acceptance_States)
|
||||||
|
{
|
||||||
|
md.emit_acc(os, aut, outm[i]) << nl;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
os << (((i & 15) && i < n) ? ' ' : nl);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
os << "--END--"; // No newline. Let the caller decide.
|
os << "--END--"; // No newline. Let the caller decide.
|
||||||
|
|
@ -316,35 +412,12 @@ namespace spot
|
||||||
const const_tgba_ptr& aut,
|
const const_tgba_ptr& aut,
|
||||||
const char* opt)
|
const char* opt)
|
||||||
{
|
{
|
||||||
bool newline = true;
|
|
||||||
hoa_acceptance acceptance = Hoa_Acceptance_States;
|
|
||||||
hoa_alias alias = Hoa_Alias_None;
|
|
||||||
|
|
||||||
if (opt)
|
|
||||||
while (*opt)
|
|
||||||
{
|
|
||||||
switch (*opt++)
|
|
||||||
{
|
|
||||||
case 'l':
|
|
||||||
newline = false;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
acceptance = Hoa_Acceptance_Mixed;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
acceptance = Hoa_Acceptance_States;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
acceptance = Hoa_Acceptance_Transitions;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto a = std::dynamic_pointer_cast<const tgba_digraph>(aut);
|
auto a = std::dynamic_pointer_cast<const tgba_digraph>(aut);
|
||||||
if (!a)
|
if (!a)
|
||||||
a = make_tgba_digraph(aut, tgba::prop_set::all());
|
a = make_tgba_digraph(aut, tgba::prop_set::all());
|
||||||
|
|
||||||
return hoa_reachable(os, a, acceptance, alias, newline);
|
return hoa_reachable(os, a, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,10 @@ namespace spot
|
||||||
/// \param os The output stream to print on.
|
/// \param os The output stream to print on.
|
||||||
/// \param g The automaton to output.
|
/// \param g The automaton to output.
|
||||||
/// \param opt a set of characters each corresponding to a possible
|
/// \param opt a set of characters each corresponding to a possible
|
||||||
/// option: (s) state-based acceptance, (t) transition-based
|
/// option: (i) implicit labels for complete and
|
||||||
/// acceptance, (m) mixed acceptance, (l) single-line output.
|
/// deterministic automata, (s) state-based acceptance, (t)
|
||||||
|
/// transition-based acceptance, (m) mixed acceptance, (l)
|
||||||
|
/// single-line output.
|
||||||
SPOT_API std::ostream&
|
SPOT_API std::ostream&
|
||||||
hoa_reachable(std::ostream& os,
|
hoa_reachable(std::ostream& os,
|
||||||
const const_tgba_ptr& g,
|
const const_tgba_ptr& g,
|
||||||
|
|
|
||||||
|
|
@ -1439,3 +1439,101 @@ State: 0
|
||||||
[!0&!1&!2] 0 {3}
|
[!0&!1&!2] 0 {3}
|
||||||
--END--
|
--END--
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
# Implicit labels
|
||||||
|
|
||||||
|
../../bin/ltl2tgba -H 'GFa & GFb & (c U d)' > out.hoa
|
||||||
|
../../bin/ltl2tgba -C -Hi 'GFa & GFb & (c U d)' > out-i.hoa
|
||||||
|
../../bin/autfilt -C -Hi out.hoa --name=%M > out-i2.hoa
|
||||||
|
diff out-i.hoa out-i2.hoa
|
||||||
|
|
||||||
|
cat >expected <<EOF
|
||||||
|
HOA: v1
|
||||||
|
name: "(c U d) & G(Fa & Fb)"
|
||||||
|
States: 3
|
||||||
|
Start: 1
|
||||||
|
AP: 4 "c" "d" "a" "b"
|
||||||
|
acc-name: generalized-Buchi 2
|
||||||
|
Acceptance: 2 Inf(0)&Inf(1)
|
||||||
|
properties: implicit-labels trans-acc complete deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0
|
||||||
|
0 {0}
|
||||||
|
0 {0}
|
||||||
|
0 {0}
|
||||||
|
0 {0}
|
||||||
|
0 {1}
|
||||||
|
0 {1}
|
||||||
|
0 {1}
|
||||||
|
0 {1}
|
||||||
|
0 {0 1}
|
||||||
|
0 {0 1}
|
||||||
|
0 {0 1}
|
||||||
|
0 {0 1}
|
||||||
|
State: 1
|
||||||
|
2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
0
|
||||||
|
State: 2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
--END--
|
||||||
|
EOF
|
||||||
|
|
||||||
|
diff out-i.hoa expected
|
||||||
|
|
||||||
|
expectok out-i.hoa --sbacc -Hi <<EOF
|
||||||
|
HOA: v1
|
||||||
|
States: 6
|
||||||
|
Start: 0
|
||||||
|
AP: 4 "c" "d" "a" "b"
|
||||||
|
acc-name: generalized-Buchi 2
|
||||||
|
Acceptance: 2 Inf(0)&Inf(1)
|
||||||
|
properties: implicit-labels state-acc complete deterministic
|
||||||
|
--BODY--
|
||||||
|
State: 0
|
||||||
|
1 0 2 2 1 0 2 2 1 0 2 2 1 0 2 2
|
||||||
|
State: 1
|
||||||
|
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
||||||
|
State: 2
|
||||||
|
2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5
|
||||||
|
State: 3 {0}
|
||||||
|
2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5
|
||||||
|
State: 4 {1}
|
||||||
|
2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5
|
||||||
|
State: 5 {0 1}
|
||||||
|
2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5
|
||||||
|
--END--
|
||||||
|
EOF
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue