Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Cabe destacar que en este apartado explicaremos paso por paso nuestro código. Se presentará,
junto con este notebook, un documento de Word que recopilará los resultados de hacer para
cada función, tipo de nodo, y número de nodo con sus respectivas conclusiones.
1. La función a evaluar
2. Obtención de Nodos Equiespaciados
3. Obtención de Nodos Ortogonales mediante las raices del polinomio de Chebyshev
4. Obtención de los Polinomios de Interpolación y Graficar: Lagrange, Baricéntrica, Newton y
Splines
La Función a Evaluar
Como necesitaremos importar varias bibliotecas para empezar a escribir nuestros códigos, lo
haremos en el siguiente apartado:
In [182…
import numpy as np
import plotly.graph_objects as go
Ahora que tenemos nuestros paquetes cargados, vamos a escribir una función muy simple que
nos devuelva nuestro f(x) a evaluar:
In [165…
def fun(xi):
return np.sin(xi)
Dejaremos el caso para sen(x) nada mas para fines ilustrativos. Ahora, cada que necesitemos
escribir una función, simplemente tenemos que cambiar la expresión en nuestra función para
ese fin. La función nos devolverá los valores correspondientes en la función de los nodos
escogidos por cualquiera de los métodos. Tambien trabajaremos con funciones y variables
simbólicas, pero se especificará en su momento.
In [166…
def NodosEq(n,a,b):
h=(b-a)/n
xi=np.zeros(n+1)
for i in range(n+1):
xi[i]=a+i*h
return xi
Así que: si queremos, por ejemplo, 11 nodos equiespaciados desde -5 a 5 usando las fórmulas
conocidas, tendremos:
In [167…
n=11
a=-5
b=5
xi=NodosEq((n),(a),(b))
xi
Out[167…
-0.45454545, 0.45454545, 1.36363636, 2.27272727, 3.18181818,
4.09090909, 5. ])
Como vemos tenemos una función que devuelve, a partir de un intervalo, el número de nodos
que le pidamos. Cabde destacar que calcularemos como se calcula en la mayoría de los libros de
texto de análisis numérico: donde se piden n nodos, pero además se agrega el nodo N0, dando
como resultado n+1 puntos que evalauar.
In [168…
def NodosOrt(a,b,n):
k= np.linspace(0,n,n+1)
f=np.cos(np.pi*(2*k+1)/(2*(n+1)))
xi=0.5*(b-a)*f+0.5*(b+a)
xi=xi[::-1]
return xi
In [169…
n=11
a=-5
b=5
xi=NodosOrt((a),(b),(n))
xi
Out[169…
-0.65263096, 0.65263096, 1.91341716, 3.04380715, 3.9667667 ,
4.61939766, 4.95722431])
Ya tenemos nuestros dos métodos de obtención de nodos. Ahora vamos por los polinomios de
interpolación:
Interpolación de Lagrange
Como dijimos, tenemos cubierto este inciso haciendo uso de las funciones que ya tenemos a
disposición en la bibliotecas que cargamos al principio.
In [170…
yi=fun(xi)
l=lagrange(xi,yi)
print (l)
11 10 9 8 7
6 5 4 3 2
La función incluso devuelve el polinomio en forma bastante simplicafada. Ahora vamos por su
gráfica.
In [172…
from numpy.polynomial.polynomial import Polynomial
Polynomial(l.coef[::-1]).coef
xp=np.linspace(min(xi),max(xi))
plt.plot()
plt.legend()
plt.show()
Gracias a la ayuda de las herramientas que tenemos a mano, pudimos no solo graficar ambas
funciones, sino que incluso tenemos la posibilidad de colocar nuestros puntos para demostrar
que en efecto estamos pasando por ellos.
Interpolación Baricéntrica
Aquí tenemos también una herramienta a usar que nos viene desde interpolation de scipy.
In [173…
yi=fun(xi)
xo=np.linspace(min(xi),max(xi),100)
p=barycentric_interpolate(xi,yi,xo)
xp=np.linspace(min(xi),max(xi))
plt.legend()
plt.show()
In [174…
def PoliBar(xi,yi):
x=syp.symbols('x',real=True)
p=0
q=0
n=len(xi)
w=1
for i in range(0,n):
for j in range(0,n):
if j==i:
continue
else:
w=w*1/((xi[i]-xi[j]))
p=p+((w*yi[i])/(x-xi[i]))
q=q+w/(x-xi[i])
w=1
r=p/q
r=syp.simplify(r)
return r
In [175…
r=PoliBar(xi,yi)
x=syp.symbols('x',real=True)
syp.plot((r,(x,-5,5)),(syp.sin(x),(x,-5,5)))
Out[175… 1.53568162914043 ⋅ 10
−8
x
11
+ 6.7762635780344 ⋅ 10
−21
x
10
− 2.50301596709575 ⋅ 10
−6
x
9
5 −16 4 3
− 0.00831517175348184x + 1.80411241501588 ⋅ 10 x + 0.166628107330418x + 4.44
Si bien que no es el polinomio más bonito, vemos que podemos obtener un polinomio
expresado como una función para este caso. Cabe notar que estamos usando la función plot del
sympy que, lamentablemente, no permite las graficas de puntos tipo scatter. Pero vemos que el
polinomio cumple con su objetivo: acomodarse a la función original, que es seno en este caso
ilustrativo.
Interpolación de Newton
Como habiamos dicho, no tenemos alguna función que venga precargada en las bibliotecas que
hemos consultado. Así que toca escribir una función propia tal como hicimos para nuestro
polinomio de la interpolación baricéntrica.
x=syp.symbols('x',real=True)
n=len(xi)
for i in range(0,n):
bn[i,0]=yi[i]
i=0
j=1
p=0
vx=1
for j in range(1,n):
for i in range(0,n-j):
bn[i,j]=(bn[i+1,j-1]-bn[i,j-1])/(xi[i+j]-xi[i])
print ('la primera fila de la tabla de diferencias que corresponde a los coefici
print (bn[0])
p=bn[0,0]
for i in range(1,n):
for j in range(0,i):
vx=vx*(x-xi[j])
p=p+bn[0,i]*vx
vx=1
return p.simplify()
In [177…
p=PoliNewton(xi,yi)
syp.plot ((p,(x,-5,5)),(syp.sin(x),(x,-5,5)))
Out[177… −1.53568162914053 ⋅ 10
−8
x
11
+ 1.01908651466533 ⋅ 10
−21
x
10
+ 2.5030159670958 ⋅ 10
−6
x
9
5 −17 4 3
+ 0.00831517175348189x − 1.39319979164387 ⋅ 10 x − 0.166628107330418x + 3.4932
Otra vez hemos obtenido tanto el polinomio para ser visualizado y su respectiva gráfica que se
amolda bastante bien a la función original en el caso de seno.
Ahora vamos al último caso de nuestras interpolaciones hechas con splines cúbicos. Como
sabemos, los splines cúbicos son funciones cúbicas a trozos. Vamos a usar el UnivariateSpline
con k=3 para poder obtener nuestra función de spline. Tenemos la desventaja que, tal y como
sucede en los casos anteriores, no tenemos la posibilidad de ver las funciones expresadas
simbólicamente directamente. Sin embargo, podemos recurrir a un par de alternativas. Sabemos
que los splines cúbicos son un poco engorrosos de calcular, y para ello podemos hacer uso
tanto de los fundamentos teóricos de los splines, como de algunos algoritmos mas
especializados. Se encontró en internet un código en base al algoritmo de Jacobi que permite
ver los coeficientes de cada uno de los trozos de gráfica. Se implementan a continuación dos
funciones:
In [178…
import pandas as pd
import numpy as np
n = A.shape[0]
x = x0.copy()
x_prev = x0.copy()
counter = 0
x_diff = tol+1
s = 0
for j in range(0,n):
if i != j:
s += A[i,j] * x_prev[j]
counter += 1
x_diff = (np.sum((x-x_prev)**2))**0.5
x_prev = x.copy()
return x
x = np.array(x)
y = np.array(y)
idx = np.argsort(x)
x = x[idx]
y = y[idx]
size = len(x)
delta_x = np.diff(x)
delta_y = np.diff(y)
A = np.zeros(shape = (size,size))
b = np.zeros(shape=(size,1))
A[0,0] = 1
A[-1,-1] = 1
for i in range(1,size-1):
A[i,i] = 2*(delta_x[i-1]+delta_x[i])
d = np.zeros(shape = (size-1,1))
b = np.zeros(shape = (size-1,1))
for i in range(0,len(d)):
In [179…
p=cubic_spline(xi, yi, tol = 1e-100)
Out[179…
0.77991455, 0.77991455, -0.3272742 , -0.98462057, -0.69040258,
-0.05934709]),
0.59869169, 0. ]),
-0.59072871]))
La primer fila hace referencia a los coeficientes de grado 1, la segunda de grado 2 y la tercera de
grado 3
In [180…
spline = UnivariateSpline(xi,yi,k=3,s=0.00)
xp=np.linspace(min(xi),max(xi))
plt.plot(xp,spline(xp),color='red',linestyle='--',label='Poli')
plt.legend()
plt.show()
inicio=default_timer()
fin=default_timer()
In [184…
a=np.linspace(min(xi),max(xi),n)
b=spline(a)
c=np.sin(a)
d=b-c
fig = go.Figure(data=[go.Table(
cells=dict(values=[a,b,c,d]))])
fig.show()
Tabla error
x Interpolación
-4.957224306869052 0.9701772544214131
-3.9657794454952415 0.7339959814686711
-2.974334584121431 -0.16597140028926202
-1.982889722747621 -0.9166960110967988
-0.9914448613738105 -0.8297763809729726
0 1.249000902703301e-16
0 99144486137381 0 8297763809729726
Esto es, en pocas palabras, nuestro código explicado paso por paso. Se presentarán los
resultados en un documento de Word de los siguientes casos:
Para los nodos equiespaciados