sccinfo: implement PROCESS_UNREACHABLE_STATES

This is actually used by next patch.

* spot/twaalgos/sccinfo.cc, spot/twaalgos/sccinfo.hh: Here.
* tests/python/sccinfo.py: Add a small test case.
* NEWS: Mention it.
This commit is contained in:
Alexandre Duret-Lutz 2023-10-02 11:54:34 +02:00
parent 70812046d2
commit c016f561fa
4 changed files with 65 additions and 10 deletions

3
NEWS
View file

@ -85,6 +85,9 @@ New in spot 2.11.6.dev (not yet released)
The above also impacts autfilt --included-in option. The above also impacts autfilt --included-in option.
- spot::scc_info has a new option PROCESS_UNREACHABLE_STATES that
causes it to enumerated even unreachable SCCs.
Bugs fixed: Bugs fixed:
- tgba_determinize()'s use_simulation option would cause it to - tgba_determinize()'s use_simulation option would cause it to

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2014-2022 Laboratoire de Recherche et Développement // Copyright (C) 2014-2023 Laboratoire de Recherche et Développement
// de l'Epita (LRDE). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -206,13 +206,21 @@ namespace spot
} }
}; };
if (!!(options & scc_info_options::PROCESS_UNREACHABLE_STATES))
{
unsigned e = aut->num_states();
for (unsigned i = 0; i < e; ++i)
push_init(i);
}
else
{
// Setup depth-first search from the initial state. But we may // Setup depth-first search from the initial state. But we may
// have a conjunction of initial state in alternating automata. // have a conjunction of initial state in alternating automata.
if (initial_state_ == -1U) if (initial_state_ == -1U)
initial_state_ = aut->get_init_state_number(); initial_state_ = aut->get_init_state_number();
for (unsigned init: aut->univ_dests(initial_state_)) for (unsigned init: aut->univ_dests(initial_state_))
push_init(init); push_init(init);
}
while (!init_states.empty()) while (!init_states.empty())
{ {
unsigned init = init_states.front(); unsigned init = init_states.front();

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2014-2021 Laboratoire de Recherche et Développement // Copyright (C) 2014-2021, 2023 Laboratoire de Recherche et Développement
// de l'Epita (LRDE). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -393,6 +393,13 @@ namespace spot
/// Conditionally track states if the acceptance conditions uses Fin. /// Conditionally track states if the acceptance conditions uses Fin.
/// This is sufficiant for determine_unknown_acceptance(). /// This is sufficiant for determine_unknown_acceptance().
TRACK_STATES_IF_FIN_USED = 8, TRACK_STATES_IF_FIN_USED = 8,
/// Also compute SCCs for the unreachable states. When this is
/// used, SCCs are first enumerated from state 0, and then from
/// the next unvisited states. In other words the initial state
/// does not play any role. If STOP_ON_ACC is used with
/// PROCESS_UNREACHABLE_STATES, the enumeration will stop as soon
/// as an SCC is found, but that SCC might not be reachable.
PROCESS_UNREACHABLE_STATES = 16,
/// Default behavior: explore everything and track states and succs. /// Default behavior: explore everything and track states and succs.
ALL = TRACK_STATES | TRACK_SUCCS, ALL = TRACK_STATES | TRACK_SUCCS,
}; };

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3 #!/usr/bin/python3
# -*- mode: python; coding: utf-8 -*- # -*- mode: python; coding: utf-8 -*-
# Copyright (C) 2017, 2021, 2022 Laboratoire de Recherche et # Copyright (C) 2017, 2021, 2022, 2023 Laboratoire de Recherche et
# Développement de l'EPITA. # Développement de l'EPITA.
# #
# This file is part of Spot, a model checking library. # This file is part of Spot, a model checking library.
@ -114,3 +114,40 @@ tc.assertTrue(si.is_accepting_scc(0))
tc.assertFalse(si.is_rejecting_scc(0)) tc.assertFalse(si.is_rejecting_scc(0))
tc.assertTrue(si.is_rejecting_scc(1)) tc.assertTrue(si.is_rejecting_scc(1))
tc.assertFalse(si.is_accepting_scc(1)) tc.assertFalse(si.is_accepting_scc(1))
a = spot.automaton("""
HOA: v1
States: 4
Start: 0
AP: 1 "a"
Acceptance: 2 Inf(0)&Fin(1)
--BODY--
State: 0
[t] 0 {1}
[t] 1 {0}
State: 1
[t] 1 {1}
[t] 0 {1}
State: 2
[t] 2 {1}
[t] 3 {0}
State: 3
[t] 3 {1}
[t] 2
--END--
""")
si = spot.scc_info(a)
si.determine_unknown_acceptance()
tc.assertEqual(si.scc_count(), 1)
tc.assertFalse(si.is_accepting_scc(0))
tc.assertTrue(si.is_rejecting_scc(0))
si = spot.scc_info_with_options \
(a,
spot.scc_info_options_PROCESS_UNREACHABLE_STATES |
spot.scc_info_options_TRACK_STATES)
si.determine_unknown_acceptance()
tc.assertEqual(si.scc_count(), 2)
tc.assertTrue(si.is_accepting_scc(1))
tc.assertFalse(si.is_rejecting_scc(1))
tc.assertTrue(si.is_rejecting_scc(0))
tc.assertFalse(si.is_accepting_scc(0))