expression.derivation(label,breaking=False)

Compute the derivation of a weighted expression.

Arguments:

  • label: the (non empty) string to derive the expression with.
  • breaking: whether to split the result.

See also:

References:

Examples

The following function will prove handy: it takes a rational expression and a list of strings, and returns a $\LaTeX$ aligned environment to display nicely the result.

In [1]:
import vcsn
from IPython.display import Latex

def diffs(r, ss):
    eqs = []
    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}}
        {0}
    \end{{aligned}}'''.format(r'\\'.join(eqs)))
:0: FutureWarning: IPython widgets are experimental and may change in the future.

Classical expressions

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.derivation('a')
Out[2]:
$\left(a + b\right) \, \left(a + b\right)$

Or, using the diffs function we defined above:

In [3]:
diffs(r, ['a', 'aa', 'aaa', 'aaaa'])
Out[3]:
\begin{aligned} \frac{\partial}{\partial a} \left(a + b\right) \, \left(a + b\right) \, \left(a + b\right)& = \left(a + b\right) \, \left(a + b\right)\\\frac{\partial}{\partial aa} \left(a + b\right) \, \left(a + b\right) \, \left(a + b\right)& = a + b\\\frac{\partial}{\partial aaa} \left(a + b\right) \, \left(a + b\right) \, \left(a + b\right)& = \varepsilon\\\frac{\partial}{\partial aaaa} \left(a + b\right) \, \left(a + b\right) \, \left(a + b\right)& = \emptyset \end{aligned}

Weighted Expressions

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', 'aa', 'ab', 'b', 'ba', 'bb'])
Out[4]:
\begin{aligned} \frac{\partial}{\partial a} \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}& = \left\langle \frac{1}{3}\right\rangle {a}^{*} \, \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}\\\frac{\partial}{\partial aa} \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}& = \left\langle \frac{4}{9}\right\rangle {a}^{*} \, \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}\\\frac{\partial}{\partial ab} \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}& = \left\langle \frac{2}{9}\right\rangle {b}^{*} \, \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}\\\frac{\partial}{\partial b} \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}& = \left\langle \frac{2}{3}\right\rangle {b}^{*} \, \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}\\\frac{\partial}{\partial ba} \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}& = \left\langle \frac{2}{9}\right\rangle {a}^{*} \, \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}\\\frac{\partial}{\partial bb} \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*}& = \left\langle \frac{10}{9}\right\rangle {b}^{*} \, \left( \left\langle \frac{1}{6} \right\rangle \,{a}^{*} + \left\langle \frac{1}{3} \right\rangle \,{b}^{*}\right)^{*} \end{aligned}

And this is tightly connected with the construction of the derived-term automaton.

In [5]:
r.derived_term()
Out[5]:
%3 I0 0 (⟨1/6⟩a*+⟨1/3⟩b*)* I0->0 F0 F1 F2 0->F0 ⟨2⟩ 1 a*(⟨1/6⟩a*+⟨1/3⟩b*)* 0->1 ⟨1/3⟩a 2 b*(⟨1/6⟩a*+⟨1/3⟩b*)* 0->2 ⟨2/3⟩b 1->F1 ⟨2⟩ 1->1 ⟨4/3⟩a 1->2 ⟨2/3⟩b 2->F2 ⟨2⟩ 2->1 ⟨1/3⟩a 2->2 ⟨5/3⟩b

Breaking derivation

The "breaking" derivation "splits" the polynomial at the end.

In [6]:
r = q.expression('[ab](<2>[ab])', 'associative')
r
Out[6]:
$\left(a + b\right) \, \left\langle 2 \right\rangle \,\left(a + b\right)$
In [7]:
r.derivation('a')
Out[7]:
$ \left\langle 2 \right\rangle \,\left(a + b\right)$
In [8]:
r.derivation('a', True)
Out[8]:
$\left\langle 2\right\rangle a \oplus \left\langle 2\right\rangle b$
In [9]:
r.derivation('a').split()
Out[9]:
$\left\langle 2\right\rangle a \oplus \left\langle 2\right\rangle b$

Again, this is tightly connected with both flavors of the derived-term automaton.

In [10]:
r.derived_term()
Out[10]:
%3 I0 0 (a+b)⟨2⟩(a+b) I0->0 F2 1 ⟨2⟩(a+b) 0->1 a, b 2 ε 1->2 ⟨2⟩a, ⟨2⟩b 2->F2
In [11]:
r.derived_term('breaking_derivation')
Out[11]:
%3 I0 0 a⟨2⟩(a+b) I0->0 I1 1 b⟨2⟩(a+b) I1->1 F4 2 a 0->2 ⟨2⟩a 3 b 0->3 ⟨2⟩a 1->2 ⟨2⟩b 1->3 ⟨2⟩b 4 ε 2->4 a 3->4 b 4->F4