Automata with no state are no longer allowed.
* NEWS, spot/twa/twa.hh: Document the change. * spot/twa/twagraph.hh, spot/kripke/kripkegraph.hh: Add an exception in get_init_state_number(). get_init_state() now calls get_init_state_number(). * spot/twa/twagraph.cc, spot/twaalgos/simulation.cc, spot/twaalgos/powerset.cc, spot/twaalgos/complete.cc, spot/twaalgos/sccfilter.cc: Remove now useless tests. * spot/twaalgos/hoa.cc: Remove now useless comment. * spot/twaalgos/minimize.cc: Never return an automaton with no state.
This commit is contained in:
parent
da6fc955a3
commit
b3ee68310f
11 changed files with 24 additions and 38 deletions
|
|
@ -595,7 +595,8 @@ namespace spot
|
|||
/// Browsing a TωA is usually achieved using two methods: \c
|
||||
/// get_init_state(), and succ(). The former returns the initial
|
||||
/// state while the latter allows iterating over the outgoing edges
|
||||
/// of any given state.
|
||||
/// of any given state. A TωA is always assumed to have at least
|
||||
/// one state, the initial one.
|
||||
///
|
||||
/// Note that although this is a transition-based automata, we never
|
||||
/// represent edges in the API. Information about edges can be
|
||||
|
|
@ -605,7 +606,7 @@ namespace spot
|
|||
/// The interface presented here is what we call the on-the-fly
|
||||
/// interface of automata, because the TωA class can be subclassed
|
||||
/// to implement an object that computes its successors on-the-fly.
|
||||
/// The down-side is that all these methods are virtual, so you you
|
||||
/// The down-side is that all these methods are virtual, so you
|
||||
/// pay the cost of virtual calls when iterating over automata
|
||||
/// constructed on-the-fly. Also the interface assumes that each
|
||||
/// successor state is a new object whose memory management is the
|
||||
|
|
|
|||
|
|
@ -154,8 +154,6 @@ namespace spot
|
|||
void twa_graph::purge_unreachable_states()
|
||||
{
|
||||
unsigned num_states = g_.num_states();
|
||||
if (SPOT_UNLIKELY(num_states == 0))
|
||||
return;
|
||||
// The TODO vector serves two purposes:
|
||||
// - it is a stack of state to process,
|
||||
// - it is a set of processed states.
|
||||
|
|
@ -166,7 +164,7 @@ namespace spot
|
|||
std::vector<unsigned> todo(num_states, 0);
|
||||
const unsigned seen = 1 << (sizeof(unsigned)*8-1);
|
||||
const unsigned mask = seen - 1;
|
||||
todo[0] = init_number_;
|
||||
todo[0] = get_init_state_number();
|
||||
todo[init_number_] |= seen;
|
||||
unsigned todo_pos = 1;
|
||||
do
|
||||
|
|
@ -197,16 +195,13 @@ namespace spot
|
|||
void twa_graph::purge_dead_states()
|
||||
{
|
||||
unsigned num_states = g_.num_states();
|
||||
if (num_states == 0)
|
||||
return;
|
||||
|
||||
std::vector<unsigned> useful(num_states, 0);
|
||||
|
||||
// Make a DFS to compute a topological order.
|
||||
std::vector<unsigned> order;
|
||||
order.reserve(num_states);
|
||||
std::vector<std::pair<unsigned, unsigned>> todo; // state, trans
|
||||
useful[init_number_] = 1;
|
||||
useful[get_init_state_number()] = 1;
|
||||
todo.emplace_back(init_number_, g_.state_storage(init_number_).succ);
|
||||
do
|
||||
{
|
||||
|
|
|
|||
|
|
@ -264,16 +264,15 @@ namespace spot
|
|||
|
||||
state_num get_init_state_number() const
|
||||
{
|
||||
// If the automaton has no state, it has no initial state.
|
||||
if (num_states() == 0)
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
throw std::runtime_error("automaton has no state at all");
|
||||
return init_number_;
|
||||
}
|
||||
|
||||
virtual const twa_graph_state* get_init_state() const override
|
||||
{
|
||||
if (num_states() == 0)
|
||||
const_cast<graph_t&>(g_).new_state();
|
||||
return state_from_number(init_number_);
|
||||
return state_from_number(get_init_state_number());
|
||||
}
|
||||
|
||||
virtual twa_succ_iterator*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue