Commit c76e651b authored by Ala-Eddine Ben-Salem's avatar Ala-Eddine Ben-Salem Committed by Alexandre Duret-Lutz
Browse files

Doxygen comments.

* src/ta/ta.cc, src/ta/ta.hh, src/ta/taexplicit.hh,
src/ta/taproduct.cc, src/ta/taproduct.hh, src/ta/tgbtaexplicit.cc,
src/ta/taexplicit.cc, src/ta/tgbtaproduct.cc,
src/taalgos/emptinessta.cc, src/taalgos/emptinessta.hh,
src/taalgos/tgba2ta.cc, src/taalgos/tgba2ta.hh,
src/tgbatest/ltl2ta.test, src/tgbatest/ltl2tgba.cc: Add Doxygen
comments.
parent a13d2c8f
......@@ -24,11 +24,6 @@
namespace spot
{
spot::state*
ta::get_artificial_initial_state() const
{
return 0;
}
scc_stack_ta::connected_component::connected_component(int i)
{
......
......@@ -31,10 +31,51 @@
namespace spot
{
// Forward declarations. See below.
class ta_succ_iterator;
/// ta representation of a Testing Automata
/// \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
/// \brief A Testing Automaton.
/// \ingroup ta_essentials
///
/// The Testing Automata (TA) were introduced by
/// Henri Hansen, Wojciech Penczek and Antti Valmari
/// in "Stuttering-insensitive automata for on-the-fly de- tection 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 transition "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 ta
{
......@@ -46,52 +87,103 @@ namespace spot
typedef std::set<state*, state_ptr_less_than> states_set_t;
/// \brief Get the initial states set of the automaton.
virtual const states_set_t
get_initial_states_set() const = 0;
virtual spot::state*
get_artificial_initial_state() 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)
spot::state*
get_artificial_initial_state() const
{
return 0;
}
/// \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* s) const = 0;
succ_iter(const spot::state* state) const = 0;
/// \brief Get an iterator over the successors of \a state
/// filtred by the changeset labeling the 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* s, bdd condition) const = 0;
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.
virtual bdd_dict*
get_dict() const = 0;
/// \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;
/// \brief Return the set of all acceptance conditions used
/// by this automaton.
/// by this automaton
/// (for Generalized form: Transition-based Generalized Testing Automata).
///
/// The goal of the emptiness check is to ensure that
/// a strongly connected component walks through each
/// of these acceptiong conditions. I.e., the union
/// of the acceptiong conditions of all transition in
/// the SCC should be equal to the result of this function.
virtual bdd all_acceptance_conditions() const = 0;
virtual bdd
all_acceptance_conditions() const = 0;
};
/// Successor iterators used by spot::ta.
/// \brief Iterate over the successors of a state.
/// \ingroup ta_essentials
///
/// 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 tgba_succ_iterator
{
public:
......@@ -109,12 +201,13 @@ namespace spot
virtual state*
current_state() const = 0;
/// \brief Get the changeset on the transition leading to current successor.
///
/// This is a boolean function of atomic propositions.
virtual bdd
current_condition() const = 0;
virtual bool
is_stuttering_transition() const = 0;
bdd
current_acceptance_conditions() const = 0;
......@@ -173,6 +266,29 @@ namespace spot
stack_type s;
};
/// \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
}
#endif // SPOT_TA_TA_HH
......@@ -80,9 +80,13 @@ namespace spot
state*
ta_explicit_succ_iterator::current_state() const
{
trace << "***ta_explicit_succ_iterator::current_state() if(done()) =***" << done() << std::endl;
trace
<< "***ta_explicit_succ_iterator::current_state() if(done()) =***"
<< done() << std::endl;
assert(!done());
trace << "***ta_explicit_succ_iterator::current_state() (*i_)->condition =***" << (*i_)->condition << std::endl;
trace
<< "***ta_explicit_succ_iterator::current_state() (*i_)->condition =***"
<< (*i_)->condition << std::endl;
state_ta_explicit* s = (*i_)->dest;
return s;
}
......@@ -101,11 +105,6 @@ namespace spot
return (*i_)->acceptance_conditions;
}
bool
ta_explicit_succ_iterator::is_stuttering_transition() const
{
return source_->get_tgba_condition() == ((*i_)->dest)->get_tgba_condition();
}
////////////////////////////////////////
// state_ta_explicit
......@@ -414,7 +413,6 @@ namespace spot
}
void
ta_explicit::create_transition(state_ta_explicit* source, bdd condition,
bdd acceptance_conditions, state_ta_explicit* dest, bool add_at_beginning)
......
......@@ -37,7 +37,8 @@ namespace spot
class ta_explicit_succ_iterator;
class ta_explicit;
/// ta_explicit explicit representa_explicittion of a Testing Automata_explicit
/// Explicit representation of a spot::ta.
/// \ingroup ta_representation
class ta_explicit : public ta
{
public:
......@@ -53,7 +54,6 @@ namespace spot
void
add_to_initial_states_set(state* s, bdd condition = bddfalse);
void
create_transition(state_ta_explicit* source, bdd condition,
bdd acceptance_conditions, state_ta_explicit* dest,
......@@ -145,11 +145,12 @@ namespace spot
};
/// states used by spot::ta_explicit.
/// \ingroup ta_
/// \ingroup ta_representation
class state_ta_explicit : public spot::state
{
public:
/// Explicit transitions.
struct transition
{
bdd condition;
......@@ -176,11 +177,11 @@ namespace spot
virtual state_ta_explicit*
clone() const;
virtual void destroy() const
virtual void
destroy() const
{
}
virtual
~state_ta_explicit()
{
......@@ -214,9 +215,12 @@ namespace spot
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();
......@@ -257,9 +261,6 @@ namespace spot
virtual bdd
current_acceptance_conditions() const;
virtual bool
is_stuttering_transition() const;
private:
state_ta_explicit::transitions* transitions_;
state_ta_explicit::transitions::const_iterator i_;
......
......@@ -348,11 +348,6 @@ namespace spot
return ta_->is_livelock_accepting_state(stp->get_ta_state());
}
spot::state*
ta_product::get_artificial_initial_state() const
{
return 0;
}
bool
ta_product::is_initial_state(const spot::state* s) const
......
......@@ -28,8 +28,9 @@ namespace spot
{
/// \brief A state for spot::ta_product.
/// \ingroup emptiness_check
///
/// This state is in fact a pair of state: the state from the ta
/// This state is in fact a pair of state: the state from the TA
/// automaton and that of Kripke structure.
class state_ta_product : public state
{
......@@ -37,7 +38,6 @@ namespace spot
/// \brief Constructor
/// \param ta_state The state from the ta automaton.
/// \param kripke_state_ The state from Kripke structure.
state_ta_product(state* ta_state, state* kripke_state) :
ta_state_(ta_state), kripke_state_(kripke_state)
{
......@@ -100,6 +100,7 @@ namespace spot
bdd
current_acceptance_conditions() const;
/// \brief Return true if the changeset of the current transition is empty
bool
is_stuttering_transition() const;
......@@ -111,6 +112,7 @@ namespace spot
void
next_non_stuttering_();
/// \brief Move to the next successor in the kripke structure
void
next_kripke_dest();
......@@ -131,31 +133,26 @@ namespace spot
};
/// \brief A lazy product. (States are computed on the fly.)
/// \brief A lazy product between a Testing automaton and a Kripke structure.
/// (States are computed on the fly.)
/// \ingroup emptiness_check
class ta_product : public ta
{
public:
ta_product(const ta* testing_automata, const kripke* kripke_structure);
/// \brief Constructor.
/// \param testing_automaton The TA component in the product.
/// \param kripke_structure The Kripke component in the product.
ta_product(const ta* testing_automaton, const kripke* kripke_structure);
virtual
~ta_product();
virtual const states_set_t
virtual const std::set<state*, state_ptr_less_than>
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 condition) const
{
if (condition == bddtrue)
return succ_iter(s);
//TODO
return 0;
}
virtual bdd_dict*
get_dict() const;
......@@ -168,12 +165,11 @@ namespace spot
virtual bool
is_livelock_accepting_state(const spot::state* s) const;
virtual spot::state*
get_artificial_initial_state() 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;
......
......@@ -46,8 +46,8 @@ namespace spot
tgba_succ_iterator*
tgbta_explicit::succ_iter(const spot::state* state,
const spot::state* global_state,
const tgba* global_automaton) const
const spot::state*,
const tgba*) const
{
return ta_explicit::succ_iter(state);
}
......@@ -55,13 +55,13 @@ namespace spot
bdd
tgbta_explicit::compute_support_conditions(const spot::state* in) const
{
return get_tgba()->support_conditions(((state_ta_explicit*) in)->get_tgba_state());
return get_tgba()->support_conditions(((const state_ta_explicit*) in)->get_tgba_state());
}
bdd
tgbta_explicit::compute_support_variables(const spot::state* in) const
{
return get_tgba()->support_variables(((state_ta_explicit*) in)->get_tgba_state());
return get_tgba()->support_variables(((const state_ta_explicit*) in)->get_tgba_state());
}
bdd_dict*
......
......@@ -58,16 +58,16 @@ namespace spot
}
tgba_succ_iterator*
tgbta_product::succ_iter(const state* local_state, const state* global_state,
const tgba* global_automaton) const
tgbta_product::succ_iter(const state* local_state, const state*,
const tgba*) const
{
const state_product* s = down_cast<const state_product*> (local_state);
assert(s);
fixed_size_pool* p = const_cast<fixed_size_pool*> (&pool_);
return new tgbta_succ_iterator_product(s, (kripke*) left_,
(tgbta *) right_, p);
return new tgbta_succ_iterator_product(s, (const kripke*) left_,
(const tgbta *) right_, p);
}
////////////////////////////////////////////////////////////
......
......@@ -43,11 +43,11 @@ namespace spot
ta_check::~ta_check()
{
}
bool
ta_check::check(bool disable_second_pass)
ta_check::check(bool disable_second_pass,
disable_heuristic_for_livelock_detection)
{
// We use five main data in this algorithm:
......@@ -67,14 +67,12 @@ namespace spot
int num = 1;
// * todo: the depth-first search stack. This holds pairs of the
// form (STATE, ITERATOR) where ITERATOR is a ta_succ_iterator
// form (STATE, ITERATOR) where ITERATOR is a ta_succ_iterator_product
// over the successors of STATE. In our use, ITERATOR should
// always be freed when TODO is popped, but STATE should not because
// it is also used as a key in H.
std::stack<pair_state_iter> todo;
Sgi::hash_map<const state*, std::string, state_ptr_hash, state_ptr_equal>
colour;
......@@ -88,7 +86,8 @@ namespace spot
bool livelock_acceptance_states_not_found = true;
bool activate_heuristic = (is_full_2_pass_ == disable_second_pass);
bool activate_heuristic = !disable_heuristic_for_livelock_detection
&& (is_full_2_pass_ == disable_second_pass);
// Setup depth-first search from initial states.
const ta* ta_ = a_->get_ta();
......@@ -117,7 +116,7 @@ namespace spot
scc.push(num);
arc.push(bddfalse);
ta_succ_iterator* iter = a_->succ_iter(init);
ta_succ_iterator_product* iter = a_->succ_iter(init);
iter->first();
todo.push(pair_state_iter(init, iter));
......@@ -133,7 +132,7 @@ namespace spot
state* curr = todo.top().first;
// We are looking at the next successor in SUCC.
ta_succ_iterator* succ = todo.top().second;
ta_succ_iterator_product* succ = todo.top().second;
// If there is no more successor, backtrack.
if (succ->done())
......@@ -147,7 +146,8 @@ namespace spot
trace
<< "PASS 1 : backtrack" << std::endl;
if (a_->is_livelock_accepting_state(curr))
if (a_->is_livelock_accepting_state(curr)
&& !a_->is_accepting_state(curr))
{
livelock_acceptance_states_not_found = false;
trace
......@@ -241,7 +241,7 @@ namespace spot
scc.push(num);
arc.push(acc_cond);
ta_succ_iterator* iter = a_->succ_iter(dest);
ta_succ_iterator_product* iter = a_->succ_iter(dest);
iter->first();
todo.push(pair_state_iter(dest, iter));
//colour[dest] = GREY;
......@@ -315,10 +315,11 @@ namespace spot
a_->get_dict(), scc.top().condition) << std::endl;
trace
<< "PASS 1: a_->all_acceptance_conditions() : "
<< ( a_->all_acceptance_conditions()) << std::endl;
<< (a_->all_acceptance_conditions()) << std::endl;
trace
<< "PASS 1 CYCLE and (scc.top().condition == a_->all_acceptance_conditions()) : "
<< (scc.top().condition == a_->all_acceptance_conditions()) << std::endl;
<< "PASS 1 CYCLE and (scc.top().condition == a_->all_acceptance_conditions()) : "
<< (scc.top().condition
== a_->all_acceptance_conditions()) << std::endl;
trace
<< "PASS 1: bddtrue : " << (a_->all_acceptance_conditions()
......@@ -407,7 +408,7 @@ namespace spot
}
bool
ta_check::livelock_detection(const ta* t)
ta_check::livelock_detection(const ta_product* t)
{
// We use five main data in this algorithm:
......@@ -460,7 +461,7 @@ namespace spot
h->insert(init, ++num);
sscc.push(num);
sscc.top().is_accepting = t->is_livelock_accepting_state(init);
ta_succ_iterator* iter = t->succ_iter(init);
ta_succ_iterator_product* iter = t->succ_iter(init);
iter->first();
todo.push(pair_state_iter(init, iter));
inc_depth();
......@@ -473,7 +474,7 @@ namespace spot
state* curr = todo.top().first;
// We are looking at the next successor in SUCC.
ta_succ_iterator* succ = todo.top().second;
ta_succ_iterator_product* succ = todo.top().second;
// If there is no more successor, backtrack.
if (succ->done())
......@@ -554,7 +555,7 @@ namespace spot
sscc.push(num);
sscc.top().is_accepting = t->is_livelock_accepting_state(dest);
ta_succ_iterator* iter = t->succ_iter(dest);
ta_succ_iterator_product* iter = t->succ_iter(dest);
iter->first();
todo.push(pair_state_iter(dest, iter));
inc_depth();
......@@ -651,26 +652,24 @@ namespace spot
delete h;
}
void
ta_check::clear(numbered_state_heap* h, std::stack<pair_state_iter> todo,
spot::ta_succ_iterator* init_states_it)
{
ta_check::clear(numbered_state_heap* h, std::stack<pair_state_iter> todo,
spot::ta_succ_iterator* init_states_it)
{
set_states(states() + h->size());
set_states(states() + h->size());
delete init_states_it;
// Release all iterators in TODO.
while (!todo.empty())
{
delete todo.top().second;
todo.pop();
dec_depth();
}
delete h;
}
// Release all iterators in TODO.
while (!todo.empty())
{
delete todo.top().second;
todo.pop();
dec_depth();
}
delete h;
}
std::ostream&
ta_check::print_stats(std::ostream& os) const
......
......@@ -36,11 +36,54 @@ namespace spot