postproc: add support for co-Büchi output

* spot/twaalgos/cobuchi.cc, spot/twaalgos/cobuchi.hh (to_nca): New
function.
(weak_to_cobuchi): New internal function, used in to_nca and to_dca
when appropriate.
* spot/twaalgos/postproc.cc, spot/twaalgos/postproc.hh: Implement
the CoBuchi option.
* python/spot/__init__.py: Support it in Python.
* bin/common_post.cc: Add support for --buchi.
* bin/autfilt.cc: Remove the --dca option.
* tests/core/dca.test, tests/python/automata.ipynb: Adjust and add
more tests.  In particular, add more complex persistence and
recurrence formulas to the list of dca.test.
* tests/python/dca.test: Adjust and rename to...
* tests/core/dca2.test: ... this.  Add more tests, to the point
that this is now failing, as described in issue #317.
* tests/python/dca.py: Remove.
* tests/Makefile.am: Adjust.
This commit is contained in:
Alexandre Duret-Lutz 2018-01-12 20:53:53 +01:00
parent 9464043d39
commit 61b0a542f1
14 changed files with 618 additions and 531 deletions

View file

@ -29,6 +29,8 @@
#include <spot/twaalgos/product.hh>
#include <spot/twaalgos/sccinfo.hh>
#include <spot/twaalgos/totgba.hh>
#include <spot/twaalgos/isdet.hh>
#include <spot/twaalgos/strength.hh>
#include <stack>
#include <unordered_map>
@ -196,7 +198,7 @@ namespace spot
bool was_rabin = false,
unsigned orig_num_st = 0)
: aut_(ref_prod),
state_based_((bool)aut_->prop_state_acc()),
state_based_(aut_->prop_state_acc().is_true()),
pairs_(pairs),
nb_pairs_(pairs.size()),
named_states_(named_states),
@ -241,29 +243,30 @@ namespace spot
twa_graph_ptr
nsa_to_nca(const const_twa_graph_ptr& ref,
nsa_to_nca(const_twa_graph_ptr ref,
bool named_states,
vect_nca_info* nca_info)
{
twa_graph_ptr ref_tmp = ref->acc().is_parity() ? to_generalized_streett(ref)
: nullptr;
if (ref->acc().is_parity())
ref = to_generalized_streett(ref);
std::vector<acc_cond::rs_pair> pairs;
if (!(ref_tmp ? ref_tmp : ref)->acc().is_streett_like(pairs))
if (!ref->acc().is_streett_like(pairs))
throw std::runtime_error("nsa_to_nca() only works with Streett-like or "
"Parity acceptance condition");
nsa_to_nca_converter nca_converter(ref_tmp ? ref_tmp : ref,
ref_tmp ? ref_tmp : ref,
pairs,
named_states,
false);
// FIXME: At the moment this algorithm does not support
// transition-based acceptance. See issue #317. Once that is
// fixed we may remove the next line.
ref = sbacc(std::const_pointer_cast<twa_graph>(ref));
nsa_to_nca_converter nca_converter(ref, ref, pairs, named_states, false);
return nca_converter.run(nca_info);
}
twa_graph_ptr
dnf_to_nca(const const_twa_graph_ptr& ref,
bool named_states,
dnf_to_nca(const_twa_graph_ptr ref, bool named_states,
vect_nca_info* nca_info)
{
const acc_cond::acc_code& code = ref->get_acceptance();
@ -287,6 +290,61 @@ namespace spot
return nca_converter.run(nca_info);
}
namespace
{
twa_graph_ptr
weak_to_cobuchi(const const_twa_graph_ptr& aut)
{
trival iw = aut->prop_inherently_weak();
if (iw.is_false())
return nullptr;
scc_info si(aut);
if (iw.is_maybe() && !is_weak_automaton(aut, &si))
return nullptr;
auto res = make_twa_graph(aut->get_dict());
res->copy_ap_of(aut);
res->prop_copy(aut, twa::prop_set::all());
res->new_states(aut->num_states());
si.determine_unknown_acceptance();
unsigned ns = si.scc_count();
for (unsigned s = 0; s < ns; ++s)
{
acc_cond::mark_t m = 0U;
if (si.is_rejecting_scc(s))
m = acc_cond::mark_t{0};
else
assert(si.is_accepting_scc(s));
for (auto& e: si.edges_of(s))
res->new_edge(e.src, e.dst, e.cond, m);
}
res->set_co_buchi();
res->set_init_state(aut->get_init_state_number());
res->prop_weak(true);
res->prop_state_acc(true);
return res;
}
}
twa_graph_ptr
to_nca(const_twa_graph_ptr aut, bool named_states)
{
if (auto weak = weak_to_cobuchi(aut))
return weak;
const acc_cond::acc_code& code = aut->get_acceptance();
std::vector<acc_cond::rs_pair> pairs;
if (aut->acc().is_streett_like(pairs) || aut->acc().is_parity())
return nsa_to_nca(aut, named_states);
else if (code.is_dnf())
return dnf_to_nca(aut, named_states);
auto tmp = make_twa_graph(aut, twa::prop_set::all());
tmp->set_acceptance(aut->acc().num_sets(),
aut->get_acceptance().to_dnf());
return to_nca(tmp, named_states);
}
namespace
{
@ -543,7 +601,7 @@ namespace spot
twa_graph_ptr
nsa_to_dca(const const_twa_graph_ptr& aut, bool named_states)
nsa_to_dca(const_twa_graph_ptr aut, bool named_states)
{
debug << "NSA_to_dca" << std::endl;
std::vector<acc_cond::rs_pair> pairs;
@ -568,7 +626,7 @@ namespace spot
twa_graph_ptr
dnf_to_dca(const const_twa_graph_ptr& aut, bool named_states)
dnf_to_dca(const_twa_graph_ptr aut, bool named_states)
{
debug << "DNF_to_dca" << std::endl;
const acc_cond::acc_code& code = aut->get_acceptance();
@ -599,8 +657,12 @@ namespace spot
twa_graph_ptr
to_dca(const const_twa_graph_ptr& aut, bool named_states)
to_dca(const_twa_graph_ptr aut, bool named_states)
{
if (is_deterministic(aut))
if (auto weak = weak_to_cobuchi(aut))
return weak;
const acc_cond::acc_code& code = aut->get_acceptance();
std::vector<acc_cond::rs_pair> pairs;
@ -608,8 +670,10 @@ namespace spot
return nsa_to_dca(aut, named_states);
else if (code.is_dnf())
return dnf_to_dca(aut, named_states);
else
throw std::runtime_error("to_dca() only works with Streett-like, Parity "
"or any acceptance condition in DNF");
auto tmp = make_twa_graph(aut, twa::prop_set::all());
tmp->set_acceptance(aut->acc().num_sets(),
aut->get_acceptance().to_dnf());
return to_nca(tmp, named_states);
}
}

View file

@ -78,7 +78,7 @@ namespace spot
/// \a named_states name each state for easier debugging.
/// \a nca_info retrieve information about state visited infinitely often.
SPOT_API twa_graph_ptr
nsa_to_nca(const const_twa_graph_ptr& aut,
nsa_to_nca(const_twa_graph_ptr aut,
bool named_states = false,
vect_nca_info* nca_info = nullptr);
@ -103,10 +103,21 @@ namespace spot
/// \a named_states name each state for easier debugging.
/// \a nca_info retrieve information about state visited infinitely often.
SPOT_API twa_graph_ptr
dnf_to_nca(const const_twa_graph_ptr& aut,
dnf_to_nca(const_twa_graph_ptr aut,
bool named_states = false,
vect_nca_info* nca_info = nullptr);
/// \brief Converts any ω-automata to non-deterministic co-buchi
///
/// The language of the resulting automaton always include the
/// original language, and is a superset iff the original language
/// can not be expressed using a co-Büchi acceptance condition.
///
/// The implementation dispatches between dnf_to_nca, nsa_to_nca,
/// and a trivial implementation for weak automata.
SPOT_API twa_graph_ptr
to_nca(const_twa_graph_ptr aut, bool named_states = false);
/// \brief Converts a nondet Streett-like aut. to a det. co-Büchi aut.
///
/// This function calls first nsa_to_nca() in order to retrieve som
@ -127,7 +138,7 @@ namespace spot
/// \a aut The automaton to convert.
/// \a named_states name each state for easier debugging.
SPOT_API twa_graph_ptr
nsa_to_dca(const const_twa_graph_ptr& aut, bool named_states = false);
nsa_to_dca(const_twa_graph_ptr aut, bool named_states = false);
/// \brief Converts an aut. with acceptance in DNF to a det. co-Büchi aut.
///
@ -149,13 +160,16 @@ namespace spot
/// \a aut The automaton to convert.
/// \a named_states name each state for easier debugging.
SPOT_API twa_graph_ptr
dnf_to_dca(const const_twa_graph_ptr& aut, bool named_states = false);
dnf_to_dca(const_twa_graph_ptr aut, bool named_states = false);
/// \brief Converts any ω-automata to det. co-buchi (when possible)
/// \brief Converts any ω-automata to deterministic co-buchi
///
/// The resulting automaton will always recognize at least the same language.
/// Actually, it can recognize more if the original language can not be
/// expressed using a co-Büchi acceptance condition.
/// The language of the resulting automaton always include the
/// original language, and is a superset iff the original language
/// can not be expressed using a co-Büchi acceptance condition.
///
/// The implementation dispatches between dnf_to_dca, nsa_to_dca,
/// and a trivial implementation for deterministic weak automata.
SPOT_API twa_graph_ptr
to_dca(const const_twa_graph_ptr& aut, bool named_states = false);
to_dca(const_twa_graph_ptr aut, bool named_states = false);
}

View file

@ -36,6 +36,8 @@
#include <spot/twaalgos/determinize.hh>
#include <spot/twaalgos/alternation.hh>
#include <spot/twaalgos/parity.hh>
#include <spot/twaalgos/cobuchi.hh>
#include <spot/twaalgos/dot.hh>
namespace spot
{
@ -194,6 +196,7 @@ namespace spot
if (type_ == BA || SBACC_)
state_based_ = true;
bool via_gba = (type_ == BA) || (type_ == TGBA) || (type_ == Monitor);
bool want_parity = (type_ & Parity) == Parity;
if (COLORED_ && !want_parity)
throw std::runtime_error("postprocessor: the Colored setting only works "
@ -234,7 +237,7 @@ namespace spot
!(type_ == Generic && PREF_ == Any && level_ == Low))
a = remove_alternation(a);
if ((type_ != Generic && !a->acc().is_generalized_buchi())
if ((via_gba && !a->acc().is_generalized_buchi())
|| (want_parity && !a->acc().is_parity()))
{
a = to_generalized_buchi(a);
@ -247,7 +250,8 @@ namespace spot
|| type_ == TGBA
|| (type_ == BA && a->is_sba())
|| (type_ == Monitor && a->num_sets() == 0)
|| (want_parity && a->acc().is_parity())))
|| (want_parity && a->acc().is_parity())
|| (type_ == CoBuchi && a->acc().is_co_buchi())))
return finalize(a);
int original_acc = a->num_sets();
@ -290,6 +294,8 @@ namespace spot
{
if (type_ == BA)
a = do_degen(a);
else if (type_ == CoBuchi)
a = to_nca(a);
return finalize(a);
}
@ -552,6 +558,21 @@ namespace spot
sim = dba ? dba : sim;
sim->remove_unused_ap();
if (type_ == CoBuchi)
{
unsigned ns = sim->num_states();
if (PREF_ == Deterministic)
sim = to_dca(sim);
else
sim = to_nca(sim);
// if the input of to_dca/to_nca was weak, the number of
// states has not changed, and running simulation is useless.
if (level_ != Low && ns < sim->num_states())
sim = do_simul(sim, simul_);
}
return finalize(sim);
}
}

View file

@ -72,8 +72,8 @@ namespace spot
/// options used for debugging or benchmarking.
postprocessor(const option_map* opt = nullptr);
enum output_type { TGBA = 0,
BA = 1,
enum output_type { TGBA = 0, // should be renamed GeneralizedBuchi
BA = 1, // should be renamed Buchi and not imply SBAcc
Monitor = 2,
Generic = 3,
Parity = 4,
@ -85,6 +85,7 @@ namespace spot
ParityMaxOdd = ParityMax | ParityOdd,
ParityMinEven = ParityMin | ParityEven,
ParityMaxEven = ParityMax | ParityEven,
CoBuchi = 128,
};
/// \brief Select the desired output type.
@ -121,6 +122,10 @@ namespace spot
/// but other parity types can be obtained from there by minor
/// adjustments.
///
/// \a CoBuchi requests a Co-Büchi automaton equivalent to
/// the input, when possible, or a Co-Büchi automaton that
/// recognize a larger language otherwise.
///
/// If set_type() is not called, the default \c output_type is \c TGBA.
void
set_type(output_type type)