postproc: add a SBAcc option

Producing state-based acceptance is now part of the postprocessing
routines.  That means we can more easily simplify automata with
state-based acceptance (using autfilt -S --small --high, for instance)
and as as side-effect, ltl2tgba can produce GBA.  However the result of
ltl2tgba -S is often larger than that of ltl2tgba -B.

* src/twaalgos/postproc.cc, src/twaalgos/postproc.hh: Implement
the SBAcc option.
* src/bin/common_post.cc, src/bin/common_post.hh: Implement -S.
* src/bin/autfilt.cc, src/bin/dstar2tgba.cc, src/bin/ltl2tgba.cc,
src/bin/ltl2tgta.cc, src/bin/ltldo.cc: Adjust.
* src/tests/sim3.test: Augment test case.
* NEWS, doc/org/ltl2tgba.org, doc/org/autfilt.org: Document it -S.
This commit is contained in:
Alexandre Duret-Lutz 2015-05-14 20:04:50 +02:00
parent dd87bdf868
commit 0786e068ae
13 changed files with 181 additions and 42 deletions

View file

@ -50,7 +50,6 @@
#include "twaalgos/are_isomorphic.hh"
#include "twaalgos/canonicalize.hh"
#include "twaalgos/mask.hh"
#include "twaalgos/sbacc.hh"
#include "twaalgos/sepsets.hh"
#include "twaalgos/stripacc.hh"
#include "twaalgos/remfin.hh"
@ -92,7 +91,6 @@ enum {
OPT_REM_DEAD,
OPT_REM_UNREACH,
OPT_REM_FIN,
OPT_SBACC,
OPT_SEED,
OPT_SEP_SETS,
OPT_SIMPLIFY_EXCLUSIVE_AP,
@ -133,9 +131,6 @@ static const argp_option options[] =
{ "destut", OPT_DESTUT, 0, 0, "allow less stuttering", 0 },
{ "mask-acc", OPT_MASK_ACC, "NUM[,NUM...]", 0,
"remove all transitions in specified acceptance sets", 0 },
{ "state-based-acceptance", OPT_SBACC, 0, 0,
"define the acceptance using states", 0 },
{ "sbacc", 0, 0, OPTION_ALIAS, 0, 0 },
{ "strip-acceptance", OPT_STRIPACC, 0, 0,
"remove the acceptance condition and all acceptance sets", 0 },
{ "keep-states", OPT_KEEP_STATES, "NUM[,NUM...]", 0,
@ -251,7 +246,6 @@ static int opt_max_count = -1;
static bool opt_destut = false;
static char opt_instut = 0;
static bool opt_is_empty = false;
static bool opt_sbacc = false;
static bool opt_stripacc = false;
static bool opt_dnf_acc = false;
static bool opt_cnf_acc = false;
@ -437,9 +431,6 @@ parse_opt(int key, char* arg, struct argp_state*)
case OPT_REM_UNREACH:
opt_rem_unreach = true;
break;
case OPT_SBACC:
opt_sbacc = true;
break;
case OPT_SEED:
opt_seed = to_int(arg);
break;
@ -583,9 +574,6 @@ namespace
if (opt->product)
aut = spot::product(std::move(aut), opt->product);
if (opt_sbacc)
aut = spot::sbacc(aut);
aut = post.run(aut, nullptr);
if (randomize_st || randomize_tr)
@ -686,7 +674,7 @@ main(int argc, char** argv)
spot::srand(opt_seed);
spot::postprocessor post(&extra_options);
post.set_pref(pref | comp);
post.set_pref(pref | comp | sbacc);
post.set_type(type);
post.set_level(level);

View file

@ -24,6 +24,7 @@
spot::postprocessor::output_type type = spot::postprocessor::TGBA;
spot::postprocessor::output_pref pref = spot::postprocessor::Small;
spot::postprocessor::output_pref comp = spot::postprocessor::Any;
spot::postprocessor::output_pref sbacc = spot::postprocessor::Any;
spot::postprocessor::optimization_level level = spot::postprocessor::High;
enum {
@ -43,6 +44,9 @@ static const argp_option options[] =
"or deterministic", 0 },
{ "complete", 'C', 0, 0, "output a complete automaton (combine "
"with other intents)", 0 },
{ "state-based-acceptance", 'S', 0, 0,
"define the acceptance using states", 0 },
{ "sbacc", 0, 0, OPTION_ALIAS, 0, 0 },
/**************************************************/
{ 0, 0, 0, 0, "Optimization level:", 21 },
{ "low", OPT_LOW, 0, 0, "minimal optimizations (fast)", 0 },
@ -62,6 +66,9 @@ static const argp_option options_disabled[] =
"or deterministic (default)", 0 },
{ "complete", 'C', 0, 0, "output a complete automaton (combine "
"with other intents)", 0 },
{ "state-based-acceptance", 'S', 0, 0,
"define the acceptance using states", 0 },
{ "sbacc", 0, 0, OPTION_ALIAS, 0, 0 },
/**************************************************/
{ 0, 0, 0, 0, "Optimization level:", 21 },
{ "low", OPT_LOW, 0, 0, "minimal optimizations (fast, default)", 0 },
@ -86,6 +93,9 @@ parse_opt_post(int key, char*, struct argp_state*)
case 'D':
pref = spot::postprocessor::Deterministic;
break;
case 'S':
sbacc = spot::postprocessor::SBAcc;
break;
case OPT_HIGH:
level = spot::postprocessor::High;
simplification_level = 3;

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2012, 2013, 2014 Laboratoire de Recherche et
// Copyright (C) 2012, 2013, 2014, 2015 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -29,4 +29,5 @@ extern const struct argp post_argp_disabled; // postprocessing disabled
extern spot::postprocessor::output_type type;
extern spot::postprocessor::output_pref pref;
extern spot::postprocessor::output_pref comp;
extern spot::postprocessor::output_pref sbacc;
extern spot::postprocessor::optimization_level level;

View file

@ -428,7 +428,7 @@ main(int argc, char** argv)
jobs.emplace_back("-", true);
spot::postprocessor post(&extra_options);
post.set_pref(pref | comp);
post.set_pref(pref | comp | sbacc);
post.set_type(type);
post.set_level(level);

View file

@ -204,7 +204,7 @@ main(int argc, char** argv)
program_name);
spot::translator trans(&extra_options);
trans.set_pref(pref | comp);
trans.set_pref(pref | comp | sbacc);
trans.set_type(type);
trans.set_level(level);
if (unambiguous)

View file

@ -232,7 +232,7 @@ main(int argc, char** argv)
program_name);
spot::translator trans(&extra_options);
trans.set_pref(pref | comp);
trans.set_pref(pref | comp | sbacc);
trans.set_type(type);
trans.set_level(level);

View file

@ -358,7 +358,7 @@ main(int argc, char** argv)
setup_sig_handler();
spot::postprocessor post;
post.set_pref(pref | comp);
post.set_pref(pref | comp | sbacc);
post.set_type(type);
post.set_level(level);

View file

@ -47,3 +47,40 @@ State: 6 {0 3}
EOF
test "`../../bin/autfilt --small input --stats=%S,%s`" = 7,5
../../bin/autfilt -S --high --small input -H > out
cat >expected <<EOF
HOA: v1
States: 5
Start: 0
AP: 2 "b" "a"
Acceptance: 4 (Fin(0) & Inf(1)) | (Fin(2) & Inf(3))
properties: trans-labels explicit-labels state-acc complete
properties: deterministic
--BODY--
State: 0 {0}
[!1] 1
[1] 3
State: 1 {1 3}
[0&!1] 1
[!0&!1] 2
[0&1] 3
[!0&1] 4
State: 2 {1}
[0&!1] 1
[!0&!1] 2
[0&1] 3
[!0&1] 4
State: 3 {0 3}
[0&!1] 1
[!0&!1] 2
[0&1] 3
[!0&1] 4
State: 4 {0}
[0&!1] 1
[!0&!1] 2
[0&1] 3
[!0&1] 4
--END--
EOF
diff out expected

View file

@ -31,6 +31,7 @@
#include "dtgbasat.hh"
#include "complete.hh"
#include "totgba.hh"
#include "sbacc.hh"
namespace spot
{
@ -107,7 +108,7 @@ namespace spot
}
twa_graph_ptr
postprocessor::do_ba_simul(const twa_graph_ptr& a, int opt)
postprocessor::do_sba_simul(const twa_graph_ptr& a, int opt)
{
if (ba_simul_ <= 0)
return a;
@ -132,11 +133,12 @@ namespace spot
degen_reset_, degen_order_,
degen_cache_, degen_lskip_,
degen_lowinit_);
return do_ba_simul(d, ba_simul_);
return do_sba_simul(d, ba_simul_);
}
#define PREF_ (pref_ & (Small | Deterministic))
#define COMP_ (pref_ & Complete)
#define SBACC_ (pref_ & SBAcc)
twa_graph_ptr
postprocessor::run(twa_graph_ptr a, const ltl::formula* f)
@ -152,6 +154,8 @@ namespace spot
{
if (COMP_)
a = tgba_complete(a);
if (SBACC_)
a = sbacc(a);
return a;
}
@ -161,7 +165,7 @@ namespace spot
ba_simul_ = (level_ == High) ? 3 : 0;
if (scc_filter_ < 0)
scc_filter_ = 1;
if (type_ == BA)
if (type_ == BA || SBACC_)
state_based_ = true;
int original_acc = a->acc().num_sets();
@ -173,7 +177,7 @@ namespace spot
a = scc_filter_states(a);
else if (scc_filter_ > 0)
{
if (type_ == BA && a->is_sba())
if (state_based_ && a->has_state_based_acc())
a = scc_filter_states(a);
else
a = scc_filter(a, scc_filter_ > 1);
@ -208,8 +212,10 @@ namespace spot
{
if (type_ == BA)
a = do_degen(a);
if (COMP_ == Complete)
if (COMP_)
a = tgba_complete(a);
if (SBACC_)
a = sbacc(a);
return a;
}
@ -243,9 +249,11 @@ namespace spot
// at hard levels if we want a small output.
if (!dba || (level_ == High && PREF_ == Small))
{
if (type_ == BA && a->is_sba() && !tba_determinisation_)
if (((SBACC_ && a->has_state_based_acc())
|| (type_ == BA && a->is_sba()))
&& !tba_determinisation_)
{
sim = do_ba_simul(a, ba_simul_);
sim = do_sba_simul(a, ba_simul_);
}
else
{
@ -254,6 +262,8 @@ namespace spot
// No need to do that if tba_determinisation_ will be used.
if (type_ == BA && !tba_determinisation_)
sim = do_degen(sim);
else if (SBACC_ && !tba_determinisation_)
sim = sbacc(sim);
}
}
@ -266,10 +276,18 @@ namespace spot
// We postponed degeneralization above i case we would need
// to perform TBA-determinisation, but now it is clear
// that we won't perform it. So do degeneralize.
if (tba_determinisation_ && type_ == BA)
if (tba_determinisation_)
{
dba = do_degen(dba);
assert(is_deterministic(dba));
if (type_ == BA)
{
dba = do_degen(dba);
assert(is_deterministic(dba));
}
else if (SBACC_)
{
dba = sbacc(dba);
assert(is_deterministic(dba));
}
}
}
@ -412,12 +430,18 @@ namespace spot
{
if (dba && !dba_is_minimal) // WDBA is already clean.
{
dba = scc_filter(dba, true);
if (state_based_ && dba->has_state_based_acc())
dba = scc_filter_states(dba);
else
dba = scc_filter(dba, true);
assert(!sim);
}
else if (sim)
{
sim = scc_filter(sim, true);
if (state_based_ && sim->has_state_based_acc())
sim = scc_filter_states(sim);
else
sim = scc_filter(sim, true);
assert(!dba);
}
}
@ -426,6 +450,8 @@ namespace spot
if (COMP_)
sim = tgba_complete(sim);
if (SBACC_)
sim = sbacc(sim);
return sim;
}

View file

@ -78,7 +78,9 @@ namespace spot
Deterministic = 2,
// 3 reserved for unambiguous
// Combine Complete as 'Small | Complete' or 'Deterministic | Complete'
Complete = 4
Complete = 4,
// Likewise. State-based acceptance.
SBAcc = 8,
};
typedef int output_pref;
@ -104,7 +106,7 @@ namespace spot
protected:
twa_graph_ptr do_simul(const twa_graph_ptr& input, int opt);
twa_graph_ptr do_ba_simul(const twa_graph_ptr& input, int opt);
twa_graph_ptr do_sba_simul(const twa_graph_ptr& input, int opt);
twa_graph_ptr do_degen(const twa_graph_ptr& input);
output_type type_;