* 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:
parent
e812e1926f
commit
661dee8633
13 changed files with 578 additions and 95 deletions
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
|
||||
tgba_run::~tgba_run()
|
||||
{
|
||||
for (steps::const_iterator i = prefix.begin(); i != prefix.end(); ++i)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue