* src/tgba/succiterconcrete.hh (next_succ_set_): Rename as ...
(succ_set_left_): ... this. (current_base_, current_base_left_): New variables. * src/tgba/succiterconcrete.cc (tgba_succ_iterator_concrete::first): Reset current_. (tgba_succ_iterator_concrete::next): Rewrite. (tgba_succ_iterator_concrete::current_state): Simplify. (tgba_succ_iterator_concrete::current_accepting_conditions): Remove atomic proposition with universal quantification. * src/tgba/ltl2tgba.cc (ltl_to_tgba): Normalize the formula. * src/tgba/tgbabddconcrete.cc (tgba_bdd_concrete::set_init_state): Complete the initial state. (tgba_bdd_concrete::succ_iter): Do not remove Now variable from the BDD passed to the iterator. * tgba/tgbabddcoredata.hh (notnow_set, var_set): New variables. * tgba/tgbabddcoredata.cc, tgba/tgbabddtranslatefactory.cc: Adjust to update notnow_set and var_set.
This commit is contained in:
parent
35be07c472
commit
6d0546c317
8 changed files with 216 additions and 32 deletions
|
|
@ -5,8 +5,12 @@ namespace spot
|
|||
{
|
||||
tgba_succ_iterator_concrete::tgba_succ_iterator_concrete
|
||||
(const tgba_bdd_core_data& d, bdd successors)
|
||||
: data_(d), succ_set_(successors), next_succ_set_(successors),
|
||||
current_(bddfalse)
|
||||
: data_(d),
|
||||
succ_set_(successors),
|
||||
succ_set_left_(successors),
|
||||
current_(bddfalse),
|
||||
current_base_(bddfalse),
|
||||
current_base_left_(bddfalse)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -17,7 +21,8 @@ namespace spot
|
|||
void
|
||||
tgba_succ_iterator_concrete::first()
|
||||
{
|
||||
next_succ_set_ = succ_set_;
|
||||
succ_set_left_ = succ_set_;
|
||||
current_ = bddfalse;
|
||||
if (!done())
|
||||
next();
|
||||
}
|
||||
|
|
@ -26,28 +31,117 @@ namespace spot
|
|||
tgba_succ_iterator_concrete::next()
|
||||
{
|
||||
assert(!done());
|
||||
// succ_set_ is the set of successors we have to explore. it
|
||||
// contains Now/Next variable and atomic propositions. Each
|
||||
// satisfaction of succ_set_ represents a transition, and we want
|
||||
// to compute as little transitions as possible. However one
|
||||
// important constraint is that all Next variables must appear in
|
||||
// the satisfaction.
|
||||
//
|
||||
// For instance if succ_set_ was
|
||||
// Now[a] * !Now[b] * (c + d) * (Next[a] + Next[b])
|
||||
// we'd like to enumerate the following six transitions
|
||||
// c * Next[a] * Next[b]
|
||||
// c * Next[a] * !Next[b]
|
||||
// c * !Next[a] * Next[b]
|
||||
// d * Next[a] * Next[b]
|
||||
// d * Next[a] * !Next[b]
|
||||
// d * !Next[a] * Next[b]
|
||||
// (We don't really care about the Now variables here.)
|
||||
//
|
||||
// Calling bdd_fullsatone on succ_set_ would compute many more
|
||||
// transitions (twice as much on this example), since all
|
||||
// atomic propositions would have to appear.
|
||||
//
|
||||
// Basically, we want to use bdd_satone for atomic propositions
|
||||
// and bdd_fullsatone for Next variable. We achieve this as
|
||||
// follows
|
||||
// (1) compute a (non-full) satisfaction of succ_set_
|
||||
// e.g. Now[a] * !Now[b] * c * Next[a]
|
||||
// (2) retain only the atomic propositions (here: c), and call it
|
||||
// our current base
|
||||
// (3) compute a full satisfaction for succ_set_ & current_base_
|
||||
// Now[a] * !Now[b] * c * d * Next[a] * Next[b]
|
||||
// (4) retain only the Next variables
|
||||
// Next[a] * Next[b]
|
||||
// (5) and finally append them to the current base
|
||||
// c * Next[a] * Next[b]
|
||||
// This is the first successor.
|
||||
//
|
||||
// This algorithm would compute only one successor. In order to
|
||||
// iterate over the other ones, we have a couple of variables that
|
||||
// remember what has been explored so far and what is yet to
|
||||
// explore.
|
||||
//
|
||||
// The next time we compute a successor, we start at (3) and
|
||||
// compute the *next* full satisfaction matching current_base_. The
|
||||
// current_base_left_ serves this purpose: holding all the
|
||||
// current_base_ satisfactions that haven't yet been explored.
|
||||
//
|
||||
// Once we've explored all satisfactions of current_base_, we
|
||||
// start over at (1) and compute the *next* (non-full)
|
||||
// satisfaction of succ_set_. To that effect, the variable
|
||||
// next_succ_set hold all these satisfactions that must still be
|
||||
// explored.
|
||||
//
|
||||
// Note: on this example we would not exactly get the six transitions
|
||||
// mentionned, but maybe something like
|
||||
// c * Next[a] * Next[b]
|
||||
// c * Next[a] * !Next[b]
|
||||
// c * !Next[a] * Next[b]
|
||||
// d * !c * Next[a] * Next[b]
|
||||
// d * !c * Next[a] * !Next[b]
|
||||
// d * !c * !Next[a] * Next[b]
|
||||
// depending on the BDD order.
|
||||
|
||||
// FIXME: Iterating on the successors this way (calling bdd_satone
|
||||
// and NANDing out the result from the set) requires several descent
|
||||
// of the BDD. Maybe it would be faster to compute all satisfying
|
||||
// formula in one operation.
|
||||
next_succ_set_ &= !current_;
|
||||
current_ = bdd_satone(next_succ_set_);
|
||||
// FIXME: It would help to have this half-full half-partial
|
||||
// satisfaction operation available as one BDD function.
|
||||
// FIXME: Iterating on the successors this way (calling
|
||||
// bdd_satone/bdd_fullsetone and NANDing out the result from a
|
||||
// set) requires several descent of the BDD. Maybe it would be
|
||||
// faster to compute all satisfying formula in one operation.
|
||||
do
|
||||
{
|
||||
if (current_ == bddfalse)
|
||||
{
|
||||
succ_set_left_ &= !current_base_;
|
||||
if (succ_set_left_ == bddfalse) // No more successors?
|
||||
return;
|
||||
// (1) (2)
|
||||
current_base_ = bdd_exist(bdd_satone(succ_set_left_),
|
||||
data_.notvar_set);
|
||||
current_base_left_ = current_base_;
|
||||
}
|
||||
// (3) (4) (5)
|
||||
current_ =
|
||||
current_base_ & bdd_exist(bdd_fullsatone(succ_set_left_
|
||||
& current_base_left_),
|
||||
data_.notnext_set);
|
||||
current_base_left_ &= !current_;
|
||||
}
|
||||
while (// No more successors with the current_base_? Compute
|
||||
// the next base.
|
||||
current_ == bddfalse
|
||||
// The destination state, computed here, should be
|
||||
// compatible with the transition relation. Otherwise
|
||||
// it won't have any successor and useless.
|
||||
|| ((current_state_ = bdd_replace(bdd_exist(current_,
|
||||
data_.notnext_set),
|
||||
data_.next_to_now))
|
||||
& data_.relation) == bddfalse);
|
||||
}
|
||||
|
||||
bool
|
||||
tgba_succ_iterator_concrete::done()
|
||||
{
|
||||
return next_succ_set_ == bddfalse;
|
||||
return succ_set_left_ == bddfalse;
|
||||
}
|
||||
|
||||
state_bdd*
|
||||
tgba_succ_iterator_concrete::current_state()
|
||||
{
|
||||
assert(!done());
|
||||
|
||||
return new state_bdd(bdd_replace(bdd_exist(current_, data_.notnext_set),
|
||||
data_.next_to_now));
|
||||
return new state_bdd(current_state_);
|
||||
}
|
||||
|
||||
bdd
|
||||
|
|
@ -61,7 +155,9 @@ namespace spot
|
|||
tgba_succ_iterator_concrete::current_accepting_conditions()
|
||||
{
|
||||
assert(!done());
|
||||
return bdd_exist(bdd_restrict(data_.accepting_conditions, current_),
|
||||
return bdd_exist(bdd_forall(bdd_restrict(data_.accepting_conditions,
|
||||
current_),
|
||||
data_.var_set),
|
||||
data_.notacc_set);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue