Rewrite tgba_succ_iterator_concrete::next for the fourth time

(or is it the fifth?).

* src/tgba/succiterconcrete.hh
(tgba_succ_iterator_concrete::trans_dest_,
tgba_succ_iterator_concrete::trans_set_,
tgba_succ_iterator_concrete::trans_set_left_,
tgba_succ_iterator_concrete::neg_trans_set_): New attributes.
* src/tgba/succiterconcrete.cc
(tgba_succ_iterator_concrete::tgba_succ_iterator_concrete): Initialize
new members.
(tgba_succ_iterator_concrete::first): Likewise.
(tgba_succ_iterator_concrete::next): Rewrite.
* tgba/tgbabddcoredata.hh (tgba_bdd_core_data::acc_set): New attribute.
* tgba/tgbabddcoredata.cc, tgba/tgbabddtranslatefactory.cc:
Handle acc_set.
This commit is contained in:
Alexandre Duret-Lutz 2003-07-02 13:19:19 +00:00
parent 42680e82bf
commit dfe74f3134
6 changed files with 147 additions and 41 deletions

View file

@ -1,3 +1,22 @@
2003-07-02 Alexandre Duret-Lutz <aduret@src.lip6.fr>
Rewrite tgba_succ_iterator_concrete::next for the fourth time
(or is it the fifth?).
* src/tgba/succiterconcrete.hh
(tgba_succ_iterator_concrete::trans_dest_,
tgba_succ_iterator_concrete::trans_set_,
tgba_succ_iterator_concrete::trans_set_left_,
tgba_succ_iterator_concrete::neg_trans_set_): New attributes.
* src/tgba/succiterconcrete.cc
(tgba_succ_iterator_concrete::tgba_succ_iterator_concrete): Initialize
new members.
(tgba_succ_iterator_concrete::first): Likewise.
(tgba_succ_iterator_concrete::next): Rewrite.
* tgba/tgbabddcoredata.hh (tgba_bdd_core_data::acc_set): New attribute.
* tgba/tgbabddcoredata.cc, tgba/tgbabddtranslatefactory.cc:
Handle acc_set.
2003-07-01 Alexandre Duret-Lutz <aduret@src.lip6.fr> 2003-07-01 Alexandre Duret-Lutz <aduret@src.lip6.fr>
* src/tgba/tgbabddtranslatefactory.cc * src/tgba/tgbabddtranslatefactory.cc

View file

@ -8,6 +8,9 @@ namespace spot
: data_(d), : data_(d),
succ_set_(successors), succ_set_(successors),
succ_set_left_(successors), succ_set_left_(successors),
trans_dest_(bddfalse),
trans_set_(bddfalse),
trans_set_left_(bddfalse),
current_(bddfalse) current_(bddfalse)
{ {
} }
@ -20,7 +23,9 @@ namespace spot
tgba_succ_iterator_concrete::first() tgba_succ_iterator_concrete::first()
{ {
succ_set_left_ = succ_set_; succ_set_left_ = succ_set_;
current_ = bddfalse; trans_dest_ = bddfalse;
trans_set_ = bddfalse;
trans_set_left_ = bddfalse;
if (!done()) if (!done())
next(); next();
} }
@ -36,44 +41,113 @@ namespace spot
// important constraint is that all Next variables must appear in // important constraint is that all Next variables must appear in
// the satisfaction. // the satisfaction.
// //
// For instance if succ_set_ was // The full satisfactions of succ_set_ maybe something
// Now[a] * !Now[b] * (c + d) * (Next[a] + Next[b]) // like this (ignoring Now variables):
// we'd like to enumerate the following six transitions // a & b & Next[a] & Next[b]
// c * Next[a] * Next[b] // !a & b & Next[a] & Next[b]
// c * Next[a] * !Next[b] // a & !b & Next[a] & Next[b]
// c * !Next[a] * Next[b] // a & b & Next[a] & !Next[b]
// d * Next[a] * Next[b] // This denotes four transitions, three of which going to
// d * Next[a] * !Next[b] // the same node. Obviously (a&b | !a&b | a&!b)
// d * !Next[a] * Next[b] // == (a | b), so it's tempting to replace these three
// (We don't really care about the Now variables here.) // transitions by the following two:
// // a & Next[a] & Next[b]
// Note: on this example it's ok to get something like // b & Next[a] & Next[b]
// c * Next[a] * Next[b] // Is this always correct? No! It depends on the
// c * Next[a] * !Next[b] // accepting conditions associated to each transition.
// c * !Next[a] * Next[b] // We cannot merge transitions which have different
// d * !c * Next[a] * Next[b] // accepting conditions.
// d * !c * Next[a] * !Next[b] // Let's label transitions with hypothetic accepting sets:
// d * !c * !Next[a] * Next[b] // a & b & Next[a] & Next[b] ; Acc[1]
// depending on the BDD order. It doesn't really matter. The important // !a & b & Next[a] & Next[b] ; Acc[2]
// point is that we don't want to list all four possible 'c' and 'd' // a & !b & Next[a] & Next[b] ; Acc[2]
// combinations. // a & b & Next[a] & !Next[b] ; Acc[1]
// FIXME: This is not what we do now: we list all possible combinations // Now it's pretty clear only the first two transitions
// of atomic propositions. // may be merged:
// b & Next[a] & Next[b] ; Acc[1]
// a & !b & Next[a] & Next[b] ; Acc[2]
// a & b & Next[a] & !Next[b] ; Acc[1]
// 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 do
{ {
succ_set_left_ &= !current_; // We performs a two-level iteration on transitions.
//
// succ_set_ and succ_set_left_ hold the information about the
// outer loop: the set of all transitiong going off this
// state.
//
// From this (outer) set, we compute subsets of transitions
// going to the same state and sharing the same accepting
// conditions. These are held by the trans_set_ and
// trans_set_left_ variables.
//
// We iterate of trans_set_ until all its transitions
// have been seen (trans_set_left_ is then empty). Then
// we remove trans_set_ from succ_set_left_ and compute another
// subset of succ_set_left_ to iterate over.
// FIXME: Iterating on the successors this way (calling
// bdd_satone{,set} 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.
if (trans_set_left_ == bddfalse)
{
succ_set_left_ &= !(trans_set_ & trans_dest_);
if (succ_set_left_ == bddfalse) // No more successors? if (succ_set_left_ == bddfalse) // No more successors?
return; return;
current_ = bdd_satoneset(succ_set_left_,
data_.varandnext_set, bddfalse); // Pick one transition, and extract its destination.
// The destination state, computed here, should be bdd trans = bdd_satoneset(succ_set_left_, data_.next_set,
// compatible with the transition relation. Otherwise bddfalse);
// it won't have any successor (a dead node). trans_dest_ = bdd_exist(trans, data_.notnext_set);
// Gather all transitions going to this destination...
bdd st = succ_set_left_ & trans_dest_;
// ... and compute their accepting sets.
bdd as = data_.accepting_conditions & st;
if (as == bddfalse)
{
// AS is false when no transition from ST belongs to
// an accepting set. Iterate over ST directly.
trans_set_ = bdd_exist(st, data_.now_set & data_.next_set);
}
else
{
// Otherwise, we have accepting sets, and we should
// only work over a set of transitions sharing the
// same accepting set.
as = bdd_exist(as, data_.now_set & data_.next_set);
// as = (a | (!a)&b) & (Acc[a] | Acc[b]) + (!a & Acc[b])
bdd cube = bdd_satone(as);
// cube = (!ab & Acc[a])
bdd prop = bdd_exist(cube, data_.acc_set);
// prop = (!a)&b
bdd acc = bdd_forall(bdd_restrict(as, prop), data_.var_set);
// acc = (Acc[a] | Acc[b])
trans_set_ = bdd_restrict(as, acc);
// trans_set = (a | (!a)&b)
}
trans_set_left_ = trans_set_;
neg_trans_set_ = !trans_set_;
}
// Pick and remove one satisfaction from trans_set_left_.
bdd cube = bdd_satone(trans_set_left_);
trans_set_left_ &= !cube;
// Let this cube grow as much as possible
// (e.g., cube "(!a)&b" taken from "a | (!a)&b" can
// be simplified to "b").
cube = bdd_simplify(cube, cube | neg_trans_set_);
// Complete with the destination.
current_ = cube & trans_dest_;
// The destination state, computed here, should be compatible
// with the transition relation. Otherwise it won't have any
// successor (a dead node) and we can skip it. We need to
// compute current_state_ anyway, so this test costs us nothing.
current_state_ = bdd_replace(bdd_exist(current_, data_.notnext_set), current_state_ = bdd_replace(bdd_exist(current_, data_.notnext_set),
data_.next_to_now); data_.next_to_now);
} }

View file

@ -38,9 +38,13 @@ namespace spot
const tgba_bdd_core_data& data_; ///< Core data of the automaton. const tgba_bdd_core_data& data_; ///< Core data of the automaton.
bdd succ_set_; ///< The set of successors. bdd succ_set_; ///< The set of successors.
bdd succ_set_left_; ///< Unexplored successors (including current_). bdd succ_set_left_; ///< Unexplored successors (including current_).
bdd current_; ///< Current successor, as a conjunction of bdd trans_dest_; ///< Destination state of currently explored subset
bdd trans_set_; ///< Set of successors with the same destination.
bdd neg_trans_set_; ///< Negation of trans_set_.
bdd trans_set_left_;///< Part of trans_set_ not yet explored.
bdd current_; ///< \brief Current successor, as a conjunction of
/// atomic proposition and Next variables. /// atomic proposition and Next variables.
bdd current_state_; ///< Current successor, as a bdd current_state_; ///< \brief Current successor, as a
/// conjunction of Now variables. /// conjunction of Now variables.
}; };
} }

View file

@ -13,6 +13,7 @@ namespace spot
var_set(bddtrue), var_set(bddtrue),
notvar_set(bddtrue), notvar_set(bddtrue),
varandnext_set(bddtrue), varandnext_set(bddtrue),
acc_set(bddtrue),
notacc_set(bddtrue), notacc_set(bddtrue),
negacc_set(bddtrue), negacc_set(bddtrue),
next_to_now(bdd_newpair()) next_to_now(bdd_newpair())
@ -30,6 +31,7 @@ namespace spot
var_set(copy.var_set), var_set(copy.var_set),
notvar_set(copy.notvar_set), notvar_set(copy.notvar_set),
varandnext_set(copy.varandnext_set), varandnext_set(copy.varandnext_set),
acc_set(copy.acc_set),
notacc_set(copy.notacc_set), notacc_set(copy.notacc_set),
negacc_set(copy.negacc_set), negacc_set(copy.negacc_set),
next_to_now(bdd_copypair(copy.next_to_now)) next_to_now(bdd_copypair(copy.next_to_now))
@ -50,6 +52,7 @@ namespace spot
var_set(left.var_set & right.var_set), var_set(left.var_set & right.var_set),
notvar_set(left.notvar_set & right.notvar_set), notvar_set(left.notvar_set & right.notvar_set),
varandnext_set(left.varandnext_set & right.varandnext_set), varandnext_set(left.varandnext_set & right.varandnext_set),
acc_set(left.acc_set & right.acc_set),
notacc_set(left.notacc_set & right.notacc_set), notacc_set(left.notacc_set & right.notacc_set),
negacc_set(left.negacc_set & right.negacc_set), negacc_set(left.negacc_set & right.negacc_set),
next_to_now(bdd_mergepairs(left.next_to_now, right.next_to_now)) next_to_now(bdd_mergepairs(left.next_to_now, right.next_to_now))
@ -102,6 +105,7 @@ namespace spot
notnow_set &= acc; notnow_set &= acc;
notnext_set &= acc; notnext_set &= acc;
notvar_set &= acc; notvar_set &= acc;
acc_set &= acc;
negacc_set &= !acc; negacc_set &= !acc;
} }
} }

View file

@ -82,6 +82,9 @@ namespace spot
/// \brief The (positive) conjunction of all Next variables /// \brief The (positive) conjunction of all Next variables
/// and atomic propositions. /// and atomic propositions.
bdd varandnext_set; bdd varandnext_set;
/// \brief The (positive) conjunction of all variables which are
/// accepting conditions.
bdd acc_set;
/// \brief The (positive) conjunction of all variables which are not /// \brief The (positive) conjunction of all variables which are not
/// accepting conditions. /// accepting conditions.
bdd notacc_set; bdd notacc_set;

View file

@ -22,7 +22,9 @@ namespace spot
data_.notvar_set = bdd_replace(in.notvar_set, rewrite); data_.notvar_set = bdd_replace(in.notvar_set, rewrite);
data_.var_set = bdd_replace(in.var_set, rewrite); data_.var_set = bdd_replace(in.var_set, rewrite);
data_.varandnext_set = bdd_replace(in.varandnext_set, rewrite); data_.varandnext_set = bdd_replace(in.varandnext_set, rewrite);
data_.acc_set = bdd_replace(in.acc_set, rewrite);
data_.notacc_set = bdd_replace(in.notacc_set, rewrite); data_.notacc_set = bdd_replace(in.notacc_set, rewrite);
data_.negacc_set = bdd_replace(in.negacc_set, rewrite);
init_ = bdd_replace(from.get_init_bdd(), rewrite); init_ = bdd_replace(from.get_init_bdd(), rewrite);