In [5]:
from IPython.display import display
import spot
spot.setup()

Definitions and examples for parity acceptance

In Spot a parity acceptance is defined by a kind, a style and a numsets:

  • The kind can be either max or min.
  • The style can be either odd or even.
  • The numsets is the number of acceptance sets used by the parity acceptance.

Here are some examples:

In [21]:
for kind in ['min', 'max']:
    for style in ['odd', 'even']:
        for sets in range(1, 5):
            name = 'parity {} {} {}'.format(kind, style, sets)
            print('{:17} = {}'.format(name, spot.acc_code(name)))
parity min odd 1  = Fin(0)
parity min odd 2  = Fin(0) & Inf(1)
parity min odd 3  = Fin(0) & (Inf(1) | Fin(2))
parity min odd 4  = Fin(0) & (Inf(1) | (Fin(2) & Inf(3)))
parity min even 1 = Inf(0)
parity min even 2 = Inf(0) | Fin(1)
parity min even 3 = Inf(0) | (Fin(1) & Inf(2))
parity min even 4 = Inf(0) | (Fin(1) & (Inf(2) | Fin(3)))
parity max odd 1  = Fin(0)
parity max odd 2  = Inf(1) | Fin(0)
parity max odd 3  = Fin(2) & (Inf(1) | Fin(0))
parity max odd 4  = Inf(3) | (Fin(2) & (Inf(1) | Fin(0)))
parity max even 1 = Inf(0)
parity max even 2 = Fin(1) & Inf(0)
parity max even 3 = Inf(2) | (Fin(1) & Inf(0))
parity max even 4 = Fin(3) & (Inf(2) | (Fin(1) & Inf(0)))

Change parity

This section describes the change_parity() method, that allows switching between different kinds and styles.

To toggle style

A new acceptance set is introduced and all the existing sets' indexes are increased by 1.

Parity max odd 5 -> Parity max even

If the acceptance is a parity max, all the transitions that do not belong to any acceptance set will belong to the new set.

In [22]:
aut_max_odd5 = tuple(spot.automata("randaut -A 'parity max odd 5' -Q4 2|"))[0]
display(aut_max_odd5.show(".a"))
Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | Fin( )))) [parity max odd 5] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 p0 & p1 3->0 p0 & !p1 3->2 !p0 & !p1 1->2 !p0 & p1 1->3 !p0 & p1 1->1 p0 & p1

The new indexes of the acceptance sets:

  • 4 -> 5
  • 3 -> 4
  • 2 -> 3
  • 1 -> 2
  • 0 -> 1
  • ∅ -> 0

Result of Parity max odd 5 -> Parity max even 6

In [3]:
aut_max_odd5_to_even = spot.change_parity(aut_max_odd5, spot.parity_kind_any, spot.parity_style_even)
display(aut_max_odd5_to_even.show(".a"))
Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | (Fin( ) & Inf( ))))) [parity max even 6] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 p0 & p1 3->0 p0 & !p1 3->2 !p0 & !p1 1->2 !p0 & p1 1->3 !p0 & p1 1->1 p0 & p1

Parity min odd 5 -> Parity min even

If the acceptance is a parity min, the new acceptance set will not be used.

In [4]:
aut_min_odd5 = tuple(spot.automata("randaut -A 'parity min odd 5' -Q4 2|"))[0]
display(aut_min_odd5.show(".a"))
Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | Fin( )))) [parity min odd 5] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 p0 & p1 3->0 p0 & !p1 3->2 !p0 & !p1 1->2 !p0 & p1 1->3 !p0 & p1 1->1 p0 & p1

The new indexes of the acceptance sets:

  • 4 -> 5
  • 3 -> 4
  • 2 -> 3
  • 1 -> 2
  • 0 -> 1
  • ∅ -> ∅

Result of Parity min odd 5 -> Parity min even 6

In [5]:
aut_min_odd5_to_even = spot.change_parity(aut_min_odd5, spot.parity_kind_any, spot.parity_style_even)
display(aut_min_odd5_to_even.show(".a"))
Inf( ) | (Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | Fin( ))))) [parity min even 6] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 p0 & p1 3->0 p0 & !p1 3->2 !p0 & !p1 1->2 !p0 & p1 1->3 !p0 & p1 1->1 p0 & p1

To toggle kind

The indexes of the acceptance sets are reversed

Parity max odd 5 ----> Parity min:

In [6]:
aut_max_odd5 = tuple(spot.automata("randaut -A 'parity max odd 5' -Q4 2|"))[0]
display(aut_max_odd5.show(".a"))
Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | Fin( )))) [parity max odd 5] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 p0 & p1 3->0 p0 & !p1 3->2 !p0 & !p1 1->2 !p0 & p1 1->3 !p0 & p1 1->1 p0 & p1

The new indexes of the acceptance sets:

  • 4 -> 0
  • 3 -> 1
  • 2 -> 2
  • 1 -> 3
  • 0 -> 4
  • ∅ -> ∅

Result of Parity max odd 5 ----> Parity min odd 5:

In [7]:
aut_max_odd5_to_min = spot.change_parity(aut_max_odd5, spot.parity_kind_min, spot.parity_style_any)
display(aut_max_odd5_to_min.show(".a"))
Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | Fin( )))) [parity min odd 5] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 p0 & p1 3->0 p0 & !p1 3->2 !p0 & !p1 1->2 !p0 & p1 1->3 !p0 & p1 1->1 p0 & p1

Parity max odd 4 ----> Parity min odd:

In [8]:
aut_max_odd4 = tuple(spot.automata("randaut -A 'parity max odd 4' -Q4 2|"))[0]
display(aut_max_odd4.show(".a"))
Inf( ) | (Fin( ) & (Inf( ) | Fin( ))) [parity max odd 4] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 !p0 & p1 3->2 !p0 & !p1 3->3 p0 & !p1 1->0 !p0 & p1 1->2 !p0 & !p1

The new indexes of the acceptance sets:

  • 3 -> 0
  • 2 -> 1
  • 1 -> 2
  • 0 -> 3
  • ∅ -> ∅

Result of Parity max odd 4 ----> Parity min even 4:

If the numsets is even and the kind is toggled, then the style will be toggled too.

In [9]:
aut_max_odd4_to_min = spot.change_parity(aut_max_odd4, spot.parity_kind_min, spot.parity_style_any)
display(aut_max_odd4_to_min.show(".a"))
Inf( ) | (Fin( ) & (Inf( ) | Fin( ))) [parity min even 4] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 !p0 & p1 3->2 !p0 & !p1 3->3 p0 & !p1 1->0 !p0 & p1 1->2 !p0 & !p1

To keep the same style a new acceptance set is introduced, thus the style is toggled once again.
The new indexes of the acceptance sets are:

  • 3 -> 0 -> 1
  • 2 -> 1 -> 2
  • 1 -> 2 -> 3
  • 0 -> 3 -> 4
  • ∅ -> ∅ -> 0 (as the resulting automaton is a parity min)

Result of Parity max odd 4 ----> Parity min even 5:

In [10]:
aut_max_odd4_to_min_bis = spot.change_parity(aut_max_odd4, spot.parity_kind_min, spot.parity_style_same)
display(aut_max_odd4_to_min_bis.show(".a"))
Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | Fin( )))) [parity min odd 5] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 !p0 & p1 3->2 !p0 & !p1 3->3 p0 & !p1 1->0 !p0 & p1 1->2 !p0 & !p1

Colorize parity

People working with parity automata usually expect all states (or edges) to be part of some acceptance set. This constraints, which come in addition to the use of a parity acceptance, is what the HOA format call "colored".

A parity automaton is a colored automaton with parity acceptance.

Coloring an automaton can be done with the colorize_parity() function.

Parity max

Transitions with multiple acceptance sets are purified by keeping only the set with the greatest index.
If there is a transition that do not belong to any acceptance set, a new acceptance set is introduced at the least significant place.
The least significant place of a parity max acceptance is where the indexes are the lowest, so all the existing acceptance sets' indexes will be shifted.

Colorize parity max odd 4

In [11]:
aut_max_odd4 = tuple(spot.automata("randaut -A 'parity max odd 4' -Q4 2|"))[0]
display(aut_max_odd4.show(".a"))
Inf( ) | (Fin( ) & (Inf( ) | Fin( ))) [parity max odd 4] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 !p0 & p1 3->2 !p0 & !p1 3->3 p0 & !p1 1->0 !p0 & p1 1->2 !p0 & !p1

The new acceptance sets are:

  • ∅ -> 0
  • 0 -> 1
  • 1 -> 2
  • 2 -> 3
  • 3 -> 4

The result of colorizing the given parity max odd 4 is

In [12]:
aut_max_odd4_colored = spot.colorize_parity(aut_max_odd4, False)
display(aut_max_odd4_colored.show(".a"))
Inf( ) | (Fin( ) & (Inf( ) | (Fin( ) & Inf( )))) [parity max even 5] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 !p0 & p1 3->2 !p0 & !p1 3->3 p0 & !p1 1->0 !p0 & p1 1->2 !p0 & !p1

You can notice that the style has been toggled.
To prevent colorize_parity from this we can add one extra acceptance set in the acceptance condition.

The new acceptance sets are now:

  • ∅ -> 1
  • 0 -> 2
  • 1 -> 3
  • 2 -> 4
  • 3 -> 5 #### The result of colorizing the given parity max odd 4 without changing the style is
In [13]:
aut_max_odd4_colored_bis = spot.colorize_parity(aut_max_odd4, True)
display(aut_max_odd4_colored_bis.show(".a"))
Inf( ) | (Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | Fin( ))))) [parity max odd 6] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 !p0 & p1 3->2 !p0 & !p1 3->3 p0 & !p1 1->0 !p0 & p1 1->2 !p0 & !p1

Parity min

Transitions with multiple acceptance sets are purified by keeping only the set with the lowest index.
If there is a transition that do not belong to any acceptance set, a new acceptance set is introduced at the least significant place.
The least significant place of a parity min acceptance is where the indexes are the greatest.

Colorize parity min odd 4

In [14]:
aut_min_odd4 = tuple(spot.automata("randaut -A 'parity min odd 4' -Q4 2|"))[0]
display(aut_min_odd4.show(".a"))
Fin( ) & (Inf( ) | (Fin( ) & Inf( ))) [parity min odd 4] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 !p0 & p1 3->2 !p0 & !p1 3->3 p0 & !p1 1->0 !p0 & p1 1->2 !p0 & !p1

The new acceptance sets are:

  • ∅ -> 4
  • 0 -> 0
  • 1 -> 1
  • 2 -> 2
  • 3 -> 3

The result of colorizing the given parity max odd 4 is

In [15]:
aut_min_odd4_colored_bis = spot.colorize_parity(aut_min_odd4, True)
display(aut_min_odd4_colored_bis.show(".a"))
Fin( ) & (Inf( ) | (Fin( ) & (Inf( ) | Fin( )))) [parity min odd 5] 0 0 I->0 2 2 0->2 !p0 & !p1 3 3 0->3 !p0 & !p1 1 1 2->1 !p0 & p1 3->2 !p0 & !p1 3->3 p0 & !p1 1->0 !p0 & p1 1->2 !p0 & !p1

Remark: colorizing a parity min won't change the style of the acceptance.