-
iliya.saroukha authorediliya.saroukha authored
ISC_421_Controle_4_Saroukhanian_Iliya.py 11.62 KiB
import numpy as np
import math
from matplotlib import pyplot as plt
from scipy.interpolate import lagrange, barycentric_interpolate
from numpy.polynomial.polynomial import Polynomial
#############################################################################
######################### Variables globales ################################
#############################################################################
Nmbre_derivees = 14
Nmbre_pts = 201
def Base_function(x): return np.sin(np.pi*np.cos(4*x*x))
Taylor_points = np.array([-0.8, 0.25, 0.8])
Borne_a = 1
Borne_b = 4
def sigma(a, b, x): return (b-a)/2*x + (b+a)/2
def amgis(a, b, x): return -1 + 2*(x-a)/(b-a)
#############################################################################
############ Fonctions necessaires a la production des donnees ##############
#############################################################################
def deltas2(lstx, lsty, depth=1):
N = len(lstx)
deltas_dic = {tuple([l]): y for l, y in enumerate(lsty)}
for k in range(1, min(depth, N)):
for l in range(N - k):
indices_now = tuple(range(l, k+l+1))
deltas_dic[indices_now] = (
deltas_dic[indices_now[1:]] - deltas_dic[indices_now[:-1]])/(lstx[k+l]-lstx[l])
return deltas_dic
def approx_der_lst(lstx, lsty, a, depth):
D = deltas2(lstx, lsty, depth=depth)
indices = [l for l, x in enumerate(lstx) if x >= a]
index = indices[0]
lst_return = []
l = 0
while (index - l >= 0) and (index + l < len(lstx)) and (l < depth):
der_temp = []
indices_now = range(index - l, index + 1)
for m in indices_now:
approx_der_temp = D[tuple(range(m, m+l+1))]*np.math.factorial(l)
der_temp.append(approx_der_temp)
approx_der = sum(der_temp)/(len(der_temp))
lst_return.append(approx_der)
l += 1
return lst_return
#############################################################################
##### Classe regroupant toutes les donnees pertinentes d'une fonction #######
#############################################################################
class Function_data:
def __init__(self, f=lambda x: x):
self.function = f
def approx_der_temp(pt, width=.1, number_points=Nmbre_derivees):
t = np.linspace(pt - width, pt + width, 2*number_points + 1)
return approx_der_lst(t, f(t), pt, number_points)
def max_der(a, b, width=.1, number_points=12, total_number=Nmbre_derivees):
ts = np.linspace(a, b, total_number)
max_ret = [0]*(number_points-1)
for p in ts:
der = approx_der_temp(p)
max_ret = [max(oldmax, abs(der[l]))
for l, oldmax in enumerate(max_ret)]
return max_ret
self.approx_derivatives = approx_der_temp
self.values = lambda t: f(t)
self.max_der = max_der
#############################################################################
######## Classe regroupant toutes les donnees fournies a l'etudiant #########
#############################################################################
class Student_data:
def __init__(self):
self.a, self.b = Borne_a, Borne_b
def f_ab(x): return Base_function(amgis(Borne_a, Borne_b, x))
F = Function_data(f_ab)
self.Maximal_derivatives_values = F.max_der(
Borne_a, Borne_b, number_points=Nmbre_derivees, total_number=Nmbre_pts)
self.Taylor_points = [sigma(Borne_a, Borne_b, p)
for p in Taylor_points]
self.Taylor_derivatives_values = {pt: F.approx_derivatives(
pt, number_points=Nmbre_derivees) for pt in self.Taylor_points}
self.f = f_ab
def compute_taylor_series(x, pt, derivs):
sum = 0
for nth_deg, nth_deriv in enumerate(derivs):
sum += (nth_deriv / math.factorial(nth_deg)) * (x - pt)**nth_deg
return sum
###########################################################################
#### Exemple d'utilisation de la classe, avec explication des donnees #####
###########################################################################
SD = Student_data()
print(f"bornes de l'intervalle considere: [{SD.a},{SD.b}]")
print()
print(f"Points ou on connait la derivee : {SD.Taylor_points}")
print(f"Valeurs des derivees 0 a {Nmbre_derivees-1}:")
for x in SD.Taylor_points:
print(f"x = {x}, dérivées: {SD.Taylor_derivatives_values[x]}")
print()
print(f"Valeurs maximales des derivees 0 a {
Nmbre_derivees-1} sur l'intervalle [{SD.a},{SD.b}]: {SD.Maximal_derivatives_values}")
print()
print("La fonction est dans la variable SD.f, si on doit l'évaluer en certains points")
print()
print(f"valeur de la fonction en x = {SD.Taylor_points} : {
[SD.f(x) for x in SD.Taylor_points]}")
print(f"valeur de la fonction en a et b: {SD.f(SD.a), SD.f(SD.b)}")
# Exemple de graphe de la fonction f.
# t = np.linspace(SD.a, SD.b, Nmbre_pts)
# y = compute_taylor_series(
# t, SD.Taylor_points[1], SD.Taylor_derivatives_values[SD.Taylor_points[1]])
# plt.plot(t, SD.f(t), "k")
# plt.show()
###########################################################################
#### Exercices #####
###########################################################################
def errmax_taylor(plot_range, eval_pt):
return (SD.Maximal_derivatives_values[-1] /
math.factorial(len(SD.Maximal_derivatives_values) + 1)) * \
(plot_range - eval_pt)**(len(SD.Maximal_derivatives_values) + 1)
def plot_taylor_poly():
t = np.linspace(SD.a, SD.b, Nmbre_pts)
y0 = compute_taylor_series(
t, SD.Taylor_points[0], SD.Taylor_derivatives_values[SD.Taylor_points[0]])
err_y0 = errmax_taylor(t, SD.Taylor_points[0])
y1 = compute_taylor_series(
t, SD.Taylor_points[1], SD.Taylor_derivatives_values[SD.Taylor_points[1]])
err_y1 = errmax_taylor(t, SD.Taylor_points[1])
y2 = compute_taylor_series(
t, SD.Taylor_points[2], SD.Taylor_derivatives_values[SD.Taylor_points[2]])
err_y2 = errmax_taylor(t, SD.Taylor_points[2])
fig, axs = plt.subplots(2, 2, figsize=(18, 12))
axs[0, 0].plot(t, SD.f(t), color='black')
axs[0, 0].set_title('Fonction $f$ originale')
axs[0, 0].grid()
axs[0, 1].plot(t, SD.f(t), color='black', label='$f$')
axs[0, 1].plot(t, y0, color='orange', label='$T_{f}$')
axs[0, 1].plot(t, err_y0, '--', color='orange',
label='Erreur maximal de $T_{f}$')
axs[0, 1].plot(SD.Taylor_points[0], SD.f(
SD.Taylor_points[0]), "-o", color='red', label=f'a = {SD.Taylor_points[0]}')
axs[0, 1].set_title(
f'Développement de $T_f$ en $a = {SD.Taylor_points[0]}$')
axs[0, 1].set_ylim([-1.2, 1.2])
axs[0, 1].grid()
axs[0, 1].legend()
axs[1, 0].plot(t, SD.f(t), color='black', label='$f$')
axs[1, 0].plot(t, y1, color='blue', label='$T_{f}$')
axs[1, 0].plot(t, err_y1, '--', color='blue',
label='ErrMax de $T_{f}$')
axs[1, 0].plot(SD.Taylor_points[1], SD.f(
SD.Taylor_points[1]), "-o", color='red', label=f'a = {SD.Taylor_points[1]}')
axs[1, 0].set_title(
f'Développement de $T_f$ en $a = {SD.Taylor_points[1]}$')
axs[1, 0].set_ylim([-1.2, 1.2])
axs[1, 0].grid()
axs[1, 0].legend()
axs[1, 1].plot(t, SD.f(t), color='black', label='$f$')
axs[1, 1].plot(t, y2, color='violet', label='$T_{f}$')
axs[1, 1].plot(t, err_y2, '--', color='violet',
label='ErrMax de $T_{f}$')
axs[1, 1].plot(SD.Taylor_points[2], SD.f(
SD.Taylor_points[2]), "-o", color='red', label=f'a = {SD.Taylor_points[2]}')
axs[1, 1].set_title(
f'Développement de $T_f$ en $a = {SD.Taylor_points[2]}$')
axs[1, 1].set_ylim([-1.2, 1.2])
axs[1, 1].grid()
axs[1, 1].legend()
fig.tight_layout()
plt.show()
def errmax_poly_interpolation(nb_points, interpolation_pts, plot_range):
errs_range = []
for pt in plot_range:
prod = 1
for inter_pt in interpolation_pts:
prod *= pt - inter_pt
err = (SD.Maximal_derivatives_values[nb_points] /
math.factorial(nb_points + 1)) * np.abs(prod)
errs_range.append(err)
return errs_range
def chebyshev_pts(start, stop, nb_points):
return (((start + stop) / 2) + ((stop - start) / 2) *
np.cos(((2 * np.arange(nb_points) + 1) * np.pi) / (2 * (nb_points))))
def plot_lagrange_poly():
nb_points = np.linspace(1, 12, 6, dtype=np.uint8)
fig, axes = plt.subplots(2, 3, figsize=(20, 12))
t = np.linspace(SD.a, SD.b, Nmbre_pts)
for i, ax in enumerate(axes.flat):
cheb_pts = chebyshev_pts(SD.a, SD.b, nb_points[i])
interpolate_pts = np.linspace(SD.a, SD.b, nb_points[i])
l_poly_uniform = lagrange(interpolate_pts, SD.f(interpolate_pts))
l_poly_chebyshev_pts = lagrange(
cheb_pts, SD.f(cheb_pts))
ax.plot(t, SD.f(t), color='black', label='f')
ax.plot(t, l_poly_uniform(t), color='red',
label='$L_{f}$, intervalle équidistants')
# ax.plot(t, np.abs(SD.f(t) - l_poly_uniform(t)), '--', color='red',
# label='$L_{f}$, intervalle équidistants, erreur')
ax.plot(t, l_poly_chebyshev_pts(t), color='blue',
label='$L_{f}$, points de Chebyshev')
# ax.plot(t, np.abs(SD.f(t) - l_poly_chebyshev_pts(t)), '--', color='blue',
# label='$L_{f}$, points de Chebyshev, erreur')
ax.plot(interpolate_pts, SD.f(interpolate_pts), 'o', color='red',
label='Points équidistants')
ax.plot(cheb_pts, SD.f(cheb_pts), 'o', color='blue',
label='Points de Chebyshev')
ax.set_title(f'n = {nb_points[i]}')
ax.set_ylim([-1.2, 1.2])
ax.legend()
fig.suptitle(f'Polynômes d\'interpolation de Lagrange de $f$ avec 2 subdivisions différentes d\'intervalle: Équidistantes (rouge) / Points de Chebyshev (bleu)')
fig.tight_layout()
plt.show()
def plot_errmax_interpolation():
nb_points = np.linspace(1, 12, 6, dtype=np.uint8)
fig, axes = plt.subplots(2, 3, figsize=(20, 12))
t = np.linspace(SD.a, SD.b, Nmbre_pts)
for i, ax in enumerate(axes.flat):
cheb_pts = chebyshev_pts(SD.a, SD.b, nb_points[i])
interpolate_pts = np.linspace(SD.a, SD.b, nb_points[i])
l_poly_uniform = lagrange(interpolate_pts, SD.f(interpolate_pts))
l_poly_chebyshev_pts = lagrange(
cheb_pts, SD.f(cheb_pts))
uniform_err = errmax_poly_interpolation(
nb_points[i], interpolate_pts, t)
chebyshev_err = errmax_poly_interpolation(nb_points[i], cheb_pts, t)
ax.plot(t, SD.f(t), color='black', label='f')
ax.plot(t, l_poly_uniform(t), color='red',
label='$L_{f}$, intervalle équidistants')
ax.plot(t, uniform_err, '--', color='red',
label='ErrMax de $L_{f}$, intervalle équidistants')
ax.plot(t, l_poly_chebyshev_pts(t), color='blue',
label='$L_{f}$, points de Chebyshev')
ax.plot(t, chebyshev_err, '--', color='blue',
label='ErrMax de $L_{f}$, points de Chebyshev')
ax.plot(interpolate_pts, SD.f(interpolate_pts), 'o', color='red',
label='Points équidistants')
ax.plot(cheb_pts, SD.f(cheb_pts), 'o', color='blue',
label='Points de Chebyshev')
ax.set_title(f'n = {nb_points[i]}')
ax.legend()
fig.suptitle(f'Erreur maximale théorique lors de l\'interpolation de $f$ avec 2 subdivisions différentes d\'intervalle: Équidistantes (rouge) / Points de Chebyshev (bleu)')
fig.tight_layout()
plt.show()
plot_taylor_poly()
plot_lagrange_poly()
plot_errmax_interpolation()