autfilt: add --unused-ap and --used-ap
Last part of #170. * bin/autfilt.cc: Implement the new options. * tests/core/remprop.test: Add a quick test. * NEWS: Mention these options.
This commit is contained in:
parent
95d16ba009
commit
f5bfc07cfc
3 changed files with 53 additions and 3 deletions
5
NEWS
5
NEWS
|
|
@ -15,6 +15,11 @@ New in spot 2.0a (not yet released)
|
||||||
actually used. This of course makes sense only for input/output
|
actually used. This of course makes sense only for input/output
|
||||||
formats that declare atomic proposition (HOA & DSTAR).
|
formats that declare atomic proposition (HOA & DSTAR).
|
||||||
|
|
||||||
|
* autfilt has two new options to filter automata by count of used or
|
||||||
|
unused atomic propositions: --used-ap=RANGE --unused-ap=RANGE.
|
||||||
|
These differ from --ap=RANGE that only consider *declared* atomic
|
||||||
|
propositions, regardless of whether they are actually used.
|
||||||
|
|
||||||
Library:
|
Library:
|
||||||
|
|
||||||
* The print_hoa() function will now output version 1.1 of the HOA
|
* The print_hoa() function will now output version 1.1 of the HOA
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,8 @@ enum {
|
||||||
OPT_STRIPACC,
|
OPT_STRIPACC,
|
||||||
OPT_TERMINAL_SCCS,
|
OPT_TERMINAL_SCCS,
|
||||||
OPT_TRIV_SCCS,
|
OPT_TRIV_SCCS,
|
||||||
|
OPT_USED_AP_N,
|
||||||
|
OPT_UNUSED_AP_N,
|
||||||
OPT_WEAK_SCCS,
|
OPT_WEAK_SCCS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -202,7 +204,13 @@ static const argp_option options[] =
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
{ nullptr, 0, nullptr, 0, "Filtering options:", 6 },
|
{ nullptr, 0, nullptr, 0, "Filtering options:", 6 },
|
||||||
{ "ap", OPT_AP_N, "RANGE", 0,
|
{ "ap", OPT_AP_N, "RANGE", 0,
|
||||||
"match automata with a number of atomic propositions in RANGE", 0 },
|
"match automata with a number of (declared) atomic propositions in RANGE",
|
||||||
|
0 },
|
||||||
|
{ "used-ap", OPT_USED_AP_N, "RANGE", 0,
|
||||||
|
"match automata with a number of used atomic propositions in RANGE", 0 },
|
||||||
|
{ "unused-ap", OPT_UNUSED_AP_N, "RANGE", 0,
|
||||||
|
"match automata with a number of declared, but unused atomic "
|
||||||
|
"propositions in RANGE", 0 },
|
||||||
{ "are-isomorphic", OPT_ARE_ISOMORPHIC, "FILENAME", 0,
|
{ "are-isomorphic", OPT_ARE_ISOMORPHIC, "FILENAME", 0,
|
||||||
"keep automata that are isomorphic to the automaton in FILENAME", 0 },
|
"keep automata that are isomorphic to the automaton in FILENAME", 0 },
|
||||||
{ "isomorphic", 0, nullptr, OPTION_ALIAS | OPTION_HIDDEN, nullptr, 0 },
|
{ "isomorphic", 0, nullptr, OPTION_ALIAS | OPTION_HIDDEN, nullptr, 0 },
|
||||||
|
|
@ -338,6 +346,9 @@ static range opt_states = { 0, std::numeric_limits<int>::max() };
|
||||||
static range opt_edges = { 0, std::numeric_limits<int>::max() };
|
static range opt_edges = { 0, std::numeric_limits<int>::max() };
|
||||||
static range opt_accsets = { 0, std::numeric_limits<int>::max() };
|
static range opt_accsets = { 0, std::numeric_limits<int>::max() };
|
||||||
static range opt_ap_n = { 0, std::numeric_limits<int>::max() };
|
static range opt_ap_n = { 0, std::numeric_limits<int>::max() };
|
||||||
|
static range opt_used_ap_n = { 0, std::numeric_limits<int>::max() };
|
||||||
|
static range opt_unused_ap_n = { 0, std::numeric_limits<int>::max() };
|
||||||
|
static bool need_unused_ap_count = false;
|
||||||
static range opt_sccs = { 0, std::numeric_limits<int>::max() };
|
static range opt_sccs = { 0, std::numeric_limits<int>::max() };
|
||||||
static range opt_acc_sccs = { 0, std::numeric_limits<int>::max() };
|
static range opt_acc_sccs = { 0, std::numeric_limits<int>::max() };
|
||||||
static range opt_rej_sccs = { 0, std::numeric_limits<int>::max() };
|
static range opt_rej_sccs = { 0, std::numeric_limits<int>::max() };
|
||||||
|
|
@ -662,6 +673,14 @@ parse_opt(int key, char* arg, struct argp_state*)
|
||||||
opt_triv_sccs = parse_range(arg, 0, std::numeric_limits<int>::max());
|
opt_triv_sccs = parse_range(arg, 0, std::numeric_limits<int>::max());
|
||||||
opt_art_sccs_set = true;
|
opt_art_sccs_set = true;
|
||||||
break;
|
break;
|
||||||
|
case OPT_USED_AP_N:
|
||||||
|
opt_used_ap_n = parse_range(arg, 0, std::numeric_limits<int>::max());
|
||||||
|
need_unused_ap_count = true;
|
||||||
|
break;
|
||||||
|
case OPT_UNUSED_AP_N:
|
||||||
|
opt_unused_ap_n = parse_range(arg, 0, std::numeric_limits<int>::max());
|
||||||
|
need_unused_ap_count = true;
|
||||||
|
break;
|
||||||
case OPT_WEAK_SCCS:
|
case OPT_WEAK_SCCS:
|
||||||
opt_weak_sccs = parse_range(arg, 0, std::numeric_limits<int>::max());
|
opt_weak_sccs = parse_range(arg, 0, std::numeric_limits<int>::max());
|
||||||
opt_weak_sccs_set = true;
|
opt_weak_sccs_set = true;
|
||||||
|
|
@ -677,6 +696,23 @@ parse_opt(int key, char* arg, struct argp_state*)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int unused_ap(const spot::const_twa_graph_ptr& aut)
|
||||||
|
{
|
||||||
|
bdd all = aut->ap_vars();
|
||||||
|
for (auto& e: aut->edges())
|
||||||
|
{
|
||||||
|
all = bdd_exist(all, bdd_support(e.cond));
|
||||||
|
if (all == bddtrue) // All APs are used.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
|
while (all != bddtrue)
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
all = bdd_high(all);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
@ -742,7 +778,13 @@ namespace
|
||||||
matched &= opt_edges.contains(aut->num_edges());
|
matched &= opt_edges.contains(aut->num_edges());
|
||||||
matched &= opt_accsets.contains(aut->acc().num_sets());
|
matched &= opt_accsets.contains(aut->acc().num_sets());
|
||||||
matched &= opt_ap_n.contains(aut->ap().size());
|
matched &= opt_ap_n.contains(aut->ap().size());
|
||||||
if (opt_is_complete)
|
if (matched && need_unused_ap_count)
|
||||||
|
{
|
||||||
|
int unused = unused_ap(aut);
|
||||||
|
matched &= opt_unused_ap_n.contains(unused);
|
||||||
|
matched &= opt_used_ap_n.contains(aut->ap().size() - unused);
|
||||||
|
}
|
||||||
|
if (matched && opt_is_complete)
|
||||||
matched &= is_complete(aut);
|
matched &= is_complete(aut);
|
||||||
if (matched && (opt_sccs_set | opt_art_sccs_set))
|
if (matched && (opt_sccs_set | opt_art_sccs_set))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ State: 0 {0}
|
||||||
--END--
|
--END--
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
autfilt automaton > output
|
autfilt automaton --used-ap=1 --unused-ap=2 > output
|
||||||
diff automaton output
|
diff automaton output
|
||||||
|
|
||||||
cat >expect <<EOF
|
cat >expect <<EOF
|
||||||
|
|
@ -132,3 +132,6 @@ EOF
|
||||||
|
|
||||||
autfilt --remove-unused-ap automaton > output
|
autfilt --remove-unused-ap automaton > output
|
||||||
diff output expect
|
diff output expect
|
||||||
|
|
||||||
|
autfilt output --used-ap=0..1 --unused-ap=0 > output2
|
||||||
|
diff output output2
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue