Diferencia entre revisiones de «Series de Fourier RAJ»

De MateWiki
Saltar a: navegación, buscar
Línea 1: Línea 1:
{{ TrabajoEDP | Series de Fourier. Grupo RAJ| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Rodrigo Gallardo García
+
{{ TrabajoED | Series de Fourier. Grupo RAJ| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Rodrigo Gallardo García
  
 
Alejandro Cogollor Torres
 
Alejandro Cogollor Torres

Revisión del 20:58 18 feb 2026

Trabajo realizado por estudiantes
Título Series de Fourier. Grupo RAJ
Asignatura EDP
Curso 2025-26
Autores Rodrigo Gallardo García

Alejandro Cogollor Torres

Javier Martín Pérez

Este artículo ha sido escrito por estudiantes como parte de su evaluación en la asignatura


import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate

def f_discontinua(x):
    """
    Define la función característica del intervalo [0, 1/4].
    Retorna 1 si 0 <= x <= 0.25, y 0 en otro caso.
    """
    # Usamos np.where para vectorizar la operación sobre arrays de numpy
    return np.where((x >= 0) & (x <= 0.25), 1.0, 0.0)

def construir_coeficientes_par(funcion, n_terminos, dx=1e-3):
    """
    Construye los coeficientes de Fourier para una extensión PAR de la función dada.

    Parámetros:
    -----------
    funcion : callable
        Función f(x) definida en [0, 1].
    n_terminos : int
        Número de coeficientes a calcular (incluyendo a0).
    dx : float
        Tamaño de la malla para la integración numérica (Sugerencia: 10^-3).

    Retorna:
    --------
    coeficientes : list
        Lista [a0, a1, ..., a_n-1] calculada mediante la regla del trapecio.
    """

    # 1. Definir la malla de integración [0, 1]
    # Se usa arange hasta 1 + dx/2 para asegurar que incluye el punto final 1.0
    x = np.arange(0, 1 + dx/2, dx)

    # 2. Evaluar la función en la malla
    y = funcion(x)

    coeficientes = []

    # 3. Calcular los coeficientes a_k
    for k in range(n_terminos):
        # Base trigonométrica par: cos(k * pi * x)
        termino_base = np.cos(k * np.pi * x)

        # Integrando: 2 * f(x) * cos(k*pi*x)
        # El factor '2' proviene de la simetría par en [-1, 1]
        integrando = 2 * y * termino_base

        # Aproximación de la integral usando la regla del trapecio
        # Tal como se sugiere en el punto 2 del texto
        a_k = scipy.integrate.trapezoid(integrando, dx=dx)

        coeficientes.append(a_k)

    return coeficientes

# ---------------------------------------------------------
# 1. Función de Reconstrucción (Solicitada al inicio)
# ---------------------------------------------------------
def reconstruir_serie_par(coeficientes, x_eval):
    """
    Reconstruye la serie de Fourier de cosenos.
    S_N(x) = a0/2 + sum(a_k * cos(k*pi*x))

    Parámetros:
    -----------
    coeficientes : list
        Coeficientes [a0, a1, ..., aN] calculados.
    x_eval : array
        Puntos donde evaluar la serie (puede ser [-1, 1]).
    """
    # 1. Término constante (siempre es a0 / 2)
    a0 = coeficientes[0]
    y_approx = (a0 / 2) * np.ones_like(x_eval)

    # 2. Sumar términos cosenos
    # La paridad (simetría) en [-1, 1] es automática con cos(k*pi*x)
    for k in range(1, len(coeficientes)):
        a_k = coeficientes[k]
        y_approx += a_k * np.cos(k * np.pi * x_eval)

    return y_approx

# ---------------------------------------------------------
# 2. Funciones Auxiliares (Coeficientes y Error)
# ---------------------------------------------------------
def f_par_extendida(x):
    """
    Define la función par en todo el eje real.
    f(x) = 1 si |x| <= 0.25, 0 en otro caso.
    """
    return np.where(np.abs(x) <= 0.25, 1.0, 0.0)

def construir_coeficientes(n_terminos, dx):
    """
    Calcula a_k integrando solo en [0, 1] (suficiente por simetría).
    Usa 'dx' para crear la malla con np.arange (sin linspace).
    """
    # Malla positiva [0, 1] para la integral
    x = np.arange(0, 1 + dx/10, dx)
    y = f_par_extendida(x)

    coefs = []
    for k in range(n_terminos):
        base = np.cos(k * np.pi * x)
        integrando = 2 * y * base
        # Integral numérica
        a_k = scipy.integrate.trapezoid(integrando, dx=dx)
        coefs.append(a_k)
    return coefs

def calcular_errores_completo(y_real, y_aprox, dx):
    """Calcula errores L2 y Uniforme en el dominio dado."""
    diff = np.abs(y_real - y_aprox)
    # L2 = sqrt( integral(diff^2) )
    err_l2 = np.sqrt(scipy.integrate.trapezoid(diff**2, dx=dx))
    # Uniforme = max(diff)
    err_unif = np.max(diff)
    return err_l2, err_unif

def reconstruir_cesaro_par(coeficientes, x_eval):
    """
    Reconstruye la Suma de Cesàro (promedio de sumas parciales).
    Matemáticamente equivale a multiplicar los coeficientes a_k
    por el peso triangular: (N - k + 1) / (N + 1).

    Parámetros:
    -----------
    coeficientes : list
        [a0, a1, ..., aN] calculados previamente.
    x_eval : array
        Puntos de evaluación.
    """
    N = len(coeficientes) - 1  # El índice máximo es N
    y_approx = np.zeros_like(x_eval)

    # El denominador común del peso es N + 1
    denominador = N + 1

    # 1. Término constante a0/2
    # El peso de Cesàro para k=0 es (N - 0 + 1)/(N+1) = 1.
    # Pero recordamos que en la serie el término es a0/2.
    a0 = coeficientes[0]
    y_approx += (a0 / 2) * np.ones_like(x_eval)

    # 2. Términos cosenos con pesos de Fejér
    for k in range(1, len(coeficientes)):
        a_k = coeficientes[k]

        # Peso triangular que define la suma de Cesàro
        peso = (N - k + 1) / denominador

        y_approx += peso * a_k * np.cos(k * np.pi * x_eval)

    return y_approx

# --- Función para Método de Lanczos (Factores Sigma) ---
def reconstruir_lanczos_par(coeficientes, x_eval):
    """
    Reconstruye usando factores Sigma (sinc).
    Suaviza Gibbs manteniendo buena pendiente.
    """
    N = len(coeficientes) - 1
    y_approx = np.zeros_like(x_eval)

    # Término a0/2
    y_approx += (coeficientes[0] / 2)

    # Términos cosenos multiplicados por sigma = sinc(k/N)
    for k in range(1, len(coeficientes)):
        # np.sinc(x) calcula sin(pi*x)/(pi*x)
        sigma = np.sinc(k / N)
        y_approx += sigma * coeficientes[k] * np.cos(k * np.pi * x_eval)

    return y_approx

# --- Función para Método de Abel (Poisson) ---
def reconstruir_abel_r_variable(coeficientes, x_eval, r):
    """
    Reconstruye la serie usando Abel con un r fijo dado por el usuario.
    """
    y_approx = np.zeros_like(x_eval)

    # Término a0/2 (r^0 = 1)
    y_approx += (coeficientes[0] / 2)

    # Términos cosenos multiplicados por r^k
    for k in range(1, len(coeficientes)):
        peso = r**k
        y_approx += peso * coeficientes[k] * np.cos(k * np.pi * x_eval)

    return y_approx

# ---------------------------------------------------------
# 3. Ejecución y Gráficas (Extensión Par Completa [-1, 1])
# ---------------------------------------------------------

# A. Parámetros Basados en Malla (Sin número fijo de puntos)
dx_malla = 1e-4      # Tamaño del paso (resolución)
N_max_calculo = 500    # Máximo N para el análisis de error
lista_N_dibujar = [1, 5, 20, 50, 100, 500]

# B. Construcción del Dominio Completo [-1, 1]
# Usamos arange: start=-1, stop=1 (con margen), step=dx
x_completo = np.arange(-1, 1 + dx_malla/10, dx_malla)
y_real = f_par_extendida(x_completo)

# C. Cálculo de Coeficientes (una sola vez hasta N_max)
coefs_totales = construir_coeficientes(N_max_calculo + 1, dx_malla)

# --- GRÁFICA 1: Función y Aproximaciones ---
plt.figure(figsize=(12, 6))

# Dibujar la función original (Exacta)
plt.plot(x_completo, y_real, 'k-', linewidth=2, label='Función Original (Par)', alpha=0.3)

# Dibujar las aproximaciones para distintos N
colores = plt.cm.magma(np.linspace(0, 0.85, len(lista_N_dibujar)))
for i, n in enumerate(lista_N_dibujar):
    coefs_n = coefs_totales[:n+1]
    y_aprox = reconstruir_serie_par(coefs_n, x_completo)

    plt.plot(x_completo, y_aprox, label=f'N={n}', color=colores[i], linewidth=1.5)

plt.title(f'Extensión Par Completa en [-1, 1] (dx={dx_malla})')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

# --- GRÁFICA 2: Evolución de Errores (L2 y Uniforme) ---
errores_l2 = []
errores_inf = []
rango_n = np.arange(1, N_max_calculo + 1)

for n in rango_n:
    coefs_n = coefs_totales[:n+1]
    y_aprox = reconstruir_serie_par(coefs_n, x_completo)

    # Calcular error sobre todo el intervalo [-1, 1]
    l2, unif = calcular_errores_completo(y_real, y_aprox, dx_malla)
    errores_l2.append(l2)
    errores_inf.append(unif)

plt.figure(figsize=(10, 6))
plt.loglog(rango_n, errores_l2, 'b-o', label='Error L2 [-1, 1]', markersize=4)
plt.loglog(rango_n, errores_inf, 'r-s', label='Error Uniforme (Max)', markersize=4)

plt.title('Evolución del Error vs Número de Términos')
plt.xlabel('N (log)')
plt.ylabel('Error (log)')
plt.legend()
plt.grid(True, which="both", alpha=0.3)
plt.show()


# Parámetros globales
dx_malla = 1e-4
N_max_calculo = 500
lista_N_dibujar = [1, 5, 20, 50, 100, 500]

# Dominio completo [-1, 1] usando arange y dx
x_completo = np.arange(-1, 1 + dx_malla/10, dx_malla)
y_real = f_par_extendida(x_completo)

# Calcular coeficientes "crudos" una sola vez
coefs_totales = construir_coeficientes_par(f_par_extendida, N_max_calculo + 1, dx_malla)

# --- GRÁFICA 1: Aproximación de Cesàro ---
plt.figure(figsize=(10, 6))

# Función original
plt.plot(x_completo, y_real, 'k-', linewidth=2, label='Original f(x)', alpha=0.6)

colores = plt.cm.magma(np.linspace(0, 0.85, len(lista_N_dibujar)))

for i, n in enumerate(lista_N_dibujar):
    # Para Cesàro de orden N, necesitamos coeficientes hasta N
    coefs_n = coefs_totales[:n+1]

    # Reconstrucción usando la función de Cesàro
    y_cesaro = reconstruir_cesaro_par(coefs_n, x_completo)

    plt.plot(x_completo, y_cesaro, label=f'Cesàro N={n}', color=colores[i], linewidth=2)

plt.title(f'Sumas de Cesàro (Mitigación de Gibbs) en [-1, 1]')
plt.xlabel('x')
plt.ylabel('S_N(x) [Cesàro]')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

# --- GRÁFICA 2: Evolución de Errores (Cesàro) ---
errores_l2 = []
errores_inf = []
rango_n = np.arange(1, N_max_calculo + 1)

for n in rango_n:
    coefs_n = coefs_totales[:n+1]
    y_cesaro = reconstruir_cesaro_par(coefs_n, x_completo)

    l2, unif = calcular_errores_completo(y_real, y_cesaro, dx_malla)
    errores_l2.append(l2)
    errores_inf.append(unif)

plt.figure(figsize=(10, 6))
plt.loglog(rango_n, errores_l2, 'b-o', label='Error L2 (Cesàro)', markersize=4)
plt.loglog(rango_n, errores_inf, 'r-s', label='Error Uniforme (Cesàro)', markersize=4)

plt.title('Evolución del Error en Sumas de Cesàro vs N')
plt.xlabel('N (log)')
plt.ylabel('Error (log)')
plt.legend()
plt.grid(True, which="both", alpha=0.3)
plt.show()



# --- Configuración (Tomamos los valores del caso anterior) ---
dx_malla = 1e-4
N_max_calculo = 500
lista_N_dibujar = [5, 20, 50, 100, 500]

# Dominio
x_completo = np.arange(-1, 1 + dx_malla/10, dx_malla)
y_real = f_par_extendida(x_completo)

# Calculamos coeficientes (si no existen ya en memoria)
# Nota: Aquí SÍ usamos dx_malla
coefs_totales = construir_coeficientes(N_max_calculo + 1, dx_malla)

# ---------------------------------------------------------
# GRÁFICAS LANCZOS
# ---------------------------------------------------------

# 1. Aproximación Visual
plt.figure(figsize=(10, 6))
plt.plot(x_completo, y_real, 'k-', linewidth=2, label='Original', alpha=0.5)

colores = plt.cm.viridis(np.linspace(0, 0.9, len(lista_N_dibujar)))

for i, n in enumerate(lista_N_dibujar):
    coefs_n = coefs_totales[:n+1]
    # Aquí NO hace falta dx, solo coeficientes y x
    y_lanczos = reconstruir_lanczos_par(coefs_n, x_completo)

    plt.plot(x_completo, y_lanczos, label=f'Lanczos N={n}', color=colores[i])

plt.title('Método de Lanczos (Factores Sigma)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

# 2. Evolución del Error
errores_l2 = []
errores_inf = []
rango_n = np.arange(1, N_max_calculo + 1)

for n in rango_n:
    coefs_n = coefs_totales[:n+1]
    y_lanczos = reconstruir_lanczos_par(coefs_n, x_completo)

    # Aquí usamos dx SOLO para calcular la integral del error L2
    l2, unif = calcular_errores_completo(y_real, y_lanczos, dx_malla)
    errores_l2.append(l2)
    errores_inf.append(unif)

plt.figure(figsize=(10, 6))
plt.loglog(rango_n, errores_l2, 'b-o', label='Error L2', markersize=4)
plt.loglog(rango_n, errores_inf, 'r-s', label='Error Uniforme', markersize=4)
plt.title('Error en Lanczos vs N')
plt.xlabel('N (log)')
plt.ylabel('Error (log)')
plt.legend()
plt.grid(True, which="both", alpha=0.3)
plt.show()


dx_malla = 1e-4
N_FIJO = 300  # Fijamos un N alto para tener "espacio" de frecuencias
lista_r_dibujar = [0.6, 0.8, 0.9, 0.95, 0.99, 0.999] # Variamos r

# Dominio
x_completo = np.arange(-1, 1 + dx_malla/10, dx_malla)
y_real = f_par_extendida(x_completo)

# Calculamos coeficientes HASTA N_FIJO
coefs_fijos = construir_coeficientes(N_FIJO + 1, dx_malla)

# ---------------------------------------------------------
# GRÁFICA 1: Aproximación Visual (N fijo, r variable)
# ---------------------------------------------------------
plt.figure(figsize=(10, 6))
plt.plot(x_completo, y_real, 'k-', linewidth=2, label='Original', alpha=0.3)

# Usamos un mapa de colores secuencial (Blues) para ver la progresión de r
colores = plt.cm.Blues(np.linspace(0.4, 1.0, len(lista_r_dibujar)))

for i, r_val in enumerate(lista_r_dibujar):
    y_abel = reconstruir_abel_r_variable(coefs_fijos, x_completo, r_val)

    plt.plot(x_completo, y_abel, label=f'r={r_val}', color=colores[i], linewidth=1.5)

plt.title(f'Método de Abel variando r (N fijo = {N_FIJO})')
plt.xlabel('x')
plt.ylabel('A_r(x)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

# ---------------------------------------------------------
# GRÁFICA 2: Evolución del Error vs r
# ---------------------------------------------------------
# Generamos muchos valores de r entre 0.5 y 0.999
r_range = np.linspace(0.5, 0.999, 100)

errores_l2 = []
errores_inf = []

for r_val in r_range:
    y_abel = reconstruir_abel_r_variable(coefs_fijos, x_completo, r_val)

    l2, unif = calcular_errores_completo(y_real, y_abel, dx_malla)
    errores_l2.append(l2)
    errores_inf.append(unif)

plt.figure(figsize=(10, 6))
plt.loglog(r_range, errores_l2, 'b-o', label='Error L2', markersize=4)
plt.loglog(r_range, errores_inf, 'r-s', label='Error Uniforme', markersize=4)
plt.title(f'Evolución del Error al aumentar r (N={N_FIJO})')
plt.xlabel('Valor de r')
plt.ylabel('Error')
plt.legend()
plt.grid(True, which="both", alpha=0.3)
plt.show()

# Invertimos el eje X si quieres ver el efecto de acercarse a 1,
# o simplemente observamos que al acercarse a 1 el error L2 baja pero el Uniforme sube (Gibbs).
plt.show()


import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate

def construir_coeficientes_par(funcion, n_terminos, dx=1e-3):

    x = np.arange(0, 1 + dx/2, dx)
    y = funcion(x)
    coeficientes = []

    for k in range(n_terminos):
        termino_base = np.cos(k * np.pi * x)
        integrando = 2 * y * termino_base
        a_k = scipy.integrate.trapezoid(integrando, dx=dx)
        coeficientes.append(a_k)

    return coeficientes


def reconstruir_serie_par(coeficientes, x_eval):

    a0 = coeficientes[0]
    y_approx = (a0 / 2) * np.ones_like(x_eval)

    for k in range(1, len(coeficientes)):
        a_k = coeficientes[k]
        y_approx += a_k * np.cos(k * np.pi * x_eval)

    return y_approx


def f_par_extendida(x):

    return np.where(np.abs(x) <= 0.25, 1.0, 0.0)

def calcular_errores_completo(y_real, y_aprox, dx):

    diff = np.abs(y_real - y_aprox)
    err_l2 = np.sqrt(scipy.integrate.trapezoid(diff**2, dx=dx))
    err_unif = np.max(diff)
    return err_l2, err_unif

def reconstruir_cesaro_par(coeficientes, x_eval):

    N = len(coeficientes) - 1
    y_approx = np.zeros_like(x_eval)

    denominador = N + 1

    a0 = coeficientes[0]
    y_approx += (a0 / 2) * np.ones_like(x_eval)

    for k in range(1, len(coeficientes)):
        a_k = coeficientes[k]

        peso = (N - k + 1) / denominador

        y_approx += peso * a_k * np.cos(k * np.pi * x_eval)

    return y_approx

def reconstruir_lanczos_par(coeficientes, x_eval):

    N = len(coeficientes) - 1
    y_approx = np.zeros_like(x_eval)

    y_approx += (coeficientes[0] / 2)

    for k in range(1, len(coeficientes)):
        sigma = np.sinc(k / N)
        y_approx += sigma * coeficientes[k] * np.cos(k * np.pi * x_eval)

    return y_approx

def reconstruir_abel_r_variable(coeficientes, x_eval, r):

    y_approx = np.zeros_like(x_eval)

    y_approx += (coeficientes[0] / 2)

    for k in range(1, len(coeficientes)):
        peso = r**k
        y_approx += peso * coeficientes[k] * np.cos(k * np.pi * x_eval)

    return y_approx


# Gráficas de Fourier

dx_malla = 1e-4
N_max_calculo = 500
lista_N_dibujar = [1, 5, 20, 50, 100, 300]

x_completo = np.arange(-1, 1 + dx_malla/10, dx_malla)
y_real = f_par_extendida(x_completo)

coefs_totales = construir_coeficientes_par(f_par_extendida, N_max_calculo + 1, dx_malla)

plt.figure(figsize=(12, 6))

plt.plot(x_completo, y_real, 'k-', linewidth=2, label='Función Original', alpha=0.3)

colores = plt.cm.magma(np.linspace(0, 0.85, len(lista_N_dibujar)))
for i, n in enumerate(lista_N_dibujar):
    coefs_n = coefs_totales[:n+1]
    y_aprox = reconstruir_serie_par(coefs_n, x_completo)

    plt.plot(x_completo, y_aprox, label=f'N={n}', color=colores[i], linewidth=1.5)

plt.title(f'Gráfica de Fourier en [-1, 1]')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()


errores_l2 = []
errores_inf = []
rango_n = np.arange(1, N_max_calculo + 1)

for n in rango_n:
    coefs_n = coefs_totales[:n+1]
    y_aprox = reconstruir_serie_par(coefs_n, x_completo)

    l2, unif = calcular_errores_completo(y_real, y_aprox, dx_malla)
    errores_l2.append(l2)
    errores_inf.append(unif)

plt.figure(figsize=(10, 6))
plt.loglog(rango_n, errores_l2, 'b-o', label='Error L2', markersize=4)
plt.loglog(rango_n, errores_inf, 'r-s', label='Error Uniforme', markersize=4)

plt.title(f'Errores de Fourier en [-1, 1]')
plt.xlabel('N (log)')
plt.ylabel('Error (log)')
plt.legend()
plt.grid(True, which="both", alpha=0.3)
plt.show()

# Gráficas de Cesaro

dx_malla = 1e-4
N_max_calculo = 500
lista_N_dibujar = [1, 5, 20, 50, 100, 300]

x_completo = np.arange(-1, 1 + dx_malla/10, dx_malla)
y_real = f_par_extendida(x_completo)

coefs_totales = construir_coeficientes_par(f_par_extendida, N_max_calculo + 1, dx_malla)


plt.figure(figsize=(10, 6))

plt.plot(x_completo, y_real, 'k-', linewidth=2, label='Función Original', alpha=0.6)

colores = plt.cm.magma(np.linspace(0, 0.85, len(lista_N_dibujar)))

for i, n in enumerate(lista_N_dibujar):
    coefs_n = coefs_totales[:n+1]

    y_cesaro = reconstruir_cesaro_par(coefs_n, x_completo)

    plt.plot(x_completo, y_cesaro, label=f'N={n}', color=colores[i], linewidth=2)

plt.title(f'Gráfica de Cesàro en [-1, 1]')
plt.xlabel('x')
plt.ylabel('S_N(x)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()


errores_l2 = []
errores_inf = []
rango_n = np.arange(1, N_max_calculo + 1)

for n in rango_n:
    coefs_n = coefs_totales[:n+1]
    y_cesaro = reconstruir_cesaro_par(coefs_n, x_completo)

    l2, unif = calcular_errores_completo(y_real, y_cesaro, dx_malla)
    errores_l2.append(l2)
    errores_inf.append(unif)

plt.figure(figsize=(10, 6))
plt.loglog(rango_n, errores_l2, 'b-o', label='Error L2', markersize=4)
plt.loglog(rango_n, errores_inf, 'r-s', label='Error Uniforme', markersize=4)

plt.title(f'Errores de Cesàro en [-1, 1]')
plt.xlabel('N (log)')
plt.ylabel('Error (log)')
plt.legend()
plt.grid(True, which="both", alpha=0.3)
plt.show()

# Gráficas de Lanczos

dx_malla = 1e-4
N_max_calculo = 500
lista_N_dibujar = [1, 5, 20, 50, 100, 300]

x_completo = np.arange(-1, 1 + dx_malla/10, dx_malla)
y_real = f_par_extendida(x_completo)

coefs_totales = construir_coeficientes_par(f_par_extendida, N_max_calculo + 1, dx_malla)


plt.figure(figsize=(10, 6))
plt.plot(x_completo, y_real, 'k-', linewidth=2, label='Función Original', alpha=0.5)

colores = plt.cm.viridis(np.linspace(0, 0.9, len(lista_N_dibujar)))

for i, n in enumerate(lista_N_dibujar):
    coefs_n = coefs_totales[:n+1]
    y_lanczos = reconstruir_lanczos_par(coefs_n, x_completo)

    plt.plot(x_completo, y_lanczos, label=f'N={n}', color=colores[i])

plt.title(f'Gráfica de Lanczos en [-1, 1]')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()


errores_l2 = []
errores_inf = []
rango_n = np.arange(1, N_max_calculo + 1)

for n in rango_n:
    coefs_n = coefs_totales[:n+1]
    y_lanczos = reconstruir_lanczos_par(coefs_n, x_completo)

    l2, unif = calcular_errores_completo(y_real, y_lanczos, dx_malla)
    errores_l2.append(l2)
    errores_inf.append(unif)

plt.figure(figsize=(10, 6))
plt.loglog(rango_n, errores_l2, 'b-o', label='Error L2', markersize=4)
plt.loglog(rango_n, errores_inf, 'r-s', label='Error Uniforme', markersize=4)
plt.title(f'Errores de Lanczos en [-1, 1]')
plt.xlabel('N (log)')
plt.ylabel('Error (log)')
plt.legend()
plt.grid(True, which="both", alpha=0.3)
plt.show()

#Gráficas de Abel

dx_malla = 1e-4
N_FIJO = 300
lista_r_dibujar = [0.6, 0.8, 0.9, 0.95, 0.99, 0.999]

x_completo = np.arange(-1, 1 + dx_malla/10, dx_malla)
y_real = f_par_extendida(x_completo)

coefs_fijos = construir_coeficientes_par(f_par_extendida, N_FIJO + 1, dx_malla)


plt.figure(figsize=(10, 6))
plt.plot(x_completo, y_real, 'k-', linewidth=2, label='Función Original', alpha=0.3)

colores = plt.cm.Blues(np.linspace(0.4, 1.0, len(lista_r_dibujar)))

for i, r_val in enumerate(lista_r_dibujar):
    y_abel = reconstruir_abel_r_variable(coefs_fijos, x_completo, r_val)

    plt.plot(x_completo, y_abel, label=f'r={r_val}', color=colores[i], linewidth=1.5)

plt.title(f'Gráfica de Abel en [-1, 1]')
plt.xlabel('x')
plt.ylabel('A_r(x)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()


r_range = np.linspace(0.5, 0.999, 100)

errores_l2 = []
errores_inf = []

for r_val in r_range:
    y_abel = reconstruir_abel_r_variable(coefs_fijos, x_completo, r_val)

    l2, unif = calcular_errores_completo(y_real, y_abel, dx_malla)
    errores_l2.append(l2)
    errores_inf.append(unif)

plt.figure(figsize=(10, 6))
plt.loglog(r_range, errores_l2, 'b-o', label='Error L2', markersize=4)
plt.loglog(r_range, errores_inf, 'r-s', label='Error Uniforme', markersize=4)
plt.title(f'Errores de Abel en [-1, 1]')
plt.xlabel('r (log)')
plt.ylabel('Error (log)')
plt.legend()
plt.grid(True, which="both", alpha=0.3)
plt.show()

plt.show()