stats: fix slow %s and inappropriate %S output

Fixes #269.

* spot/twaalgos/stats.cc: Use twa_statistics instead of
twa_sub_statistics when %t is not used.
* bin/common_aoutput.cc: Likewise, also fix %S to use twa_statistics
instead of num_states(), and document that %s,%t,%e all return
statistics about the reachable part of the automaton.
* tests/core/format.test: Add more tests.
* NEWS: Document the issue.
This commit is contained in:
Alexandre Duret-Lutz 2017-06-19 17:06:56 +02:00
parent 7b5b8f34f0
commit 413d2d6a6c
4 changed files with 81 additions and 11 deletions

6
NEWS
View file

@ -134,6 +134,12 @@ New in spot 2.3.4.dev (not yet released)
SCC) or 'y' (split universal destination by colors) universal SCC) or 'y' (split universal destination by colors) universal
edges could be connected to undefined states. edges could be connected to undefined states.
- Using --stats=%s or --stats=%s or --stats=%t could take an
unnecessary long time on automata with many atomic propositions,
due to a typo. Furthermore, %s/%e/%t/%E/%T were printing
a number of reachable states/edges/transitions, but %S was
incorrectly counting all states even unreachable.
Backward-incompatible changes: Backward-incompatible changes:
- spot::acc_cond::mark_t::operator bool() has been marked as - spot::acc_cond::mark_t::operator bool() has been marked as

View file

@ -171,11 +171,11 @@ static const argp_option io_options[] =
{ "%M, %m", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%M, %m", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"name of the automaton", 0 }, "name of the automaton", 0 },
{ "%S, %s", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%S, %s", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of states", 0 }, "number of reachable states", 0 },
{ "%E, %e", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%E, %e", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of edges", 0 }, "number of reachable edges", 0 },
{ "%T, %t", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%T, %t", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of transitions", 0 }, "number of reachable transitions", 0 },
{ "%A, %a", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%A, %a", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of acceptance sets", 0 }, "number of acceptance sets", 0 },
{ "%G, %g", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%G, %g", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -232,11 +232,11 @@ static const argp_option o_options[] =
{ "%m", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%m", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"name of the automaton", 0 }, "name of the automaton", 0 },
{ "%s", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%s", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of states", 0 }, "number of reachable states", 0 },
{ "%e", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%e", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of edges", 0 }, "number of reachable edges", 0 },
{ "%t", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%t", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of transitions", 0 }, "number of reachable transitions", 0 },
{ "%a", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%a", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
"number of acceptance sets", 0 }, "number of acceptance sets", 0 },
{ "%g", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE, { "%g", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
@ -427,9 +427,9 @@ hoa_stat_printer::print(const spot::const_parsed_aut_ptr& haut,
haut_edges_ = s.edges; haut_edges_ = s.edges;
haut_trans_ = s.transitions; haut_trans_ = s.transitions;
} }
else if (has('E')) else if (has('E') || has('S'))
{ {
spot::twa_sub_statistics s = sub_stats_reachable(haut->aut); spot::twa_statistics s = stats_reachable(haut->aut);
haut_states_ = s.states; haut_states_ = s.states;
haut_edges_ = s.edges; haut_edges_ = s.edges;
} }
@ -441,8 +441,6 @@ hoa_stat_printer::print(const spot::const_parsed_aut_ptr& haut,
else else
haut_name_.val().clear(); haut_name_.val().clear();
} }
if (has('S'))
haut_states_ = haut->aut->num_states();
if (has('A')) if (has('A'))
haut_acc_ = haut->aut->acc().num_sets(); haut_acc_ = haut->aut->acc().num_sets();

View file

@ -346,7 +346,7 @@ namespace spot
} }
else if (has('s') || has('e')) else if (has('s') || has('e'))
{ {
twa_sub_statistics s = sub_stats_reachable(aut); twa_statistics s = stats_reachable(aut);
states_ = s.states; states_ = s.states;
edges_ = s.edges; edges_ = s.edges;
} }

View file

@ -74,3 +74,69 @@ test "1,3,1,3,2,1,0" = "$out"
ltl2tgba 'a' --stats='%[z]c' 2>stderr && exit 1 ltl2tgba 'a' --stats='%[z]c' 2>stderr && exit 1
cat stderr cat stderr
grep -F "ltl2tgba: unknown option 'z' in '%[z]c'" stderr grep -F "ltl2tgba: unknown option 'z' in '%[z]c'" stderr
# From issue #269.
f='!X(FG((a & b) | (a & c) | (a & d) | (a & e) | (a & f) | (g & h) |
(g & i) | (g & j) | (g & k) | (g & l) | (m & n) | (m & o) | (m & p) |
(m & q) | (m & r) | (s & t) | (s & u) | (s & v) | (s & w) | (s & x) |
(y & z) | (ab & y) | (bb & y) | (cb & y) | (db & y) | (eb & g) | (c &
eb) | (d & eb) | (e & eb) | (eb & f) | (b & m) | (b & i) | (b & j) |
(b & k) | (b & l) | (h & s) | (h & o) | (h & p) | (h & q) | (h & r) |
(n & y) | (n & u) | (n & v) | (n & w) | (n & x) | (fb & t) | (ab & t)
| (bb & t) | (cb & t) | (db & t) | (g & gb) | (b & gb) | (d & gb) |
(e & gb) | (f & gb) | (c & m) | (c & h) | (c & j) | (c & k) | (c & l) |
(i & s) | (i & n) | (i & p) | (i & q) | (i & r) | (o & y) | (o & t) |
(o & v) | (o & w) | (o & x) | (fb & u) | (u & z) | (bb & u) | (cb &
u) | (db & u) | (g & hb) | (b & hb) | (c & hb) | (e & hb) | (f & hb) |
(d & m) | (d & h) | (d & i) | (d & k) | (d & l) | (j & s) | (j & n) |
(j & o) | (j & q) | (j & r) | (p & y) | (p & t) | (p & u) | (p & w) |
(p & x) | (fb & v) | (v & z) | (ab & v) | (cb & v) | (db & v) | (g &
ib) | (b & ib) | (c & ib) | (d & ib) | (f & ib) | (e & m) | (e & h) |
(e & i) | (e & j) | (e & l) | (k & s) | (k & n) | (k & o) | (k & p) |
(k & r) | (q & y) | (q & t) | (q & u) | (q & v) | (q & x) | (fb & w) |
(w & z) | (ab & w) | (bb & w) | (db & w) | (g & jb) | (b & jb) | (c &
jb) | (d & jb) | (e & jb) | (f & m) | (f & h) | (f & i) | (f & j) |
(f & k) | (l & s) | (l & n) | (l & o) | (l & p) | (l & q) | (r & y) |
(r & t) | (r & u) | (r & v) | (r & w) | (fb & x) | (x & z) | (ab & x) |
(bb & x) | (cb & x)) U ((a & b) | (a & c) | (a & d) | (a & e) | (a & f) |
(g & h) | (g & i) | (g & j) | (g & k) | (g & l) | (m & n) | (m & o) |
(m & p) | (m & q) | (m & r) | (s & t) | (s & u) | (s & v) | (s & w) |
(s & x) | (y & z) | (ab & y) | (bb & y) | (cb & y) | (db & y) | (eb &
g) | (c & eb) | (d & eb) | (e & eb) | (eb & f) | (b & m) | (b & i) |
(b & j) | (b & k) | (b & l) | (h & s) | (h & o) | (h & p) | (h & q) |
(h & r) | (n & y) | (n & u) | (n & v) | (n & w) | (n & x) | (fb & t) |
(ab & t) | (bb & t) | (cb & t) | (db & t) | (g & gb) | (b & gb) | (d &
gb) | (e & gb) | (f & gb) | (c & m) | (c & h) | (c & j) | (c & k) |
(c & l) | (i & s) | (i & n) | (i & p) | (i & q) | (i & r) | (o & y) |
(o & t) | (o & v) | (o & w) | (o & x) | (fb & u) | (u & z) | (bb & u)
| (cb & u) | (db & u) | (g & hb) | (b & hb) | (c & hb) | (e & hb) |
(f & hb) | (d & m) | (d & h) | (d & i) | (d & k) | (d & l) | (j & s) |
(j & n) | (j & o) | (j & q) | (j & r) | (p & y) | (p & t) | (p & u) |
(p & w) | (p & x) | (fb & v) | (v & z) | (ab & v) | (cb & v) | (db &
v) | (g & ib) | (b & ib) | (c & ib) | (d & ib) | (f & ib) | (e & m) |
(e & h) | (e & i) | (e & j) | (e & l) | (k & s) | (k & n) | (k & o) |
(k & p) | (k & r) | (q & y) | (q & t) | (q & u) | (q & v) | (q & x) |
(fb & w) | (w & z) | (ab & w) | (bb & w) | (db & w) | (g & jb) | (b &
jb) | (c & jb) | (d & jb) | (e & jb) | (f & m) | (f & h) | (f & i) |
(f & j) | (f & k) | (l & s) | (l & n) | (l & o) | (l & p) | (l & q) |
(r & y) | (r & t) | (r & u) | (r & v) | (r & w) | (fb & x) | (x & z) |
(ab & x) | (bb & x) | (cb & x)))'
test 3,5 = `ltl2tgba --low --any --stats=%s,%e "$f"`
cat >foo <<EOF
HOA: v1
States: 3
Start: 0
AP: 0
Acceptance: 0 t
--BODY--
State: 0
[t] 1
State: 1
[t] 0
State: 2
[t] 2
--END--
EOF
test 2,2 = `autfilt --stats=%S,%s foo`