Código-fonte para CB2325NumericaG1.interpolacao.interpolacao_linear

import matplotlib.pyplot as plt
import numpy as np
from typing import Callable

def _ordenar_coordenadas(x: list, y: list) -> list:
    """Ordena as coordenadas mantendo 'pareamento'.
    
    Pega as coordenadas x e y de cada ponto, ordena em ordem crescente
    as coordenadas x e mantém pareamento com y. Função privada, auxiliar
    da função principal lin_interp.

    Args:
        x: lista das coordenadas x, em x[i], de cada ponto i.
        y: lista das coordenadas y, em y[i], de cada ponto i.

    Returns:
        x_ord: lista das coordenadas x em ordem crescente.
        y_ord: lista das coordenadas y, pareadas com as coordenadas x.
    """
    
    x_np = np.array(x)
    y_np = np.array(y)

    idx = np.argsort(x_np)

    x_ord = x_np[idx]
    y_ord = y_np[idx]

    return x_ord, y_ord

def _plotar(x: list,
            y: list,
            f: Callable,
            titulo: str = 'Gráfico'):
    """Plotagem de pontos e de uma função.

    Plotagem dos pontos indicados pelas coordenadas x e y, seguindo a
    função f. Função privada, auxiliar da função principal lin_interp.

    Args:
        x: lista das coordenadas x, em x[i], de cada ponto i.
        y: lista das coordenadas y, em y[i], de cada ponto i.
        f: função que será plotada.

    Returns:
        None
    Raises:
    """
    
    x_points = np.linspace(x[0], x[-1], 500)
    y_points = [f(xp) for xp in x_points]

    _, ax = plt.subplots()
    ax.scatter(x, y, color = 'red', label = 'Dados')
    ax.plot(x_points, y_points,'b-', linewidth=2, label = 'Interpolação Linear por Partes')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title(titulo)
    ax.grid(True)
    plt.show()

    return

[documentos] def lin_interp(x: list, y: list, plot: bool = False ) -> Callable: """Interpolação linear por partes a partir dos pontos dados. Essa função ordena pontos a partir da ordem crescente das coordenadas x. Em seguida, cria retas descritas pela nova função f, que 'ligam' os pontos descritos pelas coordenadas x e y. É permitida extrapolação. Por fim, caso 'plot = True', há uma plotagem do gráfico correspondente. Args: x: lista das coordenadas x, em x[i], de cada ponto i. y: lista das coordenadas y, em y[i], de cada ponto i. plot: indica se deve haver a plotagem (True) ou não (False). Returns: f: função de interpolação linear por partes Raises: ValueError: Caso 'x' e 'y' tenham tamanhos diferentes, caso as listas estejam vazias, ou caso as coordenadas em 'x' não sejam distintas. TypeError: caso 'x' ou 'y' não sejam listas, ou caso 'plot não seja bool'. """ # Tratamento de erros try: n = len(x) m = len(y) except: raise TypeError("Os argumentos 'x' e 'y' devem ser listas.") if type(plot) != bool: raise TypeError("O argumento 'plot' deve ser bool") if n != m: raise ValueError("As listas de coordenadas x e y devem ter o mesmo tamanho.") if n == 0: raise ValueError("As listas x e y não podem estar vazias.") if len(set(x)) != n: raise ValueError("As coordenadas x devem ser todas distintas.") # Ordenação das coordenadas x em ordem crescente x, y = _ordenar_coordenadas(x, y) # Definição da função de interpolação def f(x1: float) -> float: if x1 < x[0]: # Caso fora do intervalo, continua a reta mais próxima a = (y[1] - y[0])/(x[1] - x[0]) b = y[0] y1 = b + (x1 - x[0]) * a return y1 elif x1 > x[-1]: # Caso fora do intervalo, continua a reta mais próxima a = (y[-1] - y[-2])/(x[-1] - x[-2]) b = y[-2] y1 = b + (x1 - x[-2]) * a return y1 else: for i in range (1, len(x)): # Busca intervalo do número x1 para atribuir valor f(x1) if x[i] >= x1 >= x[i-1]: a = (y[i] - y[i-1])/(x[i] - x[i-1]) b = y[i-1] y1 = b + (x1 - x[i-1]) * a # Aproximação linear return y1 # Plotagem do gráfico correspondente à função f if plot: _plotar(x, y, f, 'Interpolação Linear por Partes') return f