Whether the automaton has the twins property.
Preconditions:
See also:
import vcsn
q = vcsn.context('lal_char(ab), q')
def std(e):
return q.expression(e, 'binary').standard()
Consider the following $\mathbb{Q}$-automaton:
a = std('(ab)* + (ab)*')
a
States 1 and 4 are siblings: they can be reached from 0 with label "a" and there are two cycles in them with the same label "ba". Since these cycles have equal weights, they are twins. This automaton has only two sibling states and they are twins so it has twins property.
a.has_twins_property()
Conversely, the following automaton does not have the twins property because states 1 and 4 are siblings but not twins: the weights of cycles differ (1 vs. 2).
a = std('(<2>ab)* + (ab)*')
a
a.has_twins_property()
When the automaton has no sibling states, it has the twins property.
a = std("(aa)*+(ab)*")
a
a.has_twins_property()
In the tropical semiring ($\mathbb{Z}_{\text{min}}$), an automaton is determinizable iff the automaton has the twins property.
%%automaton a
context = "lal_char(abcd), zmin"
$ -> 0
0 -> 1 <1>a
0 -> 2 <2>a
1 -> 1 <3>b
1 -> 3 <5>c
2 -> 2 <3>b
2 -> 3 <6>d
3 -> $
This automaton has the twins property (the two sibling states $1$ and $2$ are twins), so it is determinizable (in $\mathbb{Z}_{\text{min}}$).
a.determinize()
The twins property can also be checked in $\mathbb{Z}$:
%%automaton a
context = "lal(abcd), z"
$ -> 0
0 -> 1 a
0 -> 2 <2>a
1 -> 1 <3>b
1 -> 3 <5>c
2 -> 2 <3>b
2 -> 3 <6>d
3 -> $
a.has_twins_property()
Or with tuples of weightsets:
%%automaton a
context = "lal_char(abc), lat<z,zmin>"
$ -> 0
0 -> 1 <(1, 3)>a
0 -> 2 <(1, 5)>a
1 -> 3 <(4, 8)>b
3 -> $
2 -> 4 <(6, 4)>b
4 -> $
3 -> 1 <(9, 3)>a
4 -> 2 <(6, 7)>a
a.has_twins_property()