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
4
NEWS
4
NEWS
|
|
@ -1,5 +1,9 @@
|
||||||
New in spot 2.2.1.dev (Not yet released)
|
New in spot 2.2.1.dev (Not yet released)
|
||||||
|
|
||||||
|
Library:
|
||||||
|
|
||||||
|
* A twa is required to have at least one state, the initial state.
|
||||||
|
|
||||||
Build:
|
Build:
|
||||||
|
|
||||||
* If the system has an installed libltdl library, use it instead of
|
* If the system has an installed libltdl library, use it instead of
|
||||||
|
|
|
||||||
|
|
@ -177,16 +177,15 @@ namespace spot
|
||||||
|
|
||||||
graph_t::state get_init_state_number() const
|
graph_t::state get_init_state_number() const
|
||||||
{
|
{
|
||||||
|
// If the kripke has no state, it has no initial state.
|
||||||
if (num_states() == 0)
|
if (num_states() == 0)
|
||||||
const_cast<graph_t&>(g_).new_state();
|
throw std::runtime_error("kripke has no state at all");
|
||||||
return init_number_;
|
return init_number_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const kripke_graph_state* get_init_state() const override
|
virtual const kripke_graph_state* get_init_state() const override
|
||||||
{
|
{
|
||||||
if (num_states() == 0)
|
return state_from_number(get_init_state_number());
|
||||||
const_cast<graph_t&>(g_).new_state();
|
|
||||||
return state_from_number(init_number_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Allow to get an iterator on the state we passed in
|
/// \brief Allow to get an iterator on the state we passed in
|
||||||
|
|
|
||||||
|
|
@ -595,7 +595,8 @@ namespace spot
|
||||||
/// Browsing a TωA is usually achieved using two methods: \c
|
/// Browsing a TωA is usually achieved using two methods: \c
|
||||||
/// get_init_state(), and succ(). The former returns the initial
|
/// get_init_state(), and succ(). The former returns the initial
|
||||||
/// state while the latter allows iterating over the outgoing edges
|
/// 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
|
/// Note that although this is a transition-based automata, we never
|
||||||
/// represent edges in the API. Information about edges can be
|
/// 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
|
/// The interface presented here is what we call the on-the-fly
|
||||||
/// interface of automata, because the TωA class can be subclassed
|
/// interface of automata, because the TωA class can be subclassed
|
||||||
/// to implement an object that computes its successors on-the-fly.
|
/// 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
|
/// pay the cost of virtual calls when iterating over automata
|
||||||
/// constructed on-the-fly. Also the interface assumes that each
|
/// constructed on-the-fly. Also the interface assumes that each
|
||||||
/// successor state is a new object whose memory management is the
|
/// successor state is a new object whose memory management is the
|
||||||
|
|
|
||||||
|
|
@ -154,8 +154,6 @@ namespace spot
|
||||||
void twa_graph::purge_unreachable_states()
|
void twa_graph::purge_unreachable_states()
|
||||||
{
|
{
|
||||||
unsigned num_states = g_.num_states();
|
unsigned num_states = g_.num_states();
|
||||||
if (SPOT_UNLIKELY(num_states == 0))
|
|
||||||
return;
|
|
||||||
// The TODO vector serves two purposes:
|
// The TODO vector serves two purposes:
|
||||||
// - it is a stack of state to process,
|
// - it is a stack of state to process,
|
||||||
// - it is a set of processed states.
|
// - it is a set of processed states.
|
||||||
|
|
@ -166,7 +164,7 @@ namespace spot
|
||||||
std::vector<unsigned> todo(num_states, 0);
|
std::vector<unsigned> todo(num_states, 0);
|
||||||
const unsigned seen = 1 << (sizeof(unsigned)*8-1);
|
const unsigned seen = 1 << (sizeof(unsigned)*8-1);
|
||||||
const unsigned mask = seen - 1;
|
const unsigned mask = seen - 1;
|
||||||
todo[0] = init_number_;
|
todo[0] = get_init_state_number();
|
||||||
todo[init_number_] |= seen;
|
todo[init_number_] |= seen;
|
||||||
unsigned todo_pos = 1;
|
unsigned todo_pos = 1;
|
||||||
do
|
do
|
||||||
|
|
@ -197,16 +195,13 @@ namespace spot
|
||||||
void twa_graph::purge_dead_states()
|
void twa_graph::purge_dead_states()
|
||||||
{
|
{
|
||||||
unsigned num_states = g_.num_states();
|
unsigned num_states = g_.num_states();
|
||||||
if (num_states == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::vector<unsigned> useful(num_states, 0);
|
std::vector<unsigned> useful(num_states, 0);
|
||||||
|
|
||||||
// Make a DFS to compute a topological order.
|
// Make a DFS to compute a topological order.
|
||||||
std::vector<unsigned> order;
|
std::vector<unsigned> order;
|
||||||
order.reserve(num_states);
|
order.reserve(num_states);
|
||||||
std::vector<std::pair<unsigned, unsigned>> todo; // state, trans
|
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);
|
todo.emplace_back(init_number_, g_.state_storage(init_number_).succ);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -264,16 +264,15 @@ namespace spot
|
||||||
|
|
||||||
state_num get_init_state_number() const
|
state_num get_init_state_number() const
|
||||||
{
|
{
|
||||||
|
// If the automaton has no state, it has no initial state.
|
||||||
if (num_states() == 0)
|
if (num_states() == 0)
|
||||||
const_cast<graph_t&>(g_).new_state();
|
throw std::runtime_error("automaton has no state at all");
|
||||||
return init_number_;
|
return init_number_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const twa_graph_state* get_init_state() const override
|
virtual const twa_graph_state* get_init_state() const override
|
||||||
{
|
{
|
||||||
if (num_states() == 0)
|
return state_from_number(get_init_state_number());
|
||||||
const_cast<graph_t&>(g_).new_state();
|
|
||||||
return state_from_number(init_number_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual twa_succ_iterator*
|
virtual twa_succ_iterator*
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,6 @@ namespace spot
|
||||||
{
|
{
|
||||||
unsigned complete_here(twa_graph_ptr aut)
|
unsigned complete_here(twa_graph_ptr aut)
|
||||||
{
|
{
|
||||||
// We do not use the initial state, but calling
|
|
||||||
// get_init_state_number() may create it and change the number of
|
|
||||||
// states. This has to be done before calling aut->num_states().
|
|
||||||
unsigned init = aut->get_init_state_number();
|
|
||||||
|
|
||||||
unsigned n = aut->num_states();
|
unsigned n = aut->num_states();
|
||||||
unsigned sink = -1U;
|
unsigned sink = -1U;
|
||||||
|
|
||||||
|
|
@ -87,7 +82,7 @@ namespace spot
|
||||||
|
|
||||||
// If the automaton is empty, pretend that state 0 is a sink.
|
// If the automaton is empty, pretend that state 0 is a sink.
|
||||||
if (t == 0)
|
if (t == 0)
|
||||||
sink = init;
|
sink = aut->get_init_state_number();
|
||||||
|
|
||||||
// Now complete all states (excluding any newly added the sink).
|
// Now complete all states (excluding any newly added the sink).
|
||||||
for (unsigned i = 0; i < n; ++i)
|
for (unsigned i = 0; i < n; ++i)
|
||||||
|
|
|
||||||
|
|
@ -312,16 +312,13 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calling get_init_state_number() may add a state to empty
|
|
||||||
// automata, so it has to be done first.
|
|
||||||
unsigned init = aut->get_init_state_number();
|
|
||||||
|
|
||||||
metadata md(aut, implicit_labels, state_labels);
|
metadata md(aut, implicit_labels, state_labels);
|
||||||
|
|
||||||
if (acceptance == Hoa_Acceptance_States && !md.has_state_acc)
|
if (acceptance == Hoa_Acceptance_States && !md.has_state_acc)
|
||||||
acceptance = Hoa_Acceptance_Transitions;
|
acceptance = Hoa_Acceptance_Transitions;
|
||||||
|
|
||||||
unsigned num_states = aut->num_states();
|
unsigned num_states = aut->num_states();
|
||||||
|
unsigned init = aut->get_init_state_number();
|
||||||
|
|
||||||
const char nl = newline ? '\n' : ' ';
|
const char nl = newline ? '\n' : ' ';
|
||||||
os << (v1_1 ? "HOA: v1.1" : "HOA: v1") << nl;
|
os << (v1_1 ? "HOA: v1.1" : "HOA: v1") << nl;
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,10 @@ namespace spot
|
||||||
init_state->destroy();
|
init_state->destroy();
|
||||||
res->set_init_state(init_num);
|
res->set_init_state(init_num);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res->set_init_state(res->new_state());
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- coding: utf-8 -*-
|
||||||
// Copyright (C) 2009, 2010, 2011, 2013, 2014, 2015 Laboratoire de
|
// Copyright (C) 2009-2011, 2013-2016 Laboratoire de Recherche et
|
||||||
// Recherche et Développement de l'Epita (LRDE).
|
// Développement de l'Epita (LRDE).
|
||||||
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
// Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||||
// et Marie Curie.
|
// et Marie Curie.
|
||||||
|
|
@ -101,11 +101,8 @@ namespace spot
|
||||||
|
|
||||||
unsigned nap = number_of_variables(allap);
|
unsigned nap = number_of_variables(allap);
|
||||||
|
|
||||||
// Call this before aut->num_states(), since it might add a state.
|
|
||||||
unsigned init_num = aut->get_init_state_number();
|
unsigned init_num = aut->get_init_state_number();
|
||||||
|
|
||||||
unsigned ns = aut->num_states();
|
unsigned ns = aut->num_states();
|
||||||
assert(ns > 0);
|
|
||||||
|
|
||||||
if ((-1UL / ns) >> nap == 0)
|
if ((-1UL / ns) >> nap == 0)
|
||||||
throw std::runtime_error("too many atomic propositions (or states)");
|
throw std::runtime_error("too many atomic propositions (or states)");
|
||||||
|
|
|
||||||
|
|
@ -277,8 +277,6 @@ namespace spot
|
||||||
scc_info* given_si, Args&&... args)
|
scc_info* given_si, Args&&... args)
|
||||||
{
|
{
|
||||||
unsigned in_n = aut->num_states();
|
unsigned in_n = aut->num_states();
|
||||||
if (in_n == 0) // nothing to filter.
|
|
||||||
return make_twa_graph(aut, twa::prop_set::all());
|
|
||||||
|
|
||||||
twa_graph_ptr filtered = make_twa_graph(aut->get_dict());
|
twa_graph_ptr filtered = make_twa_graph(aut->get_dict());
|
||||||
filtered->copy_ap_of(aut);
|
filtered->copy_ap_of(aut);
|
||||||
|
|
|
||||||
|
|
@ -161,14 +161,11 @@ namespace spot
|
||||||
throw std::runtime_error
|
throw std::runtime_error
|
||||||
("direct_simulation() requires separate Inf and Fin sets");
|
("direct_simulation() requires separate Inf and Fin sets");
|
||||||
|
|
||||||
// Call get_init_state_number() before anything else as it
|
|
||||||
// might add a state.
|
|
||||||
unsigned init_state_number = in->get_init_state_number();
|
|
||||||
scc_info_.reset(new scc_info(in));
|
scc_info_.reset(new scc_info(in));
|
||||||
|
|
||||||
unsigned ns = in->num_states();
|
unsigned ns = in->num_states();
|
||||||
assert(ns > 0);
|
|
||||||
size_a_ = ns;
|
size_a_ = ns;
|
||||||
|
unsigned init_state_number = in->get_init_state_number();
|
||||||
|
|
||||||
auto all_inf = in->get_acceptance().used_inf_fin_sets().first;
|
auto all_inf = in->get_acceptance().used_inf_fin_sets().first;
|
||||||
all_inf_ = all_inf;
|
all_inf_ = all_inf;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue