I've made this document with IPython Notebook. It contains the Newton and Neville's algorithms written with Python 3 using Matplotlib, Sympy and Numpy.
Polinomio interpolador de Newton y algoritmo de Neville
1. Notebook
May 1, 2014
1 POLINOMIO INTERPOLADOR DE NEWTON
Tomamos como puntos de interpolaci´on los puntos (no necesariamente equiespaciados):
(x1, y1), (x2, y2), . . . , (xn, yn)
El polinomio interpolador de Newton lo expresaremos mediante la base:
{1, (x − x1), (x − x1)(x − x2), (x − x1)(x − x2)(x − x3), . . . , (x − x1)(x − x2) · · · (x − xn)}
El polinomio interpolador expresado respecto esta base es:
pn(x) = cn+1 + cn(x − x1) + cn−1(x − x1)(x − x2) + · · · + c1(x − x1)(x − x2) · · · (x − xn)
Para averiguar los coeficientes lo hacemos mediante las Diferencias Divididas:
cn+1 = f[x1]
cn =
f[x2] − f[x1]
x2 − x1
= f[x1, x2]
cn−k+1 = f[x1, x2, . . . xk+1]
Hay que tener en cuenta que, en general, las diferencias de orden k vienen definidas por:
f[xi, xi+1, . . . , xi+k] =
f[xi+1, xi+2, . . . , xi+k] − f[xi, xi+1, . . . , xi+k−1]
xi+k − xi
Si calculamos todas las diferencias divididas las podemos almacenar en una matriz triangular inferior. De
dicha matriz los elementos de la diagonal principal son los coeficientes de nuestro polinomio interpolador de
Newton.
2 ALGORITMO INTERPOLADOR DE NEVILLE
Dentro de la interpolaci´on polin´omica tenemos el algoritmo de Neville, el cual se basa en el polinomio inter-
polador de Newton y en el algoritmo de Aitken. Partimos de un conjunto de n+1 puntos no necesariamente
equiespaciados (xi, yi); 0 ≤ i ≤ n. Denotemos por pi, j el polinomio de grado j − i, el cual pasa por los
puntos (xk, yk); k = i, i + 1, . . . , j. El pi j satisface la siguiente relaci´on de recurrencia:
pi, i(x) = yi 0 ≤ i ≤ npi, j(x) =
(xj − x)pi, j−1(x) + (x − xi)pi+1, j(x)
xj − xi
0 ≤ i < j ≤ n
Dicha recurrencia nos da el valor que buscamos, p0, n(x)
1
2. 2.0.1 EJEMPLO:
Consideremos la siguiente tabla de valores:
In [6]: import pandas
pandas.core.format.set_option(’display.notebook_repr_html’,True)
df = (pandas.read_csv(’data.csv’)).T
df
Out[6]: 0 1 2 3 4 5
x 0.15000 2.30000 3.1500 4.85000 6.25000 7.95000
y 4.79867 4.49013 4.2243 3.47313 2.66674 1.51909
Vamos a aplicar en dichos datos el polinomio interpolador de Newton y el algoritmo de Neville. Tendremos
en cuenta que los datos de la tabla son aproximaciones de la funci´on f(x) = 4.8 cos
πx
20
Para ello hemos
creado un m´odulo python en el que hemos definido mediante funciones los dos m´etodos vistos aqu´ı. Dibujamos
a parte la funci´on de la que tenemos sus aproximaciones en la tabla.
In [22]: %matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
f = lambda x: 4.8 * np.cos((np.pi * x) / 20)
fig, ax = plt.subplots(1)
fig.set_size_inches(10, 10)
x = np.linspace(0., 8., 100)
plt.plot(x, f(x), ’b-’)
ax.axis([0, 8, 0, 5])
ax.set_title(’$f(x)$’, color=’blue’, fontsize=18)
vector_legend = [’$f(x)$’]
mylegend = ax.legend(vector_legend, loc=4, ncol=3, fancybox=True,
prop={’size’:8}, title=’$FUNCION REAL$’)
plt.setp(mylegend.get_title(),fontsize=’18’, color=’red’)
plt.setp(mylegend.get_texts(),fontsize=’14’, color=’black’)
frame = mylegend.get_frame()
frame.set_facecolor(’0.95’)
ax.set_xlabel(’$Abscisa; x$’, color=’blue’, fontsize=16)
ax.set_ylabel(’$Ordenada; y$’, color=’blue’, fontsize=16)
xtcks = np.arange(0, 8)
xtckslatex = []
for i in xtcks:
xtckslatex.append(’$’ + str(i) + ’$’ )
ytcks = np.arange(0, 5)
ytckslatex = []
for i in ytcks:
ytckslatex.append(’$’ + str(i) + ’$’ )
ax.set_xticks(xtcks, xtckslatex)
ax.set_yticks(ytcks, ytckslatex)
ax.grid(’on’)
plt.show()
plt.close()
2
3. In [7]: %load diferencias.py
´Este es el c´odigo del m´odulo que utilizaremos para resolver el ejemplo. Consta de 4 funciones que est´an
debidamente documentadas siguiendo los est´andares para la creaci´on de la documentaci´on en Python.
In []: __author__ = ’tobal’
#/usr/bin/env python3
# -*- coding: utf-8 -*-
from sympy import symbols
import numpy as np
from numpy import zeros, diag
3
4. x = symbols(’x’)
def diferencias(x, y, n):
’’’
(array, array, int) -> array
Dados los n datos de una tabla (x,y) calcula sus diferencias
divididas. Nos devuelve un array con los elementos de la
diagonal principal, que son los coeficientes del polinomio
de Taylor.
’’’
T = y
for k in range(1, n + 1):
T[k: n] = (T[k: n] - T[k - 1]) / (x[k: n] - x[k - 1])
return T
def polnewton(diff, x, x0):
’’’
(array, array, float) -> list
Dados los coeficientes del Polinomio de Taylor con diff y el vector
de abscisas x nos calcula las aproximaciones del Polinomio de Taylor
centradas en el punto x0.
En una lista nos devuelve con pol el valor aproximado, y con P un array
con todas las aproximaciones obtenidas en cada paso y as´ı poderlas dibujar.
’’’
n = len(x) - 1
P = np.zeros(len(x), dtype=float)
pol = diff[n]
for k in range(1, n + 1):
pol = diff[n - k] + (x0 - x[n - k])*pol
P[k] = pol
return [pol, P]
def polnewtonsym(diff, xx):
’’’
(array, array) -> polynomial
Calcula la expresi´on simb´olica (algebraica) del Polinomio de Taylor.
’’’
n = len(xx) - 1
pol = diff[n]
for k in range(1, n + 1):
pol = diff[n - k] + (x - xx[n - k])*pol
return pol
def polneville(x, y, x0):
’’’
(array, array, float) -> list
Calcula la aproximaci´on interpolante en un punto x0 mediante el algoritmo
de Neville. En una lista nos devuelve la aproximaci´on final y las
aproximaciones en cada paso en un array para poder dibujarlas.
’’’
4
5. Q = np.zeros((len(x), len(x)), dtype=float)
for k in range(0, len(x)):
Q[k][0] = y[k]
for i in range(1, len(x)):
for j in range(1, i + 1):
Q[i][j] = ((x0-x[i-j])*Q[i][j-1]-(x0-x[i])*Q[i-1][j-1])/(x[i]-x[i-j])
return [Q[-1][-1], np.diag(Q, 0)]
In [36]: %matplotlib inline
In [37]: %load newtonvsneville.py
In [23]: __author__ = ’tobal’
#/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
from numpy import array, cos, pi
from sympy import symbols, init_printing, lambdify, horner, expand, pprint
from diferencias import diferencias, polnewton, polnewtonsym, polneville
import matplotlib.pyplot as plt
from matplotlib import rcParams
rcParams[’text.latex.unicode’] = True
rcParams[’text.usetex’] = True
rcParams[’text.latex.preamble’] = ’usepackage{amsthm}’,
’usepackage{amsmath}’, ’usepackage{amssymb}’,
’usepackage{amsfonts}’, ’usepackage[T1]{fontenc}’, ’usepackage[utf8]{inputenc}’
x = symbols(’x’)
init_printing(use_unicode=True)
datosx = np.array([0.15, 2.3, 3.15, 4.85, 6.25, 7.95], dtype=float)
datosy = np.array([4.79867, 4.49013, 4.2243, 3.47313, 2.66674, 1.51909], dtype=float)
datosy2 = datosy.copy()
diff = diferencias(datosx, datosy, len(datosx))
pprint(’ALGORITMOS INTERPOLADORES DE NEWTON Y DE NEVILLE.’)
pprint(’=================================================’)
print()
pprint(’Introduce el valor en el que desees interpolar: ’)
interpolar = eval(input())
valor = polnewton(diff, datosx, interpolar)[0]
pprint(’Para {0} obtenemos {1} con Newton. ’.format(interpolar, valor))
valorN = polneville(datosx, datosy2, interpolar)[0]
pprint(’Para {0} obtenemos {1} con Neville. ’.format(interpolar, valorN))
polnewtonsym = polnewtonsym(diff, datosx)
pprint(’El polinomio interpolador de Newton es:’)
pprint(expand(polnewtonsym))
polnewtonsym = horner(polnewtonsym)
5
7. ax1.set_xticklabels(xtckslatex, fontsize=18)
ax1.set_yticklabels(ytckslatex, fontsize=18)
ax2.set_xticklabels(xtckslatex, fontsize=18)
ax2.set_yticklabels(ytckslatex, fontsize=18)
text21 = r’$Puntos; Aprox.; Newton$’
text22 = r’$Poligonal; Aprox.; Nevwton$’
text23 = r’$Puntos; Aprox.; Neville$’
text24 = r’$Poligonal; Aprox.; Neville$’
legend2 = ax2.legend([text22, text24, text21, text23], scatterpoints=1,
markerscale = 1.5, shadow=True, loc=4)
frame2 = legend2.get_frame()
frame2.set_facecolor(’0.90’)
plt.show()
plt.close()
ALGORITMOS INTERPOLADORES DE NEWTON Y DE NEVILLE.
=================================================
Introduce el valor en el que desees interpolar:
3.5
Para 3.5 obtenemos 4.092666147572255 con Newton.
Para 3.5 obtenemos 4.092666147572256 con Neville.
El polinomio interpolador de Newton es:
5 4 3
- 2.30081527502247e-6·x + 0.000142856446368703·x - 9.39713572923442e-5·x -
2
0.0590145616002341·x - 0.00018014557743914·x + 4.80002509447959
7
8. Conclusi´on En el c´odigo anterior lo hemos ejecutado para calcular el valor aproximado interpolador 3.5
para ambos m´etodos. Vemos que por ambos m´etodos obtenemos una muy buena aproximaci´on de la funci´on
f(x)4.8·cos
π · x
20
en f(3) . Como polinomio interpolador de Newton hemos obtenido la expresi´on: P(x) =
−2.30081527502247·10−6
·x5
+0.000142856446368703·x4
−9.39713572923442·10−5
·x3
−0.0590145616002341·
x2
−0.00018014557743914·x+4.80002509447959 En la primera gr´afica de la imagen de arriba si la comparamos
con la gr´afica de la funci´on f(x) vemos que es pr´acticamente la misma, con lo que el M´etodo de Newton nos
da resultados satisfactorios. En la segunda gr´afica comparamos Neville y Newton con el valor aproximado
que obtenemos para 3.5. Apreciamos que ambos convergen a la misma soluci´on (decimal arriba, decimal
abajo), pero Neville converge mucho m´as suave y mon´otonamente que Newton. Con lo que todo nos hace
indicar que para interpolar m´as valores de nuestro ejemplo nos decantar´ıamos por Neville. Cosa que no
deber´ıa extra˜narnos, ya que en condiciones normales, Neville es una mejora de Newton.
8