* iface/gspn/gspn.cc, src/ltlvisit/basicreduce.cc,
src/ltlvisit/destroy.cc, src/ltlvisit/dotty.cc,
src/ltlvisit/dump.cc, src/ltlvisit/length.cc,
src/ltlvisit/nenoform.cc, src/ltlvisit/reduce.cc,
src/ltlvisit/syntimpl.cc, src/ltlvisit/tostring.cc,
src/tgba/formula2bdd.cc, src/tgba/tgbabddconcreteproduct.cc,
src/tgba/tgbatba.cc, src/tgbaalgos/dotty.cc,
src/tgbaalgos/dupexp.cc, src/tgbaalgos/lbtt.cc,
src/tgbaalgos/ltl2tgba_lacim.cc, src/tgbaalgos/neverclaim.cc,
src/tgbaalgos/save.cc, src/tgbaalgos/stats.cc,
src/tgbaalgos/gtec/nsheap.cc, src/tgbaalgos/gtec/nsheap.hh:
Declare private classes and helper function in anonymous namespaces.
* HACKING, src/sanity/style.test: Document and check this.
Also check for trailing { after namespace or class.
* src/ltlast/predecl.hh, src/ltlast/visitor.hh,
src/tgba/tgbareduc.hh: Fix trailing {.
This commit is contained in:
parent
5176caf4d2
commit
7d27fd3796
28 changed files with 3128 additions and 3025 deletions
|
|
@ -27,439 +27,443 @@
|
|||
namespace spot
|
||||
{
|
||||
|
||||
// state_gspn
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class state_gspn: public state
|
||||
namespace
|
||||
{
|
||||
public:
|
||||
state_gspn(State s)
|
||||
: state_(s)
|
||||
// state_gspn
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class state_gspn: public state
|
||||
{
|
||||
public:
|
||||
state_gspn(State s)
|
||||
: state_(s)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~state_gspn()
|
||||
{
|
||||
}
|
||||
|
||||
virtual int
|
||||
compare(const state* other) const
|
||||
{
|
||||
const state_gspn* o = dynamic_cast<const state_gspn*>(other);
|
||||
assert(o);
|
||||
return reinterpret_cast<char*>(o->get_state())
|
||||
- reinterpret_cast<char*>(get_state());
|
||||
}
|
||||
|
||||
virtual size_t
|
||||
hash() const
|
||||
{
|
||||
return reinterpret_cast<char*>(get_state()) - static_cast<char*>(0);
|
||||
}
|
||||
|
||||
virtual state_gspn* clone() const
|
||||
{
|
||||
return new state_gspn(get_state());
|
||||
}
|
||||
|
||||
State
|
||||
get_state() const
|
||||
{
|
||||
return state_;
|
||||
}
|
||||
|
||||
private:
|
||||
State state_;
|
||||
}; // 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;
|
||||
bdd alive_prop;
|
||||
bdd dead_prop;
|
||||
|
||||
tgba_gspn_private_(bdd_dict* dict, ltl::declarative_environment& env,
|
||||
const std::string& dead)
|
||||
: refs(1), dict(dict), all_indexes(0), last_state_conds_input(0)
|
||||
{
|
||||
const ltl::declarative_environment::prop_map& p = env.get_prop_map();
|
||||
|
||||
try
|
||||
{
|
||||
for (ltl::declarative_environment::prop_map::const_iterator i
|
||||
= p.begin(); i != p.end(); ++i)
|
||||
{
|
||||
// Skip the DEAD proposition, GreatSPN knows nothing
|
||||
// about it.
|
||||
if (i->first == dead)
|
||||
continue;
|
||||
|
||||
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(" + i->first + ")", err);
|
||||
AtomicPropKind kind;
|
||||
err = prop_kind(index, &kind);
|
||||
if (err)
|
||||
throw gspn_exeption("prop_kind(" + i->first + ")", 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);
|
||||
throw;
|
||||
}
|
||||
|
||||
// Register the "dead" proposition. There are three cases to
|
||||
// consider:
|
||||
// * If DEAD is "false", it means we are not interested in finite
|
||||
// sequences of the system.
|
||||
// * If DEAD is "true", we want to check finite sequences as well
|
||||
// as infinite sequences, but do not need to distinguish them.
|
||||
// * If DEAD is any other string, this is the name a property
|
||||
// that should be true when looping on a dead state, and false
|
||||
// otherwise.
|
||||
// We handle these three cases by setting ALIVE_PROP and DEAD_PROP
|
||||
// appropriately. ALIVE_PROP is the bdd that should be ANDed
|
||||
// to all transitions leaving a live state, while DEAD_PROP should
|
||||
// be ANDed to all transitions leaving a dead state.
|
||||
if (!strcasecmp(dead.c_str(), "false"))
|
||||
{
|
||||
alive_prop = bddtrue;
|
||||
dead_prop = bddfalse;
|
||||
}
|
||||
else if (!strcasecmp(dead.c_str(), "true"))
|
||||
{
|
||||
alive_prop = bddtrue;
|
||||
dead_prop = bddtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ltl::formula* f = env.require(dead);
|
||||
assert(f);
|
||||
int var = dict->register_proposition(f, this);
|
||||
dead_prop = bdd_ithvar(var);
|
||||
alive_prop = bdd_nithvar(var);
|
||||
}
|
||||
}
|
||||
|
||||
tgba_gspn_private_::~tgba_gspn_private_()
|
||||
{
|
||||
dict->unregister_all_my_variables(this);
|
||||
if (last_state_conds_input)
|
||||
delete last_state_conds_input;
|
||||
if (all_indexes)
|
||||
delete[] all_indexes;
|
||||
}
|
||||
|
||||
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;
|
||||
// FIXME: 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
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class tgba_succ_iterator_gspn: public tgba_succ_iterator
|
||||
{
|
||||
public:
|
||||
tgba_succ_iterator_gspn(bdd state_conds, State state,
|
||||
tgba_gspn_private_* data)
|
||||
: state_conds_(state_conds),
|
||||
successors_(0),
|
||||
size_(0),
|
||||
current_(0),
|
||||
data_(data),
|
||||
from_state_(state)
|
||||
{
|
||||
int res = succ(state, &successors_, &size_);
|
||||
if (res)
|
||||
throw gspn_exeption("succ()", res);
|
||||
// GreatSPN should return successors_ == 0 and size_ == 0 when a
|
||||
// state has no successors.
|
||||
assert((size_ <= 0) ^ (successors_ != 0));
|
||||
// If we have to stutter on a dead state, we have one successor.
|
||||
if (size_ <= 0 && data_->dead_prop != bddfalse)
|
||||
size_ = 1;
|
||||
}
|
||||
|
||||
virtual
|
||||
~tgba_succ_iterator_gspn()
|
||||
{
|
||||
if (successors_)
|
||||
succ_free(successors_);
|
||||
}
|
||||
|
||||
virtual void
|
||||
first()
|
||||
{
|
||||
current_ = 0;
|
||||
}
|
||||
|
||||
virtual void
|
||||
next()
|
||||
{
|
||||
assert(!done());
|
||||
++current_;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
done() const
|
||||
{
|
||||
return current_ >= size_;
|
||||
}
|
||||
|
||||
virtual state*
|
||||
current_state() const
|
||||
{
|
||||
// If GreatSPN returned no successor, we stutter on the dead state.
|
||||
return
|
||||
new state_gspn(successors_ ? successors_[current_].s : from_state_);
|
||||
}
|
||||
|
||||
virtual bdd
|
||||
current_condition() const
|
||||
{
|
||||
if (successors_)
|
||||
{
|
||||
bdd p = data_->index_to_bdd(successors_[current_].p);
|
||||
return state_conds_ & p & data_->alive_prop;
|
||||
}
|
||||
else
|
||||
{
|
||||
return state_conds_ & data_->dead_prop;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bdd
|
||||
current_acceptance_conditions() const
|
||||
{
|
||||
// There is no acceptance conditions in GSPN systems.
|
||||
return bddfalse;
|
||||
}
|
||||
private:
|
||||
bdd state_conds_; /// All conditions known on STATE.
|
||||
EventPropSucc* successors_; /// array of successors
|
||||
size_t size_; /// size of successors_
|
||||
size_t current_; /// current position in successors_
|
||||
tgba_gspn_private_* data_;
|
||||
State from_state_;
|
||||
}; // tgba_succ_iterator_gspn
|
||||
|
||||
|
||||
// tgba_gspn
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
/// Data private to tgba_gspn.
|
||||
struct tgba_gspn_private_;
|
||||
|
||||
class tgba_gspn: public tgba
|
||||
{
|
||||
public:
|
||||
tgba_gspn(bdd_dict* dict, ltl::declarative_environment& env,
|
||||
const std::string& dead);
|
||||
tgba_gspn(const tgba_gspn& other);
|
||||
tgba_gspn& operator=(const tgba_gspn& other);
|
||||
virtual ~tgba_gspn();
|
||||
virtual state* get_init_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 std::string format_state(const state* state) const;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const spot::state* state) const;
|
||||
virtual bdd compute_support_variables(const spot::state* state) const;
|
||||
private:
|
||||
tgba_gspn_private_* data_;
|
||||
};
|
||||
|
||||
|
||||
tgba_gspn::tgba_gspn(bdd_dict* dict, ltl::declarative_environment& env,
|
||||
const std::string& dead)
|
||||
{
|
||||
data_ = new tgba_gspn_private_(dict, env, dead);
|
||||
}
|
||||
|
||||
virtual
|
||||
~state_gspn()
|
||||
tgba_gspn::tgba_gspn(const tgba_gspn& other)
|
||||
: tgba()
|
||||
{
|
||||
data_ = other.data_;
|
||||
++data_->refs;
|
||||
}
|
||||
|
||||
virtual int
|
||||
compare(const state* other) const
|
||||
tgba_gspn::~tgba_gspn()
|
||||
{
|
||||
const state_gspn* o = dynamic_cast<const state_gspn*>(other);
|
||||
assert(o);
|
||||
return reinterpret_cast<char*>(o->get_state())
|
||||
- reinterpret_cast<char*>(get_state());
|
||||
if (--data_->refs == 0)
|
||||
delete data_;
|
||||
}
|
||||
|
||||
virtual size_t
|
||||
hash() const
|
||||
tgba_gspn&
|
||||
tgba_gspn::operator=(const tgba_gspn& other)
|
||||
{
|
||||
return reinterpret_cast<char*>(get_state()) - static_cast<char*>(0);
|
||||
if (&other == this)
|
||||
return *this;
|
||||
this->~tgba_gspn();
|
||||
new (this) tgba_gspn(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual state_gspn* clone() const
|
||||
state* tgba_gspn::get_init_state() const
|
||||
{
|
||||
return new state_gspn(get_state());
|
||||
State s;
|
||||
int err = initial_state(&s);
|
||||
if (err)
|
||||
throw gspn_exeption("initial_state()", err);
|
||||
return new state_gspn(s);
|
||||
}
|
||||
|
||||
State
|
||||
get_state() const
|
||||
tgba_succ_iterator*
|
||||
tgba_gspn::succ_iter(const state* state,
|
||||
const state* global_state,
|
||||
const tgba* global_automaton) const
|
||||
{
|
||||
return state_;
|
||||
const state_gspn* s = dynamic_cast<const state_gspn*>(state);
|
||||
assert(s);
|
||||
(void) global_state;
|
||||
(void) global_automaton;
|
||||
// FIXME: Should pass global_automaton->support_variables(state)
|
||||
// to state_conds.
|
||||
bdd state_conds = data_->state_conds(s);
|
||||
return new tgba_succ_iterator_gspn(state_conds, s->get_state(), data_);
|
||||
}
|
||||
|
||||
private:
|
||||
State state_;
|
||||
}; // 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;
|
||||
bdd alive_prop;
|
||||
bdd dead_prop;
|
||||
|
||||
tgba_gspn_private_(bdd_dict* dict, ltl::declarative_environment& env,
|
||||
const std::string& dead)
|
||||
: refs(1), dict(dict), all_indexes(0), last_state_conds_input(0)
|
||||
bdd
|
||||
tgba_gspn::compute_support_conditions(const spot::state* state) const
|
||||
{
|
||||
const ltl::declarative_environment::prop_map& p = env.get_prop_map();
|
||||
|
||||
try
|
||||
{
|
||||
for (ltl::declarative_environment::prop_map::const_iterator i
|
||||
= p.begin(); i != p.end(); ++i)
|
||||
{
|
||||
// Skip the DEAD proposition, GreatSPN knows nothing
|
||||
// about it.
|
||||
if (i->first == dead)
|
||||
continue;
|
||||
|
||||
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(" + i->first + ")", err);
|
||||
AtomicPropKind kind;
|
||||
err = prop_kind(index, &kind);
|
||||
if (err)
|
||||
throw gspn_exeption("prop_kind(" + i->first + ")", 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);
|
||||
throw;
|
||||
}
|
||||
|
||||
// Register the "dead" proposition. There are three cases to
|
||||
// consider:
|
||||
// * If DEAD is "false", it means we are not interested in finite
|
||||
// sequences of the system.
|
||||
// * If DEAD is "true", we want to check finite sequences as well
|
||||
// as infinite sequences, but do not need to distinguish them.
|
||||
// * If DEAD is any other string, this is the name a property
|
||||
// that should be true when looping on a dead state, and false
|
||||
// otherwise.
|
||||
// We handle these three cases by setting ALIVE_PROP and DEAD_PROP
|
||||
// appropriately. ALIVE_PROP is the bdd that should be ANDed
|
||||
// to all transitions leaving a live state, while DEAD_PROP should
|
||||
// be ANDed to all transitions leaving a dead state.
|
||||
if (!strcasecmp(dead.c_str(), "false"))
|
||||
{
|
||||
alive_prop = bddtrue;
|
||||
dead_prop = bddfalse;
|
||||
}
|
||||
else if (!strcasecmp(dead.c_str(), "true"))
|
||||
{
|
||||
alive_prop = bddtrue;
|
||||
dead_prop = bddtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ltl::formula* f = env.require(dead);
|
||||
assert(f);
|
||||
int var = dict->register_proposition(f, this);
|
||||
dead_prop = bdd_ithvar(var);
|
||||
alive_prop = bdd_nithvar(var);
|
||||
}
|
||||
const state_gspn* s = dynamic_cast<const state_gspn*>(state);
|
||||
assert(s);
|
||||
return data_->state_conds(s);
|
||||
}
|
||||
|
||||
tgba_gspn_private_::~tgba_gspn_private_()
|
||||
bdd
|
||||
tgba_gspn::compute_support_variables(const spot::state* state) const
|
||||
{
|
||||
dict->unregister_all_my_variables(this);
|
||||
if (last_state_conds_input)
|
||||
delete last_state_conds_input;
|
||||
if (all_indexes)
|
||||
delete[] all_indexes;
|
||||
// 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 index_to_bdd(AtomicProp index) const
|
||||
bdd_dict*
|
||||
tgba_gspn::get_dict() 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;
|
||||
return data_->dict;
|
||||
}
|
||||
|
||||
bdd state_conds(const state_gspn* s)
|
||||
std::string
|
||||
tgba_gspn::format_state(const state* state) const
|
||||
{
|
||||
// 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;
|
||||
// FIXME: 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
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class tgba_succ_iterator_gspn: public tgba_succ_iterator
|
||||
{
|
||||
public:
|
||||
tgba_succ_iterator_gspn(bdd state_conds, State state,
|
||||
tgba_gspn_private_* data)
|
||||
: state_conds_(state_conds),
|
||||
successors_(0),
|
||||
size_(0),
|
||||
current_(0),
|
||||
data_(data),
|
||||
from_state_(state)
|
||||
{
|
||||
int res = succ(state, &successors_, &size_);
|
||||
if (res)
|
||||
throw gspn_exeption("succ()", res);
|
||||
// GreatSPN should return successors_ == 0 and size_ == 0 when a
|
||||
// state has no successors.
|
||||
assert((size_ <= 0) ^ (successors_ != 0));
|
||||
// If we have to stutter on a dead state, we have one successor.
|
||||
if (size_ <= 0 && data_->dead_prop != bddfalse)
|
||||
size_ = 1;
|
||||
const state_gspn* s = dynamic_cast<const state_gspn*>(state);
|
||||
assert(s);
|
||||
char* str;
|
||||
int err = print_state(s->get_state(), &str);
|
||||
if (err)
|
||||
throw gspn_exeption("print_state()", err);
|
||||
// Strip trailing \n...
|
||||
unsigned len = strlen(str);
|
||||
while (str[--len] == '\n')
|
||||
str[len] = 0;
|
||||
std::string res(str);
|
||||
free(str);
|
||||
return res;
|
||||
}
|
||||
|
||||
virtual
|
||||
~tgba_succ_iterator_gspn()
|
||||
{
|
||||
if (successors_)
|
||||
succ_free(successors_);
|
||||
}
|
||||
|
||||
virtual void
|
||||
first()
|
||||
{
|
||||
current_ = 0;
|
||||
}
|
||||
|
||||
virtual void
|
||||
next()
|
||||
{
|
||||
assert(!done());
|
||||
++current_;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
done() const
|
||||
{
|
||||
return current_ >= size_;
|
||||
}
|
||||
|
||||
virtual state*
|
||||
current_state() const
|
||||
{
|
||||
// If GreatSPN returned no successor, we stutter on the dead state.
|
||||
return
|
||||
new state_gspn(successors_ ? successors_[current_].s : from_state_);
|
||||
}
|
||||
|
||||
virtual bdd
|
||||
current_condition() const
|
||||
{
|
||||
if (successors_)
|
||||
{
|
||||
bdd p = data_->index_to_bdd(successors_[current_].p);
|
||||
return state_conds_ & p & data_->alive_prop;
|
||||
}
|
||||
else
|
||||
{
|
||||
return state_conds_ & data_->dead_prop;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bdd
|
||||
current_acceptance_conditions() const
|
||||
bdd
|
||||
tgba_gspn::all_acceptance_conditions() const
|
||||
{
|
||||
// There is no acceptance conditions in GSPN systems.
|
||||
return bddfalse;
|
||||
}
|
||||
private:
|
||||
bdd state_conds_; /// All conditions known on STATE.
|
||||
EventPropSucc* successors_; /// array of successors
|
||||
size_t size_; /// size of successors_
|
||||
size_t current_; /// current position in successors_
|
||||
tgba_gspn_private_* data_;
|
||||
State from_state_;
|
||||
}; // tgba_succ_iterator_gspn
|
||||
|
||||
bdd
|
||||
tgba_gspn::neg_acceptance_conditions() const
|
||||
{
|
||||
// There is no acceptance conditions in GSPN systems.
|
||||
return bddtrue;
|
||||
}
|
||||
|
||||
// tgba_gspn
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
/// Data private to tgba_gspn.
|
||||
struct tgba_gspn_private_;
|
||||
|
||||
class tgba_gspn: public tgba
|
||||
{
|
||||
public:
|
||||
tgba_gspn(bdd_dict* dict, ltl::declarative_environment& env,
|
||||
const std::string& dead);
|
||||
tgba_gspn(const tgba_gspn& other);
|
||||
tgba_gspn& operator=(const tgba_gspn& other);
|
||||
virtual ~tgba_gspn();
|
||||
virtual state* get_init_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 std::string format_state(const state* state) const;
|
||||
virtual bdd all_acceptance_conditions() const;
|
||||
virtual bdd neg_acceptance_conditions() const;
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const spot::state* state) const;
|
||||
virtual bdd compute_support_variables(const spot::state* state) const;
|
||||
private:
|
||||
tgba_gspn_private_* data_;
|
||||
};
|
||||
|
||||
|
||||
tgba_gspn::tgba_gspn(bdd_dict* dict, ltl::declarative_environment& env,
|
||||
const std::string& dead)
|
||||
{
|
||||
data_ = new tgba_gspn_private_(dict, env, dead);
|
||||
}
|
||||
|
||||
tgba_gspn::tgba_gspn(const tgba_gspn& other)
|
||||
: tgba()
|
||||
{
|
||||
data_ = other.data_;
|
||||
++data_->refs;
|
||||
}
|
||||
|
||||
tgba_gspn::~tgba_gspn()
|
||||
{
|
||||
if (--data_->refs == 0)
|
||||
delete data_;
|
||||
}
|
||||
|
||||
tgba_gspn&
|
||||
tgba_gspn::operator=(const tgba_gspn& other)
|
||||
{
|
||||
if (&other == this)
|
||||
return *this;
|
||||
this->~tgba_gspn();
|
||||
new (this) tgba_gspn(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
state* tgba_gspn::get_init_state() const
|
||||
{
|
||||
State s;
|
||||
int err = initial_state(&s);
|
||||
if (err)
|
||||
throw gspn_exeption("initial_state()", err);
|
||||
return new state_gspn(s);
|
||||
}
|
||||
|
||||
tgba_succ_iterator*
|
||||
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);
|
||||
assert(s);
|
||||
(void) global_state;
|
||||
(void) global_automaton;
|
||||
// FIXME: Should pass global_automaton->support_variables(state)
|
||||
// to state_conds.
|
||||
bdd state_conds = data_->state_conds(s);
|
||||
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*
|
||||
tgba_gspn::get_dict() const
|
||||
{
|
||||
return data_->dict;
|
||||
}
|
||||
|
||||
std::string
|
||||
tgba_gspn::format_state(const state* state) const
|
||||
{
|
||||
const state_gspn* s = dynamic_cast<const state_gspn*>(state);
|
||||
assert(s);
|
||||
char* str;
|
||||
int err = print_state(s->get_state(), &str);
|
||||
if (err)
|
||||
throw gspn_exeption("print_state()", err);
|
||||
// Strip trailing \n...
|
||||
unsigned len = strlen(str);
|
||||
while (str[--len] == '\n')
|
||||
str[len] = 0;
|
||||
std::string res(str);
|
||||
free(str);
|
||||
return res;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_gspn::all_acceptance_conditions() const
|
||||
{
|
||||
// There is no acceptance conditions in GSPN systems.
|
||||
return bddfalse;
|
||||
}
|
||||
|
||||
bdd
|
||||
tgba_gspn::neg_acceptance_conditions() const
|
||||
{
|
||||
// There is no acceptance conditions in GSPN systems.
|
||||
return bddtrue;
|
||||
}
|
||||
} // anonymous
|
||||
|
||||
// gspn_interface
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue