rename src/ as spot/ and use include <spot/...>
* NEWS: Mention the change. * src/: Rename as ... * spot/: ... this, adjust all headers to include <spot/...> instead of "...", and adjust all Makefile.am to search headers from the top-level directory. * HACKING: Add conventions about #include. * spot/sanity/style.test: Add a few more grep to catch cases that do not follow these conventions. * .gitignore, Makefile.am, README, bench/stutter/Makefile.am, bench/stutter/stutter_invariance_formulas.cc, bench/stutter/stutter_invariance_randomgraph.cc, configure.ac, debian/rules, doc/Doxyfile.in, doc/Makefile.am, doc/org/.dir-locals.el.in, doc/org/g++wrap.in, doc/org/init.el.in, doc/org/tut01.org, doc/org/tut02.org, doc/org/tut03.org, doc/org/tut10.org, doc/org/tut20.org, doc/org/tut21.org, doc/org/tut22.org, doc/org/tut30.org, iface/ltsmin/Makefile.am, iface/ltsmin/kripke.test, iface/ltsmin/ltsmin.cc, iface/ltsmin/ltsmin.hh, iface/ltsmin/modelcheck.cc, wrap/python/Makefile.am, wrap/python/ajax/spotcgi.in, wrap/python/spot_impl.i, wrap/python/tests/ltl2tgba.py, wrap/python/tests/randgen.py, wrap/python/tests/run.in: Adjust.
This commit is contained in:
parent
1fddfe60ec
commit
f120dd3206
529 changed files with 1308 additions and 1262 deletions
39
spot/ta/Makefile.am
Normal file
39
spot/ta/Makefile.am
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
## -*- coding: utf-8 -*-
|
||||
## Copyright (C) 2010, 2012, 2013, 2015 Laboratoire de Recherche et
|
||||
## Développement de l'Epita (LRDE).
|
||||
##
|
||||
## This file is part of Spot, a model checking library.
|
||||
##
|
||||
## Spot is free software; you can redistribute it and/or modify it
|
||||
## under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
## License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) $(BUDDY_CPPFLAGS)
|
||||
AM_CXXFLAGS = $(WARNING_CXXFLAGS)
|
||||
|
||||
tadir = $(pkgincludedir)/ta
|
||||
|
||||
ta_HEADERS = \
|
||||
ta.hh \
|
||||
taexplicit.hh \
|
||||
taproduct.hh \
|
||||
tgta.hh \
|
||||
tgtaexplicit.hh \
|
||||
tgtaproduct.hh
|
||||
|
||||
noinst_LTLIBRARIES = libta.la
|
||||
libta_la_SOURCES = \
|
||||
ta.cc \
|
||||
taproduct.cc \
|
||||
tgtaexplicit.cc \
|
||||
taexplicit.cc \
|
||||
tgtaproduct.cc
|
||||
77
spot/ta/ta.cc
Normal file
77
spot/ta/ta.cc
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2010, 2011, 2014 Laboratoire de Recherche et
|
||||
// Developpement de l Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include <spot/ta/ta.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
|
||||
scc_stack_ta::connected_component::connected_component(int i)
|
||||
{
|
||||
index = i;
|
||||
is_accepting = false;
|
||||
condition = 0U;
|
||||
}
|
||||
|
||||
scc_stack_ta::connected_component&
|
||||
scc_stack_ta::top()
|
||||
{
|
||||
return s.front();
|
||||
}
|
||||
|
||||
const scc_stack_ta::connected_component&
|
||||
scc_stack_ta::top() const
|
||||
{
|
||||
return s.front();
|
||||
}
|
||||
|
||||
void
|
||||
scc_stack_ta::pop()
|
||||
{
|
||||
// assert(rem().empty());
|
||||
s.pop_front();
|
||||
}
|
||||
|
||||
void
|
||||
scc_stack_ta::push(int index)
|
||||
{
|
||||
s.emplace_front(index);
|
||||
}
|
||||
|
||||
std::list<const state*>&
|
||||
scc_stack_ta::rem()
|
||||
{
|
||||
return top().rem;
|
||||
}
|
||||
|
||||
size_t
|
||||
scc_stack_ta::size() const
|
||||
{
|
||||
return s.size();
|
||||
}
|
||||
|
||||
bool
|
||||
scc_stack_ta::empty() const
|
||||
{
|
||||
return s.empty();
|
||||
}
|
||||
|
||||
}
|
||||
296
spot/ta/ta.hh
Normal file
296
spot/ta/ta.hh
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2010, 2012, 2013, 2014, 2015 Laboratoire de Recherche et
|
||||
// Developpement de l Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <cassert>
|
||||
#include <spot/misc/bddlt.hh>
|
||||
#include <spot/twa/twa.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
// Forward declarations. See below.
|
||||
class ta_succ_iterator;
|
||||
|
||||
/// \defgroup ta TA (Testing Automata)
|
||||
///
|
||||
/// This type and its cousins are listed \ref ta_essentials "here".
|
||||
/// This is an abstract interface. Its implementations are \ref
|
||||
/// ta_representation "concrete representations". The
|
||||
/// algorithms that work on spot::ta are \ref tgba_algorithms
|
||||
/// "listed separately".
|
||||
|
||||
/// \addtogroup ta_essentials Essential TA types
|
||||
/// \ingroup ta
|
||||
|
||||
/// \ingroup ta_essentials
|
||||
/// \brief A Testing Automaton.
|
||||
///
|
||||
/// The Testing Automata (TA) were introduced by
|
||||
/// Henri Hansen, Wojciech Penczek and Antti Valmari
|
||||
/// in "Stuttering-insensitive automata for on-the-fly detection of livelock
|
||||
/// properties" In Proc. of FMICSÕ02, vol. 66(2) of Electronic Notes in
|
||||
/// Theoretical Computer Science.Elsevier.
|
||||
///
|
||||
/// While a TGBA automaton observes the value of the atomic propositions, the
|
||||
/// basic idea of TA is to detect the changes in these values; if a valuation
|
||||
/// does not change between two consecutive valuations of an execution,
|
||||
/// the TA stay in the same state. A TA transition \c (s,k,d) is labeled by a
|
||||
/// "changeset" \c k: i.e. the set of atomic propositions that change between
|
||||
/// states \c s and \c d, if the changeset is empty then the transition is
|
||||
/// called stuttering transition.
|
||||
/// To detect execution that ends by stuttering in the same TA state, a
|
||||
/// new kind of acceptance states is introduced: "livelock-acceptance states"
|
||||
/// (in addition to the standard Buchi-acceptance states).
|
||||
///
|
||||
/// Browsing such automaton can be achieved using two functions:
|
||||
/// \c get_initial_states_set or \c get_artificial_initial_state, and \c
|
||||
/// succ_iter. The former returns the initial state(s) while the latter lists
|
||||
/// the successor states of any state (filtred by "changeset").
|
||||
///
|
||||
/// Note that although this is a transition-based automata,
|
||||
/// we never represent transitions! Transition informations are
|
||||
/// obtained by querying the iterator over the successors of
|
||||
/// a state.
|
||||
|
||||
class SPOT_API ta
|
||||
{
|
||||
protected:
|
||||
acc_cond acc_;
|
||||
bdd_dict_ptr dict_;
|
||||
|
||||
public:
|
||||
ta(const bdd_dict_ptr& d)
|
||||
: dict_(d)
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~ta()
|
||||
{
|
||||
}
|
||||
|
||||
typedef std::set<state*, state_ptr_less_than> states_set_t;
|
||||
typedef std::set<const state*, state_ptr_less_than> const_states_set_t;
|
||||
|
||||
/// \brief Get the initial states set of the automaton.
|
||||
virtual const_states_set_t
|
||||
get_initial_states_set() const = 0;
|
||||
|
||||
/// \brief Get the artificial initial state set of the automaton.
|
||||
/// Return 0 if this artificial state is not implemented
|
||||
/// (in this case, use \c get_initial_states_set)
|
||||
/// The aim of adding this state is to have an unique initial state. This
|
||||
/// artificial initial state have one transition to each real initial state,
|
||||
/// and this transition is labeled by the corresponding initial condition.
|
||||
/// (For more details, see the paper cited above)
|
||||
virtual const spot::state*
|
||||
get_artificial_initial_state() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief Get an iterator over the successors of \a state.
|
||||
///
|
||||
/// The iterator has been allocated with \c new. It is the
|
||||
/// responsability of the caller to \c delete it when no
|
||||
/// longer needed.
|
||||
///
|
||||
virtual ta_succ_iterator*
|
||||
succ_iter(const spot::state* state) const = 0;
|
||||
|
||||
/// \brief Get an iterator over the successors of \a state
|
||||
/// filtred by the changeset on transitions
|
||||
///
|
||||
/// The iterator has been allocated with \c new. It is the
|
||||
/// responsability of the caller to \c delete it when no
|
||||
/// longer needed.
|
||||
///
|
||||
virtual ta_succ_iterator*
|
||||
succ_iter(const spot::state* state, bdd changeset) const = 0;
|
||||
|
||||
/// \brief Get the dictionary associated to the automaton.
|
||||
///
|
||||
/// State are represented as BDDs. The dictionary allows
|
||||
/// to map BDD variables back to formulae, and vice versa.
|
||||
/// This is useful when dealing with several automata (which
|
||||
/// may use the same BDD variable for different formula),
|
||||
/// or simply when printing.
|
||||
bdd_dict_ptr
|
||||
get_dict() const
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
/// \brief Format the state as a string for printing.
|
||||
///
|
||||
/// This formating is the responsability of the automata
|
||||
/// that owns the state.
|
||||
virtual std::string
|
||||
format_state(const spot::state* s) const = 0;
|
||||
|
||||
/// \brief Return true if \a s is a Buchi-accepting state, otherwise false
|
||||
virtual bool
|
||||
is_accepting_state(const spot::state* s) const = 0;
|
||||
|
||||
/// \brief Return true if \a s is a livelock-accepting state
|
||||
/// , otherwise false
|
||||
virtual bool
|
||||
is_livelock_accepting_state(const spot::state* s) const = 0;
|
||||
|
||||
/// \brief Return true if \a s is an initial state, otherwise false
|
||||
virtual bool
|
||||
is_initial_state(const spot::state* s) const = 0;
|
||||
|
||||
/// \brief Return a BDD condition that represents the valuation
|
||||
/// of atomic propositions in the state \a s
|
||||
virtual bdd
|
||||
get_state_condition(const spot::state* s) const = 0;
|
||||
|
||||
/// \brief Release a state \a s
|
||||
virtual void
|
||||
free_state(const spot::state* s) const = 0;
|
||||
|
||||
|
||||
const acc_cond& acc() const
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
acc_cond& acc()
|
||||
{
|
||||
return acc_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<ta> ta_ptr;
|
||||
typedef std::shared_ptr<const ta> const_ta_ptr;
|
||||
|
||||
/// \ingroup ta_essentials
|
||||
/// \brief Iterate over the successors of a state.
|
||||
///
|
||||
/// This class provides the basic functionalities required to
|
||||
/// iterate over the successors of a state, as well as querying
|
||||
/// transition labels. Because transitions are never explicitely
|
||||
/// encoded, labels (conditions and acceptance conditions) can only
|
||||
/// be queried while iterating over the successors.
|
||||
class ta_succ_iterator : public twa_succ_iterator
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~ta_succ_iterator()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool first() = 0;
|
||||
virtual bool next() = 0;
|
||||
virtual bool done() const = 0;
|
||||
|
||||
virtual const state* dst() const = 0;
|
||||
|
||||
/// \brief Get the changeset on the transition leading to current successor.
|
||||
///
|
||||
/// This is a boolean function of atomic propositions.
|
||||
virtual bdd cond() const = 0;
|
||||
|
||||
acc_cond::mark_t acc() const = 0;
|
||||
|
||||
};
|
||||
|
||||
#ifndef SWIG
|
||||
// A stack of Strongly-Connected Components
|
||||
class scc_stack_ta
|
||||
{
|
||||
public:
|
||||
struct connected_component
|
||||
{
|
||||
public:
|
||||
connected_component(int index = -1);
|
||||
|
||||
/// Index of the SCC.
|
||||
int index;
|
||||
|
||||
bool is_accepting;
|
||||
|
||||
/// The bdd condition is the union of all acceptance conditions of
|
||||
/// transitions which connect the states of the connected component.
|
||||
acc_cond::mark_t condition;
|
||||
|
||||
std::list<const state*> rem;
|
||||
};
|
||||
|
||||
/// Stack a new SCC with index \a index.
|
||||
void
|
||||
push(int index);
|
||||
|
||||
/// Access the top SCC.
|
||||
connected_component&
|
||||
top();
|
||||
|
||||
/// Access the top SCC.
|
||||
const connected_component&
|
||||
top() const;
|
||||
|
||||
/// Pop the top SCC.
|
||||
void
|
||||
pop();
|
||||
|
||||
/// How many SCC are in stack.
|
||||
size_t
|
||||
size() const;
|
||||
|
||||
/// The \c rem member of the top SCC.
|
||||
std::list<const state*>&
|
||||
rem();
|
||||
|
||||
/// Is the stack empty?
|
||||
bool
|
||||
empty() const;
|
||||
|
||||
typedef std::list<connected_component> stack_type;
|
||||
stack_type s;
|
||||
};
|
||||
#endif // !SWIG
|
||||
|
||||
/// \addtogroup ta_representation TA representations
|
||||
/// \ingroup ta
|
||||
|
||||
/// \addtogroup ta_algorithms TA algorithms
|
||||
/// \ingroup ta
|
||||
|
||||
/// \addtogroup ta_io Input/Output of TA
|
||||
/// \ingroup ta_algorithms
|
||||
|
||||
/// \addtogroup tgba_ta Transforming TGBA into TA
|
||||
/// \ingroup ta_algorithms
|
||||
|
||||
|
||||
/// \addtogroup ta_generic Algorithm patterns
|
||||
/// \ingroup ta_algorithms
|
||||
|
||||
/// \addtogroup ta_reduction TA simplifications
|
||||
/// \ingroup ta_algorithms
|
||||
|
||||
/// \addtogroup ta_misc Miscellaneous algorithms on TA
|
||||
/// \ingroup ta_algorithms
|
||||
}
|
||||
543
spot/ta/taexplicit.cc
Normal file
543
spot/ta/taexplicit.cc
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Laboratoire de
|
||||
// Recherche et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//#define TRACE
|
||||
|
||||
#include <iostream>
|
||||
#ifdef TRACE
|
||||
#define trace std::clog
|
||||
#else
|
||||
#define trace while (0) std::clog
|
||||
#endif
|
||||
|
||||
#include <spot/ta/taexplicit.hh>
|
||||
#include <spot/twa/formula2bdd.hh>
|
||||
#include <cassert>
|
||||
#include <spot/twa/bddprint.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
////////////////////////////////////////
|
||||
// ta_explicit_succ_iterator
|
||||
|
||||
ta_explicit_succ_iterator::ta_explicit_succ_iterator(
|
||||
const state_ta_explicit* s)
|
||||
{
|
||||
transitions_ = s->get_transitions();
|
||||
}
|
||||
|
||||
ta_explicit_succ_iterator::ta_explicit_succ_iterator(
|
||||
const state_ta_explicit* s, bdd condition)
|
||||
{
|
||||
transitions_ = s->get_transitions(condition);
|
||||
}
|
||||
|
||||
bool
|
||||
ta_explicit_succ_iterator::first()
|
||||
{
|
||||
if (!transitions_)
|
||||
return false;
|
||||
i_ = transitions_->begin();
|
||||
return i_ != transitions_->end();
|
||||
}
|
||||
|
||||
bool
|
||||
ta_explicit_succ_iterator::next()
|
||||
{
|
||||
++i_;
|
||||
return i_ != transitions_->end();
|
||||
}
|
||||
|
||||
bool
|
||||
ta_explicit_succ_iterator::done() const
|
||||
{
|
||||
return !transitions_ || i_ == transitions_->end();
|
||||
}
|
||||
|
||||
const state*
|
||||
ta_explicit_succ_iterator::dst() const
|
||||
{
|
||||
trace
|
||||
<< "***ta_explicit_succ_iterator::dst() if(done()) =***"
|
||||
<< done() << std::endl;
|
||||
assert(!done());
|
||||
trace
|
||||
<< "***ta_explicit_succ_iterator::dst() (*i_)->condition =***"
|
||||
<< (*i_)->condition << std::endl;
|
||||
return (*i_)->dest;
|
||||
}
|
||||
|
||||
bdd
|
||||
ta_explicit_succ_iterator::cond() const
|
||||
{
|
||||
assert(!done());
|
||||
return (*i_)->condition;
|
||||
}
|
||||
|
||||
acc_cond::mark_t
|
||||
ta_explicit_succ_iterator::acc() const
|
||||
{
|
||||
assert(!done());
|
||||
return (*i_)->acceptance_conditions;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// state_ta_explicit
|
||||
|
||||
state_ta_explicit::transitions*
|
||||
state_ta_explicit::get_transitions() const
|
||||
{
|
||||
return transitions_;
|
||||
}
|
||||
|
||||
// return transitions filtred by condition
|
||||
state_ta_explicit::transitions*
|
||||
state_ta_explicit::get_transitions(bdd condition) const
|
||||
{
|
||||
|
||||
std::unordered_map<int, transitions*, std::hash<int> >::const_iterator i =
|
||||
transitions_by_condition.find(condition.id());
|
||||
|
||||
if (i == transitions_by_condition.end())
|
||||
return nullptr;
|
||||
else
|
||||
return i->second;
|
||||
}
|
||||
|
||||
void
|
||||
state_ta_explicit::add_transition(state_ta_explicit::transition* t,
|
||||
bool add_at_beginning)
|
||||
{
|
||||
if (!transitions_)
|
||||
transitions_ = new transitions;
|
||||
|
||||
transitions* trans_by_condition = get_transitions(t->condition);
|
||||
|
||||
if (!trans_by_condition)
|
||||
{
|
||||
trans_by_condition = new transitions;
|
||||
transitions_by_condition[(t->condition).id()] = trans_by_condition;
|
||||
}
|
||||
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
bool transition_found = false;
|
||||
|
||||
for (it_trans = trans_by_condition->begin(); (it_trans
|
||||
!= trans_by_condition->end() && !transition_found); ++it_trans)
|
||||
{
|
||||
transition_found = ((*it_trans)->dest == t->dest);
|
||||
if (transition_found)
|
||||
{
|
||||
(*it_trans)->acceptance_conditions |= t->acceptance_conditions;
|
||||
}
|
||||
}
|
||||
|
||||
if (!transition_found)
|
||||
{
|
||||
if (add_at_beginning)
|
||||
{
|
||||
trans_by_condition->push_front(t);
|
||||
transitions_->push_front(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
trans_by_condition->push_back(t);
|
||||
transitions_->push_back(t);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
delete t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const state*
|
||||
state_ta_explicit::get_tgba_state() const
|
||||
{
|
||||
return tgba_state_;
|
||||
}
|
||||
|
||||
const bdd
|
||||
state_ta_explicit::get_tgba_condition() const
|
||||
{
|
||||
return tgba_condition_;
|
||||
}
|
||||
|
||||
bool
|
||||
state_ta_explicit::is_accepting_state() const
|
||||
{
|
||||
return is_accepting_state_;
|
||||
}
|
||||
|
||||
bool
|
||||
state_ta_explicit::is_initial_state() const
|
||||
{
|
||||
return is_initial_state_;
|
||||
}
|
||||
|
||||
void
|
||||
state_ta_explicit::set_accepting_state(bool is_accepting_state)
|
||||
{
|
||||
is_accepting_state_ = is_accepting_state;
|
||||
}
|
||||
|
||||
bool
|
||||
state_ta_explicit::is_livelock_accepting_state() const
|
||||
{
|
||||
return is_livelock_accepting_state_;
|
||||
}
|
||||
|
||||
void
|
||||
state_ta_explicit::set_livelock_accepting_state(
|
||||
bool is_livelock_accepting_state)
|
||||
{
|
||||
is_livelock_accepting_state_ = is_livelock_accepting_state;
|
||||
}
|
||||
|
||||
void
|
||||
state_ta_explicit::set_initial_state(bool is_initial_state)
|
||||
{
|
||||
is_initial_state_ = is_initial_state;
|
||||
}
|
||||
|
||||
bool
|
||||
state_ta_explicit::is_hole_state() const
|
||||
{
|
||||
state_ta_explicit::transitions* trans = get_transitions();
|
||||
return !trans || trans->empty();
|
||||
}
|
||||
|
||||
int
|
||||
state_ta_explicit::compare(const spot::state* other) const
|
||||
{
|
||||
const state_ta_explicit* o = down_cast<const state_ta_explicit*>(other);
|
||||
assert(o);
|
||||
|
||||
int compare_value = tgba_state_->compare(o->tgba_state_);
|
||||
|
||||
if (compare_value)
|
||||
return compare_value;
|
||||
|
||||
compare_value = tgba_condition_.id() - o->tgba_condition_.id();
|
||||
|
||||
// if (compare_value != 0)
|
||||
// return compare_value;
|
||||
//
|
||||
// //unique artificial_livelock_accepting_state
|
||||
// if (o->is_the_artificial_livelock_accepting_state())
|
||||
// return is_the_artificial_livelock_accepting_state();
|
||||
|
||||
return compare_value;
|
||||
}
|
||||
|
||||
size_t
|
||||
state_ta_explicit::hash() const
|
||||
{
|
||||
//return wang32_hash(tgba_state_->hash());
|
||||
return wang32_hash(tgba_state_->hash()) ^ wang32_hash(tgba_condition_.id());
|
||||
|
||||
}
|
||||
|
||||
state_ta_explicit*
|
||||
state_ta_explicit::clone() const
|
||||
{
|
||||
return new state_ta_explicit(*this);
|
||||
}
|
||||
|
||||
void
|
||||
state_ta_explicit::delete_stuttering_and_hole_successors()
|
||||
{
|
||||
state_ta_explicit::transitions* trans = get_transitions();
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
|
||||
if (trans)
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();)
|
||||
{
|
||||
auto dest = (*it_trans)->dest;
|
||||
bool is_stuttering_transition = (get_tgba_condition()
|
||||
== (dest)->get_tgba_condition());
|
||||
bool dest_is_livelock_accepting =
|
||||
dest->is_livelock_accepting_state();
|
||||
|
||||
//Before deleting stuttering transitions, propaged back livelock
|
||||
//and initial state's properties
|
||||
if (is_stuttering_transition)
|
||||
{
|
||||
if (!is_livelock_accepting_state() && dest_is_livelock_accepting)
|
||||
{
|
||||
set_livelock_accepting_state(true);
|
||||
stuttering_reachable_livelock
|
||||
= dest->stuttering_reachable_livelock;
|
||||
}
|
||||
if (dest->is_initial_state())
|
||||
set_initial_state(true);
|
||||
}
|
||||
|
||||
//remove hole successors states
|
||||
state_ta_explicit::transitions* dest_trans =
|
||||
(dest)->get_transitions();
|
||||
bool dest_trans_empty = !dest_trans || dest_trans->empty();
|
||||
if (is_stuttering_transition || (dest_trans_empty
|
||||
&& (!dest_is_livelock_accepting)))
|
||||
{
|
||||
get_transitions((*it_trans)->condition)->remove(*it_trans);
|
||||
delete *it_trans;
|
||||
it_trans = trans->erase(it_trans);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it_trans;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
state_ta_explicit::free_transitions()
|
||||
{
|
||||
state_ta_explicit::transitions* trans = transitions_;
|
||||
// We don't destroy the transitions in the state's destructor because
|
||||
// they are not cloned.
|
||||
if (trans)
|
||||
for (auto& t: *trans)
|
||||
delete t;
|
||||
delete trans;
|
||||
|
||||
std::unordered_map<int, transitions*, std::hash<int> >::iterator i =
|
||||
transitions_by_condition.begin();
|
||||
while (i != transitions_by_condition.end())
|
||||
{
|
||||
delete i->second;
|
||||
++i;
|
||||
}
|
||||
|
||||
transitions_ = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// ta_explicit
|
||||
|
||||
|
||||
ta_explicit::ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state):
|
||||
ta(tgba->get_dict()),
|
||||
tgba_(tgba),
|
||||
artificial_initial_state_(artificial_initial_state)
|
||||
{
|
||||
get_dict()->register_all_variables_of(&tgba_, this);
|
||||
acc().add_sets(n_acc);
|
||||
acc().set_generalized_buchi();
|
||||
if (artificial_initial_state)
|
||||
{
|
||||
auto is = add_state(artificial_initial_state);
|
||||
assert(is == artificial_initial_state);
|
||||
(void)is;
|
||||
}
|
||||
}
|
||||
|
||||
ta_explicit::~ta_explicit()
|
||||
{
|
||||
ta::states_set_t::iterator it;
|
||||
for (it = states_set_.begin(); it != states_set_.end(); ++it)
|
||||
{
|
||||
auto* s = const_cast<state_ta_explicit*>
|
||||
(down_cast<const state_ta_explicit*>(*it));
|
||||
|
||||
s->free_transitions();
|
||||
s->get_tgba_state()->destroy();
|
||||
delete s;
|
||||
}
|
||||
get_dict()->unregister_all_my_variables(this);
|
||||
}
|
||||
|
||||
state_ta_explicit*
|
||||
ta_explicit::add_state(state_ta_explicit* s)
|
||||
{
|
||||
std::pair<ta::states_set_t::iterator, bool> add_state_to_ta =
|
||||
states_set_.insert(s);
|
||||
|
||||
return down_cast<state_ta_explicit*>(*add_state_to_ta.first);
|
||||
}
|
||||
|
||||
void
|
||||
ta_explicit::add_to_initial_states_set(state* state, bdd condition)
|
||||
{
|
||||
state_ta_explicit* s = down_cast<state_ta_explicit*>(state);
|
||||
s->set_initial_state(true);
|
||||
if (condition == bddfalse)
|
||||
condition = get_state_condition(s);
|
||||
auto add_state = initial_states_set_.insert(s);
|
||||
if (get_artificial_initial_state())
|
||||
if (add_state.second)
|
||||
{
|
||||
auto i =
|
||||
down_cast<state_ta_explicit*>(get_artificial_initial_state());
|
||||
create_transition(i, condition, 0U, s);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ta_explicit::delete_stuttering_and_hole_successors(const spot::state* s)
|
||||
{
|
||||
auto state =
|
||||
const_cast<state_ta_explicit*>(down_cast<const state_ta_explicit*>(s));
|
||||
assert(state);
|
||||
state->delete_stuttering_and_hole_successors();
|
||||
if (state->is_initial_state())
|
||||
add_to_initial_states_set(state);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ta_explicit::create_transition(state_ta_explicit* source, bdd condition,
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning)
|
||||
{
|
||||
state_ta_explicit::transition* t = new state_ta_explicit::transition;
|
||||
t->dest = dest;
|
||||
t->condition = condition;
|
||||
t->acceptance_conditions = acceptance_conditions;
|
||||
source->add_transition(t, add_at_beginning);
|
||||
|
||||
}
|
||||
|
||||
ta::const_states_set_t
|
||||
ta_explicit::get_initial_states_set() const
|
||||
{
|
||||
return initial_states_set_;
|
||||
|
||||
}
|
||||
|
||||
bdd
|
||||
ta_explicit::get_state_condition(const spot::state* initial_state) const
|
||||
{
|
||||
const state_ta_explicit* sta =
|
||||
down_cast<const state_ta_explicit*>(initial_state);
|
||||
assert(sta);
|
||||
return sta->get_tgba_condition();
|
||||
}
|
||||
|
||||
bool
|
||||
ta_explicit::is_accepting_state(const spot::state* s) const
|
||||
{
|
||||
const state_ta_explicit* sta = down_cast<const state_ta_explicit*>(s);
|
||||
assert(sta);
|
||||
return sta->is_accepting_state();
|
||||
}
|
||||
|
||||
bool
|
||||
ta_explicit::is_initial_state(const spot::state* s) const
|
||||
{
|
||||
const state_ta_explicit* sta = down_cast<const state_ta_explicit*>(s);
|
||||
assert(sta);
|
||||
return sta->is_initial_state();
|
||||
}
|
||||
|
||||
bool
|
||||
ta_explicit::is_livelock_accepting_state(const spot::state* s) const
|
||||
{
|
||||
const state_ta_explicit* sta = down_cast<const state_ta_explicit*>(s);
|
||||
assert(sta);
|
||||
return sta->is_livelock_accepting_state();
|
||||
}
|
||||
|
||||
ta_succ_iterator*
|
||||
ta_explicit::succ_iter(const spot::state* state) const
|
||||
{
|
||||
const state_ta_explicit* s = down_cast<const state_ta_explicit*>(state);
|
||||
assert(s);
|
||||
return new ta_explicit_succ_iterator(s);
|
||||
}
|
||||
|
||||
ta_succ_iterator*
|
||||
ta_explicit::succ_iter(const spot::state* state, bdd condition) const
|
||||
{
|
||||
const state_ta_explicit* s = down_cast<const state_ta_explicit*>(state);
|
||||
assert(s);
|
||||
return new ta_explicit_succ_iterator(s, condition);
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
ta_explicit::get_dict() const
|
||||
{
|
||||
return tgba_->get_dict();
|
||||
}
|
||||
|
||||
const_twa_ptr
|
||||
ta_explicit::get_tgba() const
|
||||
{
|
||||
return tgba_;
|
||||
}
|
||||
|
||||
std::string
|
||||
ta_explicit::format_state(const spot::state* s) const
|
||||
{
|
||||
const state_ta_explicit* sta = down_cast<const state_ta_explicit*>(s);
|
||||
assert(sta);
|
||||
|
||||
if (sta->get_tgba_condition() == bddtrue)
|
||||
return tgba_->format_state(sta->get_tgba_state());
|
||||
|
||||
return tgba_->format_state(sta->get_tgba_state()) + "\n"
|
||||
+ bdd_format_formula(get_dict(), sta->get_tgba_condition());
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ta_explicit::delete_stuttering_transitions()
|
||||
{
|
||||
ta::states_set_t::iterator it;
|
||||
for (it = states_set_.begin(); it != states_set_.end(); ++it)
|
||||
{
|
||||
|
||||
const state_ta_explicit* source =
|
||||
static_cast<const state_ta_explicit*>(*it);
|
||||
|
||||
state_ta_explicit::transitions* trans = source->get_transitions();
|
||||
state_ta_explicit::transitions::iterator it_trans;
|
||||
|
||||
if (trans)
|
||||
for (it_trans = trans->begin(); it_trans != trans->end();)
|
||||
{
|
||||
if (source->get_tgba_condition()
|
||||
== ((*it_trans)->dest)->get_tgba_condition())
|
||||
{
|
||||
delete *it_trans;
|
||||
it_trans = trans->erase(it_trans);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it_trans;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ta_explicit::free_state(const spot::state*) const
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
261
spot/ta/taexplicit.hh
Normal file
261
spot/ta/taexplicit.hh
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Laboratoire de
|
||||
// Recherche et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spot/misc/hash.hh>
|
||||
#include <list>
|
||||
#include <spot/twa/twa.hh>
|
||||
#include <set>
|
||||
#include <spot/tl/formula.hh>
|
||||
#include <cassert>
|
||||
#include <spot/misc/bddlt.hh>
|
||||
#include <spot/ta/ta.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
// Forward declarations. See below.
|
||||
class state_ta_explicit;
|
||||
class ta_explicit_succ_iterator;
|
||||
class ta_explicit;
|
||||
|
||||
/// Explicit representation of a spot::ta.
|
||||
/// \ingroup ta_representation
|
||||
class SPOT_API ta_explicit : public ta
|
||||
{
|
||||
public:
|
||||
ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr);
|
||||
|
||||
const_twa_ptr
|
||||
get_tgba() const;
|
||||
|
||||
state_ta_explicit*
|
||||
add_state(state_ta_explicit* s);
|
||||
|
||||
void
|
||||
add_to_initial_states_set(state* s, bdd condition = bddfalse);
|
||||
|
||||
void
|
||||
create_transition(state_ta_explicit* source, bdd condition,
|
||||
acc_cond::mark_t acceptance_conditions,
|
||||
const state_ta_explicit* dest,
|
||||
bool add_at_beginning = false);
|
||||
|
||||
void
|
||||
delete_stuttering_transitions();
|
||||
// ta interface
|
||||
virtual
|
||||
~ta_explicit();
|
||||
virtual const_states_set_t
|
||||
get_initial_states_set() const;
|
||||
|
||||
virtual ta_succ_iterator*
|
||||
succ_iter(const spot::state* s) const;
|
||||
|
||||
virtual ta_succ_iterator*
|
||||
succ_iter(const spot::state* s, bdd condition) const;
|
||||
|
||||
virtual bdd_dict_ptr
|
||||
get_dict() const;
|
||||
|
||||
virtual std::string
|
||||
format_state(const spot::state* s) const;
|
||||
|
||||
virtual bool
|
||||
is_accepting_state(const spot::state* s) const;
|
||||
|
||||
virtual bool
|
||||
is_livelock_accepting_state(const spot::state* s) const;
|
||||
|
||||
virtual bool
|
||||
is_initial_state(const spot::state* s) const;
|
||||
|
||||
virtual bdd
|
||||
get_state_condition(const spot::state* s) const;
|
||||
|
||||
virtual void
|
||||
free_state(const spot::state* s) const;
|
||||
|
||||
spot::state*
|
||||
get_artificial_initial_state() const
|
||||
{
|
||||
return (spot::state*) artificial_initial_state_;
|
||||
}
|
||||
|
||||
void
|
||||
set_artificial_initial_state(state_ta_explicit* s)
|
||||
{
|
||||
artificial_initial_state_ = s;
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
delete_stuttering_and_hole_successors(const spot::state* s);
|
||||
|
||||
ta::states_set_t
|
||||
get_states_set()
|
||||
{
|
||||
return states_set_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow copy.
|
||||
ta_explicit(const ta_explicit& other) = delete;
|
||||
ta_explicit& operator=(const ta_explicit& other) = delete;
|
||||
|
||||
const_twa_ptr tgba_;
|
||||
state_ta_explicit* artificial_initial_state_;
|
||||
ta::states_set_t states_set_;
|
||||
ta::const_states_set_t initial_states_set_;
|
||||
};
|
||||
|
||||
/// states used by spot::ta_explicit.
|
||||
/// \ingroup ta_representation
|
||||
class SPOT_API state_ta_explicit : public spot::state
|
||||
{
|
||||
#ifndef SWIG
|
||||
public:
|
||||
|
||||
/// Explicit transitions.
|
||||
struct transition
|
||||
{
|
||||
bdd condition;
|
||||
acc_cond::mark_t acceptance_conditions;
|
||||
const state_ta_explicit* dest;
|
||||
};
|
||||
|
||||
typedef std::list<transition*> transitions;
|
||||
|
||||
state_ta_explicit(const state* tgba_state, const bdd tgba_condition,
|
||||
bool is_initial_state = false,
|
||||
bool is_accepting_state = false,
|
||||
bool is_livelock_accepting_state = false,
|
||||
transitions* trans = nullptr) :
|
||||
tgba_state_(tgba_state), tgba_condition_(tgba_condition),
|
||||
is_initial_state_(is_initial_state), is_accepting_state_(
|
||||
is_accepting_state), is_livelock_accepting_state_(
|
||||
is_livelock_accepting_state), transitions_(trans)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int
|
||||
compare(const spot::state* other) const;
|
||||
virtual size_t
|
||||
hash() const;
|
||||
virtual state_ta_explicit*
|
||||
clone() const;
|
||||
|
||||
virtual void
|
||||
destroy() const
|
||||
{
|
||||
}
|
||||
|
||||
virtual
|
||||
~state_ta_explicit()
|
||||
{
|
||||
}
|
||||
|
||||
transitions*
|
||||
get_transitions() const;
|
||||
|
||||
// return transitions filtred by condition
|
||||
transitions*
|
||||
get_transitions(bdd condition) const;
|
||||
|
||||
void
|
||||
add_transition(transition* t, bool add_at_beginning = false);
|
||||
|
||||
const state*
|
||||
get_tgba_state() const;
|
||||
const bdd
|
||||
get_tgba_condition() const;
|
||||
bool
|
||||
is_accepting_state() const;
|
||||
void
|
||||
set_accepting_state(bool is_accepting_state);
|
||||
bool
|
||||
is_livelock_accepting_state() const;
|
||||
void
|
||||
set_livelock_accepting_state(bool is_livelock_accepting_state);
|
||||
|
||||
bool
|
||||
is_initial_state() const;
|
||||
void
|
||||
set_initial_state(bool is_initial_state);
|
||||
|
||||
/// \brief Return true if the state has no successors
|
||||
bool
|
||||
is_hole_state() const;
|
||||
|
||||
/// \brief Remove stuttering transitions
|
||||
/// and transitions leading to states having no successors
|
||||
void
|
||||
delete_stuttering_and_hole_successors();
|
||||
|
||||
void
|
||||
free_transitions();
|
||||
|
||||
state_ta_explicit* stuttering_reachable_livelock;
|
||||
private:
|
||||
const state* tgba_state_;
|
||||
const bdd tgba_condition_;
|
||||
bool is_initial_state_;
|
||||
bool is_accepting_state_;
|
||||
bool is_livelock_accepting_state_;
|
||||
transitions* transitions_;
|
||||
std::unordered_map<int, transitions*, std::hash<int>>
|
||||
transitions_by_condition;
|
||||
#endif // !SWIG
|
||||
};
|
||||
|
||||
/// Successor iterators used by spot::ta_explicit.
|
||||
class SPOT_API ta_explicit_succ_iterator : public ta_succ_iterator
|
||||
{
|
||||
public:
|
||||
ta_explicit_succ_iterator(const state_ta_explicit* s);
|
||||
|
||||
ta_explicit_succ_iterator(const state_ta_explicit* s, bdd condition);
|
||||
|
||||
virtual bool first();
|
||||
virtual bool next();
|
||||
virtual bool done() const;
|
||||
|
||||
virtual const state* dst() const;
|
||||
virtual bdd cond() const;
|
||||
|
||||
virtual acc_cond::mark_t acc() const;
|
||||
|
||||
private:
|
||||
state_ta_explicit::transitions* transitions_;
|
||||
state_ta_explicit::transitions::const_iterator i_;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<ta_explicit> ta_explicit_ptr;
|
||||
typedef std::shared_ptr<const ta_explicit> const_ta_explicit_ptr;
|
||||
|
||||
inline ta_explicit_ptr
|
||||
make_ta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
{
|
||||
return std::make_shared<ta_explicit>(tgba, n_acc, artificial_initial_state);
|
||||
}
|
||||
}
|
||||
454
spot/ta/taproduct.cc
Normal file
454
spot/ta/taproduct.cc
Normal file
|
|
@ -0,0 +1,454 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2011, 2012, 2014, 2015 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <spot/ta/taproduct.hh>
|
||||
#include <cassert>
|
||||
#include <spot/misc/hashfunc.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// state_ta_product
|
||||
|
||||
state_ta_product::state_ta_product(const state_ta_product& o) :
|
||||
state(), ta_state_(o.get_ta_state()), kripke_state_(
|
||||
o.get_kripke_state()->clone())
|
||||
{
|
||||
}
|
||||
|
||||
state_ta_product::~state_ta_product()
|
||||
{
|
||||
//see ta_product::free_state() method
|
||||
kripke_state_->destroy();
|
||||
}
|
||||
|
||||
int
|
||||
state_ta_product::compare(const state* other) const
|
||||
{
|
||||
const state_ta_product* o = down_cast<const state_ta_product*> (other);
|
||||
assert(o);
|
||||
int res = ta_state_->compare(o->get_ta_state());
|
||||
if (res != 0)
|
||||
return res;
|
||||
return kripke_state_->compare(o->get_kripke_state());
|
||||
}
|
||||
|
||||
size_t
|
||||
state_ta_product::hash() const
|
||||
{
|
||||
// We assume that size_t is 32-bit wide.
|
||||
return wang32_hash(ta_state_->hash()) ^ wang32_hash(kripke_state_->hash());
|
||||
}
|
||||
|
||||
state_ta_product*
|
||||
state_ta_product::clone() const
|
||||
{
|
||||
return new state_ta_product(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ta_succ_iterator_product
|
||||
ta_succ_iterator_product::ta_succ_iterator_product(const state_ta_product* s,
|
||||
const ta* t,
|
||||
const kripke* k)
|
||||
: source_(s), ta_(t), kripke_(k)
|
||||
{
|
||||
kripke_source_condition = kripke_->state_condition(s->get_kripke_state());
|
||||
|
||||
kripke_succ_it_ = kripke_->succ_iter(s->get_kripke_state());
|
||||
kripke_current_dest_state = nullptr;
|
||||
ta_succ_it_ = nullptr;
|
||||
current_state_ = nullptr;
|
||||
}
|
||||
|
||||
ta_succ_iterator_product::~ta_succ_iterator_product()
|
||||
{
|
||||
delete current_state_;
|
||||
current_state_ = nullptr;
|
||||
delete ta_succ_it_;
|
||||
delete kripke_succ_it_;
|
||||
if (kripke_current_dest_state)
|
||||
kripke_current_dest_state->destroy();
|
||||
}
|
||||
|
||||
void
|
||||
ta_succ_iterator_product::step_()
|
||||
{
|
||||
if (!ta_succ_it_->done())
|
||||
ta_succ_it_->next();
|
||||
if (ta_succ_it_->done())
|
||||
{
|
||||
delete ta_succ_it_;
|
||||
ta_succ_it_ = nullptr;
|
||||
next_kripke_dest();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ta_succ_iterator_product::next_kripke_dest()
|
||||
{
|
||||
if (!kripke_succ_it_)
|
||||
return;
|
||||
|
||||
if (!kripke_current_dest_state)
|
||||
{
|
||||
kripke_succ_it_->first();
|
||||
}
|
||||
else
|
||||
{
|
||||
kripke_current_dest_state->destroy();
|
||||
kripke_current_dest_state = nullptr;
|
||||
kripke_succ_it_->next();
|
||||
}
|
||||
|
||||
// If one of the two successor sets is empty initially, we reset
|
||||
// kripke_succ_it_, so that done() can detect this situation easily. (We
|
||||
// choose to reset kripke_succ_it_ because this variable is already used by
|
||||
// done().)
|
||||
if (kripke_succ_it_->done())
|
||||
{
|
||||
delete kripke_succ_it_;
|
||||
kripke_succ_it_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
kripke_current_dest_state = kripke_succ_it_->dst();
|
||||
bdd kripke_current_dest_condition = kripke_->state_condition(
|
||||
kripke_current_dest_state);
|
||||
is_stuttering_transition_ = (kripke_source_condition
|
||||
== kripke_current_dest_condition);
|
||||
if (is_stuttering_transition_)
|
||||
{
|
||||
current_condition_ = bddfalse;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_condition_ = bdd_setxor(kripke_source_condition,
|
||||
kripke_current_dest_condition);
|
||||
ta_succ_it_ = ta_->succ_iter(source_->get_ta_state(),
|
||||
current_condition_);
|
||||
ta_succ_it_->first();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
ta_succ_iterator_product::first()
|
||||
{
|
||||
|
||||
next_kripke_dest();
|
||||
|
||||
if (!done())
|
||||
return next_non_stuttering_();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ta_succ_iterator_product::next()
|
||||
{
|
||||
delete current_state_;
|
||||
current_state_ = nullptr;
|
||||
if (is_stuttering_transition())
|
||||
{
|
||||
next_kripke_dest();
|
||||
}
|
||||
else
|
||||
step_();
|
||||
|
||||
if (!done())
|
||||
return next_non_stuttering_();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ta_succ_iterator_product::next_non_stuttering_()
|
||||
{
|
||||
|
||||
while (!done())
|
||||
{
|
||||
|
||||
if (is_stuttering_transition_)
|
||||
{
|
||||
//if stuttering transition, the TA automata stays in the same state
|
||||
current_state_ = new state_ta_product(source_->get_ta_state(),
|
||||
kripke_current_dest_state->clone());
|
||||
current_acceptance_conditions_ = 0U;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ta_succ_it_->done())
|
||||
{
|
||||
current_state_ = new state_ta_product(ta_succ_it_->dst(),
|
||||
kripke_current_dest_state->clone());
|
||||
current_acceptance_conditions_
|
||||
= ta_succ_it_->acc();
|
||||
return true;
|
||||
}
|
||||
|
||||
step_();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ta_succ_iterator_product::done() const
|
||||
{
|
||||
return !kripke_succ_it_ || kripke_succ_it_->done();
|
||||
}
|
||||
|
||||
state_ta_product*
|
||||
ta_succ_iterator_product::dst() const
|
||||
{
|
||||
return current_state_->clone();
|
||||
}
|
||||
|
||||
bool
|
||||
ta_succ_iterator_product::is_stuttering_transition() const
|
||||
{
|
||||
return is_stuttering_transition_;
|
||||
}
|
||||
|
||||
bdd
|
||||
ta_succ_iterator_product::cond() const
|
||||
{
|
||||
return current_condition_;
|
||||
}
|
||||
|
||||
acc_cond::mark_t
|
||||
ta_succ_iterator_product::acc() const
|
||||
{
|
||||
return current_acceptance_conditions_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ta_product
|
||||
|
||||
|
||||
ta_product::ta_product(const const_ta_ptr& testing_automata,
|
||||
const const_kripke_ptr& kripke_structure):
|
||||
ta(testing_automata->get_dict()),
|
||||
dict_(testing_automata->get_dict()),
|
||||
ta_(testing_automata),
|
||||
kripke_(kripke_structure)
|
||||
{
|
||||
assert(dict_ == kripke_structure->get_dict());
|
||||
dict_->register_all_variables_of(ta_, this);
|
||||
dict_->register_all_variables_of(kripke_, this);
|
||||
}
|
||||
|
||||
ta_product::~ta_product()
|
||||
{
|
||||
dict_->unregister_all_my_variables(this);
|
||||
}
|
||||
|
||||
ta::const_states_set_t
|
||||
ta_product::get_initial_states_set() const
|
||||
{
|
||||
//build initial states set
|
||||
|
||||
ta::const_states_set_t ta_init_states_set;
|
||||
ta::const_states_set_t::const_iterator it;
|
||||
|
||||
ta::const_states_set_t initial_states_set;
|
||||
const state* kripke_init = kripke_->get_init_state();
|
||||
bdd kripke_init_condition = kripke_->state_condition(kripke_init);
|
||||
|
||||
const spot::state* artificial_initial_state =
|
||||
ta_->get_artificial_initial_state();
|
||||
|
||||
if (artificial_initial_state)
|
||||
{
|
||||
ta_succ_iterator* ta_init_it_ = ta_->succ_iter(
|
||||
artificial_initial_state, kripke_init_condition);
|
||||
for (ta_init_it_->first(); !ta_init_it_->done(); ta_init_it_->next())
|
||||
{
|
||||
ta_init_states_set.insert(ta_init_it_->dst());
|
||||
}
|
||||
delete ta_init_it_;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ta_init_states_set = ta_->get_initial_states_set();
|
||||
}
|
||||
|
||||
for (auto s: ta_init_states_set)
|
||||
if (artificial_initial_state ||
|
||||
(kripke_init_condition == ta_->get_state_condition(s)))
|
||||
initial_states_set.insert(new state_ta_product(s,
|
||||
kripke_init->clone()));
|
||||
|
||||
kripke_init->destroy();
|
||||
return initial_states_set;
|
||||
}
|
||||
|
||||
ta_succ_iterator_product*
|
||||
ta_product::succ_iter(const state* s) const
|
||||
{
|
||||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(s);
|
||||
|
||||
return new ta_succ_iterator_product(stp, ta_.get(), kripke_.get());
|
||||
}
|
||||
|
||||
|
||||
ta_succ_iterator_product*
|
||||
ta_product::succ_iter(const spot::state* s, bdd changeset) const
|
||||
{
|
||||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(s);
|
||||
return new ta_succ_iterator_product_by_changeset(stp,
|
||||
ta_.get(), kripke_.get(),
|
||||
changeset);
|
||||
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
ta_product::get_dict() const
|
||||
{
|
||||
return dict_;
|
||||
}
|
||||
|
||||
std::string
|
||||
ta_product::format_state(const state* state) const
|
||||
{
|
||||
const state_ta_product* s = down_cast<const state_ta_product*> (state);
|
||||
assert(s);
|
||||
return kripke_->format_state(s->get_kripke_state()) + " * \n"
|
||||
+ ta_->format_state(s->get_ta_state());
|
||||
}
|
||||
|
||||
bool
|
||||
ta_product::is_accepting_state(const spot::state* s) const
|
||||
{
|
||||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(stp);
|
||||
|
||||
return ta_->is_accepting_state(stp->get_ta_state());
|
||||
}
|
||||
|
||||
bool
|
||||
ta_product::is_livelock_accepting_state(const spot::state* s) const
|
||||
{
|
||||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(stp);
|
||||
|
||||
return ta_->is_livelock_accepting_state(stp->get_ta_state());
|
||||
}
|
||||
|
||||
bool
|
||||
ta_product::is_initial_state(const spot::state* s) const
|
||||
{
|
||||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(stp);
|
||||
|
||||
const state* ta_s = stp->get_ta_state();
|
||||
const state* kr_s = stp->get_kripke_state();
|
||||
|
||||
return (ta_->is_initial_state(ta_s))
|
||||
&& ((kripke_->get_init_state())->compare(kr_s) == 0)
|
||||
&& ((kripke_->state_condition(kr_s))
|
||||
== (ta_->get_state_condition(ta_s)));
|
||||
}
|
||||
|
||||
bool
|
||||
ta_product::is_hole_state_in_ta_component(const spot::state* s) const
|
||||
{
|
||||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
ta_succ_iterator* ta_succ_iter = get_ta()->succ_iter(stp->get_ta_state());
|
||||
bool is_hole_state = ta_succ_iter->done();
|
||||
delete ta_succ_iter;
|
||||
return is_hole_state;
|
||||
}
|
||||
|
||||
bdd
|
||||
ta_product::get_state_condition(const spot::state* s) const
|
||||
{
|
||||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(stp);
|
||||
const state* ta_s = stp->get_ta_state();
|
||||
return ta_->get_state_condition(ta_s);
|
||||
}
|
||||
|
||||
void
|
||||
ta_product::free_state(const spot::state* s) const
|
||||
{
|
||||
|
||||
const state_ta_product* stp = down_cast<const state_ta_product*> (s);
|
||||
assert(stp);
|
||||
ta_->free_state(stp->get_ta_state());
|
||||
delete stp;
|
||||
|
||||
}
|
||||
|
||||
ta_succ_iterator_product_by_changeset::
|
||||
ta_succ_iterator_product_by_changeset(const state_ta_product* s, const ta* t,
|
||||
const kripke* k, bdd changeset)
|
||||
: ta_succ_iterator_product(s, t, k)
|
||||
{
|
||||
current_condition_ = changeset;
|
||||
}
|
||||
|
||||
void
|
||||
ta_succ_iterator_product_by_changeset::next_kripke_dest()
|
||||
{
|
||||
if (!kripke_succ_it_)
|
||||
return;
|
||||
|
||||
if (!kripke_current_dest_state)
|
||||
{
|
||||
kripke_succ_it_->first();
|
||||
}
|
||||
else
|
||||
{
|
||||
kripke_current_dest_state->destroy();
|
||||
kripke_current_dest_state = nullptr;
|
||||
kripke_succ_it_->next();
|
||||
}
|
||||
|
||||
// If one of the two successor sets is empty initially, we reset
|
||||
// kripke_succ_it_, so that done() can detect this situation easily. (We
|
||||
// choose to reset kripke_succ_it_ because this variable is already used by
|
||||
// done().)
|
||||
if (kripke_succ_it_->done())
|
||||
{
|
||||
delete kripke_succ_it_;
|
||||
kripke_succ_it_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
kripke_current_dest_state = kripke_succ_it_->dst();
|
||||
bdd kripke_current_dest_condition = kripke_->state_condition(
|
||||
kripke_current_dest_state);
|
||||
|
||||
if (current_condition_ != bdd_setxor(kripke_source_condition,
|
||||
kripke_current_dest_condition))
|
||||
next_kripke_dest();
|
||||
is_stuttering_transition_ = (kripke_source_condition
|
||||
== kripke_current_dest_condition);
|
||||
if (!is_stuttering_transition_)
|
||||
{
|
||||
ta_succ_it_ = ta_->succ_iter(source_->get_ta_state(),
|
||||
current_condition_);
|
||||
ta_succ_it_->first();
|
||||
}
|
||||
}
|
||||
}
|
||||
221
spot/ta/taproduct.hh
Normal file
221
spot/ta/taproduct.hh
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2011, 2012, 2013, 2014 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spot/ta/ta.hh>
|
||||
#include <spot/kripke/kripke.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
/// \ingroup ta_emptiness_check
|
||||
/// \brief A state for spot::ta_product.
|
||||
///
|
||||
/// This state is in fact a pair of state: the state from the TA
|
||||
/// automaton and that of Kripke structure.
|
||||
class SPOT_API state_ta_product : public state
|
||||
{
|
||||
public:
|
||||
/// \brief Constructor
|
||||
/// \param ta_state The state from the ta automaton.
|
||||
/// \param kripke_state The state from Kripke structure.
|
||||
state_ta_product(const state* ta_state, const state* kripke_state) :
|
||||
ta_state_(ta_state), kripke_state_(kripke_state)
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
state_ta_product(const state_ta_product& o);
|
||||
|
||||
virtual
|
||||
~state_ta_product();
|
||||
|
||||
const state*
|
||||
get_ta_state() const
|
||||
{
|
||||
return ta_state_;
|
||||
}
|
||||
|
||||
const state*
|
||||
get_kripke_state() const
|
||||
{
|
||||
return kripke_state_;
|
||||
}
|
||||
|
||||
virtual int
|
||||
compare(const state* other) const;
|
||||
virtual size_t
|
||||
hash() const;
|
||||
virtual state_ta_product*
|
||||
clone() const;
|
||||
|
||||
private:
|
||||
const state* ta_state_; ///< State from the ta automaton.
|
||||
const state* kripke_state_; ///< State from the kripke structure.
|
||||
};
|
||||
|
||||
/// \brief Iterate over the successors of a product computed on the fly.
|
||||
class SPOT_API ta_succ_iterator_product : public ta_succ_iterator
|
||||
{
|
||||
public:
|
||||
ta_succ_iterator_product(const state_ta_product* s, const ta* t,
|
||||
const kripke* k);
|
||||
|
||||
virtual
|
||||
~ta_succ_iterator_product();
|
||||
|
||||
// iteration
|
||||
bool first();
|
||||
bool next();
|
||||
bool done() const;
|
||||
|
||||
// inspection
|
||||
state_ta_product*
|
||||
dst() const;
|
||||
bdd
|
||||
cond() const;
|
||||
|
||||
acc_cond::mark_t
|
||||
acc() const;
|
||||
|
||||
/// \brief Return true if the changeset of the current transition is empty
|
||||
bool
|
||||
is_stuttering_transition() const;
|
||||
|
||||
protected:
|
||||
//@{
|
||||
/// Internal routines to advance to the next successor.
|
||||
void step_();
|
||||
bool next_non_stuttering_();
|
||||
|
||||
/// \brief Move to the next successor in the kripke structure
|
||||
void
|
||||
next_kripke_dest();
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
const state_ta_product* source_;
|
||||
const ta* ta_;
|
||||
const kripke* kripke_;
|
||||
ta_succ_iterator* ta_succ_it_;
|
||||
twa_succ_iterator* kripke_succ_it_;
|
||||
const state_ta_product* current_state_;
|
||||
bdd current_condition_;
|
||||
acc_cond::mark_t current_acceptance_conditions_;
|
||||
bool is_stuttering_transition_;
|
||||
bdd kripke_source_condition;
|
||||
const state* kripke_current_dest_state;
|
||||
|
||||
};
|
||||
|
||||
/// \ingroup ta_emptiness_check
|
||||
/// \brief A lazy product between a Testing automaton and a Kripke structure.
|
||||
/// (States are computed on the fly.)
|
||||
class SPOT_API ta_product: public ta
|
||||
{
|
||||
public:
|
||||
/// \brief Constructor.
|
||||
/// \param testing_automaton The TA component in the product.
|
||||
/// \param kripke_structure The Kripke component in the product.
|
||||
ta_product(const const_ta_ptr& testing_automaton,
|
||||
const const_kripke_ptr& kripke_structure);
|
||||
|
||||
virtual
|
||||
~ta_product();
|
||||
|
||||
virtual ta::const_states_set_t
|
||||
get_initial_states_set() const;
|
||||
|
||||
virtual ta_succ_iterator_product*
|
||||
succ_iter(const spot::state* s) const;
|
||||
|
||||
virtual ta_succ_iterator_product*
|
||||
succ_iter(const spot::state* s, bdd changeset) const;
|
||||
|
||||
virtual bdd_dict_ptr
|
||||
get_dict() const;
|
||||
|
||||
virtual std::string
|
||||
format_state(const spot::state* s) const;
|
||||
|
||||
virtual bool
|
||||
is_accepting_state(const spot::state* s) const;
|
||||
|
||||
virtual bool
|
||||
is_livelock_accepting_state(const spot::state* s) const;
|
||||
|
||||
virtual bool
|
||||
is_initial_state(const spot::state* s) const;
|
||||
|
||||
/// \brief Return true if the state \a s has no succeseurs
|
||||
/// in the TA automaton (the TA component of the product automaton)
|
||||
virtual bool
|
||||
is_hole_state_in_ta_component(const spot::state* s) const;
|
||||
|
||||
virtual bdd
|
||||
get_state_condition(const spot::state* s) const;
|
||||
|
||||
virtual void
|
||||
free_state(const spot::state* s) const;
|
||||
|
||||
const const_ta_ptr&
|
||||
get_ta() const
|
||||
{
|
||||
return ta_;
|
||||
}
|
||||
|
||||
const const_kripke_ptr&
|
||||
get_kripke() const
|
||||
{
|
||||
return kripke_;
|
||||
}
|
||||
|
||||
private:
|
||||
bdd_dict_ptr dict_;
|
||||
const_ta_ptr ta_;
|
||||
const_kripke_ptr kripke_;
|
||||
|
||||
// Disallow copy.
|
||||
ta_product(const ta_product&) = delete;
|
||||
ta_product& operator=(const ta_product&) = delete;
|
||||
};
|
||||
|
||||
|
||||
typedef std::shared_ptr<ta_product> ta_product_ptr;
|
||||
typedef std::shared_ptr<const ta_product> const_ta_product_ptr;
|
||||
inline ta_product_ptr product(const const_ta_ptr& testing_automaton,
|
||||
const const_kripke_ptr& kripke_structure)
|
||||
{
|
||||
return std::make_shared<ta_product>(testing_automaton, kripke_structure);
|
||||
}
|
||||
|
||||
class SPOT_API ta_succ_iterator_product_by_changeset :
|
||||
public ta_succ_iterator_product
|
||||
{
|
||||
public:
|
||||
ta_succ_iterator_product_by_changeset(const state_ta_product* s,
|
||||
const ta* t, const kripke* k,
|
||||
bdd changeset);
|
||||
|
||||
/// \brief Move to the next successor in the Kripke structure
|
||||
void next_kripke_dest();
|
||||
};
|
||||
}
|
||||
87
spot/ta/tgta.hh
Normal file
87
spot/ta/tgta.hh
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Laboratoire de
|
||||
// Recherche et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANta_explicitBILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more deta_explicitils.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spot/twa/twa.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
/// \ingroup ta_essentials
|
||||
/// \brief A Transition-based Generalized Testing Automaton (TGTA).
|
||||
///
|
||||
/// Transition-based Generalized Testing Automaton (TGTA) is a new
|
||||
/// kind of automaton that combines features from both TA and TGBA.
|
||||
/// From TA, we take the idea of labeling transitions with
|
||||
/// changesets, however we remove the use of livelock-acceptance
|
||||
/// (because it may require a two-pass emptiness check), and the
|
||||
/// implicit stuttering. From TGBA, we inherit the use of
|
||||
/// transition-based generalized acceptance conditions. The
|
||||
/// resulting Chimera, which we call "Transition-based Generalized
|
||||
/// Testing Automaton" (TGTA), accepts only stuttering-insensitive
|
||||
/// languages like TA, and inherits advantages from both TA and
|
||||
/// TGBA: it has a simple one-pass emptiness-check procedure (the
|
||||
/// same as algorithm the one for TGBA), and can benefit from
|
||||
/// reductions based on the stuttering of the properties pretty much
|
||||
/// like a TA. Livelock acceptance states, which are no longer
|
||||
/// supported are emulated using states with a Büchi accepting
|
||||
/// self-loop labeled by empty changeset.
|
||||
///
|
||||
/// Browsing such automaton can be achieved using two functions:
|
||||
/// \c get_initial_state and \c
|
||||
/// succ_iter. The former returns the initial state(s) while the latter lists
|
||||
/// the successor states of any state. A second implementation of \c succ_iter
|
||||
/// returns only the successors reached through a changeset passed as
|
||||
/// a parameter.
|
||||
///
|
||||
/// Note that although this is a transition-based automata,
|
||||
/// we never represent transitions! Transition informations are
|
||||
/// obtained by querying the iterator over the successors of
|
||||
/// a state.
|
||||
|
||||
class SPOT_API tgta : public twa
|
||||
{
|
||||
|
||||
protected:
|
||||
tgta(const bdd_dict_ptr& d)
|
||||
: twa(d)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~tgta()
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief Get an iterator over the successors of \a state
|
||||
/// filtred by the value of the changeset on transitions between the
|
||||
/// \a state and his successors
|
||||
///
|
||||
/// The iterator has been allocated with \c new. It is the
|
||||
/// responsability of the caller to \c delete it when no
|
||||
/// longer needed.
|
||||
///
|
||||
virtual twa_succ_iterator*
|
||||
succ_iter_by_changeset(const spot::state* s, bdd change_set) const =0;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<tgta> tgta_ptr;
|
||||
typedef std::shared_ptr<const tgta> const_tgta_ptr;
|
||||
}
|
||||
73
spot/ta/tgtaexplicit.cc
Normal file
73
spot/ta/tgtaexplicit.cc
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2010, 2011, 2012, 2014, 2015 Laboratoire de Recherche
|
||||
// et Developpement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <spot/ta/tgtaexplicit.hh>
|
||||
#include <spot/twa/formula2bdd.hh>
|
||||
#include <spot/twa/bddprint.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
tgta_explicit::tgta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state) :
|
||||
tgta(tgba->get_dict()),
|
||||
ta_(make_ta_explicit(tgba, n_acc, artificial_initial_state))
|
||||
{
|
||||
}
|
||||
|
||||
state*
|
||||
tgta_explicit::get_init_state() const
|
||||
{
|
||||
return ta_->get_artificial_initial_state();
|
||||
}
|
||||
|
||||
twa_succ_iterator*
|
||||
tgta_explicit::succ_iter(const spot::state* state) const
|
||||
{
|
||||
return ta_->succ_iter(state);
|
||||
}
|
||||
|
||||
bdd
|
||||
tgta_explicit::compute_support_conditions(const spot::state* in) const
|
||||
{
|
||||
const state_ta_explicit* s = down_cast<const state_ta_explicit*>(in);
|
||||
assert(s);
|
||||
return ta_->get_tgba()->support_conditions(s->get_tgba_state());
|
||||
}
|
||||
|
||||
bdd_dict_ptr
|
||||
tgta_explicit::get_dict() const
|
||||
{
|
||||
return ta_->get_dict();
|
||||
}
|
||||
|
||||
std::string
|
||||
tgta_explicit::format_state(const spot::state* s) const
|
||||
{
|
||||
return ta_->format_state(s);
|
||||
}
|
||||
|
||||
spot::twa_succ_iterator*
|
||||
tgta_explicit::succ_iter_by_changeset(const spot::state* s, bdd chngset) const
|
||||
{
|
||||
return ta_->succ_iter(s, chngset);
|
||||
}
|
||||
|
||||
}
|
||||
76
spot/ta/tgtaexplicit.hh
Normal file
76
spot/ta/tgtaexplicit.hh
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Laboratoire de
|
||||
// Recherche et Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANta_explicitBILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more deta_explicitils.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spot/misc/hash.hh>
|
||||
#include <list>
|
||||
#include <spot/twa/twa.hh>
|
||||
#include <set>
|
||||
#include <spot/tl/formula.hh>
|
||||
#include <cassert>
|
||||
#include <spot/misc/bddlt.hh>
|
||||
#include <spot/ta/taexplicit.hh>
|
||||
#include <spot/ta/tgta.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
/// Explicit representation of a spot::tgta.
|
||||
/// \ingroup ta_representation
|
||||
class SPOT_API tgta_explicit : public tgta
|
||||
{
|
||||
public:
|
||||
tgta_explicit(const const_twa_ptr& tgba,
|
||||
unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state);
|
||||
|
||||
// tgba interface
|
||||
virtual spot::state* get_init_state() const;
|
||||
|
||||
virtual twa_succ_iterator*
|
||||
succ_iter(const spot::state* local_state) const;
|
||||
|
||||
virtual bdd_dict_ptr
|
||||
get_dict() const;
|
||||
|
||||
const_ta_explicit_ptr get_ta() const { return ta_; }
|
||||
ta_explicit_ptr get_ta() { return ta_; }
|
||||
|
||||
virtual std::string format_state(const spot::state* s) const;
|
||||
|
||||
virtual twa_succ_iterator*
|
||||
succ_iter_by_changeset(const spot::state* s, bdd change_set) const;
|
||||
protected:
|
||||
virtual bdd compute_support_conditions(const spot::state* state) const;
|
||||
|
||||
ta_explicit_ptr ta_;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<tgta_explicit> tgta_explicit_ptr;
|
||||
typedef std::shared_ptr<const tgta_explicit> const_tgta_explicit_ptr;
|
||||
|
||||
inline tgta_explicit_ptr
|
||||
make_tgta_explicit(const const_twa_ptr& tgba, unsigned n_acc,
|
||||
state_ta_explicit* artificial_initial_state = nullptr)
|
||||
{
|
||||
return std::make_shared<tgta_explicit>(tgba, n_acc,
|
||||
artificial_initial_state);
|
||||
}
|
||||
}
|
||||
253
spot/ta/tgtaproduct.cc
Normal file
253
spot/ta/tgtaproduct.cc
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2012, 2014, 2015 Laboratoire de Recherche et
|
||||
// Développement de l Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
//#define TRACE
|
||||
|
||||
#include <iostream>
|
||||
#ifdef TRACE
|
||||
#define trace std::clog
|
||||
#else
|
||||
#define trace while (0) std::clog
|
||||
#endif
|
||||
|
||||
#include <spot/ta/tgtaproduct.hh>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <spot/misc/hashfunc.hh>
|
||||
#include <spot/kripke/kripke.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// tgta_succ_iterator_product
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// tgta_product
|
||||
|
||||
tgta_product::tgta_product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right):
|
||||
twa_product(left, right)
|
||||
{
|
||||
}
|
||||
|
||||
const state*
|
||||
tgta_product::get_init_state() const
|
||||
{
|
||||
fixed_size_pool* p = const_cast<fixed_size_pool*> (&pool_);
|
||||
return new (p->allocate()) state_product(left_->get_init_state(),
|
||||
right_->get_init_state(), p);
|
||||
}
|
||||
|
||||
twa_succ_iterator*
|
||||
tgta_product::succ_iter(const state* state) const
|
||||
{
|
||||
const state_product* s = down_cast<const state_product*> (state);
|
||||
assert(s);
|
||||
|
||||
fixed_size_pool* p = const_cast<fixed_size_pool*> (&pool_);
|
||||
|
||||
auto l = std::static_pointer_cast<const kripke>(left_);
|
||||
auto r = std::static_pointer_cast<const tgta>(right_);
|
||||
return new tgta_succ_iterator_product(s, l, r, p);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// tgbtgta_succ_iterator_product
|
||||
tgta_succ_iterator_product::tgta_succ_iterator_product(
|
||||
const state_product* s,
|
||||
const const_kripke_ptr& k, const const_tgta_ptr& t,
|
||||
fixed_size_pool* pool)
|
||||
: source_(s), tgta_(t), kripke_(k), pool_(pool)
|
||||
{
|
||||
|
||||
const state* tgta_init_state = tgta_->get_init_state();
|
||||
if ((s->right())->compare(tgta_init_state) == 0)
|
||||
source_ = nullptr;
|
||||
|
||||
if (!source_)
|
||||
{
|
||||
kripke_succ_it_ = nullptr;
|
||||
kripke_current_dest_state = kripke_->get_init_state();
|
||||
current_condition_
|
||||
= kripke_->state_condition(kripke_current_dest_state);
|
||||
tgta_succ_it_ = tgta_->succ_iter_by_changeset(
|
||||
tgta_init_state, current_condition_);
|
||||
tgta_succ_it_->first();
|
||||
trace
|
||||
<< "*** tgta_succ_it_->done() = ***" << tgta_succ_it_->done()
|
||||
<< std::endl;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
kripke_source_condition = kripke_->state_condition(s->left());
|
||||
kripke_succ_it_ = kripke_->succ_iter(s->left());
|
||||
kripke_current_dest_state = nullptr;
|
||||
tgta_succ_it_ = nullptr;
|
||||
}
|
||||
|
||||
tgta_init_state->destroy();
|
||||
current_state_ = nullptr;
|
||||
}
|
||||
|
||||
tgta_succ_iterator_product::~tgta_succ_iterator_product()
|
||||
{
|
||||
// ta_->free_state(current_state_);
|
||||
if (current_state_)
|
||||
current_state_->destroy();
|
||||
current_state_ = nullptr;
|
||||
delete tgta_succ_it_;
|
||||
delete kripke_succ_it_;
|
||||
if (kripke_current_dest_state)
|
||||
kripke_current_dest_state->destroy();
|
||||
}
|
||||
|
||||
void
|
||||
tgta_succ_iterator_product::step_()
|
||||
{
|
||||
if (!tgta_succ_it_->done())
|
||||
tgta_succ_it_->next();
|
||||
if (tgta_succ_it_->done())
|
||||
{
|
||||
delete tgta_succ_it_;
|
||||
tgta_succ_it_ = nullptr;
|
||||
next_kripke_dest();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tgta_succ_iterator_product::next_kripke_dest()
|
||||
{
|
||||
if (!kripke_succ_it_)
|
||||
return;
|
||||
|
||||
if (!kripke_current_dest_state)
|
||||
{
|
||||
kripke_succ_it_->first();
|
||||
}
|
||||
else
|
||||
{
|
||||
kripke_current_dest_state->destroy();
|
||||
kripke_current_dest_state = nullptr;
|
||||
kripke_succ_it_->next();
|
||||
}
|
||||
|
||||
// If one of the two successor sets is empty initially, we reset
|
||||
// kripke_succ_it_, so that done() can detect this situation
|
||||
// easily. (We choose to reset kripke_succ_it_ because this
|
||||
// variable is already used by done().)
|
||||
if (kripke_succ_it_->done())
|
||||
{
|
||||
delete kripke_succ_it_;
|
||||
kripke_succ_it_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
kripke_current_dest_state = kripke_succ_it_->dst();
|
||||
bdd kripke_current_dest_condition = kripke_->state_condition(
|
||||
kripke_current_dest_state);
|
||||
|
||||
current_condition_ = bdd_setxor(kripke_source_condition,
|
||||
kripke_current_dest_condition);
|
||||
tgta_succ_it_ = tgta_->succ_iter_by_changeset(source_->right(),
|
||||
current_condition_);
|
||||
tgta_succ_it_->first();
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
tgta_succ_iterator_product::first()
|
||||
{
|
||||
|
||||
next_kripke_dest();
|
||||
trace << "*** first() .... if(done()) = ***" << done() << std::endl;
|
||||
return find_next_succ_();
|
||||
}
|
||||
|
||||
bool
|
||||
tgta_succ_iterator_product::next()
|
||||
{
|
||||
current_state_->destroy();
|
||||
current_state_ = nullptr;
|
||||
|
||||
step_();
|
||||
|
||||
trace << "*** next() .... if(done()) = ***" << done() << std::endl;
|
||||
|
||||
return find_next_succ_();
|
||||
}
|
||||
|
||||
bool
|
||||
tgta_succ_iterator_product::find_next_succ_()
|
||||
{
|
||||
while (!done())
|
||||
{
|
||||
if (!tgta_succ_it_->done())
|
||||
{
|
||||
current_state_ = new (pool_->allocate()) state_product(
|
||||
kripke_current_dest_state->clone(),
|
||||
tgta_succ_it_->dst(), pool_);
|
||||
current_acceptance_conditions_
|
||||
= tgta_succ_it_->acc();
|
||||
return true;
|
||||
}
|
||||
|
||||
step_();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
tgta_succ_iterator_product::done() const
|
||||
{
|
||||
if (!source_)
|
||||
{
|
||||
return !tgta_succ_it_ || tgta_succ_it_->done();
|
||||
}
|
||||
else
|
||||
{
|
||||
return !kripke_succ_it_ || kripke_succ_it_->done();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
state_product*
|
||||
tgta_succ_iterator_product::dst() const
|
||||
{
|
||||
trace
|
||||
<< "*** dst() .... if(done()) = ***" << done() << std::endl;
|
||||
return current_state_->clone();
|
||||
}
|
||||
|
||||
bdd
|
||||
tgta_succ_iterator_product::cond() const
|
||||
{
|
||||
return current_condition_;
|
||||
}
|
||||
|
||||
acc_cond::mark_t
|
||||
tgta_succ_iterator_product::acc() const
|
||||
{
|
||||
return current_acceptance_conditions_;
|
||||
}
|
||||
|
||||
}
|
||||
101
spot/ta/tgtaproduct.hh
Normal file
101
spot/ta/tgtaproduct.hh
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2011, 2012, 2013, 2014 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
// Spot is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spot/twa/twa.hh>
|
||||
#include <spot/twa/twaproduct.hh>
|
||||
#include <spot/misc/fixpool.hh>
|
||||
#include <spot/kripke/kripke.hh>
|
||||
#include <spot/ta/tgta.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
/// \brief A lazy product. (States are computed on the fly.)
|
||||
class SPOT_API tgta_product : public twa_product
|
||||
{
|
||||
public:
|
||||
tgta_product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right);
|
||||
|
||||
virtual const state* get_init_state() const;
|
||||
|
||||
virtual twa_succ_iterator*
|
||||
succ_iter(const state* local_state) const;
|
||||
};
|
||||
|
||||
inline twa_ptr product(const const_kripke_ptr& left,
|
||||
const const_tgta_ptr& right)
|
||||
{
|
||||
return std::make_shared<tgta_product>(left, right);
|
||||
}
|
||||
|
||||
/// \brief Iterate over the successors of a product computed on the fly.
|
||||
class SPOT_API tgta_succ_iterator_product : public twa_succ_iterator
|
||||
{
|
||||
public:
|
||||
tgta_succ_iterator_product(const state_product* s,
|
||||
const const_kripke_ptr& k,
|
||||
const const_tgta_ptr& tgta,
|
||||
fixed_size_pool* pool);
|
||||
|
||||
virtual
|
||||
~tgta_succ_iterator_product();
|
||||
|
||||
// iteration
|
||||
bool first();
|
||||
bool next();
|
||||
bool done() const;
|
||||
|
||||
// inspection
|
||||
state_product*
|
||||
dst() const;
|
||||
bdd
|
||||
cond() const;
|
||||
|
||||
acc_cond::mark_t
|
||||
acc() const;
|
||||
|
||||
private:
|
||||
//@{
|
||||
/// Internal routines to advance to the next successor.
|
||||
void
|
||||
step_();
|
||||
bool find_next_succ_();
|
||||
|
||||
void
|
||||
next_kripke_dest();
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
const state_product* source_;
|
||||
const_tgta_ptr tgta_;
|
||||
const_kripke_ptr kripke_;
|
||||
fixed_size_pool* pool_;
|
||||
twa_succ_iterator* tgta_succ_it_;
|
||||
twa_succ_iterator* kripke_succ_it_;
|
||||
state_product* current_state_;
|
||||
bdd current_condition_;
|
||||
acc_cond::mark_t current_acceptance_conditions_;
|
||||
bdd kripke_source_condition;
|
||||
const state* kripke_current_dest_state;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue