Código-fonte para CB2325NumericaG1.aproximacao.aproximacao_trig_linear

import numpy as np
import matplotlib.pyplot as plt
from typing import List, Tuple
import numpy.typing as npt


[documentos] def ajuste_linear(x: npt.ArrayLike, y: npt.ArrayLike, plot: bool = False) -> tuple[float, float]: """ Calcula o coeficiente angular 'a' e o coeficiente linear 'b' de uma regressão linear simples (y = ax + b). Args: x (npt.ArrayLike): Vetor contendo os valores da variável independente. y (npt.ArrayLike): Vetor contendo os valores da variável dependente. plot (bool, optional): Se `True`, exibe o gráfico dos dados e da linha de regressão. Padrão é `False`. (Este argumento foi inferido da função `regressao_logaritmica`, mas não estava na sua docstring original da linear). Returns: tuple[float, float]: Uma tupla contendo (a, b), onde: a (float): Coeficiente angular da linha de regressão. b (float): Coeficiente linear da linha de regressão. Raises: ValueError: Se 'x' e 'y' tiverem comprimentos diferentes ou se tiverem menos de 2 pontos de dados, o que é insuficiente para a regressão. Dependencies: - `numpy` (importada como `np`) - `matplotlib.pyplot` (importada como `plt`) - Se plot=True Notes: - A regressão é realizada utilizando o Método dos Mínimos Quadrados Ordinários (MQO). """ # Converter para arrays numpy x_arr = np.array(x) y_arr = np.array(y) if len(x_arr) != len(y_arr): raise ValueError("Os vetores x e y devem ter o mesmo tamanho.") n = len(x_arr) if n == 0: raise ValueError("Os vetores x e y não podem estar vazios.") # Implementação do método dos mínimos quadrados # Usando as médias, que é numericamente mais estável x_mean = np.mean(x_arr) y_mean = np.mean(y_arr) # Calcular 'a' (coeficiente angular) # a = Sxy / Sxx numerador = np.sum((x_arr - x_mean) * (y_arr - y_mean)) denominador = np.sum((x_arr - x_mean)**2) if denominador == 0: # Isso acontece se todos os valores de x forem iguais raise ValueError("Não é possível calcular a regressão: todos os valores de x são iguais.") a = numerador / denominador # Calcular 'b' (intercepto) # b = y_media - a * x_media b = y_mean - (a * x_mean) if plot: # Gerar pontos para a reta ajustada x_line = np.linspace(np.min(x_arr), np.max(x_arr), 100) y_line = a * x_line + b plt.figure(figsize=(10, 6)) plt.scatter(x_arr, y_arr, color='red', label='Pontos Reais (Dados)') plt.plot(x_line, y_line, color='blue', linewidth=2, label=f'Ajuste Linear: y = {a:.2f}x + {b:.2f}') plt.title("Ajuste Linear por Mínimos Quadrados") plt.xlabel("Eixo x") plt.ylabel("Eixo y") plt.legend() plt.grid(True) plt.show() return (a, b)
[documentos] def ajuste_trigonometrico(x: List[float], y: List[float], periodo: float, plot: bool = False) -> Tuple[float, float, float]: ''' Calcula o ajuste trigonométrico (Série de Fourier de 1ª ordem) de um conjunto de pontos (x, y) usando o método dos mínimos quadrados. Encontra os coeficientes c0, c1, c2 para a função: y = c0 + c1*cos(omega*x) + c2*sin(omega*x) onde omega = 2*pi / periodo. Parâmetros : x : Lista ou array de valores para o eixo x. y : Lista ou array de valores para o eixo y. periodo (T) : O período fundamental estimado dos dados. Estimar corretamente é crucial para um bom ajuste. plot : Se True, plota o gráfico. Retorna : Uma tupla (c0, c1, c2) contendo os coeficientes do ajuste. (c0 = offset, c1 = amplitude do cosseno, c2 = amplitude do seno) ''' x_arr = np.array(x) y_arr = np.array(y) if len(x_arr) != len(y_arr): raise ValueError("Os vetores x e y devem ter o mesmo tamanho.") if len(x_arr) < 3: raise ValueError("São necessários pelo menos 3 pontos para este ajuste (3 coeficientes).") if periodo <= 0: raise ValueError("O período deve ser um valor positivo.") # Calcular frequência angular omega = (2 * np.pi) / periodo # 1. Montar a matriz do sistema (Design Matrix) A # Queremos resolver Ac = y, onde c = [c0, c1, c2] # Cada linha de A é [1, cos(omega*xi), sin(omega*xi)] A = np.column_stack([ np.ones_like(x_arr), # Coluna para c0 (intercepto) np.cos(omega * x_arr), # Coluna para c1 (cosseno) np.sin(omega * x_arr) # Coluna para c2 (seno) ]) # 2. Resolver o sistema de equações lineares por mínimos quadrados # c = (A^T A)^-1 * (A^T y) # O np.linalg.lstsq faz isso de forma eficiente e estável # Retorna (coeficientes, resíduos, rank, valores singulares) # Pegamos apenas o primeiro item (coeficientes) [0] try: coeficientes, _, _, _ = np.linalg.lstsq(A, y_arr, rcond=None) except np.linalg.LinAlgError as e: raise ValueError(f"Não foi possível resolver o sistema: {e}") c0, c1, c2 = coeficientes if plot: plt.figure(figsize=(10, 6)) # Pontos originais plt.scatter(x_arr, y_arr, color='red', label='Pontos Reais (Dados)') # Gerar linha para o ajuste # Usamos mais pontos (500) para garantir uma curva suave x_line = np.linspace(np.min(x_arr), np.max(x_arr), 500) y_line = c0 + c1 * np.cos(omega * x_line) + c2 * np.sin(omega * x_line) plt.plot(x_line, y_line, color='purple', linewidth=2, label=f'Ajuste Trig: y = {c0:.2f} + {c1:.2f}cos(ωx) + {c2:.2f}sin(ωx)\n(Período T={periodo:.2f}, ω={omega:.2f})') plt.title("Ajuste Trigonométrico por Mínimos Quadrados") plt.xlabel("Eixo x") plt.ylabel("Eixo y") plt.legend() plt.grid(True) plt.show() return (c0, c1, c2)