Compute the (accessible part of the) determinization of an automaton.
Preconditions:
Postconditions:
Caveats:
See also:
In [1]:
import vcsn
lady4 = vcsn.context('lal_char(abc), b').ladybird(3)
lady4
Out[1]:
In [2]:
lady4d = lady4.determinize()
lady4d
Out[2]:
The resulting automaton has states labeled with subsets of the input automaton set of states.
If the input automaton has an empty accessible part (i.e., it has no initial state), then the output is empty (which is genuinely displayed as nothing below).
In [3]:
%%automaton a
context = "lal_char(a), b"
0 -> 1 a
In [4]:
a.determinize()
Out[4]:
In [5]:
%%automaton a
context = "lal_char, q"
$ -> 0 <2>
0 -> 1 <2>a
0 -> 2 <3>a
1 -> 1 <3>b
1 -> 3 <5>c
2 -> 2 <3>b
2 -> 3 <3>d
3 -> $
In [6]:
d = a.determinize()
d
Out[6]:
Which is obviously deterministic. Of course they are equivalent:
In [7]:
a.is_equivalent(d)
Out[7]:
The next example works in $\mathbb{Z}_{\min}$, which features a division: the usual subtraction.
In [8]:
%%automaton a
context = "lal_char, zmin"
$ -> 0 <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 -> $ <0>
In [9]:
d = a.determinize()
d
Out[9]:
Of course, they are equivalent. However we cannot use automaton.is_equivalent here.
In [10]:
a.shortest(10)
Out[10]:
In [11]:
d.shortest(10)
Out[11]:
Some weighted automata cannot be determinized. See automaton.has_twins_property for a possible means to detect whether the procedure will terminate.
The following automaton, for example, admits no equivalent deterministic automaton.
In [12]:
vcsn.context('lal_char, q').expression('a*+(<2>a)*').automaton()
Out[12]: