* src/tgbaalgos/emptinesscheck.hh (emptiness_check::check2): Move

into ...
(emptiness_check_shy): This new subclass of emptiness_check.
* src/tgbaalgos/emptinesscheck.cc, src/tgbatest/ltl2tgba.cc,
iface/gspn/ltlgspn.cc: Adjust.
This commit is contained in:
Alexandre Duret-Lutz 2004-04-13 11:44:42 +00:00
parent be17fc19f5
commit b85e930232
5 changed files with 77 additions and 48 deletions

View file

@ -1,5 +1,11 @@
2004-04-13 Alexandre Duret-Lutz <adl@src.lip6.fr> 2004-04-13 Alexandre Duret-Lutz <adl@src.lip6.fr>
* src/tgbaalgos/emptinesscheck.hh (emptiness_check::check2): Move
into ...
(emptiness_check_shy): This new subclass of emptiness_check.
* src/tgbaalgos/emptinesscheck.cc, src/tgbatest/ltl2tgba.cc,
iface/gspn/ltlgspn.cc: Adjust.
* src/tgba/bdddict.hh (bdd_dict::annon_free_list): Hide from Swig. * src/tgba/bdddict.hh (bdd_dict::annon_free_list): Hide from Swig.
* src/tgbaalgo/semptinesscheck.hh (counter_example): New class, * src/tgbaalgo/semptinesscheck.hh (counter_example): New class,

View file

@ -169,13 +169,16 @@ main(int argc, char **argv)
case Couvreur: case Couvreur:
case Couvreur2: case Couvreur2:
{ {
spot::emptiness_check ec(prod); spot::emptiness_check* ec;
bool res;
if (check == Couvreur) if (check == Couvreur)
res = ec.check(); ec = new spot::emptiness_check(prod);
else else
res = ec.check2(); ec = new spot::emptiness_check_shy(prod);
const spot::emptiness_check_status* ecs = ec.result();
bool res = ec->check();
const spot::emptiness_check_status* ecs = ec->result();
if (!res) if (!res)
{ {
if (compute_counter_example) if (compute_counter_example)
@ -196,6 +199,7 @@ main(int argc, char **argv)
ecs->print_stats(std::cout); ecs->print_stats(std::cout);
} }
std::cout << std::endl; std::cout << std::endl;
delete ec;
if (!res) if (!res)
exit(1); exit(1);
} }

View file

@ -111,8 +111,6 @@ namespace spot
typedef std::pair<const spot::state*, tgba_succ_iterator*> pair_state_iter; typedef std::pair<const spot::state*, tgba_succ_iterator*> pair_state_iter;
emptiness_check::emptiness_check(const tgba* a) emptiness_check::emptiness_check(const tgba* a)
{ {
ecs_ = new emptiness_check_status(a); ecs_ = new emptiness_check_status(a);
@ -309,6 +307,23 @@ namespace spot
return true; return true;
} }
const emptiness_check_status*
emptiness_check::result() const
{
return ecs_;
}
//////////////////////////////////////////////////////////////////////
emptiness_check_shy::emptiness_check_shy(const tgba* a)
: emptiness_check(a)
{
}
emptiness_check_shy::~emptiness_check_shy()
{
}
struct successor { struct successor {
bdd acc; bdd acc;
const spot::state* s; const spot::state* s;
@ -316,7 +331,7 @@ namespace spot
}; };
bool bool
emptiness_check::check2() emptiness_check_shy::check()
{ {
// We use five main data in this algorithm: // We use five main data in this algorithm:
// * emptiness_check::root, a stack of strongly connected components (SCC), // * emptiness_check::root, a stack of strongly connected components (SCC),
@ -474,12 +489,6 @@ namespace spot
} }
} }
const emptiness_check_status*
emptiness_check::result() const
{
return ecs_;
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
bool bool

View file

@ -80,6 +80,7 @@ namespace spot
void print_stats(std::ostream& os) const; void print_stats(std::ostream& os) const;
}; };
//@{
/// \brief Check whether the language of an automate is empty. /// \brief Check whether the language of an automate is empty.
/// ///
/// This is based on the following paper. /// This is based on the following paper.
@ -100,41 +101,39 @@ namespace spot
/// isbn = {3-540-66587-0} /// isbn = {3-540-66587-0}
/// } /// }
/// \endverbatim /// \endverbatim
///
/// check() returns true if the automaton's language is empty. When
/// it return false, a stack of SCC has been built and can
/// later be used by counter_example().
///
/// There are two variants of this algorithm: emptiness_check() and
/// emptiness_check_shy(). They differ in their memory usage, the
/// number for successors computed before they are used and the way
/// the depth first search is directed.
///
/// emptiness_check() performs a straightforward depth first search.
/// The DFS stacks store tgba_succ_iterators, so that only the
/// iterators which really are explored are computed.
///
/// emptiness_check_shy() try to explore successors which are
/// visited states first. this helps to merge SCCs and generally
/// helps to produce shorter counter-examples. However this
/// algorithm cannot stores unprocessed successors as
/// tgba_succ_iterators: it must compute all successors of a state
/// at once in order to decide which to explore first, and must keep
/// a list of all unexplored successors in its DFS stack.
class emptiness_check class emptiness_check
{ {
public: public:
emptiness_check(const tgba* a); emptiness_check(const tgba* a);
~emptiness_check(); virtual ~emptiness_check();
//@{ /// check whether the automaton's language is empty
/// \brief check whether an automaton's language is empty virtual bool check();
///
/// Returns true if the automaton's language is empty. When
/// it return false, a stack of SCC has been built and can
/// later be used by counter_example().
///
/// There are two variants of this algorithm: check() and check2().
/// They differ in their memory usage, the number for successors computed
/// before they are used and the way the depth first search is directed.
///
/// check() performs a straightforward depth first search. The DFS
/// stacks store tgba_succ_iterators, so that only the iterators which
/// really are explored are computed.
///
/// check2() try to explore successors which are visited states first.
/// this helps to merge SCCs and generally helps to produce shorter
/// counter-examples. However this algorithm cannot stores unprocessed
/// successors as tgba_succ_iterators: it must compute all successors
/// of a state at once in order to decide which to explore first, and
/// must keep a list of all unexplored successors in its DFS stack.
bool check();
bool check2();
//@}
const emptiness_check_status* result() const; const emptiness_check_status* result() const;
private: protected:
emptiness_check_status* ecs_; emptiness_check_status* ecs_;
/// \brief Remove a strongly component from the hash. /// \brief Remove a strongly component from the hash.
/// ///
@ -142,9 +141,18 @@ namespace spot
/// state. In other words, it removes the strongly connected /// state. In other words, it removes the strongly connected
/// component that contains this state. /// component that contains this state.
void remove_component(const state* start_delete); void remove_component(const state* start_delete);
}; };
class emptiness_check_shy : public emptiness_check
{
public:
emptiness_check_shy(const tgba* a);
virtual ~emptiness_check_shy();
virtual bool check();
};
//@}
class counter_example class counter_example
{ {

View file

@ -364,28 +364,30 @@ main(int argc, char** argv)
case Couvreur: case Couvreur:
case Couvreur2: case Couvreur2:
{ {
spot::emptiness_check ec = spot::emptiness_check(a); spot::emptiness_check* ec;
bool res;
if (echeck == Couvreur) if (echeck == Couvreur)
res = ec.check(); ec = new spot::emptiness_check(a);
else else
res = ec.check2(); ec = new spot::emptiness_check_shy(a);
bool res = ec->check();
if (expect_counter_example) if (expect_counter_example)
{ {
if (res) if (res)
{ {
exit_code = 1; exit_code = 1;
delete ec;
break; break;
} }
spot::counter_example ce(ec.result()); spot::counter_example ce(ec->result());
ce.print_result(std::cout); ce.print_result(std::cout);
} }
else else
{ {
exit_code = !res; exit_code = !res;
} }
delete ec;
} }
break; break;
case MagicSearch: case MagicSearch: