import spot
from spot.jupyter import display_inline
spot.setup(show_default='.bav')
The following automata are what we will use as examples.
aut1, aut2, aut3, aut4, aut5 = spot.automata('''
HOA: v1 tool: "ltl3ba" "1.1.3" name: "VWAA for FGa && GFb" States: 6
Start: 0 acc-name: co-Buchi Acceptance: 1 Fin(0) AP: 2 "a" "b" properties:
trans-labels explicit-labels state-acc univ-branch very-weak --BODY--
State: 0 "(FG(a) && GF(b))" [t] 3&1 State: 1 "GF(b)" [(1)] 1 [(!1)]
2&1 State: 2 "F(b)" {0} [(1)] 5 [(!1)] 2 State: 3 "FG(a)" {0} [(0)] 4
[t] 3 State: 4 "G(a)" [(0)] 4 State: 5 "t" [t] 5 --END--
/* Example from ADL's PSL2TGBA talk. */
HOA: v1 States: 3 Start: 0 acc-name: co-Buchi Acceptance: 1 Fin(0) AP:
3 "a" "b" "p" --BODY-- State: 0 "(a;a*;b)*" {0} [0] 1 [!0] 2 State: 1
"a*;b;(a;a*;b)*" {0} [0&1&2] 0&1 [!1&2] 1 [!0&!1] 2 [!0&1&2] 0 State:
2 [t] 2 --END--
HOA: v1 States: 5 Start: 3 acc-name: co-Buchi Acceptance: 1 Fin(0) AP:
3 "a" "b" "p" --BODY-- State: 0 "(a;a*;b)*" {0} [0] 1 [!0] 2 State: 1
"a*;b;(a;a*;b)*" {0} [0&1&2] 0&1 [!1&2] 1 [!0&!1] 2 [!0&1&2] 0 State:
2 [t] 2 State: 3 [0] 4&0 State: 4 [t] 3 --END--
HOA: v1 States: 3 Start: 0 acc-name: co-Buchi Acceptance: 1 Fin(0) AP:
3 "a" "b" "p" --BODY-- State: 0 "(a;a*;b)*" {0} [0] 1 [!0] 2 State: 1
"a*;b;(a;a*;b)*" {0} [0&1&2] 0&1 [!1&2] 1 [!0&!1] 2 [!0&1&2] 0 State:
2 [t] 2 --END--
HOA: v1 tool: "ltl3dra" "0.2.2" name: "VWAA for GFa" States: 3 Start: 0
acc-name: co-Buchi Acceptance: 1 Fin(0) AP: 1 "a" properties: trans-labels
explicit-labels state-acc univ-branch very-weak --BODY-- State: 0 "GF(a)"
[t] 1&0 State: 1 "F(a)" {0} [(0)] 2 [t] 1 State: 2 "t" [t] 2 --END--
''')
Here is the default output, using the bav
options as set by default in the first cell.
display_inline(aut1, aut2, aut3, aut4, aut5)
If the state labels take too much space, you can reduce the size of the automaton by forcing states to be numbered with option 1
. The original label is still displayed as a tooltip when the mouse is over the state.
Note that passing option show=...
to display_inline
is similar to calling aut.show(...)
on each argument.
display_inline(aut1, aut2, aut3, aut4, aut5, show='.bav1')
When working with alternating automata, it is quite common to hide "true states", and display "exiting transitions instead". You can do that with option u
.
display_inline(aut1, aut2, aut3, aut4, aut5, show='.bav1u')
Let's make sure that option u
and s
(to display SCCs) work well together:
display_inline(aut1, aut2, aut3, aut4, aut5, show='.bav1us')
The remove_alternation()
function works on any alternating automaton that is weak (not necessarily very weak), i.e., in each SCC all transition should belong to the same accepting sets.
The second argument of remove_alternation()
, set to True
below, simply asks for states to be labeled to help debugging. As the function builds Transition-based Generalized Büchi acceptance, it can be worthwhile to apply scc_filter()
in an attempt to reduce the number of acceptance sets.
The next cell shows this two-step process on our first example automaton.
nba1t = spot.remove_alternation(aut1, True)
nba1 = spot.scc_filter(nba1t, True)
display_inline(aut1.show('.bav1u'), nba1t, nba1)
Let's apply this process to the other 4 automata (which are not very-weak, unlike aut1
). The states marked with ~
are part of a break-point construction.
nba2, nba3, nba4, nba5 = [spot.scc_filter(spot.remove_alternation(a, True), True) for a in (aut2, aut3, aut4, aut5)]
display_inline(nba2, nba3, nba4, nba5)
The following demonstrates that very weak (non-alternating) Büchi automata can be complemented via alternation removal.
pos = spot.automaton("""HOA: v1 name: "(a & (Fa R XFb)) | (!a & (G!a U
XG!b))" States: 6 Start: 0 AP: 2 "a" "b" acc-name: Buchi Acceptance: 1
Inf(0) properties: trans-labels explicit-labels state-acc
semi-deterministic --BODY-- State: 0 [0] 1 [!0] 2 [!0] 3 State: 1 [!1]
1 [1] 4 State: 2 {0} [!1] 2 State: 3 [!0] 3 [!0] 5 State: 4 {0} [t] 4
State: 5 {0} [!0&!1] 5 --END--""")
altneg = spot.dualize(pos)
neg = spot.remove_alternation(altneg)
display_inline(pos, altneg.show('.bvu'), neg)
# Issue #382.
w = spot.parse_word('cycle{!a&b}').as_automaton()
assert pos.intersects(w) != neg.intersects(w)