* src/misc/optionmap.cc, src/misc/optionmap.hh (option_map): New class.

* src/misc/Makefile.am: Add it.
* src/tgbaalgos/emptiness.cc, src/tgbaalgos/emptiness.hh: Add option
facilities to the classes emptiness_check and emptiness_result
* src/tgbaalgos/magic.cc, src/tgbaalgos/magic.hh,
src/tgbaalgos/se05.cc, src/tgbaalgos/se05.hh: Compute optionnaly
accepting runs from stack.
* src/tgbatest/randtgba.cc: Make this option public.
This commit is contained in:
Denis Poitrenaud 2005-02-07 15:18:41 +00:00
parent e812e1926f
commit 661dee8633
13 changed files with 578 additions and 95 deletions

View file

@ -27,7 +27,6 @@
namespace spot
{
tgba_run::~tgba_run()
{
for (steps::const_iterator i = prefix.begin(); i != prefix.end(); ++i)

View file

@ -22,9 +22,11 @@
#ifndef SPOT_TGBAALGOS_EMPTINESS_HH
# define SPOT_TGBAALGOS_EMPTINESS_HH
#include <map>
#include <list>
#include <iosfwd>
#include <bdd.h>
#include "misc/optionmap.hh"
#include "tgba/state.hh"
#include "emptiness_stats.hh"
@ -74,8 +76,13 @@ namespace spot
class emptiness_check_result
{
public:
emptiness_check_result(const tgba* a)
: a_(a)
emptiness_check_result(const tgba* a, option_map o = option_map())
: a_(a), o_(o)
{
}
virtual
~emptiness_check_result()
{
}
@ -100,19 +107,43 @@ namespace spot
return a_;
}
/// Return the options parametrizing how the accepting run is computed.
const option_map&
options() const
{
return o_;
}
/// Modify the options parametrizing how the accepting run is computed.
const char*
parse_options(char* options)
{
option_map old(o_);
const char* s = o_.parse_options(options);
options_updated(old);
return s;
}
/// Return statistics, if available.
virtual const unsigned_statistics* statistics() const;
protected:
/// React when options are modified.
virtual void options_updated(const option_map& old)
{
(void)old;
}
const tgba* a_; ///< The automaton.
option_map o_; ///< The options
};
/// Common interface to emptiness check algorithms.
class emptiness_check
{
public:
emptiness_check(const tgba* a)
: a_(a)
emptiness_check(const tgba* a, option_map o = option_map())
: a_(a), o_(o)
{
}
virtual ~emptiness_check();
@ -124,6 +155,23 @@ namespace spot
return a_;
}
/// Return the options parametrizing how the emptiness check is realized.
const option_map&
options() const
{
return o_;
}
/// Modify the options parametrizing how the accepting run is realized.
const char*
parse_options(char* options)
{
option_map old(o_);
const char* s = o_.parse_options(options);
options_updated(old);
return s;
}
/// \brief Check whether the automaton contain an accepting run.
///
/// Return 0 if the automaton accept no run. Return an instance
@ -142,8 +190,15 @@ namespace spot
/// Print statistics, if any.
virtual std::ostream& print_stats(std::ostream& os) const;
/// React when options are modified.
virtual void options_updated(const option_map& old)
{
(void)old;
}
protected:
const tgba* a_; ///< The automaton.
option_map o_; ///< The options
};
/// @}

View file

@ -53,8 +53,8 @@ namespace spot
///
/// \pre The automaton \a a must have at most one accepting
/// condition (i.e. it is a TBA).
magic_search(const tgba *a, size_t size)
: emptiness_check(a),
magic_search(const tgba *a, size_t size, option_map o = option_map())
: emptiness_check(a, o),
h(size),
all_cond(a->all_acceptance_conditions())
{
@ -96,17 +96,17 @@ namespace spot
h.add_new_state(s0, BLUE);
push(st_blue, s0, bddfalse, bddfalse);
if (dfs_blue())
return new ndfs_result<magic_search<heap>, heap>(*this);
return new magic_search_result(*this, options());
}
else
{
h.pop_notify(st_red.front().s);
pop(st_red);
if (!st_red.empty() && dfs_red())
return new ndfs_result<magic_search<heap>, heap>(*this);
return new magic_search_result(*this, options());
else
if (dfs_blue())
return new ndfs_result<magic_search<heap>, heap>(*this);
return new magic_search_result(*this, options());
}
return 0;
}
@ -314,6 +314,108 @@ namespace spot
return false;
}
class result_from_stack: public emptiness_check_result,
public acss_statistics
{
public:
result_from_stack(magic_search& ms)
: emptiness_check_result(ms.automaton()), ms_(ms)
{
}
virtual tgba_run* accepting_run()
{
assert(!ms_.st_blue.empty());
assert(!ms_.st_red.empty());
tgba_run* run = new tgba_run;
typename stack_type::const_reverse_iterator i, j, end;
tgba_run::steps* l;
l = &run->prefix;
i = ms_.st_blue.rbegin();
end = ms_.st_blue.rend(); --end;
j = i; ++j;
for (; i != end; ++i, ++j)
{
tgba_run::step s = { i->s->clone(), j->label, j->acc };
l->push_back(s);
}
l = &run->cycle;
j = ms_.st_red.rbegin();
tgba_run::step s = { i->s->clone(), j->label, j->acc };
l->push_back(s);
i = j; ++j;
end = ms_.st_red.rend(); --end;
for (; i != end; ++i, ++j)
{
tgba_run::step s = { i->s->clone(), j->label, j->acc };
l->push_back(s);
}
return run;
}
unsigned acss_states() const
{
return 0;
}
private:
magic_search& ms_;
};
# define FROM_STACK "ar:from_stack"
class magic_search_result: public emptiness_check_result
{
public:
magic_search_result(magic_search& m, option_map o = option_map())
: emptiness_check_result(m.automaton(), o), ms(m)
{
if (options()[FROM_STACK])
computer = new result_from_stack(ms);
else
computer = new ndfs_result<magic_search<heap>, heap>(ms);
}
virtual void options_updated(const option_map& old)
{
if (old[FROM_STACK] && !options()[FROM_STACK])
{
delete computer;
computer = new ndfs_result<magic_search<heap>, heap>(ms);
}
else if (!old[FROM_STACK] && options()[FROM_STACK])
{
delete computer;
computer = new result_from_stack(ms);
}
}
virtual ~magic_search_result()
{
delete computer;
}
virtual tgba_run* accepting_run()
{
return computer->accepting_run();
}
virtual const unsigned_statistics* statistics() const
{
return computer->statistics();
}
private:
emptiness_check_result* computer;
magic_search& ms;
};
};
class explicit_magic_search_heap
@ -471,15 +573,15 @@ namespace spot
} // anonymous
emptiness_check* explicit_magic_search(const tgba *a)
emptiness_check* explicit_magic_search(const tgba *a, option_map o)
{
return new magic_search<explicit_magic_search_heap>(a, 0);
return new magic_search<explicit_magic_search_heap>(a, 0, o);
}
emptiness_check* bit_state_hashing_magic_search(
const tgba *a, size_t size)
emptiness_check* bit_state_hashing_magic_search(const tgba *a, size_t size,
option_map o)
{
return new magic_search<bsh_magic_search_heap>(a, size);
return new magic_search<bsh_magic_search_heap>(a, size, o);
}
}

View file

@ -23,6 +23,7 @@
# define SPOT_TGBAALGOS_MAGIC_HH
#include <cstddef>
#include "misc/optionmap.hh"
namespace spot
{
@ -93,7 +94,8 @@ namespace spot
/// }
/// \endverbatim
///
emptiness_check* explicit_magic_search(const tgba *a);
emptiness_check* explicit_magic_search(const tgba *a,
option_map o = option_map());
/// \brief Returns an emptiness checker on the spot::tgba automaton \a a.
///
@ -113,13 +115,17 @@ namespace spot
/// }
/// \endverbatim
///
/// Consequently, the detection of an acceptence cycle is not ensured. The
/// implemented algorithm is the same as the one of
/// Consequently, the detection of an acceptence cycle is not ensured.
///
/// The size of the heap is limited to \n size bytes.
///
/// The implemented algorithm is the same as the one of
/// spot::explicit_magic_search.
///
/// \sa spot::explicit_magic_search
///
emptiness_check* bit_state_hashing_magic_search(const tgba *a, size_t size);
emptiness_check* bit_state_hashing_magic_search(const tgba *a, size_t size,
option_map o = option_map());
/// @}
}

View file

@ -37,8 +37,6 @@
#include "se05.hh"
#include "ndfs_result.hxx"
/// FIXME: make compiling depedent the taking into account of weights.
namespace spot
{
namespace
@ -55,9 +53,8 @@ namespace spot
///
/// \pre The automaton \a a must have at most one accepting
/// condition (i.e. it is a TBA).
se05_search(const tgba *a, size_t size)
: emptiness_check(a),
ec_statistics(),
se05_search(const tgba *a, size_t size, option_map o = option_map())
: emptiness_check(a, o),
h(size),
all_cond(a->all_acceptance_conditions())
{
@ -99,17 +96,17 @@ namespace spot
h.add_new_state(s0, CYAN);
push(st_blue, s0, bddfalse, bddfalse);
if (dfs_blue())
return new ndfs_result<se05_search<heap>, heap>(*this);
return new se05_result(*this, options());
}
else
{
h.pop_notify(st_red.front().s);
pop(st_red);
if (!st_red.empty() && dfs_red())
return new ndfs_result<se05_search<heap>, heap>(*this);
return new se05_result(*this, options());
else
if (dfs_blue())
return new ndfs_result<se05_search<heap>, heap>(*this);
return new se05_result(*this, options());
}
return 0;
}
@ -322,6 +319,114 @@ namespace spot
return false;
}
class result_from_stack: public emptiness_check_result,
public acss_statistics
{
public:
result_from_stack(se05_search& ms)
: emptiness_check_result(ms.automaton()), ms_(ms)
{
}
virtual tgba_run* accepting_run()
{
assert(!ms_.st_blue.empty());
assert(!ms_.st_red.empty());
tgba_run* run = new tgba_run;
typename stack_type::const_reverse_iterator i, j, end;
tgba_run::steps* l;
const state* target = ms_.st_red.front().s;
l = &run->prefix;
i = ms_.st_blue.rbegin();
end = ms_.st_blue.rend(); --end;
j = i; ++j;
for (; i != end; ++i, ++j)
{
if (l == &run->prefix && i->s->compare(target) == 0)
l = &run->cycle;
tgba_run::step s = { i->s->clone(), j->label, j->acc };
l->push_back(s);
}
if (l == &run->prefix && i->s->compare(target) == 0)
l = &run->cycle;
assert(l == &run->cycle);
j = ms_.st_red.rbegin();
tgba_run::step s = { i->s->clone(), j->label, j->acc };
l->push_back(s);
i = j; ++j;
end = ms_.st_red.rend(); --end;
for (; i != end; ++i, ++j)
{
tgba_run::step s = { i->s->clone(), j->label, j->acc };
l->push_back(s);
}
return run;
}
unsigned acss_states() const
{
return 0;
}
private:
se05_search& ms_;
};
# define FROM_STACK "ar:from_stack"
class se05_result: public emptiness_check_result
{
public:
se05_result(se05_search& m, option_map o = option_map())
: emptiness_check_result(m.automaton(), o), ms(m)
{
if (options()[FROM_STACK])
computer = new result_from_stack(ms);
else
computer = new ndfs_result<se05_search<heap>, heap>(ms);
}
virtual void options_updated(const option_map& old)
{
if (old[FROM_STACK] && !options()[FROM_STACK])
{
delete computer;
computer = new ndfs_result<se05_search<heap>, heap>(ms);
}
else if (!old[FROM_STACK] && options()[FROM_STACK])
{
delete computer;
computer = new result_from_stack(ms);
}
}
virtual ~se05_result()
{
delete computer;
}
virtual tgba_run* accepting_run()
{
return computer->accepting_run();
}
virtual const unsigned_statistics* statistics() const
{
return computer->statistics();
}
private:
emptiness_check_result* computer;
se05_search& ms;
};
};
class explicit_se05_search_heap
@ -559,14 +664,15 @@ namespace spot
} // anonymous
emptiness_check* explicit_se05_search(const tgba *a)
emptiness_check* explicit_se05_search(const tgba *a, option_map o)
{
return new se05_search<explicit_se05_search_heap>(a, 0);
return new se05_search<explicit_se05_search_heap>(a, 0, o);
}
emptiness_check* bit_state_hashing_se05_search(const tgba *a, size_t size)
emptiness_check* bit_state_hashing_se05_search(const tgba *a, size_t size,
option_map o)
{
return new se05_search<bsh_se05_search_heap>(a, size);
return new se05_search<bsh_se05_search_heap>(a, size, o);
}
}

View file

@ -23,6 +23,7 @@
# define SPOT_TGBAALGOS_SE05_HH
#include <cstddef>
#include "misc/optionmap.hh"
namespace spot
{
@ -100,8 +101,8 @@ namespace spot
///
/// \sa spot::explicit_magic_search
///
emptiness_check* explicit_se05_search(const tgba *a);
emptiness_check* explicit_se05_search(const tgba *a,
option_map o = option_map());
/// \brief Returns an emptiness checker on the spot::tgba automaton \a a.
///
/// \pre The automaton \a a must have at most one accepting condition (i.e.
@ -120,13 +121,17 @@ namespace spot
/// }
/// \endverbatim
///
/// Consequently, the detection of an acceptence cycle is not ensured. The
/// implemented algorithm is the same as the one of
/// Consequently, the detection of an acceptence cycle is not ensured.
///
/// The size of the heap is limited to \n size bytes.
///
/// The implemented algorithm is the same as the one of
/// spot::explicit_se05_search.
///
/// \sa spot::explicit_se05_search
///
emptiness_check* bit_state_hashing_se05_search(const tgba *a, size_t size);
emptiness_check* bit_state_hashing_se05_search(const tgba *a, size_t size,
option_map o = option_map());
/// @}
}