# Taylor Expansions

Series expansions are used in a variety of circumstances:
- When we need a tractable approximation to some ugly equation
- To transform between equivalent ways of looking at a problem (e.g. time domain vs frequency domain)
- When they are (part of) a solution to a particular class of differential equation

For approximations, there is an important divide between getting the best fit *near a point* (e.g. [Taylor series](#taylor)) and getting the best fit *over an interval* (e.g. Fourier series). This notebook only deals with the former; there is a separate notebook for Fourier, Bessel, etc.

## Fitting near a point

What is the best (low order) polymomial approximating my function at *this* point? It doesn't matter if it diverges wildly as we get far away from the point, though adding higher-order terms may extend the range of usefulness.



## Taylor and Maclaurin series

A function $f(x)$ can be approximated at a point $x=a$ by the polynomial

$$ f(x) \approx f(a) + f'(a) (x-a) + \frac{1}{2} f''(a) (x-a)^2 \dots \frac{1}{n!} f^n(a) (x-a)^n $$

For this to converge, either $(x-a)$ should be small so we can ignore high powers, or the differentials should become zero.

The general case for $x=a$ is the Taylor Series. The special case where $x=0$ is sometimes called the Maclaurin series.

For the Python sections we will need a substantial range of imports, adding SymPy to the usual set of numpy, matplotlib and widgets.


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

from ipywidgets import interact, interactive, fixed, interact_manual, Layout
import ipywidgets as w

plt.rcParams.update({'font.size': 16})

from sympy import * # TODO - narrow this later
init_printing()
from sympy.functions import sin, cos

from sympy.parsing.sympy_parser import parse_expr
from sympy.parsing.sympy_parser import standard_transformations, implicit_multiplication_application
transformations = (standard_transformations + (implicit_multiplication_application,))

```

Define some functions to be used later, plus a SymPy symbol.


```python
# Define the variable for SymPy functions
x = Symbol('x')

# Taylor approximation at x=a of function f, to order n
def taylor(f, a, n):
    # f is a SymPy function
    terms = []
    for i in range(n+1):
        terms.append((f.diff(x, i).subs(x, a))/(factorial(i))*(x - a)**i)
    return terms

# Plot results
def plotTaylor(f_sympy, a, n):
    
    # get a NumPy-style function from the SymPy version
    f_np = lambdify(x, f_sympy, 'numpy')
    
    # plot the starting function
    x_lims = [-5,5]
    x1 = np.linspace(x_lims[0], x_lims[1], 500)
    plt.figure(figsize=(9, 9))
    plt.plot(x1, f_np(x1), 'k.', label=f_sympy)
    
    # get n terms of a Taylor series 
    f_taylor_terms = taylor(f_sympy, 0, n) # a list
    f_taylor = sum(f_taylor_terms) # the whole func to order n
    display(f_sympy) # display shows LaTex, print wouldn't
    print('Taylor expansion at x = {:.2f}, n = {:d}:'.format(a, n))
    display(f_taylor)

    # plot the successive approximations
    y = np.zeros(len(x1))
    for i in range(n):
        term = f_taylor_terms[i]
        if term.is_zero: 
            # odd or even functions only use alternate terms
            continue
        term_np = lambdify(x, term, 'numpy')
        y += term_np(x1)
        plt.plot(x1, y, label='order ' + str(i+1))

    # graph housekeeping
    plt.xlim(x_lims)
    plt.ylim([-3,3])
    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    plt.grid(True)
    plt.title('Taylor series approximation of ' + str(f_sympy))
```

We will want to enter arbitrary functions into a text box, but these need to be parsed into a form that SymPy (and plotTaylor()) can use.

Note the variety of formats for our function: we start with a text string, parse it to a SymPy object suitable for symbolic math (differentiation, etc), 'lambdify' it to a NumPy function which can handle array input, and finally generate a plottable array of y-values.


```python
def parse_input(f_txt, a, n):
    f_sympy = parse_expr(f_txt, transformations=transformations)
    plotTaylor(f_sympy, a, n)
```

Enter any valid Python function into the text box. Enter or Tab will get trigger a redraw. Don't forget to use `**` for exponentiation rather than `^`!

Implicit multiplication may work, e.g. `x sin(x)` as a synonym for `x*sin(x)`. Adding a space improves your chances of success.

The parser presumably has limits but it's unclear what they are. Experiment...


```python
style = {'description_width': 'initial'} # to avoid the labels getting truncated
interact(parse_input, 
             f_txt = w.Text(description='f(x):',
                                            layout=Layout(width='80%'),
                                            continuous_update=False,
                                            value='sin(x)'),
             a = w.FloatSlider(description="Evaluation point $a$", style=style,
                                            layout=Layout(width='80%'),
                                            continuous_update=False,
                                            min=-4, max=4, 
                                            value=0),
             n = w.IntSlider(description="Number of terms $n$", style=style,
                                            layout=Layout(width='80%'),
                                            continuous_update=False, 
                                            min=1, max=20,
                                            value=6));
```


    interactive(children=(Text(value='sin(x)', continuous_update=False, description='f(x):', layout=Layout(width='…


<a id='refs'></a>

## References

Boas, "Mathematical methods in the physical sciences"


```python

```

8627dd9a982c9a60d10ac54f625ec9595fb44cf3
ipynb
Jupyter Notebook
math/TaylorExpansions.ipynb
colinleach/astro-Jupyter
8d7618068f0460ff0c514075ce84d2bda31870b6
MIT
2020-06-06T15:35:35.000Z
2020-06-06T15:35:35.000Z
math/TaylorExpansions.ipynb
colinleach/astro-Jupyter
8d7618068f0460ff0c514075ce84d2bda31870b6
MIT
2019-06-08T11:44:15.000Z
2019-06-10T17:42:32.000Z
math/TaylorExpansions.ipynb
colinleach/astro-Jupyter
8d7618068f0460ff0c514075ce84d2bda31870b6
MIT
2021-04-14T15:28:43.000Z
2021-04-14T15:28:43.000Z
Qwen/Qwen-72B
1. YES
2. YES