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

@ -1,6 +1,45 @@
2003-07-17 Alexandre Duret-Lutz <aduret@src.lip6.fr> 2003-07-17 Alexandre Duret-Lutz <aduret@src.lip6.fr>
* iface/gspn/gspn.cc (EVENT_TRUE): Override temporarily.. 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.
* iface/gspn/gspn.cc (EVENT_TRUE): Override temporarily.
(tgba_gspn::succ_iter): Fix usage of cube. (tgba_gspn::succ_iter): Fix usage of cube.
2003-07-16 Alexandre Duret-Lutz <aduret@src.lip6.fr> 2003-07-16 Alexandre Duret-Lutz <aduret@src.lip6.fr>

View file

@ -1,26 +1,25 @@
#include "gspn.hh" #include "gspn.hh"
#include "tgbaalgos/dotty.hh" #include "tgbaalgos/dotty.hh"
int int
main(int argc, char **argv) main(int argc, char **argv)
try try
{ {
spot::gspn_interface gspn(argc, argv); spot::gspn_interface gspn(argc, argv);
spot::gspn_environment env; spot::gspn_environment env;
env.declare("obs"); env.declare("obs");
spot::bdd_dict* dict = new spot::bdd_dict(); spot::bdd_dict* dict = new spot::bdd_dict();
spot::tgba_gspn a(dict, env); spot::tgba_gspn a(dict, env);
spot::dotty_reachable(std::cout, &a); spot::dotty_reachable(std::cout, &a);
delete dict; delete dict;
} }
catch (spot::gspn_exeption e) catch (spot::gspn_exeption e)
{ {
std::cerr << e << std::endl; std::cerr << e << std::endl;
throw; throw;
} }

View file

@ -5,7 +5,7 @@
#include "gspn.hh" #include "gspn.hh"
#include "ltlvisit/destroy.hh" #include "ltlvisit/destroy.hh"
// FIXME: Override signed definition of EVENT_TRUE until this is fixed // FIXME: Override signed definition of EVENT_TRUE until this is fixed
// in gspnlib.h. // in gspnlib.h.
#undef EVENT_TRUE #undef EVENT_TRUE
#define EVENT_TRUE 0U #define EVENT_TRUE 0U
@ -28,74 +28,6 @@ namespace spot
} }
// tgba_gspn_private_
//////////////////////////////////////////////////////////////////////
struct tgba_gspn_private_
{
int refs; // reference count
bdd_dict* dict;
typedef std::pair<AtomicPropKind, bdd> ab_pair;
typedef std::map<AtomicProp, ab_pair> prop_map;
prop_map prop_dict;
AtomicProp *all_indexes;
size_t index_count;
tgba_gspn_private_(bdd_dict* dict, const gspn_environment& env)
: refs(0), dict(dict)
{
const gspn_environment::prop_map& p = env.get_prop_map();
try
{
for (gspn_environment::prop_map::const_iterator i = p.begin();
i != p.end(); ++i)
{
int var = dict->register_proposition(i->second, this);
AtomicProp index;
int err = prop_index(i->first.c_str(), &index);
if (err)
throw gspn_exeption("prop_index()", err);
AtomicPropKind kind;
err = prop_kind(index, &kind);
if (err)
throw gspn_exeption("prop_kind()", err);
prop_dict[index] = ab_pair(kind, bdd_ithvar(var));
}
index_count = prop_dict.size();
all_indexes = new AtomicProp[index_count];
unsigned idx = 0;
for (prop_map::const_iterator i = prop_dict.begin();
i != prop_dict.end(); ++i)
all_indexes[idx++] = i->first;
}
catch (...)
{
// If an exception occurs during the loop, we need to clean
// all BDD variables which have been registered so far.
dict->unregister_all_my_variables(this);
}
}
tgba_gspn_private_::~tgba_gspn_private_()
{
dict->unregister_all_my_variables(this);
}
bdd index_to_bdd(AtomicProp index) const
{
if (index == EVENT_TRUE)
return bddtrue;
prop_map::const_iterator i = prop_dict.find(index);
assert(i != prop_dict.end());
return i->second.second;
}
};
// state_gspn // state_gspn
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -137,6 +69,110 @@ namespace spot
}; // state_gspn }; // state_gspn
// tgba_gspn_private_
//////////////////////////////////////////////////////////////////////
struct tgba_gspn_private_
{
int refs; // reference count
bdd_dict* dict;
typedef std::pair<AtomicPropKind, bdd> ab_pair;
typedef std::map<AtomicProp, ab_pair> prop_map;
prop_map prop_dict;
AtomicProp *all_indexes;
size_t index_count;
const state_gspn* last_state_conds_input;
bdd last_state_conds_output;
tgba_gspn_private_(bdd_dict* dict, const gspn_environment& env)
: refs(0), dict(dict), last_state_conds_input(0)
{
const gspn_environment::prop_map& p = env.get_prop_map();
try
{
for (gspn_environment::prop_map::const_iterator i = p.begin();
i != p.end(); ++i)
{
int var = dict->register_proposition(i->second, this);
AtomicProp index;
int err = prop_index(i->first.c_str(), &index);
if (err)
throw gspn_exeption("prop_index()", err);
AtomicPropKind kind;
err = prop_kind(index, &kind);
if (err)
throw gspn_exeption("prop_kind()", err);
prop_dict[index] = ab_pair(kind, bdd_ithvar(var));
}
index_count = prop_dict.size();
all_indexes = new AtomicProp[index_count];
unsigned idx = 0;
for (prop_map::const_iterator i = prop_dict.begin();
i != prop_dict.end(); ++i)
all_indexes[idx++] = i->first;
}
catch (...)
{
// If an exception occurs during the loop, we need to clean
// all BDD variables which have been registered so far.
dict->unregister_all_my_variables(this);
}
}
tgba_gspn_private_::~tgba_gspn_private_()
{
dict->unregister_all_my_variables(this);
if (last_state_conds_input)
delete last_state_conds_input;
}
bdd index_to_bdd(AtomicProp index) const
{
if (index == EVENT_TRUE)
return bddtrue;
prop_map::const_iterator i = prop_dict.find(index);
assert(i != prop_dict.end());
return i->second.second;
}
bdd state_conds(const state_gspn* s)
{
// Use cached value if possible.
if (!last_state_conds_input ||
last_state_conds_input->compare(s) != 0)
{
// Build the BDD of the conditions available on this state.
unsigned char* cube = 0;
// This is temporary. We ought to ask only what we need.
AtomicProp* want = all_indexes;
size_t count = index_count;
int res = satisfy(s->get_state(), want, &cube, count);
if (res)
throw gspn_exeption("satisfy()", res);
assert(cube);
last_state_conds_output = bddtrue;
for (size_t i = 0; i < count; ++i)
{
bdd v = index_to_bdd(want[i]);
last_state_conds_output &= cube[i] ? v : !v;
}
satisfy_free(cube);
if (last_state_conds_input)
delete last_state_conds_input;
last_state_conds_input = s->clone();
}
return last_state_conds_output;
}
};
// tgba_succ_iterator_gspn // tgba_succ_iterator_gspn
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -302,31 +338,46 @@ namespace spot
} }
tgba_succ_iterator* tgba_succ_iterator*
tgba_gspn::succ_iter(const state* state) const tgba_gspn::succ_iter(const state* state,
const state* global_state,
const tgba* global_automaton) const
{ {
const state_gspn* s = dynamic_cast<const state_gspn*>(state); const state_gspn* s = dynamic_cast<const state_gspn*>(state);
assert(s); assert(s);
(void) global_state;
// Build the BDD of the conditions available on this state. (void) global_automaton;
unsigned char* cube = 0; // FIXME: Should pass global_automaton->support_variables(state)
// This is temporary. We ought to ask only what we need. // to state_conds.
AtomicProp* want = data_->all_indexes; bdd state_conds = data_->state_conds(s);
size_t count = data_->index_count;
int res = satisfy(s->get_state(), want, &cube, count);
if (res)
throw gspn_exeption("satisfy()", res);
assert(cube);
bdd state_conds = bddtrue;
for (size_t i = 0; i < count; ++i)
{
bdd v = data_->index_to_bdd(want[i]);
state_conds &= cube[i] ? v : !v;
}
satisfy_free(cube);
return new tgba_succ_iterator_gspn(state_conds, s->get_state(), data_); return new tgba_succ_iterator_gspn(state_conds, s->get_state(), data_);
} }
bdd
tgba_gspn::compute_support_conditions(const spot::state* state) const
{
const state_gspn* s = dynamic_cast<const state_gspn*>(state);
assert(s);
return data_->state_conds(s);
}
bdd
tgba_gspn::compute_support_variables(const spot::state* state) const
{
// FIXME: At the time of writing, only tgba_gspn calls
// support_variables on the root of a product to gather the
// variables used by all other automata and let GPSN compute only
// these. Because support_variables() is recursive over the
// product treee, tgba_gspn::support_variables should not output
// all the variables known by GSPN; this would ruin the sole
// purpose of this function.
// However this works because we assume there is at most one
// tgba_gspn automata in a product (a legitimate assumption
// since the GSPN API is not re-entrant) and only this automata
// need to call support_variables (now _this_ is shady).
(void) state;
return bddtrue;
}
bdd_dict* bdd_dict*
tgba_gspn::get_dict() const tgba_gspn::get_dict() const
{ {

View file

@ -90,11 +90,17 @@ namespace spot
tgba_gspn& operator=(const tgba_gspn& other); tgba_gspn& operator=(const tgba_gspn& other);
virtual ~tgba_gspn(); virtual ~tgba_gspn();
virtual state* get_init_state() const; virtual state* get_init_state() const;
virtual tgba_succ_iterator* succ_iter(const state* state) const; virtual tgba_succ_iterator*
succ_iter(const state* local_state,
const state* global_state = 0,
const tgba* global_automaton = 0) const;
virtual bdd_dict* get_dict() const; virtual bdd_dict* get_dict() const;
virtual std::string format_state(const state* state) const; virtual std::string format_state(const state* state) const;
virtual bdd all_accepting_conditions() const; virtual bdd all_accepting_conditions() const;
virtual bdd neg_accepting_conditions() const; 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;
private: private:
tgba_gspn_private_* data_; tgba_gspn_private_* data_;
}; };

View file

@ -26,6 +26,7 @@ libtgba_la_SOURCES = \
bddprint.cc \ bddprint.cc \
statebdd.cc \ statebdd.cc \
succiterconcrete.cc \ succiterconcrete.cc \
tgba.cc \
tgbabddconcrete.cc \ tgbabddconcrete.cc \
tgbabddconcretefactory.cc \ tgbabddconcretefactory.cc \
tgbabddconcreteproduct.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. /// a state.
class tgba class tgba
{ {
public: protected:
virtual tgba();
~tgba() virtual ~tgba();
{
}
public:
/// \brief Get the initial state of the automaton. /// \brief Get the initial state of the automaton.
/// ///
/// The state has been allocated with \c new. It is the /// The state has been allocated with \c new. It is the
@ -44,18 +43,63 @@ namespace spot
/// longer needed. /// longer needed.
virtual state* get_init_state() const = 0; 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 /// The iterator has been allocated with \c new. It is the
/// responsability of the caller to \c delete it when no /// responsability of the caller to \c delete it when no
/// longer needed. /// 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 /// This pointer is not adopted in any way by \c succ_iter, and
/// it is still the caller's responsability to delete it when /// it is still the caller's responsability to delete it when
/// appropriate (this can be done during the lifetime of /// appropriate (this can be done during the lifetime of
/// the iterator). /// 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. /// \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, /// <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 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 /// set should be augmented with the neg_accepting_conditions() of
/// the other operand. /// the other operand.
virtual bdd neg_accepting_conditions() const = 0; 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_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); const state_bdd* s = dynamic_cast<const state_bdd*>(state);
assert(s); assert(s);
bdd succ_set = data_.relation & s->as_bdd(); 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); 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 std::string
tgba_bdd_concrete::format_state(const state* state) const 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. /// \brief Construct a tgba_bdd_concrete with known initial state.
tgba_bdd_concrete(const tgba_bdd_factory& fact, bdd init); tgba_bdd_concrete(const tgba_bdd_factory& fact, bdd init);
~tgba_bdd_concrete(); virtual ~tgba_bdd_concrete();
/// \brief Set the initial state. /// \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. /// \brief Get the initial state directly as a BDD.
/// ///
@ -39,9 +39,12 @@ namespace spot
/// \endcode /// \endcode
bdd get_init_bdd() const; 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; bdd_dict* get_dict() const;
@ -56,6 +59,9 @@ namespace spot
virtual bdd neg_accepting_conditions() const; virtual bdd neg_accepting_conditions() const;
protected: 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. tgba_bdd_core_data data_; ///< Core data associated to the automaton.
bdd init_; ///< Initial state. bdd init_; ///< Initial state.
private: private:

View file

@ -206,14 +206,46 @@ namespace spot
} }
tgba_succ_iterator* 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); const state_explicit* s = dynamic_cast<const state_explicit*>(state);
assert(s); assert(s);
(void) global_state;
(void) global_automaton;
return new tgba_explicit_succ_iterator(s->get_state(), return new tgba_explicit_succ_iterator(s->get_state(),
all_accepting_conditions()); 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* bdd_dict*
tgba_explicit::get_dict() const tgba_explicit::get_dict() const
{ {

View file

@ -42,7 +42,9 @@ namespace spot
virtual ~tgba_explicit(); virtual ~tgba_explicit();
virtual spot::state* get_init_state() const; virtual spot::state* get_init_state() const;
virtual tgba_succ_iterator* 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 bdd_dict* get_dict() const;
virtual std::string format_state(const spot::state* state) const; virtual std::string format_state(const spot::state* state) const;
@ -50,6 +52,9 @@ namespace spot
virtual bdd neg_accepting_conditions() const; virtual bdd neg_accepting_conditions() const;
protected: 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); state* add_state(const std::string& name);
bdd get_condition(ltl::formula* f); bdd get_condition(ltl::formula* f);
bdd get_accepting_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_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); assert(s);
tgba_succ_iterator* li = left_->succ_iter(s->left()); // If global_automaton is not specified, THIS is the root of a
tgba_succ_iterator* ri = right_->succ_iter(s->right()); // 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, return new tgba_product_succ_iterator(li, ri,
left_->neg_accepting_conditions(), left_->neg_accepting_conditions(),
right_->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* bdd_dict*
tgba_product::get_dict() const tgba_product::get_dict() const
{ {

View file

@ -101,7 +101,9 @@ namespace spot
virtual state* get_init_state() const; virtual state* get_init_state() const;
virtual tgba_product_succ_iterator* 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; virtual bdd_dict* get_dict() const;
@ -110,6 +112,10 @@ namespace spot
virtual bdd all_accepting_conditions() const; virtual bdd all_accepting_conditions() const;
virtual bdd neg_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: private:
bdd_dict* dict_; bdd_dict* dict_;
const tgba* left_; const tgba* left_;