diff --git a/spot/twaalgos/sbacc.cc b/spot/twaalgos/sbacc.cc index c2db036ca..c64ca321f 100644 --- a/spot/twaalgos/sbacc.cc +++ b/spot/twaalgos/sbacc.cc @@ -64,6 +64,10 @@ namespace spot { common_in[d] &= e.acc; common_out[e.src] &= e.acc; + // Any state with an accepting edge labeled by true is a + // "true state". We will merge all true states, and + // ignore other outgoing edges. See issue #276 for an + // example. if (e.src == e.dst && e.cond == bddtrue && old->acc().accepting(e.acc)) { @@ -89,6 +93,9 @@ namespace spot std::map s2n; std::vector> todo; + auto* origin = new std::vector; + origin->reserve(ns); + res->set_named_prop("original-states", origin); auto new_state = [&](unsigned state, acc_cond::mark_t m) -> unsigned @@ -107,6 +114,8 @@ namespace spot if (p.second) // This is a new state { unsigned s = res->new_state(); + assert(origin->size() == s); + origin->push_back(state); p.first->second = s; if (ts) { @@ -175,6 +184,12 @@ namespace spot } res->merge_edges(); + // Compose original-states with the any previously existing one. + if (auto old_orig_states = + old->get_named_prop>("original-states")) + for (auto& s: *origin) + s = (*old_orig_states)[s]; + // If the automaton was marked as not complete or not universal, // and we have ignored some unreachable state, then it is possible // that the result becomes complete or universal. diff --git a/spot/twaalgos/sbacc.hh b/spot/twaalgos/sbacc.hh index 68067239d..11bc99e35 100644 --- a/spot/twaalgos/sbacc.hh +++ b/spot/twaalgos/sbacc.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2015 Laboratoire de Recherche et Développement +// Copyright (C) 2015, 2021 Laboratoire de Recherche et Développement // de l'Epita. // // This file is part of Spot, a model checking library. @@ -23,8 +23,31 @@ namespace spot { + /// \ingroup twa_algorithms /// \brief Transform an automaton to use state-based acceptance /// - /// This is independent on the acceptance condition used. + /// This transformation is independent on the acceptance condition + /// used. The implementation supports alternating automata. + /// + /// It works by creating an automaton whose states correspond to + /// pairs (s,colors) for each edge entering state s with colors. In + /// other words, we are pushing colors from the edges to their + /// outgoing states. The implementation is also able to pull colors + /// on incoming states in cases where that helps. + /// + /// When called on automata that are already known to have + /// state-based acceptance, this function returns the input + /// unmodified, not a copy. + /// + /// Trues states (any state with an accepting self-loop labeled by + /// true) are merged in the process. + /// + /// The output will have a named property called "original-states" + /// that is a vector indexed by the produced states, and giving the + /// corresponding state in the input automaton. If the input + /// automaton also had an "original-states" property, the two + /// vectors will be composed, so the `original-states[s]` in the + /// output will contains the value of `original-states[y] if state s + /// was created from state y. SPOT_API twa_graph_ptr sbacc(twa_graph_ptr aut); } diff --git a/tests/python/sbacc.py b/tests/python/sbacc.py index b0c457846..445845dbc 100644 --- a/tests/python/sbacc.py +++ b/tests/python/sbacc.py @@ -1,6 +1,6 @@ # -*- mode: python; coding: utf-8 -*- -# Copyright (C) 2017, 2018 Laboratoire de Recherche et Développement de l'Epita -# (LRDE). +# Copyright (C) 2017-2018, 2021 Laboratoire de Recherche et +# Développement de l'Epita (LRDE). # # This file is part of Spot, a model checking library. # @@ -45,6 +45,7 @@ State: 2 --END--""") s = spot.sbacc(aut) +s.copy_state_names_from(aut) h = s.to_str('hoa') assert h == """HOA: v1 @@ -54,9 +55,9 @@ AP: 2 "a" "b" Acceptance: 2 Inf(0) | Inf(1) properties: trans-labels explicit-labels state-acc deterministic --BODY-- -State: 0 +State: 0 "0" [0] 1 -State: 1 {1} +State: 1 "2" {1} [t] 1 --END--""" @@ -79,6 +80,7 @@ State: 2 --END--""") d = spot.degeneralize(aut) +d.copy_state_names_from(aut) h = d.to_str('hoa') assert h == """HOA: v1 @@ -89,8 +91,8 @@ acc-name: Buchi Acceptance: 1 Inf(0) properties: trans-labels explicit-labels state-acc deterministic --BODY-- -State: 0 +State: 0 "0#0" [0] 1 -State: 1 {0} +State: 1 "2#0" {0} [t] 1 --END--"""