expression
.derived_term(
algo
="expansion",
lazy
=False,
deterministic
=False,
breaking
=False)
¶Generate the derived-term automaton from an expression.
The arguments are:
algo
:"derivation"
: rely on the expression.derivation
."expansion"
: rely on the expression.expansion
.lazy
: whether to build the result lazily, on the flydeterministic
: whether to build a deterministic automaton.breaking
: split
the polynomials at each stepPreconditions:
deterministic
might not terminate on some expressions (in which case consider lazy
)Also known as:
See also:
References:
In the classical case (labels are letters, and weights are Boolean), this is the construct as described by Antimirov.
import vcsn
bexp = vcsn.B.expression
r = bexp('[ab]*a[ab]{3}')
a = r.derived_term()
a
The states of the resulting automaton are decorated by their expressions. This can be stripped:
a.strip()
The result does not depend on the core computation: expansions and derivations compute the same terms:
r.derived_term('derivation')
Alternatively, one can request a deterministic result:
qexp = vcsn.Q.expression
r = qexp('aba+a(a+<-1>ba)')
nfa = r.derived_term()
nfa
dfa = r.derived_term(deterministic=True)
dfa
nfa.determinize()
Extended expressions are supported. For instance, words starting with a
s and then b
s, but not exactly ab
:
r = bexp('a*b* & (ab){c}')
r
a = r.derived_term()
a
a.shortest(10)
The following example is taken from lombardy.2005.tcs:
r = qexp('(<1/6>a*+<1/3>b*)*')
r.derived_term()
"Breaking" variants of derivation and expansion "split" the polynomials at each step. In short, it means that no state will be labeled by an addition: rather the addition is split into several states. As a consequence, the automaton might have several initial states.
r = qexp('[ab]{2}')
r.derived_term()
r.derived_term(breaking=True)
The derived-term automaton can be built on-the-fly, on-demand: states are uncovered on needed (e.g., when traversed by an evaluation). This is especially useful when considering an expression on which the process does not terminate (i.e., would generate an "infinite" automaton).
r = qexp('a*+b*'); r
a = r.derived_term(lazy=True)
a
print(a('')); a
print(a('a')); a
print(a('b')); a
The following expression does not admit a (finite) deterministic automaton (and determinizing the non-deterministic derived-term automaton would not terminate either). Repeatedly calling the evaluation uncovers portions of an "infinite" deterministic automaton.
r = qexp('a*+(<2>a)*'); r
a = r.derived_term(deterministic=True, lazy=True)
a
print(a('')); a
print(a('a')); a
print(a('aaa')); a
Note that lazy determinization is also available: see automaton.determinize to see the corresponding example.
Since it entails a "local" determinization ("under" the complement operator), the algorithm fails would not terminate.
r = r.complement()
r
a = r.derived_term(lazy=True)
a
print(a('aa')); a
print(a('b')); a