stats: add options to count unreachable states and transitions
Based on a request from Pierre Ganty. * spot/twaalgos/stats.cc, spot/twaalgos/stats.hh, bin/common_aoutput.cc, bin/common_aoutput.hh: Implement those options. * tests/core/format.test: Add test case. * doc/org/autfilt.org: Update doc. * NEWS: Mention them.
This commit is contained in:
parent
52ed3d1e8f
commit
de29ba9e4c
7 changed files with 197 additions and 52 deletions
7
NEWS
7
NEWS
|
|
@ -1,5 +1,12 @@
|
|||
New in spot 2.11.1.dev (not yet released)
|
||||
|
||||
Command-line tools:
|
||||
|
||||
- The --stats specifications %s, %e, %t for printing the number of
|
||||
(reachable) states, edges, and transitions, learned to support
|
||||
options [r], [u], [a] to indicate if only reachable, unreachable,
|
||||
or all elements should be counted.
|
||||
|
||||
Library:
|
||||
|
||||
- spot::reduce_parity() now has a "layered" option to force all
|
||||
|
|
|
|||
|
|
@ -203,12 +203,18 @@ static const argp_option io_options[] =
|
|||
"to specify additional options as in --hoa=opt)", 0 },
|
||||
{ "%M, %m", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"name of the automaton", 0 },
|
||||
{ "%S, %s", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of reachable states", 0 },
|
||||
{ "%E, %e", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of reachable edges", 0 },
|
||||
{ "%T, %t", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of reachable transitions", 0 },
|
||||
{ "%S, %s, %[LETTER]S, %[LETTER]s",
|
||||
0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of states (add one LETTER to select (r) reachable [default], "
|
||||
"(u) unreachable, (a) all).", 0 },
|
||||
{ "%E, %e, %[LETTER]E, %[LETTER]e",
|
||||
0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of edges (add one LETTER to select (r) reachable [default], "
|
||||
"(u) unreachable, (a) all).", 0 },
|
||||
{ "%T, %t, %[LETTER]E, %[LETTER]e",
|
||||
0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of transitions (add one LETTER to select (r) reachable "
|
||||
"[default], (u) unreachable, (a) all).", 0 },
|
||||
{ "%A, %a", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of acceptance sets", 0 },
|
||||
{ "%G, %g, %[LETTERS]G, %[LETTERS]g", 0, nullptr,
|
||||
|
|
@ -268,12 +274,15 @@ static const argp_option o_options[] =
|
|||
"to specify additional options as in --hoa=opt)", 0 },
|
||||
{ "%m", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"name of the automaton", 0 },
|
||||
{ "%s", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of reachable states", 0 },
|
||||
{ "%e", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of reachable edges", 0 },
|
||||
{ "%t", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of reachable transitions", 0 },
|
||||
{ "%s, %[LETTER]s", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of states (add one LETTER to select (r) reachable [default], "
|
||||
"(u) unreachable, (a) all).", 0 },
|
||||
{ "%e, %[LETTER]e", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of edges (add one LETTER to select (r) reachable [default], "
|
||||
"(u) unreachable, (a) all).", 0 },
|
||||
{ "%t, %[LETTER]t", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of transitions (add one LETTER to select (r) reachable "
|
||||
"[default], (u) unreachable, (a) all).", 0 },
|
||||
{ "%a", 0, nullptr, OPTION_DOC | OPTION_NO_USAGE,
|
||||
"number of acceptance sets", 0 },
|
||||
{ "%g, %[LETTERS]g", 0, nullptr,
|
||||
|
|
@ -472,15 +481,15 @@ hoa_stat_printer::print(const spot::const_parsed_aut_ptr& haut,
|
|||
if (has('T'))
|
||||
{
|
||||
spot::twa_sub_statistics s = sub_stats_reachable(haut->aut);
|
||||
haut_states_ = s.states;
|
||||
haut_edges_ = s.edges;
|
||||
haut_trans_ = s.transitions;
|
||||
haut_states_.set(s.states, haut->aut->num_states());
|
||||
haut_edges_.set(s.edges, haut->aut->num_edges());
|
||||
haut_trans_.set(s.transitions, count_all_transitions(haut->aut));
|
||||
}
|
||||
else if (has('E') || has('S'))
|
||||
{
|
||||
spot::twa_statistics s = stats_reachable(haut->aut);
|
||||
haut_states_ = s.states;
|
||||
haut_edges_ = s.edges;
|
||||
haut_states_.set(s.states, haut->aut->num_states());
|
||||
haut_edges_.set(s.edges, haut->aut->num_edges());
|
||||
}
|
||||
if (has('M'))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -166,9 +166,9 @@ private:
|
|||
spot::printable_value<std::string> aut_word_;
|
||||
spot::printable_value<std::string> haut_word_;
|
||||
spot::printable_acc_cond haut_gen_acc_;
|
||||
spot::printable_value<unsigned> haut_states_;
|
||||
spot::printable_value<unsigned> haut_edges_;
|
||||
spot::printable_value<unsigned long long> haut_trans_;
|
||||
spot::printable_size haut_states_;
|
||||
spot::printable_size haut_edges_;
|
||||
spot::printable_long_size haut_trans_;
|
||||
spot::printable_value<unsigned> haut_acc_;
|
||||
printable_varset haut_ap_;
|
||||
printable_varset aut_ap_;
|
||||
|
|
|
|||
|
|
@ -145,7 +145,8 @@ ltl2tgba --help | sed -n '/ sequences:/,/^$/p' | sed '1d;$d'
|
|||
(iw) inherently weak. Use uppercase letters to
|
||||
negate them.
|
||||
%d 1 if the output is deterministic, 0 otherwise
|
||||
%e number of reachable edges
|
||||
%e, %[LETTER]e number of edges (add one LETTER to select (r)
|
||||
reachable [default], (u) unreachable, (a) all).
|
||||
%f the formula, in Spot's syntax
|
||||
%F name of the input file
|
||||
%g, %[LETTERS]g acceptance condition (in HOA syntax); add brackets
|
||||
|
|
@ -170,8 +171,11 @@ ltl2tgba --help | sed -n '/ sequences:/,/^$/p' | sed '1d;$d'
|
|||
LETTERS to restrict to(u) user time, (s) system
|
||||
time, (p) parent process, or (c) children
|
||||
processes.
|
||||
%s number of reachable states
|
||||
%t number of reachable transitions
|
||||
%s, %[LETTER]s number of states (add one LETTER to select (r)
|
||||
reachable [default], (u) unreachable, (a) all).
|
||||
%t, %[LETTER]t number of transitions (add one LETTER to select
|
||||
(r) reachable [default], (u) unreachable, (a)
|
||||
all).
|
||||
%u, %[e]u number of states (or [e]dges) with universal
|
||||
branching
|
||||
%u, %[LETTER]u 1 if the automaton contains some universal
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2008, 2011-2018, 2020 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
// Copyright (C) 2008, 2011-2018, 2020, 2022 Laboratoire de Recherche
|
||||
// et Développement de l'Epita (LRDE).
|
||||
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
|
|
@ -33,6 +33,16 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
unsigned long long
|
||||
count_all_transitions(const const_twa_graph_ptr& g)
|
||||
{
|
||||
unsigned long long tr = 0;
|
||||
bdd v = g->ap_vars();
|
||||
for (auto& e: g->edges())
|
||||
tr += bdd_satcountset(e.cond, v);
|
||||
return tr;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class stats_bfs: public twa_reachable_iterator_breadth_first
|
||||
|
|
@ -82,6 +92,7 @@ namespace spot
|
|||
};
|
||||
|
||||
|
||||
|
||||
template<typename SU, typename EU>
|
||||
void dfs(const const_twa_graph_ptr& ge, SU state_update, EU edge_update)
|
||||
{
|
||||
|
|
@ -344,10 +355,73 @@ namespace spot
|
|||
<< std::string(beg, end + 2) << ", ";
|
||||
tmp << e.what();
|
||||
throw std::runtime_error(tmp.str());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void printable_size::print(std::ostream& os, const char* pos) const
|
||||
{
|
||||
char p = 'r';
|
||||
if (*pos == '[')
|
||||
{
|
||||
p = pos[1];
|
||||
if (pos[2] != ']' || !(p == 'r' || p == 'u' || p == 'a'))
|
||||
{
|
||||
const char* end = strchr(pos + 1, ']');
|
||||
std::ostringstream tmp;
|
||||
tmp << "while processing %"
|
||||
<< std::string(pos, end + 2) << ", "
|
||||
<< "only [a], [r], or [u] is supported.";
|
||||
throw std::runtime_error(tmp.str());
|
||||
}
|
||||
}
|
||||
switch (p)
|
||||
{
|
||||
case 'r':
|
||||
os << reachable_;
|
||||
return;
|
||||
case 'a':
|
||||
os << all_;
|
||||
return;
|
||||
case 'u':
|
||||
os << all_ - reachable_;
|
||||
return;
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
void printable_long_size::print(std::ostream& os, const char* pos) const
|
||||
{
|
||||
char p = 'r';
|
||||
if (*pos == '[')
|
||||
{
|
||||
p = pos[1];
|
||||
if (pos[2] != ']' || !(p == 'r' || p == 'u' || p == 'a'))
|
||||
{
|
||||
const char* end = strchr(pos + 1, ']');
|
||||
std::ostringstream tmp;
|
||||
tmp << "while processing %"
|
||||
<< std::string(pos, end + 2) << ", "
|
||||
<< "only [a], [r], or [u] is supported.";
|
||||
throw std::runtime_error(tmp.str());
|
||||
}
|
||||
}
|
||||
switch (p)
|
||||
{
|
||||
case 'r':
|
||||
os << reachable_;
|
||||
return;
|
||||
case 'a':
|
||||
os << all_;
|
||||
return;
|
||||
case 'u':
|
||||
os << all_ - reachable_;
|
||||
return;
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
stat_printer::stat_printer(std::ostream& os, const char* format)
|
||||
: format_(format)
|
||||
|
|
@ -376,15 +450,15 @@ namespace spot
|
|||
if (has('t'))
|
||||
{
|
||||
twa_sub_statistics s = sub_stats_reachable(aut);
|
||||
states_ = s.states;
|
||||
edges_ = s.edges;
|
||||
trans_ = s.transitions;
|
||||
states_.set(s.states, aut->num_states());
|
||||
edges_.set(s.edges, aut->num_edges());
|
||||
trans_.set(s.transitions, count_all_transitions(aut));
|
||||
}
|
||||
else if (has('s') || has('e'))
|
||||
{
|
||||
twa_statistics s = stats_reachable(aut);
|
||||
states_ = s.states;
|
||||
edges_ = s.edges;
|
||||
states_.set(s.states, aut->num_states());
|
||||
edges_.set(s.edges, aut->num_edges());
|
||||
}
|
||||
|
||||
if (has('a'))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2008, 2011-2017, 2020 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
// Copyright (C) 2008, 2011-2017, 2020, 2022 Laboratoire de Recherche
|
||||
// et Développement de l'Epita (LRDE).
|
||||
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
// et Marie Curie.
|
||||
|
|
@ -55,6 +55,9 @@ namespace spot
|
|||
/// \brief Compute sub statistics for an automaton.
|
||||
SPOT_API twa_sub_statistics sub_stats_reachable(const const_twa_ptr& g);
|
||||
|
||||
/// \brief Count all transtitions, even unreachable ones.
|
||||
SPOT_API unsigned long long
|
||||
count_all_transitions(const const_twa_graph_ptr& g);
|
||||
|
||||
class SPOT_API printable_formula: public printable_value<formula>
|
||||
{
|
||||
|
|
@ -102,6 +105,36 @@ namespace spot
|
|||
void print(std::ostream& os, const char* pos) const override;
|
||||
};
|
||||
|
||||
class SPOT_API printable_size final:
|
||||
public spot::printable
|
||||
{
|
||||
unsigned reachable_ = 0;
|
||||
unsigned all_ = 0;
|
||||
public:
|
||||
void set(unsigned reachable, unsigned all)
|
||||
{
|
||||
reachable_ = reachable;
|
||||
all_ = all;
|
||||
}
|
||||
|
||||
void print(std::ostream& os, const char* pos) const override;
|
||||
};
|
||||
|
||||
class SPOT_API printable_long_size final:
|
||||
public spot::printable
|
||||
{
|
||||
unsigned long long reachable_ = 0;
|
||||
unsigned long long all_ = 0;
|
||||
public:
|
||||
void set(unsigned long long reachable, unsigned long long all)
|
||||
{
|
||||
reachable_ = reachable;
|
||||
all_ = all;
|
||||
}
|
||||
|
||||
void print(std::ostream& os, const char* pos) const override;
|
||||
};
|
||||
|
||||
/// \brief prints various statistics about a TGBA
|
||||
///
|
||||
/// This object can be configured to display various statistics
|
||||
|
|
@ -123,9 +156,9 @@ namespace spot
|
|||
const char* format_;
|
||||
|
||||
printable_formula form_;
|
||||
printable_value<unsigned> states_;
|
||||
printable_value<unsigned> edges_;
|
||||
printable_value<unsigned long long> trans_;
|
||||
printable_size states_;
|
||||
printable_size edges_;
|
||||
printable_long_size trans_;
|
||||
printable_value<unsigned> acc_;
|
||||
printable_scc_info scc_;
|
||||
printable_value<unsigned> nondetstates_;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2016, 2017 Laboratoire de Recherche et Développement de
|
||||
# l'Epita (LRDE).
|
||||
# Copyright (C) 2016, 2017, 2022 Laboratoire de Recherche et
|
||||
# Développement de l'Epita (LRDE).
|
||||
#
|
||||
# This file is part of Spot, a model checking library.
|
||||
#
|
||||
|
|
@ -139,18 +139,36 @@ test 3,5 = `ltl2tgba --low --any --stats=%s,%e "$f"`
|
|||
test 3,4 = `ltl2tgba --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--
|
||||
HOA: v1 States: 7 Start: 5 AP: 1 "a" acc-name: Buchi
|
||||
Acceptance: 1 Inf(0) properties: trans-labels explicit-labels
|
||||
state-acc deterministic properties: terminal --BODY-- State: 0 [0] 6
|
||||
State: 1 [t] 0 State: 2 [t] 1 State: 3 [f] 2 State: 4 [t] 3 State: 5
|
||||
[t] 4 State: 6 {0} [t] 6 --END--
|
||||
EOF
|
||||
test 2,2 = `autfilt --stats=%S,%s foo`
|
||||
(
|
||||
autfilt --stats='%s,%[r]s,%[u]s,%[a]s' foo;
|
||||
autfilt --remove-dead --stats='%s,%[r]s,%[u]s,%[a]s' foo;
|
||||
autfilt --remove-dead --stats='%S,%[r]S,%[u]S,%[a]S' foo;
|
||||
autfilt --stats='%e,%[r]e,%[u]e,%[a]e' foo;
|
||||
autfilt --remove-dead --stats='%e,%[r]e,%[u]e,%[a]e' foo;
|
||||
autfilt --remove-dead --stats='%E,%[r]E,%[u]E,%[a]E' foo;
|
||||
autfilt --stats='%t,%[r]t,%[u]t,%[a]t' foo;
|
||||
autfilt --remove-dead --stats='%t,%[r]t,%[u]t,%[a]t' foo;
|
||||
autfilt --remove-dead --stats='%T,%[r]T,%[u]T,%[a]T' foo;
|
||||
) > stats
|
||||
|
||||
cat >expected <<EOF
|
||||
3,3,4,7
|
||||
1,1,0,1
|
||||
3,3,4,7
|
||||
2,2,4,6
|
||||
0,0,0,0
|
||||
2,2,4,6
|
||||
4,4,7,11
|
||||
0,0,0,0
|
||||
4,4,7,11
|
||||
EOF
|
||||
diff stats expected
|
||||
|
||||
autfilt --stats='%[x]T' foo 2>err && exit 1
|
||||
grep 'only \[a\], \[r\], or \[u\] is supported' err
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue