```python
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
```

```python
from sympy import Symbol, symbols, Eq, Function #, init_printing; init_printing()
R, Z, Phi = symbols("R, Z, \phi", real=True)
x0_R, x0_Z = symbols("x_{0R}, x_{0Z}", real=True)
X_R, X_Z = [Function(latexstr, real=True)(x0_R, x0_Z, Phi) for latexstr in ["X_R", "X_Z"] ]
X_Phi = Symbol("X_{\phi}", real=True)
XRdot = Function("\dot{X}_{R}", real=True)(X_R, X_Z, X_Phi)
# XRdot, XZdot = symbols("$X_R$, dot{X_Z}", cls=Function)
```

```python
XRdot
```

$\displaystyle \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

```python
from sympy import Array
from sympy.core.numbers import Integer
from sympy.core.function import Derivative
from sympy.core.power import Pow
ndiff_R, ndiff_Z = 3, 1
result = XRdot.diff(x0_R, ndiff_R, x0_Z, ndiff_Z)

import numpy as np
import pandas as pd
ndiff = ndiff_R + ndiff_Z
XRZ_index = ['C']
for idiff in range(1, ndiff+1):
    for idiff_R in range(idiff+1):
        idiff_Z = idiff - idiff_R
        XRZ_index.append('XR['+str(idiff_R)+','+str(idiff_Z)+']')
        XRZ_index.append('XZ['+str(idiff_R)+','+str(idiff_Z)+']')

# for R_diff_order in range(ndiff_R+ndiff_Z, -1, -1):
#     for Z_diff_order in range(ndiff_R+ndiff_Z -R_diff_order, -1, -1 ):
#         if R_diff_order >= 2:
#             R_partdiff_substr = "\partial_{R}^{"+f"{R_diff_order}"+"}"
#         elif R_diff_order == 1:
#             R_partdiff_substr = "\partial_{R}"
#         elif R_diff_order == 0:
#             R_partdiff_substr = ""

#         if Z_diff_order >= 2:
#             Z_partdiff_substr = "\partial_{Z}^{"+f"{Z_diff_order}"+"}"
#         elif Z_diff_order == 1:
#             Z_partdiff_substr = "\partial_{Z}"
#         elif Z_diff_order == 0:
#             Z_partdiff_substr = ""

#         result = result.subs(
#             XRdot.diff(X_R, R_diff_order, X_Z, Z_diff_order),
#             Symbol(R_partdiff_substr + Z_partdiff_substr + " \dot{X}_{R}", real=True))

# for x0_R_diff_order in range(ndiff_R, -1, -1):
#     for x0_Z_diff_order in range(ndiff_Z, -1, -1):
#         if x0_R_diff_order >= 2:
#             x0_R_partdiff_substr = "\partial_{x_{0R}}^{"+f"{x0_R_diff_order}"+"}"
#         elif x0_R_diff_order == 1:
#             x0_R_partdiff_substr = "\partial_{x_{0R}}"
#         elif x0_R_diff_order == 0:
#             x0_R_partdiff_substr = ""

#         if x0_Z_diff_order >= 2:
#             x0_Z_partdiff_substr = "\partial_{x_{0Z}}^{"+f"{x0_Z_diff_order}"+"}"
#         elif x0_Z_diff_order == 1:
#             x0_Z_partdiff_substr = "\partial_{x_{0Z}}"
#         elif x0_Z_diff_order == 0:
#             x0_Z_partdiff_substr = ""

#         result = result.subs(
#             X_R.diff(x0_R, x0_R_diff_order, x0_Z, x0_Z_diff_order),
#             Symbol(x0_R_partdiff_substr+x0_Z_partdiff_substr+" X_{R}",real=True) )

#         result = result.subs(
#             X_Z.diff(x0_R, x0_R_diff_order, x0_Z, x0_Z_diff_order),
#             Symbol(x0_R_partdiff_substr+x0_Z_partdiff_substr+" X_{Z}",real=True) )

print("We show them term-by-term as the following:")
factored_result = result.factor()
how_many_terms_in_result = len(factored_result.args)
XRZ_df = pd.DataFrame(np.zeros( (len(XRZ_index),how_many_terms_in_result ), dtype=int), index= XRZ_index)
for i, term in enumerate(factored_result.args):
    term
    for factor in term.args:
        if factor.func is Integer:
            combinatorial_coeff = factor # Combinatorial number
            XRZ_df.at['C', i] = combinatorial_coeff
            continue

        if factor.func is Pow:
            factor_inside_power = factor.args[0]
            factor_power = factor.args[1]
        else:
            factor_inside_power = factor
            factor_power = 1

        assert(factor_inside_power.func is Derivative)
        if factor_inside_power.args[0] == XRdot:
            continue

        if factor_inside_power.args[0] == X_R:
            XR_or_XZ = 'XR'
        elif factor_inside_power.args[0] == X_Z:
            XR_or_XZ = 'XZ'

        x0_R_diff_n = 0
        x0_Z_diff_n = 0
        for xdiff in factor_inside_power.args[1:]:
            if xdiff[0] == x0_R:
                x0_R_diff_n = xdiff[1]
            elif xdiff[0] == x0_Z:
                x0_Z_diff_n = xdiff[1]

        XRZ_df.at[XR_or_XZ+'['+str(x0_R_diff_n)+','+str(x0_Z_diff_n)+']', i] = factor_power
    if XRZ_df.at['C', i] == 0:
        XRZ_df.at['C', i] = 1

pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)
pd.set_option('display.width', None)
pd.set_option('display.max_colwidth', None)
# df.head()

XRZ_df
```

    We show them term-by-term as the following:

$\displaystyle \frac{\partial}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)} \frac{\partial^{4}}{\partial x_{0Z}\partial x_{0R}^{3}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}$

$\displaystyle \frac{\partial}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)} \frac{\partial^{4}}{\partial x_{0Z}\partial x_{0R}^{3}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}$

$\displaystyle \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{3} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{4}}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{4}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{3} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{4}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{3} \frac{\partial^{4}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{3} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{4}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{4}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \frac{\partial^{3}}{\partial x_{0R}^{3}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \frac{\partial^{3}}{\partial x_{0R}^{3}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial x_{0R}^{3}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \frac{\partial^{3}}{\partial x_{0R}^{3}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial^{3}}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}$

$\displaystyle 3 \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}$

$\displaystyle 3 \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)} \frac{\partial^{3}}{\partial x_{0Z}\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial x_{0Z}\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}$

$\displaystyle 3 \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)} \frac{\partial^{3}}{\partial x_{0Z}\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial x_{0Z}\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}$

$\displaystyle 3 \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{4}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{4}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial^{4}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{4}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0Z}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0Z}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 6 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 6 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0Z}\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
      <th>10</th>
      <th>11</th>
      <th>12</th>
      <th>13</th>
      <th>14</th>
      <th>15</th>
      <th>16</th>
      <th>17</th>
      <th>18</th>
      <th>19</th>
      <th>20</th>
      <th>21</th>
      <th>22</th>
      <th>23</th>
      <th>24</th>
      <th>25</th>
      <th>26</th>
      <th>27</th>
      <th>28</th>
      <th>29</th>
      <th>30</th>
      <th>31</th>
      <th>32</th>
      <th>33</th>
      <th>34</th>
      <th>35</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>C</th>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>3</td>
      <td>6</td>
      <td>6</td>
    </tr>
    <tr>
      <th>XR[0,1]</th>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[0,1]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[1,0]</th>
      <td>0</td>
      <td>0</td>
      <td>3</td>
      <td>3</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>2</td>
      <td>2</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>2</td>
      <td>2</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <th>XZ[1,0]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>3</td>
      <td>3</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>2</td>
      <td>2</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>2</td>
      <td>2</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <th>XR[0,2]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[0,2]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[1,1]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[1,1]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
    </tr>
    <tr>
      <th>XR[2,0]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[2,0]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[0,3]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[0,3]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[1,2]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[1,2]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[2,1]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[2,1]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[3,0]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[3,0]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[0,4]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[0,4]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[1,3]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[1,3]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[2,2]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[2,2]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[3,1]</th>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[3,1]</th>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XR[4,0]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>XZ[4,0]</th>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
  </tbody>
</table>
</div>

```python

```

```python

```

```python

# for X_R_x0_R_diff_order in range(ndiff_R, -1, -1):
#     for X_R_x0_Z_diff_order in range(ndiff_Z, -1, -1):
#         for X_Z_x0_R_diff_order in range(ndiff_R, -1, -1):
#             for X_Z_x0_Z_diff_order in range(ndiff_Z, -1, -1):
#                 for term in result.factor().args:

#                     if x0_R_diff_order >= 2:
#                         x0_R_partdiff_substr = "\partial_{x_{0R}}^{"+f"{x0_R_diff_order}"+"}"
#                     elif x0_R_diff_order == 1:
#                         x0_R_partdiff_substr = "\partial_{x_{0R}}"
#                     elif x0_R_diff_order == 0:
#                         x0_R_partdiff_substr = ""

#                     if x0_Z_diff_order >= 2:
#                         x0_Z_partdiff_substr = "\partial_{x_{0Z}}^{"+f"{x0_Z_diff_order}"+"}"
#                     elif x0_Z_diff_order == 1:
#                         x0_Z_partdiff_substr = "\partial_{x_{0Z}}"
#                     elif x0_Z_diff_order == 0:
#                         x0_Z_partdiff_substr = ""

#                     result = result.subs(
#                         X_R.diff(x0_R, x0_R_diff_order, x0_Z, x0_Z_diff_order),
#                         Symbol(x0_R_partdiff_substr+x0_Z_partdiff_substr+" X_{R}",real=True) )

#                     result = result.subs(
#                         X_Z.diff(x0_R, x0_R_diff_order, x0_Z, x0_Z_diff_order),
#                         Symbol(x0_R_partdiff_substr+x0_Z_partdiff_substr+" X_{Z}",real=True) )
```

```python
XRdot.diff(X_R).subs(XRdot.diff(X_R), Symbol("\partial_{1} \dot{X}_R", real=True))
```

$\displaystyle \partial_{1} \dot{X}_R$

```python
from sympy import FiniteSet
len(FiniteSet(FiniteSet(5,5,7),FiniteSet(3,6)))
```

    2

```python
from sympy import FiniteSet
def list_of_all_partitions(set_to_partition):

    def partition_into_two_parts(set_to_split):
        set_size = len(set_to_split)
        all_partitions = []
        list_elements = list(set_to_split)
        first_ele = list_elements[0]
        for i in range( 1, 2**(set_size-1) ): # we skip i==0, because that is full set
            first_part = [first_ele]
            second_part = [ ]
            for j, ele in enumerate(list_elements[1:]):
                if (i >> j) % 2 == 0:
                    first_part.append(ele)
                else:
                    second_part.append(ele)
            if len(second_part)!=0:
                all_partitions.append([FiniteSet(*first_part), FiniteSet(*second_part)])
    #             all_partitions.append(FiniteSet(
    #                 FiniteSet(*first_part), FiniteSet(*second_part)))
            else:
                all_partitions.append( [FiniteSet(*first_part)] )
    #             all_partitions.append(FiniteSet(
    #                 FiniteSet(*first_part) ))

        return all_partitions # FiniteSet(*all_partitions)
    all_partitions = [ [set_to_partition] ]
    binary_partitions = partition_into_two_parts(set_to_partition)
    for bi_part in binary_partitions:
        if len(bi_part[-1])>1:
            first_part = bi_part[0]
            for secondpart_partition in list_of_all_partitions(bi_part[-1]):
                all_partitions.append([first_part] + secondpart_partition)
        else:
            all_partitions.append(bi_part)
    return all_partitions

```

```python
list(FiniteSet(FiniteSet(5),1,2))
```

    [FiniteSet(5), 1, 2]

```python
from random import randrange
from sympy import derive_by_array, Intersection, tensorproduct, tensorcontraction
ndiff_R, ndiff_Z = 3, 0
ndiff = ndiff_R+ndiff_Z
sum_over_big_pi = 0
for small_pi in list_of_all_partitions(  FiniteSet(*list(range(1, ndiff+1))) ):
    small_pi_size = len(small_pi)
    repeated_grad_result = XRdot
    for _ in range(small_pi_size):
        repeated_grad_result = derive_by_array(repeated_grad_result, [X_R, X_Z])

    term_of_small_pi = repeated_grad_result
    for iB, B in enumerate(small_pi):
        B_size = len(B)
        _ndiff_R = len(Intersection(  B, FiniteSet(*list(range(1, ndiff_R+1))) ))
        _ndiff_Z = len(Intersection(  B, FiniteSet(*list(range(ndiff_R+1, ndiff+1))) ))
        term_of_small_pi = tensorcontraction(tensorproduct(
            term_of_small_pi,
            [X_R.diff(x0_R, _ndiff_R, x0_Z, _ndiff_Z), X_Z.diff(x0_R, _ndiff_R, x0_Z, _ndiff_Z)]),
          (randrange(small_pi_size - iB), small_pi_size - iB) ) # (small_pi_size - iB -1, small_pi_size - iB)
    sum_over_big_pi += term_of_small_pi
result = sum_over_big_pi
```

```python
print("We show them term-by-term as the following:")
for term in result.factor().args:
    term
```

    We show them term-by-term as the following:

$\displaystyle \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{3} \frac{\partial^{3}}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{3} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{3}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \frac{\partial^{3}}{\partial x_{0R}^{3}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle \frac{\partial^{3}}{\partial x_{0R}^{3}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \left(\frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\right)^{2} \frac{\partial^{3}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}\partial \operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

$\displaystyle 3 \frac{\partial}{\partial x_{0R}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial x_{0R}^{2}} \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)} \frac{\partial^{2}}{\partial \operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)}^{2}} \dot{X}_{R}{\left(\operatorname{X_{R}}{\left(x_{0R},x_{0Z},\phi \right)},\operatorname{X_{Z}}{\left(x_{0R},x_{0Z},\phi \right)},X_{\phi} \right)}$

```python

```

```python
list_of_all_partitions(  FiniteSet(*list(range(1, ndiff+1))) )
```

    [[FiniteSet(1, 2, 3)],
     [FiniteSet(1, 3), FiniteSet(2)],
     [FiniteSet(1, 2), FiniteSet(3)],
     [FiniteSet(1), FiniteSet(2, 3)],
     [FiniteSet(1), FiniteSet(2, 3)],
     [FiniteSet(1), FiniteSet(2), FiniteSet(3)]]

```python

```


# Random Signals and LTI-Systems

*This jupyter notebook is part of a [collection of notebooks](../index.ipynb) on various topics of Digital Signal Processing. Please direct questions and suggestions to [Sascha.Spors@uni-rostock.de](mailto:Sascha.Spors@uni-rostock.de).*

## Linear Mean

In the following we aim at finding a relation between the linear mean $\mu_x[k]$ of the input signal $x[k]$ and the linear mean $\mu_y[k]$ of the output signal $y[k] = \mathcal{H} \{ x[k] \}$ of a linear time-invariant (LTI) system.

### Non-Stationary Input Signal

Let's first impose no restrictions in terms of stationarity to the input signal. The [linear mean](../random_signals/ensemble_averages.ipynb#Linear-mean) of the output signal is then given as

\begin{equation}
\mu_y[k] = E\{ y[k] \} = E\{ x[k] * h[k] \}
\end{equation}

where $h[k]$ denotes the impulse response of the system. Since the convolution and the ensemble average are linear operations, and $h[k]$ is a deterministic signal, this can be rewritten as

\begin{equation}
\mu_y[k] = \mu_x[k] * h[k]
\end{equation}

The linear mean of the output signal $\mu_y[k]$ is given as the convolution of the linear mean of the input signal $\mu_x[k]$ with the impulse response $h[k]$ of the system.

#### Example

The linear mean $\mu_y[k]$ of the output of an LTI system with given impulse response $h[k]$ and non-stationary random input signal $x[k]$ is computed. The estimated linear means $\hat{\mu}_x[k]$ and $\hat{\mu}_y[k]$ of the input and output signals are plotted.

```python
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

L = 32  # number of random samples
N = 10000  # number of sample functions

# generate input signal (white Gaussian noise)
np.random.seed(2)
x = np.random.normal(size=(N, L))
x[:, L//2] += 1
# generate output signal
h = 2*np.fft.irfft([1,1,1,0,0,0])
y = np.asarray([np.convolve(x[n,:], h, mode='full') for n in range(N)])

# estimate and plot linear mean
def estimate_plot_linear_mean(x):
    # estimate linear mean by ensemble average
    mu = 1/N * np.sum(x, 0)
    # plot linear mean
    plt.stem(mu)
    plt.xlabel(r'$k$')
    plt.ylabel(r'$\hat{\mu}[k]$')
    plt.axis([0, x.shape[1], -1.2, 1.2])

plt.figure(figsize = (10, 3))
plt.title(r'Estimated linear mean $\hat{\mu}_x[k]$ of input signal')
estimate_plot_linear_mean(x)

plt.figure(figsize = (10, 3))
plt.title(r'Estimated linear mean $\hat{\mu}_y[k]$ of output signal')
estimate_plot_linear_mean(y)
```

**Exercise**

* Can you estimate the impulse response $h[k]$ of the system from above plots of $\hat{\mu}_x[k]$ and $\hat{\mu}_y[k]$?
* You can check your results by plotting the impulse response $h[k]$, for instance with the command `plt.stem(h)`.

Solution: Inspecting above plot, the linear mean of the input signal can be approximated as $\mu_x[k] = \delta[k]$. The linear mean of the output is then given as $\mu_y[k] = \delta[k] * h[k] = h[k]$. It follows that the impulse response of the LTI system can be estimated from the linear mean $\mu_y[k]$.

### Stationary Input Signal

For a (wide-sense) stationary process, the linear mean of the input signal $\mu_x[k] = \mu_x$ does not depend on the time index $k$. For a (wide-sense) stationary input signal, also the output signal of the system is (wide-sense) stationary. Using the result for the non-stationary case above yields

\begin{align}
\mu_y &= \mu_x * h[k] \\
&= \sum_{\kappa = -\infty}^{\infty}\mu_x[k-\kappa]h[\kappa] \\
&= \mu_x \cdot \sum_{\kappa = -\infty}^{\infty}h[\kappa] \\
&= \mu_x \cdot \sum_{\kappa = -\infty}^{\infty}h[\kappa]\cdot\mathrm{e}^{-\mathrm{j}\Omega\kappa} \hspace{5mm} \text{for}\,\,\Omega=0 \\
&= \mu_x \cdot H(\mathrm{e}^{\,\mathrm{j}\,\Omega}) \big\vert_{\Omega = 0}
\end{align}

where $H(\mathrm{e}^{\,\mathrm{j}\,\Omega}) = \mathcal{F}_* \{ h[k] \}$ denotes the discrete time Fourier transformation (DTFT) of the impulse response. The linear mean of a (wide-sense) stationary input signal is weighted by the transmission characteristics for the constant (i.e. DC, $\Omega = 0$) component of the LTI system. This implies that for a system which just attenuates the input signal $y[k] = A \cdot x[k]$, e.g. an ideal amplifier, the linear mean at the output is given as $\mu_y = A \cdot \mu_x$. Furthermore, if the input signal is zero-mean $\mu_x = 0$, the output signal is also zero-mean $\mu_y = 0$.

**Copyright**

This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources). Feel free to use the notebook for your own purposes. The text is licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/), the code of the IPython examples under the [MIT license](https://opensource.org/licenses/MIT). Please attribute the work as follows: *Sascha Spors, Digital Signal Processing - Lecture notes featuring computational examples, 2016-2018*.


# 2. 2-D example with 1 parameters

The following example shows how to construct the kernel, automatically, from a symbolic expression defining the linear differential operator in **2D**.

We consider the following operator, for an unknwon *u*

$$
\mathcal{L}^{\phi} u := \phi u + \partial_x u + \partial_{yy} u
$$

```python
# imports
from mlhiphy.calculus import dx, dy, dz
from mlhiphy.calculus import Constant
from mlhiphy.calculus import Unknown
from mlhiphy.kernels import compute_kernel, generic_kernel

from sympy import expand
from sympy import symbols
from sympy import exp
from sympy import Tuple
```

```python
x, x_i, x_j = symbols('x x_i x_j')
y, y_i, y_j = symbols('y y_i y_j')

X  = Tuple(x,y)
X_i = Tuple(x_i,y_i)
X_j = Tuple(x_j,y_j)

u = Unknown('u')

phi = Constant('phi')
theta_1 = Constant('theta_1')
theta_2 = Constant('theta_2')

expr = phi * u + dx(u) + dy(dy(u))
```

```python
kuu = generic_kernel(expr, u, (X_i, X_j))
```

```python
from IPython.display import Math
from sympy import latex

Math(latex(expand(kuu)))
```

$$\phi^{2} u{\left (x_{i},y_{i},x_{j},y_{j} \right )} + \phi \frac{\partial}{\partial x_{i}} u{\left (x_{i},y_{i},x_{j},y_{j} \right )} + \phi \frac{\partial}{\partial x_{j}} u{\left (x_{i},y_{i},x_{j},y_{j} \right )} + \phi \frac{\partial^{2}}{\partial y_{i}^{2}}  u{\left (x_{i},y_{i},x_{j},y_{j} \right )} + \phi \frac{\partial^{2}}{\partial y_{j}^{2}}  u{\left (x_{i},y_{i},x_{j},y_{j} \right )} + \frac{\partial^{2}}{\partial x_{i}\partial x_{j}}  u{\left (x_{i},y_{i},x_{j},y_{j} \right )} + \frac{\partial^{3}}{\partial x_{i}\partial y_{j}^{2}}  u{\left (x_{i},y_{i},x_{j},y_{j} \right )} + \frac{\partial^{3}}{\partial x_{j}\partial y_{i}^{2}}  u{\left (x_{i},y_{i},x_{j},y_{j} \right )} + \frac{\partial^{4}}{\partial y_{i}^{2}\partial y_{j}^{2}}  u{\left (x_{i},y_{i},x_{j},y_{j} \right )}$$

```python
# RBF kernel

kuu = exp(- theta_1 * (x_i - x_j)**2 - theta_2 * (y_i - y_j)**2)

kuf = compute_kernel(expr, kuu, X_i)
kfu = compute_kernel(expr, kuu, X_j)
kff = compute_kernel(expr, kuu, (X_i, X_j))
```

```python
Math(latex(expand(kuf)))
```

$$\phi u{\left (x_{i},y_{i} \right )} - 2 \theta_{1} x_{i} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 2 \theta_{1} x_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 4 \theta_{2}^{2} y_{i}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 8 \theta_{2}^{2} y_{i} y_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 4 \theta_{2}^{2} y_{j}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 2 \theta_{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}}$$

```python
Math(latex(expand(kfu)))
```

$$\phi u{\left (x_{j},y_{j} \right )} + 2 \theta_{1} x_{i} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 2 \theta_{1} x_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 4 \theta_{2}^{2} y_{i}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 8 \theta_{2}^{2} y_{i} y_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 4 \theta_{2}^{2} y_{j}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 2 \theta_{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}}$$

```python
Math(latex(expand(kff)))
```

$$\phi^{2} u{\left (x_{i},y_{i},x_{j},y_{j} \right )} - 2 \phi \theta_{1} x_{i} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 2 \phi \theta_{1} x_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 8 \phi \theta_{2}^{2} y_{i}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 16 \phi \theta_{2}^{2} y_{i} y_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 8 \phi \theta_{2}^{2} y_{j}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 4 \phi \theta_{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + \phi \frac{\partial}{\partial x_{j}} u{\left (x_{i},y_{i},x_{j},y_{j} \right )} - 4 \theta_{1}^{2} x_{i}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 8 \theta_{1}^{2} x_{i} x_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 4 \theta_{1}^{2} x_{j}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 2 \theta_{1} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 16 \theta_{2}^{4} y_{i}^{4} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 64 \theta_{2}^{4} y_{i}^{3} y_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 96 \theta_{2}^{4} y_{i}^{2} y_{j}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 64 \theta_{2}^{4} y_{i} y_{j}^{3} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 16 \theta_{2}^{4} y_{j}^{4} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 48 \theta_{2}^{3} y_{i}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 96 \theta_{2}^{3} y_{i} y_{j} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} - 48 \theta_{2}^{3} y_{j}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}} + 12 \theta_{2}^{2} e^{- \theta_{1} x_{i}^{2}} e^{- \theta_{1} x_{j}^{2}} e^{- \theta_{2} y_{i}^{2}} e^{- \theta_{2} y_{j}^{2}} e^{2 \theta_{1} x_{i} x_{j}} e^{2 \theta_{2} y_{i} y_{j}}$$

```python
from IPython.core.display import HTML
def css_styling():
    styles = open("../styles/custom.css", "r").read()
    return HTML(styles)
css_styling()
```

<link href='http://fonts.googleapis.com/css?family=Fenix' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Alegreya+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Source+Code+Pro:300,400' rel='stylesheet' type='text/css'>
<style>
    @font-face {
        font-family: "Computer Modern";
        src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');
    }
    div.cell{
        width:600px;
        margin-left:16% !important;
        margin-right:auto;
    }
    h1 {
        font-family: 'Alegreya Sans', sans-serif;
    }
    h2 {
        font-family: 'Fenix', serif;
    }
    h3{
		font-family: 'Fenix', serif;
        margin-top:12px;
        margin-bottom: 3px;
       }
	h4{
		font-family: 'Fenix', serif;
       }
    h5 {
        font-family: 'Alegreya Sans', sans-serif;
    }
    div.text_cell_render{
        font-family: 'Alegreya Sans',Computer Modern, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
        line-height: 135%;
        font-size: 120%;
        width:600px;
        margin-left:auto;
        margin-right:auto;
    }
    .CodeMirror{
            font-family: "Source Code Pro";
			font-size: 90%;
    }
/*    .prompt{
        display: None;
    }*/
    .text_cell_render h1 {
        font-weight: 200;
        font-size: 50pt;
		line-height: 100%;
        color:#054BCD;
        margin-bottom: 0.5em;
        margin-top: 0.5em;
        display: block;
    }
    .text_cell_render h5 {
        font-weight: 300;
        font-size: 16pt;
        color: #054BCD;
        font-style: italic;
        margin-bottom: .5em;
        margin-top: 0.5em;
        display: block;
    }

    .warning{
        color: rgb( 240, 20, 20 )
        }
</style>

```python

```


# Calculating $R_0$ for a SIR model...and beyond

Here we discuss some expanded SIR models and we look at the desirability and efficacy of certain types of policy interventions. First, we have $R_0$ as the so-called basic reproductive rate. I am following [some online notes](https://web.stanford.edu/~jhj1/teachingdocs/Jones-on-R0.pdf) which must be great because they are from Stanford.

Some questions:

- What impact does reducing $R_0$ have?
- What measures reduce $R$?
- What costs are imposed on society by these measures?

What is $R_0$, intuitively?

$$
R_0 = \frac{\textrm{infection}}{\textrm{contact}}\frac{\textrm{contact}}{\textrm{time}}\frac{\textrm{time}}{\textrm{infection}}
$$

In the SIR model, we have:

$$
\begin{array}{ccc}
\dot{s} & = & - \beta i s\\
\dot{i} & = &  \beta i s - \nu i \\
\dot{r} & = & \nu i
\end{array}
$$

To calculate $R_0$ in a way that is more amenable to policy (at least as economics think about it), it is helpful to think about the above in terms of a discrete time framework, and in terms of the so-called _next-generation matrix_.

$\mathbf{G}$. Generically

$$
\frac{\dot{i}}{{i}}=\beta s- \nu
$$

Another tidbit - minimize the number of people that are infected in the end...or minimize some weighted average of what is called $s_\infty$ or $d$. We can write these two things as functions of $R_0$.

Some add-on questions:

- what if we are late to the party?
- what technological measures can we use to do all of this?

```python
from sympy import *
```

Let's look at the SEIM model, where we have four equations:

$$
\begin{array}{ccc}
\dot{s} & = & - \beta i s\\
\dot{i} & = &  \beta i s - \nu i \\
\dot{r} & = & \nu i
\end{array}
$$

What does the model look like in discrete time?

It would be :

$$
\begin{array}{ccc}
s_{t+1} & = & s_t- \beta i_t s_t\\
i_{t+1} & = & i_t +\beta i_t s_t - \nu i_t \\
r_{t+1} & = & r_t+\nu i_t
\end{array}
$$

So, note that we can write this as a transition matrix equation:

$$
\left[
\begin{array}{c}
s_{t+1} \\
i_{t+1} \\
r_{t+1}
\end{array}
\right]
=\left[
\begin{array}{ccc}
1 & -\beta s_t & 0 \\
\beta i_t & 1-\nu & 0 \\
0 & \nu & 1
\end{array}
\right]
\left[
\begin{array}{c}
s_{t} \\
i_{t} \\
r_{t}
\end{array}
\right]
$$

First, let's develop a little simulator of the system. In this case, we have:

```python
import numpy as np

import matplotlib.pyplot as plt

def sirmodel(s0=.99, i0=.01, r0 =0, beta=.1, nu=.03, its=1000, tol=.005):

    '''Simulation of the SIR model. The model stops running when the number of infecteds
       falls below tolerance or when the maximum iterations are reached.
       Tolerance must be less than i0 or the model will never
       get going.'''

    S = []
    I = []
    R = []

    s = s0
    i = i0
    r = r0

    t=0

    while t<its and i> tol:

        sp = s - beta*s*i
        ip = i + beta*s*i - nu*i
        rp = r + nu*i

        S.append(sp)
        I.append(ip)
        R.append(rp)

        s = sp
        i = ip
        r = rp

        t += 1

    return({'s':S, 'i':I, 'r':R})
```

```python
sim = sirmodel()
xs  = np.arange(len(sim['s']))

sline = plt.plot(xs, sim['s'])
rline = plt.plot(xs, sim['r'])
iline = plt.plot(xs, sim['i'])

legen = plt.legend(['Susceptible', 'Recovered', 'Infected'])
```

What does the model look like with my modification using the minimum function?

```python
import numpy as np

import matplotlib.pyplot as plt

def sirmodel_min(s0=.99, i0=.01, r0 =0, beta=.1, nu=.03, its=1000, tol=.005):

    '''Simulation of the SIR model. The model stops running when the number of infecteds
       falls below tolerance or when the maximum iterations are reached.
       Tolerance must be less than i0 or the model will never
       get going.'''

    S = []
    I = []
    R = []

    s = s0
    i = i0
    r = r0

    t=0

    while t<its and i> tol:

        sp = s - beta*min((s,i))
        ip = i + beta*min((s,i)) - nu*i
        rp = r + nu*i

        S.append(sp)
        I.append(ip)
        R.append(rp)

        s = sp
        i = ip
        r = rp

        t += 1

    return({'s':S, 'i':I, 'r':R})
```

```python
sim = sirmodel_min()
xs  = np.arange(len(sim['s']))

sline = plt.plot(xs, sim['s'])
rline = plt.plot(xs, sim['r'])
iline = plt.plot(xs, sim['i'])

legen = plt.legend(['Susceptible', 'Recovered', 'Infected'])
```

With this in mind, let's note that the model has very similar behavior to the SIR model, but is actually more aggresive in the way it models outbreaks. In any event, we can consider two regimes and a variable-time free sort of model. What would control of this model look like?

Controlling the outbreak:
- We might suppose that we can reduce $\beta$ by some amount, so that we have: $\beta=(1-z_t)$, but also let's suppose it is not possible to reduce it too much...
- There are costs of control, but let's suppose that actually enforcing the policy isn't all that costly. It is just social costs.
- Then, the costs per unit time are:

$$
c_t = c_t (z_t)
$$

Note that what we would really want is for this to be something like $c_t(z_tn_t)$, but our population is normalized at unity. We also have the costs of immediate care of infecteds, which we will suppose is $d_t(i_t)$. This should certainly be quadratic and is a major motivation for everything!

```python
import numpy as np

import matplotlib.pyplot as plt

def sirmodel_min_pol(s0=.99, i0=.01, r0 =0, beta=.1, nu=.03, z=.1, its=1000, tol=.005):

    '''Simulation of the SIR model. The model stops running when the number of infecteds
       falls below tolerance or when the maximum iterations are reached.
       Tolerance must be less than i0 or the model will never
       get going.'''

    S = []
    I = []
    R = []

    s = s0
    i = i0
    r = r0

    t=0

    while t<its and i> tol:

        sp = s - beta*min((s,i))*(1-z)
        ip = i + beta*min((s,i))*(1-z) - nu*i
        rp = r + nu*i

        S.append(sp)
        I.append(ip)
        R.append(rp)

        s = sp
        i = ip
        r = rp

        t += 1

    return({'s':S, 'i':I, 'r':R})
```

```python
sim1 = sirmodel_min()
sim2 = sirmodel_min_pol(z=.2)
xs1  = np.arange(len(sim1['s']))
xs2  = np.arange(len(sim2['s']))

sline  = plt.plot(xs1, sim1['s'])
rline  = plt.plot(xs1, sim1['r'])
iline  = plt.plot(xs1, sim1['i'])
slinep = plt.plot(xs2, sim2['s'], linestyle='dashed')
rlinep = plt.plot(xs2, sim2['r'], linestyle='dashed')
ilnep  = plt.plot(xs2, sim2['i'], linestyle='dashed')

legen = plt.legend(['Susceptible', 'Recovered', 'Infected', 'Susceptible', 'Recovered', 'Infected'])
```

```python
sirmodel_policy
```

# Hamiltonian:

In the down-tick regime, we have, $s_t<i_t$, so:

$$
H_t = c_t(z_t)+d_t(i_t) + \lambda_t(s_t-\beta (1-z_t) s_t)+\mu_t(i_t+\beta (1-z_t) s_t-\nu i_t)
$$

So, the optimality conditions are:

$$
c_t'(z_t) + \lambda_t \beta s_t - \mu_t\beta s_t
$$

$$
\lambda_t = \lambda_t(1-\beta(1-z_t))+\mu_t\beta(1-z_t)
$$

$$
\mu_t = d'_t(i_t) + \mu_t(1-\nu)
$$

From the second equation, we get: $\mu_t=\frac{d_t'(i_t)}{\nu}$. Quite simply the shadow value of delay is the discounted recovery value. More interestingly, we have, from the second equation, $\lambda_t=\mu_t$. Note that when plugged into the first equation, this gives us: $c'(z_t)=0$.

Question: would discounting change this?

What about the other side of the coin?

Here, the Hamiltonian is:

$$
H_t = c_t(z_t)+d_t(i_t) + \lambda_t(s_t-\beta (1-z_t) i_t)+\mu_t(i_t+\beta (1-z_t) i_t-\nu i_t)
$$

With optimality conditions:

$$
c_t'(z_t) + \lambda_t \beta s_t - \mu_t\beta i_t
$$

$$
\lambda_t = \lambda_t(1-\beta(1-z_t))
$$

$$
\mu_t = d'_t(i_t) - \lambda_t\beta(1-z_t)+\mu_t(1-\nu+\beta(1-z_t))
$$

My hunch is that $\lambda_t=0$ is part of the solution; it doesn't really matter here. So, we really have a one-variable control problem. The remaining equations are:

$$
c_t'(z_t)=\mu_t\beta i_t
$$
$$
\mu_t = d'_t(i_t)+\mu_t(1-\nu+\beta(1-z_t))
$$

If we solve the second equation, we have the following:

$$
\mu_t(\nu-\beta(1-z_t)) = d'_t(i_t)
$$

So then, we have:

$$
c'_t(z_t)(\nu-\beta(1-z_t))=\beta i_td'_t(i_t)
$$

So, if costs of the policy are constant and so are the costs, we have:

$$
c(\nu-\beta+\beta z_t) = \beta d'(i_t)i_t
$$

Which in the end becomes the linear feedback rule:

$$
z_t = \frac{\beta d'(i_t)i_t}{c}+\beta - \nu
$$

```python
def sirmodel_pol(s0=.99, i0=.01, r0 =0, beta=.1, z=.1, zstart=0, zend=.05, nu=.03, its=1000, tol=.005):

    '''Simulation of the SIR model. The model stops running when the number of infecteds
       falls below tolerance or when the maximum iterations are reached.
       Tolerance must be less than i0 or the model will never
       get going.'''

    S = []
    I = []
    R = []
    Z = []

    s = s0
    i = i0
    r = r0

    t=0
    switch = 0
    zh = 0

    while t < its and i > tol:

        if (i>=zstart) and (switch == 0):
            zh=z
            if (i > zend):
                switch = 1

        if (i<=zend) and (switch == 1):
            zh=0

        sp = s - beta*s*i*(1-zh)
        ip = i + beta*s*i*(1-zh) - nu*i
        rp = r + nu*i

        S.append(sp)
        I.append(ip)
        R.append(rp)
        Z.append(zh)

        s = sp
        i = ip
        r = rp

        t += 1

    return({'s':S, 'i':I, 'r':R, 'z':Z})
```

```python
sim1 = sirmodel()
sim2 = sirmodel_pol(z=.39, zstart=0, zend=0.01)
xs1  = np.arange(len(sim1['s']))
xs2  = np.arange(len(sim2['s']))

sline  = plt.plot(xs1, sim1['s'])
rline  = plt.plot(xs1, sim1['r'])
iline  = plt.plot(xs1, sim1['i'])
slinep = plt.plot(xs2, sim2['s'], linestyle='dashed')
rlinep = plt.plot(xs2, sim2['r'], linestyle='dashed')
ilinep = plt.plot(xs2, sim2['i'], linestyle='dashed')
pline  = plt.plot(xs2, sim2['z'], linestyle='dotted')

legen = plt.legend(['Susceptible', 'Recovered', 'Infected', 'Susceptible', 'Recovered', 'Infected', 'Policy'])
```

```python
print('Total periods of surpression:', np.sum(sim2['z']))
print('Total time length: ', len(sim2['z']))
print('Total infected: ', sim2['r'][-1])
print('Peak infection: ', np.max(sim2['i']))

# Without Policy

print('')

print('Total infected without intervention:', np.sum(sim1['i']))
print('Total time length: ', len(sim1['i']))
print('Total infected: ', sim1['r'][-1])
print('Peak infection: ', np.max(sim1['i']))
```

    Total periods of surpression: 19.199999999999996
    Total time length:  287
    Total infected:  0.93841418816132
    Peak infection:  0.3073602184279912

    Total infected without intervention: 31.84804909848912
    Total time length:  267
    Total infected:  0.9555933642236504
    Peak infection:  0.346216183226024

```python
from sympy import *

init_printing()
```

```python
s, nu, beta = symbols('s nu beta')
```

```python
eq = 1-s + nu/beta*log(s)
eq
```

```python
ssta = solve(eq, s)[0]
ssta.subs({beta:.2, nu:.1})
```

```python

```


---
## 01. Interpolación de Funciones

Eduard Larrañaga (ealarranaga@unal.edu.co)

---

## Interpolación

### Resumen

En este cuaderno se presentan algunas de las técnicas de interpolación de una función.

---

## Interpolación

Los datos astrofísicos (experimentales y sintéticos) usualmente consiten de un conjunto de valores discretos con la forma $(x_j, f_j)$ en donde se representa el valor de una función $f(x)$ paa un conjunto finito de argumentos $\{ x_0, x_1, x_2, ..., x_{n} \}$. Sin embargo, en muchas ocasiones se necesita conocer el valor de la función en puntos adicionales (que no pertenecen al conjunto dado). La **interpolación** es el método que permite obtener estos valores.

Por **interpolación** entenderemos el definir una función $g(x)$, utilizando la información discreta conocida y de tal forma que $g(x_j) = f(x_j)$ y que se aproxime el valor de la función $f$ en cualquier punto $x \in [x_{min}, x_{max}]$, done $x_{min} = \min [x_j]$ y $x_{max} = \max \{ x_j \}$.

Por otro lado, la **extrapolación** correspondería a aproximar el valor de la función $f$ en un punto $x \notin [x_{min}, x_{max}]$}. Sin embargo, este caso no será analizado aquí.

---
## Interpolación Lineal Simple

El método de interpolación más simple es denominado **Interpolación Polinomial** y consiste en encontrar un polinomio $p_n(x)$ de grado $n$ que pasa por $N = n+1$ puntos $x_j$ tomando los valores $p(x_j) = f(x_j)$, donde $j=0,1,2,...,n$.

El polinomio se escribe en la forma general

$p_n(x) = a_0 + a_1 x + a_2 x^2 + \cdots + a_n x^n$

donde $a_i$ son $n+1$-constantes reales que se determinarán por las condiciones

$\left(
\begin{array}{ccccc}
1&x_0^1&x_0^2&\cdots&x_0^n\\
\vdots&\vdots&\vdots&\vdots&\vdots\\
\vdots&\vdots&\vdots&\vdots&\vdots\\
1&x_n^1&x_n^2&\cdots&x_n^n\\
\end{array}
\right)
\left(\begin{array}{c}
a_0\\
\vdots\\
\vdots\\
a_n
\end{array}\right)
=
\left(\begin{array}{c}
f(x_0)\\
\vdots\\
\vdots\\
f(x_n)
\end{array}\right)$

La solución de este sistema es fácil de obtener en los casos de interpolación lineal ($n=1$) y cuadrática  ($n=2$), pero puede ser dificil de encontrar para un valor grande de $n$.

---
###  Interpolación Lineal

La interpolación lineal ($n=1$) de una función $f(x)$ en un intervalo
$[x_i,x_{i+1}]$ requiere conocer solamente  dos puntos.

Resolviendo el sistema lineal resultante se obtiene el polinomio interpolado

\begin{equation}
p_1(x) = f(x_i) + \frac{f(x_{i+1}) - f(x_i)}{x_{i+1} - x_i} (x-x_i) + \mathcal{O}(\Delta x^2)
\end{equation}

donde $\Delta x = x_{i+1} - x_i$.

El método de interpolación lineal provee un polinomio con una precisión de segundo orden que puede ser derivado una vez, pero esta derivada no es continua en los puntos extremos del intervalo de interpolación, $x_i$ y $x_{i+1}$.

#### Ejemplo. Interpolación Lineal por intervalos

A continuación se leerá un conjunto de datos desde un archivo .txt y se interpolará linealmente entre cada par de puntos (*piecewise interpolation*)

```python
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# Reading the data
data = np.loadtxt('data_points.txt', comments='#', delimiter=',')
x = data[:,0]
f = data[:,1]

plt.figure()
plt.scatter(x,f)
plt.xlabel(r'$x$')
plt.ylabel(r'$f(x)$')
plt.show()
```

```python
data.shape
```

    (20, 2)

```python
def linearInterpolation(x1, x2, f1, f2, x):
    p1 = f1 + ((f2-f1)/(x2-x1))*(x-x1)
    return p1

N = len(x)

plt.figure(figsize=(7,5))
plt.scatter(x, f, color='black')

for i in range(N-1):
    x_interval = np.linspace(x[i],x[i+1],3)
    # Note that the number 3 in thie above line indeicates the number of
    # points interpolated in each interval !
    # (including the extreme points of the interval)
    y_interval = linearInterpolation(x[i], x[i+1], f[i], f[i+1], x_interval)
    plt.plot(x_interval, y_interval,'r')

plt.title(r'Linear Piecewise Interpolation')
plt.xlabel(r'$x$')
plt.ylabel(r'$p_1(x)$')
plt.show()
```

---
###  Interpolación Cuadrática

La interpolación cuadrática ($n=2$) requiere información de tres puntos.

Por ejemplo, se pueden tomar los tres puntos $x_i$ , $x_{i+1}$ y $x_{i+2}$ para interpolar la función $f(x)$ en el rango$[x_{i},x_{i+1}]$. Al solucionar el sistema de ecuaciones lineales correspondiente se obtiene el polinomio

$p_2(x) = \frac{(x-x_{i+1})(x-x_{i+2})}{(x_i - x_{i+1})(x_i - x_{i+2})} f(x_i)
+ \frac{(x-x_{i})(x-x_{i+2})}{(x_{i+1} - x_{i})(x_{i+1} - x_{i+2})} f(x_{i+1})
+ \frac{(x-x_i)(x-x_{i+1})}{(x_{i+2} - x_i)(x_{i+2} - x_{i+1})} f(x_{i+2}) + \mathcal{O}(\Delta x^3)$,

donde $\Delta x = \max \{ x_{i+2}-x_{i+1},x_{i+1}-x_i \}$.

En este caso, el polinomio interpolado se puede derivar dos veces pero, aunque su primera derivada es continua, la segunda derivada no es continua en los puntos extremos del intervalo.

#### Ejemplo. Interpolación Cuadrática por Intervalos

A continuación se leerá un conjunto de datos desde un archivo .txt y se interpolará cuadráticamente en sub-intervalos (*quadratic piecewise interpolation*)

```python
import numpy as np
import matplotlib.pyplot as plt

# Reading the data
data = np.loadtxt('data_points.txt', comments='#', delimiter=',')
x = data[:,0]
f = data[:,1]

def quadraticInterpolation(x1, x2, x3, f1, f2, f3, x):
    p2 = (((x-x2)*(x-x3))/((x1-x2)*(x1-x3)))*f1 +\
    (((x-x1)*(x-x3))/((x2-x1)*(x2-x3)))*f2 +\
    (((x-x1)*(x-x2))/((x3-x1)*(x3-x2)))*f3
    return p2

N = len(x)

plt.figure(figsize=(7,5))
plt.scatter(x, f, color='black')

for i in range(N-2):
    x_interval = np.linspace(x[i],x[i+1],6) # 6 interpolate points in each interval
    y_interval = quadraticInterpolation(x[i], x[i+1], x[i+2], f[i], f[i+1], f[i+2], x_interval)
    plt.plot(x_interval, y_interval,'r')

plt.title(r' Quadratic Polynomial Piecewise Interpolation')
plt.xlabel(r'$x$')
plt.ylabel(r'$p_2(x)$')
plt.show()
```

**Nota:** Por la forma de realizar la interpolación cuadrática, el último intervalo queda sin información. En esta región se puede extender la interpolación del penúltimo intervalo o también se puede interpolar un polinomio lineal.

---
## Interpolación de Lagrange

La **Interpolación de Lagrange Interpolation** también busca un polinomio de grado $n$ utilizando $n+1$ puntos, pero utiliza un método alternativo de encontrar los coeficientes. Para comprender esta idea, re-escribimos el polinomio lineal encontrado antes en la forma

\begin{equation}
p_1(x) = \frac{x-x_{i+1}}{x_i - x_{i+1}} f(x_i) + \frac{x-x_i}{x_{i+1}-x_i} f(x_{i+1}) + \mathcal{O}(\Delta x^2),
\end{equation}

o así,

\begin{equation}
p_1(x) = \sum_{j=i}^{i+1} f(x_j) L_{1j}(x) + \mathcal{O}(\Delta x^2)
\end{equation}

donde se han introducido los *coeficientes de Lagrange*

\begin{equation}
L_{1j}(x) = \frac{x-x_k}{x_j-x_k}\bigg|_{k\ne j}.
\end{equation}

Nótese que estos coeficientes aseguran que el polinomio pasa por los puntos conocidos, i.e. $p_1(x_i) = f(x_i)$ y $p_1(x_{i+1}) = f(x_{i+1})$

La **interpolación de Lagrange** generaliza estas expresiones para un polinomio de grado $n$ que pasa por los $n+1$ puntos conocidos,

\begin{equation}
p_n (x) = \sum_{j=0}^{n} f(x_j) L_{nj}(x) + \mathcal{O}(\Delta x^{n+1})\,, \label{eq:LagrangeInterpolation}
\end{equation}

donde los coeficientes de Lagrange se generalizan a

\begin{equation}
L_{nj}(x) = \prod_{k\ne j}^{n} \frac{x-x_k}{x_j - x_k}\,.
\end{equation}

De nuevo, es posible notar que estos coeficientes aseguran que el polinomio pasa por los puntos concidos $p(x_j) = f(x_j)$.

```python
# %load lagrangeInterpolation
'''
Eduard Larrañaga
Computational Astrophysics
2020

Lagrange Interpolation Method
'''

import numpy as np

#Lagrange Coefficients
def L(x, xi, j):
	'''
	------------------------------------------
	L(x, xi, j)
	------------------------------------------
    Returns the Lagrange coefficient for the
    interpolation evaluated at points x
    Receives as arguments:
    x : array of points where the interpolated
    polynomial will be evaluated
    xi : array of N data points
    j : index of the coefficient to be
    calculated
	------------------------------------------
	'''
	# Number of points
	N = len(xi)

	prod = 1
	for k in range(N):
		if (k != j):
			prod = prod * (x - xi[k])/(xi[j] - xi[k])
	return prod

# Interpolated Polynomial
def p(x, xi, fi):
	'''
	------------------------------------------
    p(x, xi, fi)
    ------------------------------------------
    Returns the values of the Lagrange
    interpolated polynomial in a set of points
    defined by x
    x : array of points where the interpolated
    polynomial will be evaluated
    xi : array of N data points points
    fi : values of the function to be
    interpolated
    ------------------------------------------
	'''
	# Number of points
	N = len(xi)

	summ = 0
	for j in range(N):
		summ = summ + fi[j]*L(x, xi, j)
	return summ

```

```python
import numpy as np
import matplotlib.pyplot as plt
#import lagrangeInterpolation as lagi
import sys

# Reading the data
data = np.loadtxt('data_points.txt', comments='#', delimiter=',')
x = data[:,0]
f = data[:,1]

N = len(x)

# Degree of the polynomial to be interpolated piecewise
n = 3

# Check if the number of point is enough to interpolate such a polynomial
if n>=N:
    print('\nThere are not enough points to interpolate this polynomial.')
    print(f'Using {N:.0f} points it is possible to interpolate polynomials up to order n={N-1:.0f}')
    sys.exit()

plt.figure(figsize=(7,5))
plt.title(f'Lagrange Polynomial Piecewise Interpolation n={n:.0f}')
plt.scatter(x, f, color='black')

# Piecewise Interpolation Loop
for i in range(N-n):
    xi = x[i:i+n+1]
    fi = f[i:i+n+1]
    x_interval = np.linspace(x[i],x[i+1],3*n)
    y_interval = p(x_interval,xi,fi)
    plt.plot(x_interval, y_interval,'r')

plt.xlabel(r'$x$')
plt.ylabel(r'$p_n(x)$')
plt.show()
```

Nótese que los últimos $n$ puntos no estan interpolados. Qué se puede hacer?

```python
import numpy as np
import matplotlib.pyplot as plt
#import lagrangeInterpolation as lagi
import sys

# Reading the data
data = np.loadtxt('data_points.txt', comments='#', delimiter=',')
x = data[:,0]
f = data[:,1]

N = len(x)

# Degree of the polynomial to be interpolated piecewise
n = 6

# Check if the number of point is enough to interpolate such a polynomial
if n>=N:
    print('\nThere are not enough points to interpolate this polynomial.')
    print(f'Using {N:.0f} points it is possible to interpolate polynomials up to order n={N-1:.0f}')
    sys.exit()

plt.figure(figsize=(7,5))
plt.title(f'Lagrange Polynomial Piecewise Interpolation n={n:.0f}')
plt.scatter(x, f, color='black')

# Piecewise Interpolation Loop
for i in range(N-n):
    xi = x[i:i+n+1]
    fi = f[i:i+n+1]
    x_interval = np.linspace(x[i],x[i+1],3*n)
    y_interval = p(x_interval,xi,fi)
    plt.plot(x_interval, y_interval,'r')

# Piecewise Interpolation for the final N-n points,
# using a lower degree polynomial
while n>1:
    m = n-1
    for i in range(N-n,N-m):
        xi = x[i:i+m+1]
        fi = f[i:i+m+1]
        x_interval = np.linspace(x[i],x[i+1],3*m)
        y_interval = p(x_interval,xi,fi)
        plt.plot(x_interval, y_interval,'r')
    n=n-1

plt.xlabel(r'$x$')
plt.ylabel(r'$p_n(x)$')
plt.show()
```

### Fenómeno de Runge

Por qué se se interpola por sub-intervalos? Cuando se tiene una gran cantidad de puntos conocidos, es posible interpolar un polinomio de grado alto. Sin embargo, el comportamiento del polinomio interpolado puede no ser el esperado (especialmente en los extremos del intervalo de interpolación) debido a la existencia de oscilaciones no controladas. A este comportamiento se le denomina el fenómeno de Runge.

Por ejemplo, para un conjunto de datos con $20$ puntos es posible interpolar un polinomio de orden $n=19$,

```python
import numpy as np
import matplotlib.pyplot as plt
import lagrangeInterpolation as lagi
import sys

# Reading the data
data = np.loadtxt('data_points.txt', comments='#', delimiter=',')
x = data[:,0]
f = data[:,1]

N = len(x)

# Higher Degree polynomial to be interpolated
n = N-1

plt.figure(figsize=(7,5))
plt.title(f'Lagrange Polynomial Piecewise Interpolation n={n:.0f}')
plt.scatter(x, f, color='black')

#Interpolation of the higher degree polynomial
x_int = np.linspace(x[0],x[N-1],3*n)
y_int = lagi.p(x_int,x,f)
plt.plot(x_int, y_int,'r')

plt.xlabel(r'$x$')
plt.ylabel(r'$p_n(x)$')
plt.show()
```

Sin embargo, es claro que el comportamiento del polinomio interpolado no es bueno en los extremos del intervalo considerado. Por esta razón, es muy aconsejable utilizar una interpolación de polinomios de grado pequeño por sub-intervalos.

---
## Interpolación Cúbica de Hermite por Intervalos

La interpolación de Hermite es unc aso particular de interpolación polinomica que utiliza un conjunto de puntos conocidos en donde se conoce el valor de la función $f(x_j)$ y su derivada $f'(x_j)$. Al incorporar la primera derivada se pueden interpolar polinomios de un grado alto controlando las osiclaciones no deseadas. Adicionalmente, al conocer la primera derivada, se necesitan menos puntos para realizar la interpolación.

Dentro de este tipo de interpolación, la más utilizada es la de polinomios de tercer orden. DE esta forma, en un intervalo $[x_i , x_{i+1}]$, se requiere conocer (o evaluar) los valores de $f(x_i)$, $f(x_{i+1})$, $f'(x_i)$ y $f'(x_{i+1})$ para obtener el polinomio interpolado de Hermite cúbico,

\begin{equation}
H_3(x) = f(x_i)\psi_0(z) + f(x_{i+1})\psi_0(1-z)+ f'(x_i)(x_{i+1} - x_{i})\psi_1(z) - f'(x_{i+1})(x_{i+1}-x_i)\psi_1 (1-z),
\end{equation}

donde

\begin{equation}
z = \frac{x-x_i}{x_{i+1}-x_i}
\end{equation}

y

\begin{align}
\psi_0(z) =&2z^3 - 3z^2 + 1 \\
\psi_1(z) =&z^3-2z^2+z\,\,.
\end{align}

Nótese que con esta formulación, es posible interpolar un polinomio de tercer orden en un intervalo con solo dos puntos. De esta forma, al trabajar con un conjunto de muhos puntos, se podría interpolar un polinomio cúbico entre cada par de datos, incluso en el último sub-intervalo!

```python
# %load HermiteInterpolation
'''
Eduard Larrañaga
Computational Astrophysics
2020

Hermite Interpolation Method
'''

import numpy as np

#Hermite Coefficients
def psi0(z):
	'''
	------------------------------------------
	psi0(z)
	------------------------------------------
	Returns the Hermite coefficients Psi_0
	for the interpolation
	Receives as arguments: z
	------------------------------------------
	'''
	psi_0 = 2*z**3 - 3*z**2 + 1
	return psi_0

def psi1(z):
	'''
	------------------------------------------
	psi1(z)
	------------------------------------------
	Returns the Hermite coefficients Psi_1 for
	the interpolation
	Receives as arguments: z
	------------------------------------------
	'''
	psi_1 = z**3 - 2*z**2 + z
	return psi_1

# Interpolated Polynomial
def H3(x, xi, fi, dfidx):
	'''
	------------------------------------------
    H3(x, xi, fi, dfidx)
    ------------------------------------------
    Returns the values of the Cubic Hermite
    interpolated polynomial in a set of points
    defined by x
    x : array of points where the interpolated
    polynomial will be evaluated
    xi : array of 2 data points
    fi : array of values of the function at xi
    dfidx : array of values of the derivative
    of the function at xi
    ------------------------------------------
	'''
	# variable z in the interpolation
	z = (x - xi[0])/(xi[1] - x[0])

	h1 = psi0(z) * fi[0]
	h2 = psi0(1-z)*fi[1]
	h3 = psi1(z)*(xi[1] - xi[0])*dfidx[0]
	h4 = psi1(1-z)*(xi[1] - xi[0])*dfidx[1]
	H =  h1 + h2 + h3 - h4
	return H

```

```python
import numpy as np
import matplotlib.pyplot as plt
import HermiteInterpolation as heri

def Derivative(x, f):
    '''
    ------------------------------------------
    Derivative(x, f)
    ------------------------------------------
    This function returns the numerical
    derivative of a discretely-sample function
    using one-side derivatives in the extreme
    points of the interval and second order
    accurate derivative in the middle points.
    The data points may be evenly or unevenly
    spaced.
    ------------------------------------------
    '''
    # Number of points
    N = len(x)
    dfdx = np.zeros([N, 2])
    dfdx[:,0] = x

    # Derivative at the extreme points
    dfdx[0,1] = (f[1] - f[0])/(x[1] - x[0])
    dfdx[N-1,1] = (f[N-1] - f[N-2])/(x[N-1] - x[N-2])

    #Derivative at the middle points
    for i in range(1,N-1):
        h1 = x[i] - x[i-1]
        h2 = x[i+1] - x[i]
        dfdx[i,1] = h1*f[i+1]/(h2*(h1+h2)) - (h1-h2)*f[i]/(h1*h2) -\
                    h2*f[i-1]/(h1*(h1+h2))

    return dfdx

# Loading the data
data = np.loadtxt('data_points.txt', comments='#', delimiter=',')
x = data[:,0]
f = data[:,1]
N = len(x)

# Calling the derivative function and chosing only the second column
dfdx = Derivative(x,f)[:,1]

plt.figure(figsize=(7,5))
plt.title(f'Cubic Hermite Polynomial Piecewise Interpolation')
plt.scatter(x, f, color='black')

# Piecewise Hermite Interpolation Loop
for i in range(N-1):
    xi = x[i:i+2]
    fi = f[i:i+2]
    dfidx = dfdx[i:i+2]
    x_interval = np.linspace(x[i],x[i+1],4)
    y_interval = heri.H3(x_interval, xi, fi, dfidx)
    plt.plot(x_interval, y_interval,'r')

plt.xlabel(r'$x$')
plt.ylabel(r'$H_3(x)$')
plt.show()

```

```python

```


# HOMEWORK 3: Designing Closed Loop Systems

This homework involves designing a closed loop system with a PID controller.

```python
!pip -q install controlSBML
import controlSBML as ctl
import control
from controlSBML.util import makeSimulationTimes
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import sympy as sy
import tellurium as te
import sympy
print("controlSBML version: " + ctl.__version__)
```

    controlSBML version: 0.2.14

```python
# Use the local file if it's available
BIOMD823 = "https://www.ebi.ac.uk/biomodels/model/download/BIOMD0000000823.2?filename=Varusai2018.xml"
```

**Transfer Functions**
\begin{eqnarray}
H_{RY}(s) & = & \frac{Y(s)}{R(s)} & = & \frac{C(s) G(s)}{1 + C(s) G(s) F(s)} \\
H_{RE}(s) & = & \frac{E(s)}{R(s)} & = & \frac{1}{1 + C(s) G(s) F(s)} \\
H_{NY}(s) & = & \frac{Y(s)}{N(s)} & = & -\frac{ F(s)}{1 + C(s) G(s) F(s)} \\
H_{DY}(s) & = & \frac{Y(s)}{D(s)} & = & \frac{ C(s)}{1 + C(s) G(s) F(s)} \\
\end{eqnarray}

In this homework, you will design a closed loop system for controlling pDEPTOR in the mTOR system as modelled in BioModels 823.
Use pAkt as the control input.
1. **Build**. (4 pt) Implement the function ``evaluateDesign`` that evaluates the control design of
a closed loop system for mTOR.
The evaluation is in the form of a plot of the step response of the system
to a change in the reference input.
The plot should include the reference input along with the pAkt and pDEPTO
values for the closed loop mTOR system. The function has as inputs the design parameters kp, ki, kd.
1. **Design**. (2 pt) Use ``evaluateDesign`` to design a system that has no bias for a unit step response in the reference and settles within 10 seconds.
1. **Analysis**. (3 pt) Construct the transfer function
for mTOR from pAkt to pDEPTOR
and the transfer function $H_{NY} (s)$ for the design parameters you used in (2)
(Obtain the Jacobian at time 1 from the open loop mTOR system.)
Use these transfer functions to answer the following questions about how the closed loop system should behave *in theory*.
   1. Why are large control inputs required to control the mTOR system?
   1. Why are there no long term oscillations in the closed loop system?
   1. How will a step increase in noise affect the output of the closed loop system?
1. **Discussion**. (1 pt) Plot the values of pAkt for the closed loop system you designed in (2).
What issues do you see with using this closed loop system in practice?

# Q1. Build

# Q2. Design

# Q3. Analyze

# Q4. Discussion