Commit cac85dbc authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

* src/tgba/tgbatba.hh (tgba_sba_proxy): New class, with the

functionality of the old tgba_tba_proxy.
* src/tgba/tgbatba.cc (tgba_tba_proxy_succ_iterator,
tgba_tba_proxy): Rewrite to produce TBA with at most N copies of
each state, skipping the `bddtrue' stage now used only in
tgba_sba_proxy.  Doing so removes approximately 6% of states in
the degeneralized tests of spotlbtt.test.
(tgba_sba_proxy): Implement it.
* src/tgbaalgos/neverclaim.hh, src/tgbaalgos/neverclaim.cc: Adjust
to take a tgba_sba_proxy.
* src/tgbatest/ltl2tgba.cc: Add option -DS and adjust call to
never_claim_reachable().
parent ee546210
2004-11-16 Alexandre Duret-Lutz <adl@src.lip6.fr>
* src/tgba/tgbatba.hh (tgba_sba_proxy): New class, with the
functionality of the old tgba_tba_proxy.
* src/tgba/tgbatba.cc (tgba_tba_proxy_succ_iterator,
tgba_tba_proxy): Rewrite to produce TBA with at most N copies of
each state, skipping the `bddtrue' stage now used only in
tgba_sba_proxy. Doing so removes approximately 6% of states in
the degeneralized tests of spotlbtt.test.
(tgba_sba_proxy): Implement it.
* src/tgbaalgos/neverclaim.hh, src/tgbaalgos/neverclaim.cc: Adjust
to take a tgba_sba_proxy.
* src/tgbatest/ltl2tgba.cc: Add option -DS and adjust call to
never_claim_reachable().
* src/tgba/tgbatba.cc (state_tba_proxy::hash): Use wang32_hash.
* src/tgba/tgbaproduct.cc (state_product::hash): Likewise.
......@@ -8,7 +21,7 @@
* src/evtgba/product.cc (evtgba_product_state::hash): ... here.
* src/misc/Makefile.am (misc_HEADERS): Add hashfunc.hh.
2004-11-15 Alexandre Duret-Lutz <adl@gnu.org>
2004-11-15 Alexandre Duret-Lutz <adl@src.lip6.fr>
* src/tgbatest/ltl2tgba.cc (main): For non-generalized emptiness
check, degeneralize the automaton only if it has too much
......
......@@ -112,9 +112,10 @@ namespace spot
typedef tgba_tba_proxy::cycle_list::const_iterator iterator;
public:
tgba_tba_proxy_succ_iterator(tgba_succ_iterator* it,
iterator expected, iterator end,
iterator expected,
const list& cycle,
bdd the_acceptance_cond)
: it_(it), expected_(expected), end_(end),
: it_(it), expected_(expected), cycle_(cycle),
the_acceptance_cond_(the_acceptance_cond)
{
}
......@@ -131,12 +132,14 @@ namespace spot
first()
{
it_->first();
sync_();
}
void
next()
{
it_->next();
sync_();
}
bool
......@@ -150,27 +153,7 @@ namespace spot
state_tba_proxy*
current_state() const
{
// A transition in the *EXPECTED acceptance set should be directed
// to the next acceptance set. If the current transition is also
// in the next acceptance set, then go the one after, etc.
//
// See Denis Oddoux's PhD thesis for a nice explanation (in French).
// @PhDThesis{ oddoux.03.phd,
// author = {Denis Oddoux},
// title = {Utilisation des automates alternants pour un
// model-checking efficace des logiques temporelles
// lin{\'e}aires.},
// school = {Universit{\'e}e Paris 7},
// year = {2003},
// address = {Paris, France},
// month = {December}
// }
//
iterator next = expected_;
bdd acc = it_->current_acceptance_conditions();
while ((acc & *next) == *next && next != end_)
++next;
return new state_tba_proxy(it_->current_state(), next);
return new state_tba_proxy(it_->current_state(), next_);
}
bdd
......@@ -182,13 +165,66 @@ namespace spot
bdd
current_acceptance_conditions() const
{
return the_acceptance_cond_;
return accepting_ ? the_acceptance_cond_ : bddfalse;
}
protected:
void
sync_()
{
if (done())
return;
bdd acc = it_->current_acceptance_conditions();
// bddtrue is a special condition used for tgba_sba_proxy
// to denote the (N+1)th copy of the state, after all acceptance
// conditions have been traversed. Such state is always accepting,
// so do not check acc for this.
// bddtrue is also used by tgba_tba_proxy if the automata do not
// use acceptance conditions. In that cases, all state are accepting.
if (*expected_ != bddtrue)
{
// A transition in the *EXPECTED acceptance set should be
// directed to the next acceptance set. If the current
// transition is also in the next acceptance set, then go
// the one after, etc.
//
// See Denis Oddoux's PhD thesis for a nice explanation (in French).
// @PhDThesis{ oddoux.03.phd,
// author = {Denis Oddoux},
// title = {Utilisation des automates alternants pour un
// model-checking efficace des logiques temporelles
// lin{\'e}aires.},
// school = {Universit{\'e}e Paris 7},
// year = {2003},
// address= {Paris, France},
// month = {December}
// }
next_ = expected_;
while (next_ != cycle_.end() && (acc & *next_) == *next_)
++next_;
if (next_ != cycle_.end())
{
accepting_ = false;
return;
}
}
// The transition is accepting.
accepting_ = true;
// Skip as much acceptance conditions as we can on our cycle.
next_ = cycle_.begin();
while (next_ != expected_ && (acc & *next_) == *next_)
++next_;
}
tgba_succ_iterator* it_;
const iterator expected_;
const iterator end_;
iterator next_;
bool accepting_;
const list& cycle_;
const bdd the_acceptance_cond_;
friend class tgba_tba_proxy;
};
......@@ -198,23 +234,26 @@ namespace spot
tgba_tba_proxy::tgba_tba_proxy(const tgba* a)
: a_(a)
{
bdd all = a_->all_acceptance_conditions();
// We will use one acceptance condition for this automata.
// Let's call it Acc[True].
int v = get_dict()
->register_acceptance_variable(ltl::constant::true_instance(), this);
the_acceptance_cond_ = bdd_ithvar(v);
// Now build the "cycle" of acceptance conditions.
acc_cycle_.push_front(bddtrue);
while (all != bddfalse)
if (a->number_of_acceptance_conditions() == 0)
{
acc_cycle_.push_front(bddtrue);
}
else
{
bdd next = bdd_satone(all);
all -= next;
acc_cycle_.push_front(next);
// Build a cycle of expected acceptance conditions.
bdd all = a_->all_acceptance_conditions();
while (all != bddfalse)
{
bdd next = bdd_satone(all);
all -= next;
acc_cycle_.push_front(next);
}
}
}
......@@ -241,13 +280,8 @@ namespace spot
tgba_succ_iterator* it = a_->succ_iter(s->real_state(),
global_state, global_automaton);
cycle_list::const_iterator j = s->acceptance_iterator();
cycle_list::const_iterator i = j++;
if (j == acc_cycle_.end())
return new tgba_tba_proxy_succ_iterator(it, acc_cycle_.begin(),
acc_cycle_.end(),
the_acceptance_cond_);
return new tgba_tba_proxy_succ_iterator(it, i, acc_cycle_.end(), bddfalse);
return new tgba_tba_proxy_succ_iterator(it, s->acceptance_iterator(),
acc_cycle_, the_acceptance_cond_);
}
bdd_dict*
......@@ -290,15 +324,6 @@ namespace spot
return !the_acceptance_cond_;
}
bool
tgba_tba_proxy::state_is_accepting(const state* state) const
{
const state_tba_proxy* s =
dynamic_cast<const state_tba_proxy*>(state);
assert(s);
return bddtrue == s->acceptance_cond();
}
bdd
tgba_tba_proxy::compute_support_conditions(const state* state) const
{
......@@ -326,4 +351,23 @@ namespace spot
return a_->transition_annotation(i->it_);
}
////////////////////////////////////////////////////////////////////////
// tgba_sba_proxy
tgba_sba_proxy::tgba_sba_proxy(const tgba* a)
: tgba_tba_proxy(a)
{
if (a->number_of_acceptance_conditions() > 0)
acc_cycle_.push_back(bddtrue);
}
bool
tgba_sba_proxy::state_is_accepting(const state* state) const
{
const state_tba_proxy* s =
dynamic_cast<const state_tba_proxy*>(state);
assert(s);
return bddtrue == s->acceptance_cond();
}
}
......@@ -29,13 +29,12 @@
namespace spot
{
/// \brief Degeneralize a spot::tgba on the fly.
/// \brief Degeneralize a spot::tgba on the fly, producing a TBA.
///
/// This class acts as a proxy in front of a spot::tgba, that should
/// be degeneralized on the fly.
///
/// This automaton is a spot::tgba, but it will always have exactly
/// one acceptance condition.
/// be degeneralized on the fly. The result is still a spot::tgba,
/// but it will always have exactly one acceptance condition so
/// it could be called TBA (without the G).
///
/// The degeneralization is done by synchronizing the input
/// automaton with a "counter" automaton such as the one shown in
......@@ -43,8 +42,10 @@ namespace spot
/// Couveur, FME99).
///
/// If the input automaton uses N acceptance conditions, the output
/// automaton can have at most max(N,1)+1 times more states and
/// automaton can have at most max(N,1) times more states and
/// transitions.
///
/// \see tgba_sba_proxy
class tgba_tba_proxy : public tgba
{
public:
......@@ -71,29 +72,48 @@ namespace spot
virtual bdd all_acceptance_conditions() const;
virtual bdd neg_acceptance_conditions() const;
/// \brief Whether the state is accepting.
///
/// A particularity of a spot::tgba_tba_proxy automaton is that
/// when a state has an outgoing accepting arc, all its outgoing
/// arcs are accepting. The state itself can therefore be
/// considered accepting. This is useful to many algorithms
/// working on degeneralized automata with state acceptance
/// conditions.
bool state_is_accepting(const state* state) const;
typedef std::list<bdd> cycle_list;
protected:
virtual bdd compute_support_conditions(const state* state) const;
virtual bdd compute_support_variables(const state* state) const;
cycle_list acc_cycle_;
private:
const tgba* a_;
cycle_list acc_cycle_;
bdd the_acceptance_cond_;
// Disallow copy.
tgba_tba_proxy(const tgba_tba_proxy&);
tgba_tba_proxy& tgba_tba_proxy::operator=(const tgba_tba_proxy&);
};
/// \brief Degeneralize a spot::tgba on the fly, producing an SBA.
///
/// This class acts as a proxy in front of a spot::tgba, that should
/// be degeneralized on the fly.
///
/// This is similar to tgba_tba_proxy, except that automata produced
/// with this algorithms can also been see as State-based Büchi
/// Automata (SBA). See tgba_sba_proxy::state_is_accepting(). (An
/// SBA is a TBA, and a TBA is a TGBA.)
///
/// This extra property has a small cost in size: if the input
/// automaton uses N acceptance conditions, the output automaton can
/// have at most max(N,1)+1 times more states and transitions.
/// (This is only max(N,1) for tgba_tba_proxy.)
class tgba_sba_proxy : public tgba_tba_proxy
{
public:
tgba_sba_proxy(const tgba* a);
/// \brief Whether the state is accepting.
///
/// A particularity of a spot::tgba_sba_proxy automaton is that
/// when a state has an outgoing accepting arc, all its outgoing
/// arcs are accepting. The state itself can therefore be
/// considered accepting. This is useful in algorithms working on
/// degeneralized automata with state acceptance conditions.
bool state_is_accepting(const state* state) const;
};
}
#endif // SPOT_TGBA_TGBATBA_HH
......@@ -37,7 +37,7 @@ namespace spot
class never_claim_bfs : public tgba_reachable_iterator_breadth_first
{
public:
never_claim_bfs(const tgba_tba_proxy* a, std::ostream& os,
never_claim_bfs(const tgba_sba_proxy* a, std::ostream& os,
const ltl::formula* f)
: tgba_reachable_iterator_breadth_first(a),
os_(os), f_(f), accept_all_(-1), fi_needed_(false)
......@@ -76,7 +76,7 @@ namespace spot
state_is_accepting(const state *s)
{
return
dynamic_cast<const tgba_tba_proxy*>(automata_)->state_is_accepting(s);
dynamic_cast<const tgba_sba_proxy*>(automata_)->state_is_accepting(s);
}
std::string
......@@ -184,7 +184,7 @@ namespace spot
} // anonymous
std::ostream&
never_claim_reachable(std::ostream& os, const tgba_tba_proxy* g,
never_claim_reachable(std::ostream& os, const tgba_sba_proxy* g,
const ltl::formula* f)
{
never_claim_bfs n(g, os, f);
......
......@@ -35,7 +35,7 @@ namespace spot
/// \param f The (optional) formula associated to the automaton. If given
/// it will be output as a comment.
std::ostream& never_claim_reachable(std::ostream& os,
const tgba_tba_proxy* g,
const tgba_sba_proxy* g,
const ltl::formula* f = 0);
}
......
......@@ -58,7 +58,8 @@ syntax(char* prog)
<< std::endl
<< " -A same as -a, but as a set" << std::endl
<< " -d turn on traces during parsing" << std::endl
<< " -D degeneralize the automaton" << std::endl
<< " -D degeneralize the automaton as a TBA" << std::endl
<< " -DS degeneralize the automaton as an SBA" << std::endl
<< " -e[ALGO] emptiness-check, expect and compute an "
<< "accepting run" << std::endl
<< " -E[ALGO] emptiness-check, expect no accepting run"
......@@ -134,7 +135,7 @@ main(int argc, char** argv)
int exit_code = 0;
bool debug_opt = false;
bool degeneralize_opt = false;
enum { NoDegen, DegenTBA, DegenSBA } degeneralize_opt = NoDegen;
bool degeneralize_maybe = false;
bool fm_opt = false;
bool fm_exprop_opt = false;
......@@ -182,7 +183,11 @@ main(int argc, char** argv)
}
else if (!strcmp(argv[formula_index], "-D"))
{
degeneralize_opt = true;
degeneralize_opt = DegenTBA;
}
else if (!strcmp(argv[formula_index], "-DS"))
{
degeneralize_opt = DegenSBA;
}
else if (!strncmp(argv[formula_index], "-e", 2))
{
......@@ -231,7 +236,7 @@ main(int argc, char** argv)
}
else if (!strcmp(argv[formula_index], "-N"))
{
degeneralize_opt = true;
degeneralize_opt = DegenSBA;
output = 8;
}
else if (!strcmp(argv[formula_index], "-p"))
......@@ -494,10 +499,14 @@ main(int argc, char** argv)
spot::tgba_tba_proxy* degeneralized = 0;
if (degeneralize_maybe && a->number_of_acceptance_conditions() > 1)
degeneralize_opt = true;
if (degeneralize_opt)
if (degeneralize_maybe
&& degeneralize_opt == NoDegen
&& a->number_of_acceptance_conditions() > 1)
degeneralize_opt = DegenTBA;
if (degeneralize_opt == DegenTBA)
a = degeneralized = new spot::tgba_tba_proxy(a);
else if (degeneralize_opt == DegenSBA)
a = degeneralized = new spot::tgba_sba_proxy(a);
spot::tgba_reduc* aut_red = 0;
if (reduc_aut != spot::Reduce_None)
......@@ -602,8 +611,13 @@ main(int argc, char** argv)
spot::lbtt_reachable(std::cout, a);
break;
case 8:
spot::never_claim_reachable(std::cout, degeneralized, f);
break;
{
assert(degeneralize_opt == DegenSBA);
const spot::tgba_sba_proxy* s =
static_cast<const spot::tgba_sba_proxy*>(degeneralized);
spot::never_claim_reachable(std::cout, s, f);
break;
}
default:
assert(!"unknown output option");
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment