Interpolación de Lagrange

abril 16, 2017


Mé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
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]:
<matplotlib.legend.Legend at 0x166509cb5f8>
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]:
<matplotlib.legend.Legend at 0x16650af2860>
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]:
<matplotlib.legend.Legend at 0x16650bb0a20>

You Might Also Like

0 comments

Apoyado por: