Previous topic

Taylor’s Series

This Page

Lie operators for vector fields

In order to compute the normal form of an equation \(\dot{x}=f(x)\), the normal_forms.normal_form.normal_form class solves a sequence of equations \(L_1g_j=f_j-h_j\) and applies a sequence of transformations \(e^{L_j}\) to the \(k\)-jet of \(f\), where \(L_1(\cdot)=[\cdot,f_1(x)]\) and \(L_j(\cdot)=[\cdot,g_j(x)]\) are the Lie brackets with particular homogenous polynomial vector fields \(f_1(x)=f'(x_0)x\) or \(g_j(x)\). This package uses the Lie bracket for vector fields definition \([f(x),g(x)]=f'(x)g(x)-g'(x)f(x)\). The class that implements the Lie bracket with a particular polynomial vector field is normal_forms.lie_operator.lie_operator.

Let \(\mathcal{V}^n_i\) denote the space of \(n\)-dim, degree \(i\) polynomial vector fields, and let \(s(i)\) denote the simplicial number \({n+i-1 \choose i}\). For any degree \(i\), the vector field \(f_i\in\mathcal{V}_i^n\) may be represented as a \(ns(i)\)-dim column vector, the operator \(L_j:\mathcal{V}_i^n\rightarrow\mathcal{V}_{i+j-1}^n\) defined by \(L_j=[\cdot,g_j(x)]\) may be represented as a \(ns(i+j-1)\times ns(i)\) matrix, and \(L_j(f_i)\) may be represented as the matrix-vector product.

These representations depend on the choice of basis for \(\mathcal{V}^n\). This package implements a basis for \(\mathcal{V}_i^n\) ordered first by coordinate then by multiindex. For example, the basis for \(\mathcal{V}^2_3\) is

\[\begin{split}\left\{\begin{bmatrix}x_1^3\\0\end{bmatrix}, \begin{bmatrix}x_1^2x_2\\0\end{bmatrix} \begin{bmatrix}x_1x_2^2\\0\end{bmatrix} \begin{bmatrix}x_2^3\\0\end{bmatrix} \begin{bmatrix}0\\x_1^3\end{bmatrix} \begin{bmatrix}0\\x_1^2x_2\end{bmatrix} \begin{bmatrix}0\\x_1x_2^2\end{bmatrix} \begin{bmatrix}0\\x_2^3\end{bmatrix}\right\}.\end{split}\]

The underlying list of multiindices, \((3,0), (2,1), (1,2), (0,3)\) in the example, assumes a descending order according to a dictionary ordering, i.e.for two multiindices \(m=(m_1,\ldots,m_n)\) and \(p=(p_1,\ldots,p_n)\), \(m>p\) if \(m_i=p_i\) and \(m_j>p_j\), for all \(i\) and a particular \(j\) such that \(0\leq i<j\leq n\).

For example, a vector field

\[\begin{split}\begin{bmatrix}c_{11}&c_{12}&c_{13}&c_{14}\\c_{21}&c_{22}&c_{23}&c_{24}\end{bmatrix}\begin{bmatrix}x_1^3\\x_1^2x_2\\x_1x_2^2\\x_2^3\end{bmatrix}\end{split}\]

in \(\mathcal{V}_3^2\) is represented as the column vector \(\begin{bmatrix}c_{11}&c_{12}&c_{13}&c_{14}&c_{21}&c_{22}&c_{23}&c_{24}\end{bmatrix}^T\).

And, the columns of the matrix representation of \(L_j:\mathcal{V}_i^n\rightarrow\mathcal{V}_{i+j-1}^n\) are the column vector representations of \(L_j\) applied to the basis of \(\mathcal{V}_i^n\). For example, let \(g_2(x_1,x_2)=\begin{bmatrix}x_1^2\\x_2^2\end{bmatrix}\) and consider \(L_2:\mathcal{V}_3^2\rightarrow\mathcal{V}_4^2\) defined by \(L_2(\cdot)=[\cdot,g_2(x)]\). Since

\[\begin{split}L_2(e_1) = e_1'(x)g_2(x)-g_2'(x)e_1(x) = \begin{bmatrix}3x_1^2&0\\0&0\end{bmatrix}\begin{bmatrix}x_1^2\\x_2^2\end{bmatrix}-\begin{bmatrix}2x_1&0\\0&2x_2\end{bmatrix}\begin{bmatrix}x_1^3\\0\end{bmatrix}=\begin{bmatrix}x_1^4\\0\end{bmatrix}\end{split}\]

the first column of the matrix representation of \(L_2:\mathcal{V}_3^2\rightarrow\mathcal{V}_4^2\) is \(\begin{bmatrix}1&0&0&0&0 & 0&0&0&0&0\end{bmatrix}^T\).

Finally, \(L_j(f_i)\) is represented as a column vector computed by the appropriate matrix representation of \(L_j\) times the column vector representation of \(f_i\).

The normal_forms.lie_operator.lie_operator class is accessible from the top-level of this package. To create a lie_operator object, a vector field g as a sympy.Matrix and a list of sympy.symbols representing the variables \(x_1,\ldots,x_n\) should be supplied. Once the lie_operator object is constructed, the matrix representation of its action on \(\mathcal{V}_j^n\) can be accessed as index j of the object.

In [1]: from normal_forms import lie_operator

In [2]: import sympy

In [3]: x = sympy.symbols('x_1 x_2')

In [4]: g2 = sympy.Matrix([[x[0]**2],[x[1]**2]])

In [5]: L2 = lie_operator(g2, x)

In [6]: L2[3]
Out[6]: 
array([[ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  1., -1.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  2., -2.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  3.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  3.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0., -2.,  2.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0., -1.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.]])

The lie_operator object can be evaluated by passing it a vector field in the form of a sympy.Matrix as an argument:

In [7]: f3 = sympy.Matrix([[x[0]**3],[0]])

In [8]: L2(f3)
Out[8]: 
Matrix([
[1.0*x_1**4],
[         0]])