#!/usr/bin/env python # coding: utf-8 # # Interpolation Methods # Due to the discrete (and sometimes sparse) nature of experiments and observations, data taking procedures will always produce discrete data as well. Even, as we have seen before, information only can be discretely presented into a computer due to the binary representation. However, when we are dealing with physical models, continuous and smooth properties are of course preferred. Interpolation techniques allow then to recover a continuous field (intermediate values) from sparse datasets. Throughout this section we shall cover some of these interpolation methods. # - - - # - [Linear Interpolation](#Linear-Interpolation) # - [Steps](#Steps-LI) # - [Example 1](#Example-1) # - [Lagrange Polynomial](#Lagrange-Polynomial) # - [Derivation](#Derivation) # - [Steps](#Steps-LP) # - [Activity](#Activity-LP) # - [Divided Differences](#Divided-Differences) # - [Example 2](#Example-2) # - [Hermite Interpolation](#Hermite-Interpolation) # - [Derivation in terms of divided differences](#Derivation-in-terms-of-divided-differences) # - [Example 3](#Example-3) # - - - # In[4]: import numpy as np get_ipython().run_line_magic('pylab', 'inline') import matplotlib.pyplot as plt # JSAnimation import available at https://github.com/jakevdp/JSAnimation from JSAnimation import IPython_display from matplotlib import animation from IPython.core.display import Image # - - - # # Linear Interpolation # When we have a set of discrete points of the form $(x_i, y_i)$ for $1\leq i \leq N$, the most natural way to obtain (approximate) any intermediate value is assuming points connected by lines. Let's assume a set of points $(x_i, y_i)$ such that $y_i = f(x_i)$ for an unknown function $f(x)$, if we want to approximate the value $f(x)$ for $x_i\leq x \leq x_{i+1}$, we construct an equation of a line passing through $(x_i,y_i)$ and $(x_{i+1},y_{i+1})$, yielding: # # $$\frac{y-y_i}{x-x_i} = \frac{y_{i+1}-y_i}{x_{i+1}-x_i} \ \ \longrightarrow f(x)\approx y = \frac{y_{i+1}-y_i}{x_{i+1}-x_i}(x-x_i) + y_i $$ # # and this can be applied for any $x$ such that $x_0\leq x \leq x_N$ and where it has been assumed an ordered set $\left\{x_i\right\}_i$. # ## Steps LI # Once defined the mathematical basis behind linear interpolation, we proceed to establish the algorithmic steps for an implementation. # # 1. Establish the dataset you want to interpolate, i.e. you must provide a set of the form $(x_i,y_i)$. # 2. Give the value $x$ where you want to approximate the value $f(x)$. # 3. Find the interval $[x_i, x_{i+1}]$ in which $x$ is embedded. # 4. Use the above expression in order to find $y=f(x)$. # ## Example 1 # Sample the function $f(x) = \sin(x)$ between $0$ and $2\pi$ using $N=10$ intervals. Plot both, the interpolation and the original function. # In[2]: #Linear Interpolating Function def LinearInterpolator( x, Xn, Yn ): #Sorting data, in case they are not Yn = Yn[np.argsort(Xn)] Xn = Xn[np.argsort(Xn)] #Detecting size of x try: Ninter = len(x) except: Ninter = 1 x = np.array([x,]) #Constructing function for each iteration term = lambda x, i: (Yn[i+1] - Yn[i])/(Xn[i+1] - Xn[i])*(x - Xn[i]) + Yn[i] #Detecting intervals for each x, [x_i, x_i+1] and interpolating y = [] for n in xrange(Ninter): for i in xrange(len(Xn)): if x[n] <= Xn[i]: break y.append( term(x[n],i-1) ) return np.array(y) # In[3]: #Function def function(x): return np.sin(x) #Number of intervals for data Ndat = 10 Xn = np.linspace( 0, 2*np.pi, Ndat ) Yn = function(Xn) #Obtaining linear interpolation Ninter = 100 x = np.linspace( 0, 2*np.pi, Ninter ) y = LinearInterpolator( x, Xn, Yn ) f = function(x) #Plotting plt.figure( figsize=(12,6) ) plt.plot( x, y, color="green", linewidth=2, label="linear interpolation" ) plt.plot( x, f, color="blue", linewidth=2, label="real function" ) plt.plot( Xn, Yn, "o", color="red", label="data" ) #Formatting plt.legend() plt.grid() plt.xlabel( "x" ) plt.xlabel( "y" ) plt.ylim( (-1.5,1.5) ) plt.title( "Linear interpolation of $\sin(x)$" ) # ## **Activity** # # # In an IPython notebook, use the previous code and explore the behaviour of the Linear Interpolation algorithm when varying the number of data used. # # - - - # # Lagrange Polynomial # Algebraic polynomials are very special functions as they have properties like differentiability (unlike linear interpolation) and continuity that make them useful for approximations like interpolation. A Polynomial is defined as a function given by the general expression: # # $$P_n(x) = a_nx^n + a_{n-1}x^{n-1} + \cdots + a_1 x + a_0$$ # # where $n$ is the polynomial degree. # # Another important property of polynomials is given by the [Weierstrass Approximation Theorem](http://en.wikipedia.org/wiki/Stone%E2%80%93Weierstrass_theorem), which states given a cotinuous function $f$ defined on a interval $[a,b]$, for all $\epsilon >0$, there exits a polynomial $P(x)$ such that # # $$|f(x) - P(x)|<\epsilon\ \ \ \ \ \mbox{for all }\ x\ \mbox{ in }\ [a,b].$$ # # This theorem guarantees the existence of such a polynomial, however it is necessary to propose a scheme to build it. # ## Derivation # Let's suppose a well-behaved yet unknown function $f$ and two points $(x_0,y_0)$ and $(x_1,y_1)$ for which $f(x_0) = y_0$ and $f(x_1) = y_1$. With this information we can build a first-degree polynomial that passes through both points by using the last equation in sec. [Linear Interpolation](interpolation.ipynb#Linear-Interpolation), we have # # $$P_1(x) = \left[ \frac{y_{1}-y_0}{x_{1}-x_0} \right]x + \left[ y_0 - \frac{y_{1}-y_0}{x_{1}-x_0}x_0 \right]$$ # # We can readily rewrite this expression like: # # $$P_1(x) = L_0(x)f(x_0) + L_1(x)f(x_1)$$ # # where we define the functions $L_0(x)$ and $L_1(x)$ as: # # $$L_0(x) = \frac{x-x_1}{x_0-x_1} \mbox{ and } L_1(x) = \frac{x-x_0}{x_1-x_0}$$ # # Note then that # # $$L_0(x_0) = 1,\ \ \ L_0(x_1) = 0,\ \ \ L_1(x_0) = 0,\ \ \ L_1(x_1) = 1$$ # # implying: # # $$P_1(x_0) = f(x_0) = y_0$$ # # $$P_1(x_1) = f(x_1) = y_1$$ # # Although all this procedure may seem unnecessary for a line, a generalization to larger datasets is direct. # ## General case # Let's assume again a well-behaved and unknown function $f$ sampled by using a set of $n+1$ data $(x_m,y_m)$ ($0\leq m \leq n$). # We call the set of $[x_0,x_1,\ldots,x_n]$ as the _node_ points of the _interpolation polynomial in the Lagrange form_, $P_n(x)$, where: # $$f(x)\approx P_n(x)\,,$$ # # $$P_n(x) = \sum_{i=0}^n f(x_i)L_{n,i}(x) = \sum_{i=0}^n y_iL_{n,i}(x)$$ # # # We need to find the _Lagrange polynomials_, $L_{n,i}(x)$, such that # $$L_{n,i}(x_i) = 1\,,\qquad\text{and}\,,\qquad L_{n,i}(x_j) = 0\quad\text{for $i\neq j$}$$ # A function that satisfies this criterion is # # $$L_{n,i}(x) = \prod_{\begin{smallmatrix}m=0\\ m\neq i\end{smallmatrix}}^n \frac{x-x_m}{x_i-x_m} =\frac{(x-x_0)}{(x_i-x_0)}\frac{(x-x_1)}{(x_i-x_1)}\cdots \frac{(x-x_{i-1})}{(x_i-x_{i-1})}\underbrace{\frac{}{}}_{m\ne i} # \frac{(x-x_{i+1})}{(x_i-x_{i+1})} \cdots \frac{(x-x_{n-1})}{(x_i-x_{n-1})}\frac{(x-x_n)}{(x_i-x_n)} $$ # Please note that in the expansion the term $(x-x_i)$ does not appears in both the numerator and the denominator as stablished in the productory condition $m\neq i$. # # Moreower # $$L_{n,i}(x_i) = \prod_{\begin{smallmatrix}m=0\\ m\neq i\end{smallmatrix}}^n \frac{x_i-x_m}{x_i-x_m} =1$$ # and, for $j\ne i$ # $$L_{n,i}(x_j) = \prod_{\begin{smallmatrix}m=0\\ m\neq i\end{smallmatrix}}^n \frac{x_j-x_m}{x_i-x_m} =\frac{(x_j-x_0)}{(x_i-x_0)}\cdots \frac{(\boldsymbol{x_j}-\boldsymbol{x_j})}{(x_i-x_j)}\cdots\frac{(x_j-x_n)}{(x_i-x_n)}=0.$$ # # # Then, the polynomial of $n$th-degree $P_n(x)$ will satisfy the definitory property for a interpolating polynomial, i.e. $P_n(x_i) = y_i$ for any $i$ and it is called the _interpolation Polynomial in the Lagrange form_. # # Check [this implementation in sympy](./LagrangePoly.ipynb) # # **Further details at:** # [Wikipedia](https://en.wikipedia.org/wiki/Lagrange_polynomial) # ### Example: # Obtain the Lagrange Polynomials for a Interpolation polynomial of degree 1. # # $i=0$, $n=1$ # $$ L_{2,0}=\prod_{\begin{smallmatrix}m=0\\ m\neq 0\end{smallmatrix}}^1 \frac{x-x_m}{x_i-x_m}=\prod_{\begin{smallmatrix}m=1\end{smallmatrix}}^1 \frac{x-x_m}{x_0-x_m}=\frac{x-x_1}{x_0-x_1}$$ # $i=i$, $n=1$ # $$ L_{2,1}=\prod_{\begin{smallmatrix}m=0\\ m\neq 1\end{smallmatrix}}^1 \frac{x-x_m}{x_i-x_m}=\prod_{\begin{smallmatrix}m=0\end{smallmatrix}}^0 \frac{x-x_m}{x_1-x_m}=\frac{x-x_0}{x_1-x_0}$$ # # ### Exercise: # Obtain the Lagrange Polynomials for a Interpolation polynomial of degree 1. # ## Steps LP # Once defined the formal procedure for constructing a Lagrange Polynomial, we proceed to describe the explicit algorithm: # # 1. Give the working dataset $(x_i, y_i)$ and stablish how many points you have. # 2. Define the functions $L_{n,i}(x)$ in a general way. # 3. Add each of those terms as shown in last expression. # 4. Evaluate your result wherever you want. # ## **Activity** # # # Along with the professor, write an implementation of the previous algorithm during classtime. # # ## Activity LP #