expression
.expansion()
Compute the expansion of a weighted expression. An expansion is a structure that combines three different features of a (weighted) rational expression $r$:
If one denotes $d(r)$ the expansion of $r$, it holds that: $$ d(r) = c(r) \oplus \bigoplus_{a \in f(r)} a \odot \frac{\partial}{\partial a}r $$
The main use of expansions (and derivations) is to compute the derived-term automaton of an expression. The advantage of expansions over derivations is their independence with respect to the alphabet. As a matter of fact, they do not require a finite-alphabet (see examples below). Besides, the reunite constant-term, first, and derivation into a single concept.
See also:
The following function will prove handy to demonstrate the relation between the expansion on the one hand, and, on the other hand, the constant-term and the derivations. It takes an expression $r$ and a list of letters, and returns a $\LaTeX$ aligned
environment to display:
In [1]:
import vcsn
from IPython.display import Latex
def diffs(r, ss):
eqs = [r'd\left({0}\right) &= {1}'.format(r.format('latex'), r.expansion().format('latex')),
r'c\left({0}\right) &= {1}'.format(r.format('latex'), r.constant_term().format('latex'))]
for s in ss:
eqs.append(r'\frac{{\partial}}{{\partial {0}}} {1} &= {2}'
.format(s,
r.format('latex'),
r.derivation(s).format('latex')))
return Latex(r'''\begin{{aligned}}
{eqs}
\end{{aligned}}'''.format(eqs = r'\\'.join(eqs)))
In the classical case (labels are letters, and weights are Boolean), this is the construct as described by Antimirov.
In [2]:
b = vcsn.context('lal_char(ab), b')
r = b.expression('[ab]{3}')
r.expansion()
Out[2]:
Or, using the diffs
function we defined above:
In [3]:
diffs(r, ['a', 'b'])
Out[3]:
Of course, expressions can be weighted.
In [4]:
q = vcsn.context('lal_char(abc), q')
r = q.expression('(<1/6>a*+<1/3>b*)*')
diffs(r, ['a', 'b'])
Out[4]:
And this is tightly connected with the construction of the derived-term automaton.
In [5]:
r.derived_term()
Out[5]:
There is (currently) no means to break an expansion (which would mean breaking its polynomials). The construction of the derived-term automaton does it on the fly.
Contrary to derivation, which requires a finite alphabet, expansions support labels which are words, or even tuples.
Below, we define a two-tape-of-words context, and a simple expression that uses three different multitape labels: $(\mathrm{11}|\mathrm{eleven})$, etc. Then derived_term
is used to build the automaton.
In [6]:
ctx = vcsn.context('lat<law_char(0-9), law_char(a-zA-Z)>, b')
ctx
Out[6]:
In [7]:
r = ctx.expression("(11|eleven+12|twelve+13|thirteen)*")
r
Out[7]:
In [8]:
r.expansion()
Out[8]:
This enables the construction of the associated derived-term automaton.
In [9]:
r.derived_term()
Out[9]: