specialize scc_filter for inherently_weak automata

Part of issue #351.

* spot/twaalgos/sccfilter.cc, spot/twaalgos/sccfilter.hh: Specialize
for inherently-weak automata.
* spot/twaalgos/postproc.cc: Simplify.
* tests/core/dca2.test, tests/core/parity2.test,
tests/core/prodor.test, tests/core/randomize.test,
tests/python/automata.ipynb, tests/python/highlighting.ipynb,
tests/python/product.ipynb, tests/python/remfin.py,
tests/python/stutter-inv.ipynb: Adjust.
* NEWS: Mention it.
This commit is contained in:
Alexandre Duret-Lutz 2018-06-11 15:01:49 +02:00
parent 2fad1ff6de
commit 95d732e331
13 changed files with 1245 additions and 2011 deletions

View file

@ -38,7 +38,6 @@
#include <spot/twaalgos/alternation.hh>
#include <spot/twaalgos/parity.hh>
#include <spot/twaalgos/cobuchi.hh>
#include <spot/twaalgos/dot.hh>
#include <spot/twaalgos/rabin2parity.hh>
namespace spot
@ -166,10 +165,7 @@ namespace spot
{
if (scc_filter_ == 0)
return a;
// If the automaton is weak, using transition-based acceptance
// won't help, so let's preserve state-based acceptance.
if ((state_based_ || a->prop_inherently_weak().is_true())
&& a->prop_state_acc().is_true())
if (state_based_ && a->prop_state_acc().is_true())
return scc_filter_states(a, arg);
else
return scc_filter(a, arg);

View file

@ -124,6 +124,53 @@ namespace spot
}
};
// Transform inherently weak automata into weak Büchi automata.
template <bool buchi, class next_filter = id_filter>
struct weak_filter: next_filter
{
acc_cond::mark_t acc_m = {0};
acc_cond::mark_t rej_m = {};
template<typename... Args>
weak_filter(scc_info* si, Args&&... args)
: next_filter(si, std::forward<Args>(args)...)
{
if (!buchi)
{
acc_m = {};
if (si->get_aut()->acc().is_co_buchi())
rej_m = {0};
}
}
filtered_trans trans(unsigned src, unsigned dst,
bdd cond, acc_cond::mark_t acc)
{
bool keep;
std::tie(keep, cond, acc) =
this->next_filter::trans(src, dst, cond, acc);
if (keep)
{
unsigned ss = this->si->scc_of(src);
if (this->si->is_accepting_scc(ss))
acc = acc_m;
else
acc = rej_m;
}
return filtered_trans(keep, cond, acc);
}
void fix_acceptance(const twa_graph_ptr& out)
{
if (buchi)
out->set_buchi();
else
out->copy_acceptance_of(this->si->get_aut());
}
};
// Remove acceptance conditions from all edges outside of
// non-accepting SCCs. If "RemoveAll" is false, keep those on
// transitions entering accepting SCCs. If "PreserveSBA", is set
@ -160,7 +207,7 @@ namespace spot
unsigned v = this->si->scc_of(dst);
// The basic rules are as follows:
//
// - If an edge is between two SCCs, is OK to remove
// - If an edge is between two SCCs, it is OK to remove
// all acceptance sets, as this edge cannot be part
// of any loop.
// - If an edge is in an non-accepting SCC, we can only
@ -370,6 +417,10 @@ namespace spot
scc_info* given_si)
{
twa_graph_ptr res;
// For weak automata, scc_filter() is already doing the right
// thing and preserves state-based acceptance.
if (aut->prop_inherently_weak())
return scc_filter(aut, remove_all_useless, given_si);
if (remove_all_useless)
res = scc_filter_apply<state_filter
<acc_filter_mask<true, true>>>(aut, given_si);
@ -385,9 +436,18 @@ namespace spot
scc_info* given_si)
{
twa_graph_ptr res;
// acc_filter_simplify only works for generalized Büchi
if (aut->acc().is_generalized_buchi())
if (aut->prop_inherently_weak())
{
if (aut->acc().is_t() || aut->acc().is_co_buchi())
res =
scc_filter_apply<state_filter<weak_filter<false>>>(aut, given_si);
else
res =
scc_filter_apply<state_filter<weak_filter<true>>>(aut, given_si);
}
else if (aut->acc().is_generalized_buchi())
{
// acc_filter_simplify only works for generalized Büchi
if (remove_all_useless)
res =
scc_filter_apply<state_filter
@ -421,6 +481,11 @@ namespace spot
false,
true,
});
if (aut->prop_inherently_weak())
{
res->prop_weak(true);
res->prop_state_acc(true);
}
return res;
}

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2009, 2010, 2012, 2013, 2014, 2015 Laboratoire de
// Copyright (C) 2009, 2010, 2012, 2013, 2014, 2015, 2018 Laboratoire de
// Recherche et Developpement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -50,13 +50,18 @@ namespace spot
/// degeneralization) will work better if transitions going to an
/// accepting SCC are accepting.
///
/// If the input is inherently weak, the output will be a weak
/// automaton with state-based acceptance. The acceptance condition
/// is set to Büchi unless the input was co-Büchi or t (in which
/// case we keep this acceptance).
///
/// If \a given_sm is supplied, the function will use its result
/// without computing a map of its own.
///
/// \warning Calling scc_filter on a TωA that has the SBA property
/// (i.e., transitions leaving accepting states are all marked as
/// accepting) may destroy this property. Use scc_filter_states()
/// instead.
/// \warning Calling scc_filter on a TωA that is not inherently weak
/// and has the SBA property (i.e., transitions leaving accepting
/// states are all marked as accepting) may destroy this property.
/// Use scc_filter_states() instead.
SPOT_API twa_graph_ptr
scc_filter(const const_twa_graph_ptr& aut, bool remove_all_useless = false,
scc_info* given_si = nullptr);