Interpolación de Lagrange
abril 16, 2017Método que permite encontrar un polinomio que interpola un conjunto de puntos mediante un sistema de ecuaciones. El grado del polinomio resultante depende directamente de la cantidad de puntos dada y se verá en algunos ejemplos que la cantidad de puntos puede generar oscilaciones indeseadas en las curvas generadas dependiendo de la naturaleza de las funciones.
Creado: Abril 16 de 2017
Modificado: Noviembre 12 de 2018
Testeado en Python 3.6.4
Modificado: Noviembre 12 de 2018
Testeado en Python 3.6.4
Se encontrará un polinomio que interpole $k+1$ puntos diferentes $(x_0, y_0), (x_1, y_1), ..., (x_k, y_k)$ usando el método de interpolación de Lagrange. El polinomio generado es una combinación lineal de la forma:
Dónde $l_j$ son las bases polinómicas de Lagrange definidas como:
In [1]:
import sympy
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
Implementación del método¶
In [2]:
def arg_prod(i, j):
""" Argumento de la productoria de las bases polinómicas de
Lagrange.
"""
# Variable simbólica
x_sim = sympy.symbols('x')
return (x_sim-x[i]) / (x[j]-x[i]) if i != j else 1
def interpolacion_lagrage(x, y, num_puntos=100):
""" Estima la curva generada por el polinomio de lagrange que
interpola los puntos datos
args:
x (np.array): Datos del eje x
y (np.array): Datos del eje y
num_puntos (int): Número de puntos estimados a partir del polinomio
returns:
Puntos (x, y) estimados a partir del polinomio encontrado. Tupla
"""
# Variable simbólica
x_sim = sympy.symbols('x')
# Número de puntos ingresados
points = len(x)
# Bases polinómicas lj = [l1, l2, ..., lk]
lj = []
for k in range(points):
lk = np.prod([arg_prod(i, k) for i in range(points)])
lj.append(lk)
# Polinomio de lagrange
pol = sum(y*lj)
# Se generan los datos x, y a partir del polinomio encontrado
x_test = np.linspace(min(x), max(x), num_puntos)
y_pol = [pol.subs(x_sim, i) for i in x_test]
return x_test, y_pol
Aplicación¶
Se aproximará la función seno a un polinomio tomando solo 4 puntos
In [3]:
# Datos
x = np.linspace(-np.pi, np.pi, 4)
y = np.array([np.sin(i) for i in x])
# Puntos generados por el polinomio de Lagrange
x_test, y_pol = interpolacion_lagrage(x, y)
# Gráfica
plt.plot(x_test, y_pol)
plt.scatter(x, y)
plt.legend(['Lagrange', 'Datos'], loc='best')
Out[3]:
Para mejorar la precisión se aumenta la cantidad de puntos a 15
In [4]:
# Datos
x = np.linspace(-np.pi, np.pi, 15)
y = np.array([np.sin(i) for i in x])
# Puntos generados por el polinomio de Lagrange
x_test, y_pol = interpolacion_lagrage(x, y)
# Gráfica
plt.plot(x_test, y_pol)
plt.scatter(x, y)
plt.legend(['Lagrange', 'Datos'], loc='best')
Out[4]:
El grado del polinomio aumenta que se aumentan los puntos a interpolar por lo que, dependiendo de la naturaleza de la función, para una gran cantidad de puntos las oscilaciones entre estos son mayores. Veamos un ejemplo tomando 10 puntos:
In [5]:
# Datos
x = np.array([-3.2300, 2.0000, -1.0023, 0.0000, 2.1230,
-3.5120, 0.1223, 5.6420, -2.2574, 5.3410])
y = np.array([-3.4360, 3.4120, 0.9300, 1.5960, 0.0000,
0.9315, 4.1230, 0.0140, -0.2320, 2.123])
# Puntos generados por el polinomio de Lagrange
x_test, y_pol = interpolacion_lagrage(x, y)
# Gráfica
plt.plot(x_test, y_pol)
plt.scatter(x, y)
plt.legend(['Lagrange', 'Datos'], loc='best')
Out[5]:
0 comments