Commit 566118a5 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

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.
parent 5749fe6f
...@@ -49,13 +49,14 @@ static const argp_option options[] = ...@@ -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[] = ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -299,12 +346,61 @@ namespace spot
} }
os << nl; os << nl;
for (auto& t: aut->out(i)) if (!implicit_labels)
{
for (auto& t: aut->out(i))
{
os << '[' << md.sup[t.cond] << "] " << t.dst;
if (this_acc == Hoa_Acceptance_Transitions)
md.emit_acc(os, aut, t.acc);
os << nl;
}
}
else
{ {
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); bdd cond = t.cond;
os << nl; 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 ...@@ -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 ...@@ -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 ...@@ -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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment