Improve purge_unreachable_states()

* NEWS: document it
* spot/twa/twagraph.hh, spot/twa/twagraph.cc: implement it
* tests/core/tgbagraph.test, tests/core/twagraph.cc: test it
This commit is contained in:
Maximilien Colange 2018-02-23 11:39:17 +01:00
parent d08ca97624
commit d44cc82eb7
5 changed files with 35 additions and 4 deletions

5
NEWS
View file

@ -6,6 +6,11 @@ New in spot 2.5.1.dev (not yet released)
remove from the acceptance condition the parity colors that are remove from the acceptance condition the parity colors that are
not used in the automaton. not used in the automaton.
- twa_graph::purge_unreachable_states() now takes a function which
is called with the new numbering of states. This is useful to
update an external structure that references states of the twa
that we want to purge.
New in spot 2.5.1 (2018-02-20) New in spot 2.5.1 (2018-02-20)
Library: Library:

View file

@ -231,7 +231,7 @@ namespace spot
g_.chain_edges_(); g_.chain_edges_();
} }
void twa_graph::purge_unreachable_states() void twa_graph::purge_unreachable_states(shift_action* f, void* action_data)
{ {
unsigned num_states = g_.num_states(); unsigned num_states = g_.num_states();
// The TODO vector serves two purposes: // The TODO vector serves two purposes:
@ -280,6 +280,9 @@ namespace spot
if (prop_complete().is_false()) if (prop_complete().is_false())
prop_complete(trival::maybe()); prop_complete(trival::maybe());
if (f)
(*f)(todo, action_data);
defrag_states(std::move(todo), current); defrag_states(std::move(todo), current);
} }

View file

@ -576,8 +576,16 @@ namespace spot
/// purge_dead_states() will remove more states than /// purge_dead_states() will remove more states than
/// purge_unreachable_states(), but it is more costly. /// purge_unreachable_states(), but it is more costly.
/// ///
/// You can pass a function to this method, which will be invoked
/// with a vector indicating the renumbering of states.
/// newst[i] == -1U means that state i is unreachable and thus deleted.
/// Otherwise, state i is renumbered newst[i].
///
/// \see purge_dead_states /// \see purge_dead_states
void purge_unreachable_states(); typedef void (*shift_action)(const std::vector<unsigned>& newst,
void* action_data);
void purge_unreachable_states(shift_action* f = nullptr,
void* action_data = nullptr);
/// \brief Remove unused atomic propositions /// \brief Remove unused atomic propositions
/// ///

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2014-2017 Laboratoire de Recherche et Développement de # Copyright (C) 2014-2018 Laboratoire de Recherche et Développement de
# l'Epita (LRDE). # l'Epita (LRDE).
# #
# This file is part of Spot, a model checking library. # This file is part of Spot, a model checking library.
@ -230,6 +230,9 @@ digraph G {
1 [label="s2"] 1 [label="s2"]
2 [label="s3", style="bold", color="#505050"] 2 [label="s3", style="bold", color="#505050"]
} }
0 -> deleted
1 -> deleted
2 -> 0
digraph G { digraph G {
rankdir=LR rankdir=LR
node [shape="circle"] node [shape="circle"]

View file

@ -105,7 +105,19 @@ static void f2()
} }
tg->set_init_state(s3); tg->set_init_state(s3);
spot::print_dot(std::cout, tg); spot::print_dot(std::cout, tg);
tg->purge_unreachable_states(); void (*action)(const std::vector<unsigned>&, void*) =
[](const std::vector<unsigned>& newst, void*)
{
for (unsigned i = 0; i != newst.size(); ++i)
{
std::cout << i << " -> ";
if (newst[i] == -1U)
std::cout << "deleted" << std::endl;
else
std::cout << newst[i] << std::endl;
}
};
tg->purge_unreachable_states(&action);
spot::print_dot(std::cout, tg); spot::print_dot(std::cout, tg);
} }