strength: fix is_terminal()

Fix #198.  Reported by Maximilien Colange.

* spot/twaalgos/strength.cc (is_terminal): Test that no accepting
transition lead to a rejecting SCC.
* tests/core/strength.test: Add test case.
* spot/twaalgos/strength.hh, spot/twa/twa.hh, doc/org/concepts.org:
Adjust documentation.
* NEWS: Mention the fix.
This commit is contained in:
Alexandre Duret-Lutz 2016-11-28 16:19:05 +01:00
parent 2fbc75f439
commit 9bc978a90f
6 changed files with 133 additions and 15 deletions

5
NEWS
View file

@ -5,6 +5,11 @@ New in spot 2.2.1.dev (Not yet released)
* scc_filter() had a left-over print statement that would print * scc_filter() had a left-over print statement that would print
"names" when copying the name of the states. "names" when copying the name of the states.
* is_terminal() should reject automata that have accepting
transitions going into rejecting SCCs. The whole point of
being a terminal automaton is that reaching an accepting
transition guarantees that any suffix will be accepted.
New in spot 2.2.1 (2016-11-21) New in spot 2.2.1 (2016-11-21)
Bug fix: Bug fix:

View file

@ -991,11 +991,11 @@ There are actually several property flags that are stored into each
automaton, and that can be queried or set by algorithms: automaton, and that can be queried or set by algorithms:
| flag name | meaning when =true= | | flag name | meaning when =true= |
|---------------------+---------------------------------------------------------------------------------------| |---------------------+----------------------------------------------------------------------------------------------|
| =state_acc= | automaton should be considered has having state-based acceptance | | =state_acc= | automaton should be considered has having state-based acceptance |
| =inherently_weak= | accepting and rejecting cycles cannot be mixed in the same SCC | | =inherently_weak= | accepting and rejecting cycles cannot be mixed in the same SCC |
| =weak= | transitions of an SCC all belong to the same acceptance sets | | =weak= | transitions of an SCC all belong to the same acceptance sets |
| =terminal= | automaton is weak, accepting SCCs are complete and may not reach rejecting cycles | | =terminal= | automaton is weak, accepting SCCs are complete, accepting edges may not go to rejecting SCCs |
| =deterministic= | there is at most one run *recognizing* a word, but not necessarily accepting it | | =deterministic= | there is at most one run *recognizing* a word, but not necessarily accepting it |
| =unambiguous= | there is at most one run *accepting* a word (but it might be recognized several time) | | =unambiguous= | there is at most one run *accepting* a word (but it might be recognized several time) |
| =stutter_invariant= | the property recognized by the automaton is [[https://www.lrde.epita.fr/~adl/dl/adl/michaud.15.spin.pdf][stutter-invariant]] | | =stutter_invariant= | the property recognized by the automaton is [[https://www.lrde.epita.fr/~adl/dl/adl/michaud.15.spin.pdf][stutter-invariant]] |

View file

@ -1179,10 +1179,12 @@ namespace spot
/// \brief Whether the automaton is terminal. /// \brief Whether the automaton is terminal.
/// ///
/// An automaton is terminal if it is weak, no non-accepting cycle /// An automaton is terminal if it is weak, its accepting strongly
/// can be reached from an accepting cycle, and the accepting /// components are complete, and no accepting edge lead to a
/// strongly components are complete (i.e., any suffix is accepted /// non-accepting SCC.
/// as soon as we enter an accepting component). ///
/// This property ensures that a word can be accepted as soon as
/// on of its prefixes move through an accepting edge.
/// ///
/// \see prop_weak() /// \see prop_weak()
/// \see prop_inherently_weak() /// \see prop_inherently_weak()

View file

@ -79,6 +79,17 @@ namespace spot
break; break;
} }
} }
// A terminal automaton should accept any word that as a prefix
// leading to an accepting edge. In other words, we cannot have
// an accepting edge that goes into a rejecting SCC.
if (terminal && is_term)
for (auto& e: aut->edges())
if (si->is_rejecting_scc(si->scc_of(e.dst))
&& aut->acc().accepting(e.acc))
{
is_term = false;
break;
}
exit: exit:
if (need_si) if (need_si)
delete si; delete si;

View file

@ -25,8 +25,12 @@ namespace spot
{ {
/// \brief Whether an automaton is terminal. /// \brief Whether an automaton is terminal.
/// ///
/// An automaton is terminal if it is weak, and all accepting SCCs /// An automaton is terminal if it is weak, all its accepting SCCs
/// are complete. /// are complete, and no accepting transitions lead to a
/// non-accepting SCC.
///
/// This property guarantees that a word is accepted if it has some
/// prefix that reaches an accepting transition.
/// ///
/// \param aut the automaton to check /// \param aut the automaton to check
/// ///

View file

@ -589,3 +589,99 @@ EOF
diff out expected diff out expected
autfilt -q expected autfilt -q expected
cat >input <<EOF
/* This Büchi automaton is not terminal, because of the
accepting edge between states 0 and 1. */
HOA: v1
States: 2
Start: 1
AP: 1 "a"
Acceptance: 1 Inf(0)
--BODY--
State: 0
[t] 0
State: 1
[0] 0 {0}
[!0] 1
--END--
/* This co-Büchi automaton not terminal for the same reason. */
HOA: v1
States: 2
Start: 1
AP: 1 "a"
Acceptance: 1 Fin(0)
--BODY--
State: 0
[t] 0
State: 1
[0] 0 {0}
[!0] 1
--END--
/* This co-Büchi automaton is terminal. */
HOA: v1
States: 2
Start: 1
AP: 1 "a"
Acceptance: 1 Fin(0)
--BODY--
State: 0
[t] 0
State: 1
[0] 0 {0}
[!0] 1 {0}
--END--
EOF
autfilt --check=strength input >output
cat >expected <<EOF
HOA: v1
States: 2
Start: 1
AP: 1 "a"
acc-name: Buchi
Acceptance: 1 Inf(0)
properties: trans-labels explicit-labels trans-acc complete
properties: deterministic weak
--BODY--
State: 0
[t] 0
State: 1
[0] 0 {0}
[!0] 1
--END--
HOA: v1
States: 2
Start: 1
AP: 1 "a"
acc-name: co-Buchi
Acceptance: 1 Fin(0)
properties: trans-labels explicit-labels trans-acc complete
properties: deterministic weak
--BODY--
State: 0
[t] 0
State: 1
[0] 0 {0}
[!0] 1
--END--
HOA: v1
States: 2
Start: 1
AP: 1 "a"
acc-name: co-Buchi
Acceptance: 1 Fin(0)
properties: trans-labels explicit-labels state-acc complete
properties: deterministic terminal
--BODY--
State: 0
[t] 0
State: 1 {0}
[0] 0
[!0] 1
--END--
EOF
diff output expected