Now succ_iter() can fetch extra information from

the root of a product to reduce its number of successors.
* src/tgba/Makefile.am (libtgba_la_SOURCES): Add tgba.cc.
* src/tgba/tgba.hh (tgba::succ_iter): Add the global_state and
global_automaton arguments.
(tgba::support_conditions, tgba::support_variables,
tgba::compute_support_conditions, tgba::compute_support_variables):
New functions.
(tgba::last_support_conditions_input_,
tgba::last_support_conditions_output_,
tgba::last_support_variables_input_,
tgba::last_support_variables_output_): New attributes.
* src/tgba/tgbabddconcrete.cc (tgba_bdd_concrete::succ_iter):
Handle the two new arguments.
(tgba_bdd_concrete::compute_support_conditions,
tgba_bdd_concrete::compute_support_variables): Implement them.
* src/tgba/tgbabddconcrete.hh: Adjust.
* src/tgba/tgbaexplicit.cc (tgba_explicit::succ_iter):	Ignore
the two new arguments.
(tgba_explicit::compute_support_conditions,
tgba_explicit::compute_support_variables): Implement them.
* src/tgba/tgbaexplicit.hh: Adjust.
* src/tgba/tgbaproduct.cc (tgba_product::succ_iter): Handle the
two new arguments.
(tgba_product::compute_support_conditions,
tgba_product::compute_support_variables): Implement them.
* src/tgba/tgbaproduct.hh: Adjust.
* iface/gspn/gspn.cc (tgba_gspn_private_::last_state_cond_input,
tgba_gspn_private_::last_state_cond_output,
(tgba_gspn_private_::tgba_gspn_private_): Set last_state_cond_input.
(tgba_gspn_private_::~tgba_gspn_private_): Delete
last_state_cond_input.
(tgba_gspn_private_::state_conds): New function, eved out
from tgba_gspn::succ_iter.
(tgba_gspn::succ_iter): Use it.  Use the two new arguments.
(tgba_gspn::compute_support_conditions,
tgba_gspn::compute_support_variables): New functions.
* iface/gspn/gspn.hh: Adjust.
This commit is contained in:
Alexandre Duret-Lutz 2003-07-17 15:11:49 +00:00
parent 4bf6c52bea
commit 1d9c3d6409
13 changed files with 435 additions and 119 deletions

View file

@ -26,6 +26,7 @@ libtgba_la_SOURCES = \
bddprint.cc \
statebdd.cc \
succiterconcrete.cc \
tgba.cc \
tgbabddconcrete.cc \
tgbabddconcretefactory.cc \
tgbabddconcreteproduct.cc \

49
src/tgba/tgba.cc Normal file
View file

@ -0,0 +1,49 @@
#include "tgba.hh"
namespace spot
{
tgba::tgba()
: last_support_conditions_input_(0),
last_support_variables_input_(0)
{
}
tgba::~tgba()
{
if (last_support_conditions_input_)
delete last_support_conditions_input_;
if (last_support_variables_input_)
delete last_support_variables_input_;
}
bdd
tgba::support_conditions(const state* state) const
{
if (! last_support_conditions_input_
|| last_support_conditions_input_->compare(state) != 0)
{
last_support_conditions_output_ =
compute_support_conditions(state);
if (last_support_conditions_input_)
delete last_support_conditions_input_;
last_support_conditions_input_ = state->clone();
}
return last_support_conditions_output_;
}
bdd
tgba::support_variables(const state* state) const
{
if (! last_support_variables_input_
|| last_support_variables_input_->compare(state) != 0)
{
last_support_variables_output_ =
compute_support_variables(state);
if (last_support_variables_input_)
delete last_support_variables_input_;
last_support_variables_input_ = state->clone();
}
return last_support_variables_output_;
}
}

View file

@ -31,12 +31,11 @@ namespace spot
/// a state.
class tgba
{
public:
virtual
~tgba()
{
}
protected:
tgba();
virtual ~tgba();
public:
/// \brief Get the initial state of the automaton.
///
/// The state has been allocated with \c new. It is the
@ -44,18 +43,63 @@ namespace spot
/// longer needed.
virtual state* get_init_state() const = 0;
/// \brief Get an iterator over the successors of \a state.
/// \brief Get an iterator over the successors of \a local_state.
///
/// The iterator has been allocated with \c new. It is the
/// responsability of the caller to \c delete it when no
/// longer needed.
///
/// \param state is the state whose successors are to be explored.
/// During synchornized products, additional informations are
/// passed about the entire product and its state. Recall that
/// products can be nested, forming a tree of spot::tgba where
/// most values are computed on demand. \a global_automaton
/// designate the root spot::tgba, and \a global_state its
/// state. This two objects can be used by succ_iter() to
/// restrict the set of successors to compute.
///
/// \param local_state The state whose successors are to be explored.
/// This pointer is not adopted in any way by \c succ_iter, and
/// it is still the caller's responsability to delete it when
/// appropriate (this can be done during the lifetime of
/// the iterator).
virtual tgba_succ_iterator* succ_iter(const state* state) const = 0;
/// \param global_state In a product, the state of the global
/// product automaton. Otherwise, 0. Like \a locale_state,
/// \a global_state is not adopted by \c succ_iter.
/// \param global_automaton In a product, the state of the global
/// product automaton. Otherwise, 0.
virtual tgba_succ_iterator*
succ_iter(const state* local_state,
const state* global_state = 0,
const tgba* global_automaton = 0) const = 0;
/// \brief Get a formula that must hold whatever successor is taken.
///
/// \return A formula which must be verified for all successors
/// of \a state.
///
/// This can be as simple as \c bddtrue, or more completely
/// the disjunction of the condition of all successors. This
/// is used as an hint by \c succ_iter() to reduce the number
/// of successor to compute in a product.
///
/// Sub classes should implement compute_support_conditions(),
/// this function is just a wrapper that will cache the
/// last return value for efficiency.
bdd support_conditions(const state* state) const;
/// \brief Get the conjunctions of variables tested by
/// the outgoing transitions of \a state.
///
/// All variables tested by outgoing transitions must be
/// returned. This is mandatory.
///
/// This is used as an hint by some \c succ_iter() to reduce the
/// number of successor to compute in a product.
///
/// Sub classes should implement compute_support_variables(),
/// this function is just a wrapper that will cache the
/// last return value for efficiency.
bdd support_variables(const state* state) const;
/// \brief Get the dictionary associated to the automaton.
///
@ -89,10 +133,21 @@ namespace spot
/// <tt>Acc[b]</tt> and <tt>Acc[c]</tt> to describe accepting sets,
/// this function should return <tt>!Acc[a]\&!Acc[b]\&!Acc[c]</tt>.
///
/// This is useful when making products: each operand conditions
/// This is useful when making products: each operand's condition
/// set should be augmented with the neg_accepting_conditions() of
/// the other operand.
virtual bdd neg_accepting_conditions() const = 0;
protected:
/// Do the actual computation of tgba::support_conditions().
virtual bdd compute_support_conditions(const state* state) const = 0;
/// Do the actual computation of tgba::support_variables().
virtual bdd compute_support_variables(const state* state) const = 0;
private:
mutable const state* last_support_conditions_input_;
mutable bdd last_support_conditions_output_;
mutable const state* last_support_variables_input_;
mutable bdd last_support_variables_output_;
};
}

View file

@ -71,14 +71,46 @@ namespace spot
}
tgba_succ_iterator_concrete*
tgba_bdd_concrete::succ_iter(const state* state) const
tgba_bdd_concrete::succ_iter(const state* state,
const state* global_state,
const tgba* global_automaton) const
{
const state_bdd* s = dynamic_cast<const state_bdd*>(state);
assert(s);
bdd succ_set = data_.relation & s->as_bdd();
// If we are in a product, inject the local conditions of
// all other automata to limit the number of successors.
if (global_automaton)
{
bdd varused = bdd_support(succ_set);
bdd global_conds = global_automaton->support_conditions(global_state);
succ_set = bdd_appexcomp(succ_set, global_conds, bddop_and, varused);
}
return new tgba_succ_iterator_concrete(data_, succ_set);
}
bdd
tgba_bdd_concrete::compute_support_conditions(const state* st) const
{
const state_bdd* s = dynamic_cast<const state_bdd*>(st);
assert(s);
return bdd_relprod(s->as_bdd(), data_.relation, data_.notvar_set);
}
bdd
tgba_bdd_concrete::compute_support_variables(const state* st) const
{
const state_bdd* s = dynamic_cast<const state_bdd*>(st);
assert(s);
bdd succ_set = data_.relation & s->as_bdd();
// bdd_support must be called BEFORE bdd_exist
// because bdd_exist(bdd_support((a&Next[f])|(!a&Next[g])),Next[*])
// is obviously not the same as bdd_support(a|!a).
// In other words: we can reuse compute_support_conditions() for
// this computation.
return bdd_exist(bdd_support(succ_set), data_.notvar_set);
}
std::string
tgba_bdd_concrete::format_state(const state* state) const
{

View file

@ -21,12 +21,12 @@ namespace spot
/// \brief Construct a tgba_bdd_concrete with known initial state.
tgba_bdd_concrete(const tgba_bdd_factory& fact, bdd init);
~tgba_bdd_concrete();
virtual ~tgba_bdd_concrete();
/// \brief Set the initial state.
void set_init_state(bdd s);
virtual void set_init_state(bdd s);
state_bdd* get_init_state() const;
virtual state_bdd* get_init_state() const;
/// \brief Get the initial state directly as a BDD.
///
@ -39,9 +39,12 @@ namespace spot
/// \endcode
bdd get_init_bdd() const;
tgba_succ_iterator_concrete* succ_iter(const state* state) const;
virtual tgba_succ_iterator_concrete*
succ_iter(const state* local_state,
const state* global_state = 0,
const tgba* global_automaton = 0) const;
std::string format_state(const state* state) const;
virtual std::string format_state(const state* state) const;
bdd_dict* get_dict() const;
@ -56,6 +59,9 @@ namespace spot
virtual bdd neg_accepting_conditions() const;
protected:
virtual bdd compute_support_conditions(const state* state) const;
virtual bdd compute_support_variables(const state* state) const;
tgba_bdd_core_data data_; ///< Core data associated to the automaton.
bdd init_; ///< Initial state.
private:

View file

@ -206,14 +206,46 @@ namespace spot
}
tgba_succ_iterator*
tgba_explicit::succ_iter(const spot::state* state) const
tgba_explicit::succ_iter(const spot::state* state,
const spot::state* global_state,
const tgba* global_automaton) const
{
const state_explicit* s = dynamic_cast<const state_explicit*>(state);
assert(s);
(void) global_state;
(void) global_automaton;
return new tgba_explicit_succ_iterator(s->get_state(),
all_accepting_conditions());
}
bdd
tgba_explicit::compute_support_conditions(const spot::state* in) const
{
const state_explicit* s = dynamic_cast<const state_explicit*>(in);
assert(s);
const state* st = s->get_state();
bdd res = bddtrue;
tgba_explicit::state::const_iterator i;
for (i = st->begin(); i != st->end(); ++i)
res |= (*i)->condition;
return res;
}
bdd
tgba_explicit::compute_support_variables(const spot::state* in) const
{
const state_explicit* s = dynamic_cast<const state_explicit*>(in);
assert(s);
const state* st = s->get_state();
bdd res = bddtrue;
tgba_explicit::state::const_iterator i;
for (i = st->begin(); i != st->end(); ++i)
res &= bdd_support((*i)->condition);
return res;
}
bdd_dict*
tgba_explicit::get_dict() const
{

View file

@ -42,7 +42,9 @@ namespace spot
virtual ~tgba_explicit();
virtual spot::state* get_init_state() const;
virtual tgba_succ_iterator*
succ_iter(const spot::state* state) const;
succ_iter(const spot::state* local_state,
const spot::state* global_state = 0,
const tgba* global_automaton = 0) const;
virtual bdd_dict* get_dict() const;
virtual std::string format_state(const spot::state* state) const;
@ -50,6 +52,9 @@ namespace spot
virtual bdd neg_accepting_conditions() const;
protected:
virtual bdd compute_support_conditions(const spot::state* state) const;
virtual bdd compute_support_variables(const spot::state* state) const;
state* add_state(const std::string& name);
bdd get_condition(ltl::formula* f);
bdd get_accepting_condition(ltl::formula* f);

View file

@ -171,18 +171,53 @@ namespace spot
}
tgba_product_succ_iterator*
tgba_product::succ_iter(const state* state) const
tgba_product::succ_iter(const state* local_state,
const state* global_state,
const tgba* global_automaton) const
{
const state_bdd_product* s = dynamic_cast<const state_bdd_product*>(state);
const state_bdd_product* s =
dynamic_cast<const state_bdd_product*>(local_state);
assert(s);
tgba_succ_iterator* li = left_->succ_iter(s->left());
tgba_succ_iterator* ri = right_->succ_iter(s->right());
// If global_automaton is not specified, THIS is the root of a
// product tree.
if (! global_automaton)
{
global_automaton = this;
global_state = local_state;
}
tgba_succ_iterator* li = left_->succ_iter(s->left(),
global_state, global_automaton);
tgba_succ_iterator* ri = right_->succ_iter(s->right(),
global_state, global_automaton);
return new tgba_product_succ_iterator(li, ri,
left_->neg_accepting_conditions(),
right_->neg_accepting_conditions());
}
bdd
tgba_product::compute_support_conditions(const state* in) const
{
const state_bdd_product* s =
dynamic_cast<const state_bdd_product*>(in);
assert(s);
bdd lsc = left_->support_conditions(s->left());
bdd rsc = right_->support_conditions(s->right());
return lsc & rsc;
}
bdd
tgba_product::compute_support_variables(const state* in) const
{
const state_bdd_product* s =
dynamic_cast<const state_bdd_product*>(in);
assert(s);
bdd lsc = left_->support_variables(s->left());
bdd rsc = right_->support_variables(s->right());
return lsc & rsc;
}
bdd_dict*
tgba_product::get_dict() const
{

View file

@ -101,7 +101,9 @@ namespace spot
virtual state* get_init_state() const;
virtual tgba_product_succ_iterator*
succ_iter(const state* state) const;
succ_iter(const state* local_state,
const state* global_state = 0,
const tgba* global_automaton = 0) const;
virtual bdd_dict* get_dict() const;
@ -110,6 +112,10 @@ namespace spot
virtual bdd all_accepting_conditions() const;
virtual bdd neg_accepting_conditions() const;
protected:
virtual bdd compute_support_conditions(const state* state) const;
virtual bdd compute_support_variables(const state* state) const;
private:
bdd_dict* dict_;
const tgba* left_;