twa_graph: add a method to merge states with same outgoing edges
* spot/twa/twagraph.hh, spot/twa/twagraph.cc: here * NEWS: document it * tests/core/twagraph.cc, tests/core/tgbagraph.test: test it
This commit is contained in:
parent
5b9088006c
commit
5a819e0c93
5 changed files with 89 additions and 1 deletions
|
|
@ -231,6 +231,48 @@ namespace spot
|
|||
g_.chain_edges_();
|
||||
}
|
||||
|
||||
void twa_graph::merge_states()
|
||||
{
|
||||
if (!is_existential())
|
||||
throw std::runtime_error(
|
||||
"twa_graph::merge_states() does not work on alternating automata");
|
||||
|
||||
const unsigned nb_states = num_states();
|
||||
std::vector<unsigned> remap(nb_states, -1U);
|
||||
for (unsigned i = 0; i != nb_states; ++i)
|
||||
{
|
||||
auto out1 = out(i);
|
||||
for (unsigned j = 0; j != i; ++j)
|
||||
{
|
||||
auto out2 = out(j);
|
||||
if (std::equal(out1.begin(), out1.end(), out2.begin(), out2.end(),
|
||||
[](const edge_storage_t& a,
|
||||
const edge_storage_t& b)
|
||||
{ return a.dst == b.dst && a.data() == b.data(); }))
|
||||
{
|
||||
remap[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& e: edges())
|
||||
if (remap[e.dst] != -1U)
|
||||
e.dst = remap[e.dst];
|
||||
|
||||
if (remap[get_init_state_number()] != -1U)
|
||||
set_init_state(remap[get_init_state_number()]);
|
||||
|
||||
unsigned st = 0;
|
||||
for (auto& s: remap)
|
||||
if (s == -1U)
|
||||
s = st++;
|
||||
else
|
||||
s = -1U;
|
||||
|
||||
defrag_states(std::move(remap), st);
|
||||
}
|
||||
|
||||
void twa_graph::purge_unreachable_states(shift_action* f, void* action_data)
|
||||
{
|
||||
unsigned num_states = g_.num_states();
|
||||
|
|
|
|||
|
|
@ -553,6 +553,14 @@ namespace spot
|
|||
/// This is already called by merge_edges().
|
||||
void merge_univ_dests();
|
||||
|
||||
/// \brief Merge states that can be merged.
|
||||
///
|
||||
/// This merges states that have the exact same outgoing edges. This method
|
||||
/// compares the successors of states in the order in which they are stored.
|
||||
/// Therefore, it is better to call it when you know that the edges are
|
||||
/// stored, e.g. after a call to merge_edges().
|
||||
void merge_states();
|
||||
|
||||
/// \brief Remove all dead states
|
||||
///
|
||||
/// Dead states are all the states that cannot be part of
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue