* src/tgba/succiterconcrete.cc (tgba_succ_iterator_concrete::next):

Rewrite using bdd_satoneset.  This time it's for real.  (I hope.)
* src/tgba/succiterconcrete.hh (current_base_,
current_base_left_): Delete.
* tgba/tgbabddcoredata.hh (next_set): New variable.
* tgba/tgbabddcoredata.cc, tgba/tgbabddtranslatefactory.cc: Adjust
to update next_set.
This commit is contained in:
Alexandre Duret-Lutz 2003-06-25 19:06:02 +00:00
parent 60bd2d17c9
commit 832a504d8d
6 changed files with 51 additions and 82 deletions

View file

@ -1,5 +1,13 @@
2003-06-25 Alexandre Duret-Lutz <aduret@src.lip6.fr> 2003-06-25 Alexandre Duret-Lutz <aduret@src.lip6.fr>
* src/tgba/succiterconcrete.cc (tgba_succ_iterator_concrete::next):
Rewrite using bdd_satoneset. This time it's for real. (I hope.)
* src/tgba/succiterconcrete.hh (current_base_,
current_base_left_): Delete.
* tgba/tgbabddcoredata.hh (next_set): New variable.
* tgba/tgbabddcoredata.cc, tgba/tgbabddtranslatefactory.cc: Adjust
to update next_set.
* src/tgba/bddprint.hh, src/tgba/tgbabddconcretefactory.hh, * src/tgba/bddprint.hh, src/tgba/tgbabddconcretefactory.hh,
src/tgba/tgbaproduct.hh: Fix Doxygen comments. src/tgba/tgbaproduct.hh: Fix Doxygen comments.

View file

@ -8,9 +8,7 @@ namespace spot
: data_(d), : data_(d),
succ_set_(successors), succ_set_(successors),
succ_set_left_(successors), succ_set_left_(successors),
current_(bddfalse), current_(bddfalse)
current_base_(bddfalse),
current_base_left_(bddfalse)
{ {
} }
@ -49,41 +47,6 @@ namespace spot
// d * !Next[a] * Next[b] // d * !Next[a] * Next[b]
// (We don't really care about the Now variables here.) // (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 // Note: on this example we would not exactly get the six transitions
// mentionned, but maybe something like // mentionned, but maybe something like
// c * Next[a] * Next[b] // c * Next[a] * Next[b]
@ -92,43 +55,27 @@ namespace spot
// d * !c * Next[a] * Next[b] // d * !c * Next[a] * Next[b]
// d * !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. // depending on the BDD order. It doesn't really matter. The important
// point is that we don't list all four possible 'c' and 'd' combinations.
// 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 // FIXME: Iterating on the successors this way (calling
// bdd_satone/bdd_fullsetone and NANDing out the result from a // bdd_satone/bdd_fullsetone and NANDing out the result from a
// set) requires several descent of the BDD. Maybe it would be // set) requires several descent of the BDD. Maybe it would be
// faster to compute all satisfying formula in one operation. // faster to compute all satisfying formula in one operation.
do do
{ {
if (current_ == bddfalse) succ_set_left_ &= !current_;
{ if (succ_set_left_ == bddfalse) // No more successors?
succ_set_left_ &= !current_base_; return;
if (succ_set_left_ == bddfalse) // No more successors? current_ = bdd_satoneset(succ_set_left_, data_.next_set, bddfalse);
return;
// (1) (2) // The destination state, computed here, should be
current_base_ = bdd_exist(bdd_satone(succ_set_left_), // compatible with the transition relation. Otherwise
data_.notvar_set); // it won't have any successor (a dead node).
current_base_left_ = current_base_; current_state_ = bdd_replace(bdd_exist(current_, data_.notnext_set),
} data_.next_to_now);
// (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 while ((current_state_ & data_.relation) == bddfalse);
// 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 bool

View file

@ -17,8 +17,8 @@ namespace spot
/// conditions and accepting conditions, represented as a BDD. /// conditions and accepting conditions, represented as a BDD.
/// The job of this iterator will be to enumerate the /// The job of this iterator will be to enumerate the
/// satisfactions of that BDD and split them into destination /// satisfactions of that BDD and split them into destination
/// states and conditions, and compute accepting conditions. /// states and conditions, and compute accepting conditions.
/// \param d The core data of the automata. /// \param d The core data of the automata.
/// These contains sets of variables useful to split a BDD, and /// These contains sets of variables useful to split a BDD, and
/// compute accepting conditions. /// compute accepting conditions.
tgba_succ_iterator_concrete(const tgba_bdd_core_data& d, bdd successors); tgba_succ_iterator_concrete(const tgba_bdd_core_data& d, bdd successors);
@ -42,10 +42,6 @@ namespace spot
/// atomic proposition and Next variables. /// atomic proposition and Next variables.
bdd current_state_; ///< Current successor, as a bdd current_state_; ///< Current successor, as a
/// conjunction of Now variables. /// conjunction of Now variables.
bdd current_base_; ///< Current successor base.
bdd current_base_left_; ///< Used to lists all possible full satisfaction
/// current_base_ which haven't been explored.
}; };
} }

View file

@ -3,20 +3,33 @@
namespace spot namespace spot
{ {
tgba_bdd_core_data::tgba_bdd_core_data() tgba_bdd_core_data::tgba_bdd_core_data()
: relation(bddtrue), accepting_conditions(bddfalse), : relation(bddtrue),
now_set(bddtrue), negnow_set(bddtrue), accepting_conditions(bddfalse),
notnow_set(bddtrue), notnext_set(bddtrue), var_set(bddtrue), now_set(bddtrue),
notvar_set(bddtrue), notacc_set(bddtrue), negacc_set(bddtrue), next_set(bddtrue),
negnow_set(bddtrue),
notnow_set(bddtrue),
notnext_set(bddtrue),
var_set(bddtrue),
notvar_set(bddtrue),
notacc_set(bddtrue),
negacc_set(bddtrue),
next_to_now(bdd_newpair()) next_to_now(bdd_newpair())
{ {
} }
tgba_bdd_core_data::tgba_bdd_core_data(const tgba_bdd_core_data& copy) tgba_bdd_core_data::tgba_bdd_core_data(const tgba_bdd_core_data& copy)
: relation(copy.relation), accepting_conditions(copy.accepting_conditions), : relation(copy.relation),
now_set(copy.now_set), negnow_set(copy.negnow_set), accepting_conditions(copy.accepting_conditions),
notnow_set(copy.notnow_set), notnext_set(copy.notnext_set), now_set(copy.now_set),
var_set(copy.var_set), notvar_set(copy.notvar_set), next_set(copy.next_set),
notacc_set(copy.notacc_set), negacc_set(copy.negacc_set), negnow_set(copy.negnow_set),
notnow_set(copy.notnow_set),
notnext_set(copy.notnext_set),
var_set(copy.var_set),
notvar_set(copy.notvar_set),
notacc_set(copy.notacc_set),
negacc_set(copy.negacc_set),
next_to_now(bdd_copypair(copy.next_to_now)) next_to_now(bdd_copypair(copy.next_to_now))
{ {
} }
@ -28,6 +41,7 @@ namespace spot
accepting_conditions(left.accepting_conditions accepting_conditions(left.accepting_conditions
| right.accepting_conditions), | right.accepting_conditions),
now_set(left.now_set & right.now_set), now_set(left.now_set & right.now_set),
next_set(left.next_set & right.next_set),
negnow_set(left.negnow_set & right.negnow_set), negnow_set(left.negnow_set & right.negnow_set),
notnow_set(left.notnow_set & right.notnow_set), notnow_set(left.notnow_set & right.notnow_set),
notnext_set(left.notnext_set & right.notnext_set), notnext_set(left.notnext_set & right.notnext_set),
@ -59,6 +73,7 @@ namespace spot
tgba_bdd_core_data::declare_now_next(bdd now, bdd next) tgba_bdd_core_data::declare_now_next(bdd now, bdd next)
{ {
now_set &= now; now_set &= now;
next_set &= next;
negnow_set &= !now; negnow_set &= !now;
notnext_set &= now; notnext_set &= now;
notnow_set &= next; notnow_set &= next;

View file

@ -62,6 +62,8 @@ namespace spot
/// The conjunction of all Now variables, in their positive form. /// The conjunction of all Now variables, in their positive form.
bdd now_set; bdd now_set;
/// The conjunction of all Next variables, in their positive form.
bdd next_set;
/// The conjunction of all Now variables, in their negated form. /// The conjunction of all Now variables, in their negated form.
bdd negnow_set; bdd negnow_set;
/// \brief The (positive) conjunction of all variables which are /// \brief The (positive) conjunction of all variables which are

View file

@ -15,6 +15,7 @@ namespace spot
data_.relation = bdd_replace(in.relation, rewrite); data_.relation = bdd_replace(in.relation, rewrite);
data_.accepting_conditions = bdd_replace(in.accepting_conditions, rewrite); data_.accepting_conditions = bdd_replace(in.accepting_conditions, rewrite);
data_.now_set = bdd_replace(in.now_set, rewrite); data_.now_set = bdd_replace(in.now_set, rewrite);
data_.next_set = bdd_replace(in.next_set, rewrite);
data_.negnow_set = bdd_replace(in.negnow_set, rewrite); data_.negnow_set = bdd_replace(in.negnow_set, rewrite);
data_.notnow_set = bdd_replace(in.notnow_set, rewrite); data_.notnow_set = bdd_replace(in.notnow_set, rewrite);
data_.notnext_set = bdd_replace(in.notnext_set, rewrite); data_.notnext_set = bdd_replace(in.notnext_set, rewrite);