Exercice 1 : Interpolation polynomiale de Lagrange
1. Ecrire le programme Python permettant de calculer la valeur de $P$ au point $x =50$ en utilisant le polynôme d’interpolation de Lagrange
passant par les points suivants: $$ \{(x_i,y_i)\}_{i=0,...,5} = \{(0,26.0) \ ; \ (20,48.6) \ ; \ (40, 61.2)\ ; \ (60,71.2)\ ; \ (80, 74.8)\ ; \ (100,75.2)\} $$
In [12]:
x=[0,20,40,60,80,100]
y=[26.0,48.6,61.6,71.2,74.8,75.2]
m=len(x)
n=m-1 # degré du polynôme
xp=50
yp=0
for i in range(n+1):
P=1
for j in range(n+1):
if j != i:
P *= (xp - x[j])/(x[i]-x[j])
yp += y[i]*P
print('for x=%.2f , y= %.4f' %(xp,yp))
for x=50.00 , y= 66.9477
In [21]:
x=[0,20,40,60,80,100]
y=[26.0,48.6,61.6,71.2,74.8,75.2]
m=len(x)
n=m-1 # degré du polynôme
xp= float(input('Entrer la valeur de x:'))
yp=0
for i in range(n+1):
P=1
for j in range(n+1):
if j != i:
P *= (xp - x[j])/(x[i]-x[j])
yp += y[i]*P
print('for x=%.2f , y= %f' %(xp,yp))
Entrer la valeur de x:50
for x=50.00 , y= 66.947656
In [5]:
import numpy as np
x=np.array([0,20,40,60,80,100],float)
y=np.array([26.0,48.6,61.6,71.2,74.8,75.2],float)
xp= float(input('Entrer la valeur de x:'))
yp=0
for xi,yi in zip(x,y):
P=np.prod((xp-x[x!=xi])/(xi-x[x!=xi]))
yp += yi *P
print('for x=%.2f , y= %f' %(xp,yp))
Entrer la valeur de x:50
for x=50.00 , y= 66.947656
1. Réecrire le programme en utilisant la fonction "interp" du module Numpy. Afficher le graphe de polynôme d'interpolation.
In [22]:
import numpy as np
import matplotlib.pyplot as plt
x=np.array([0,20,40,60,80,100],float)
y=np.array([26.0,48.6,61.6,71.2,74.8,75.2],float)
xp= float(input('Entrer la valeur de x:'))
yp= np.interp(xp,x,y)
print('for x=%.2f , y= %f' %(xp,yp))
plt.plot(x,y,'o-',xp,yp,'*r')
plt.xlabel("x")
plt.ylabel("y")
plt.show()
Entrer la valeur de x:50
for x=50.00 , y= 66.400000
Rappel : Module Scipy
Le module $Scipy$ est un ensemble de fonctions mathématiques avancées (résolution d’équations différentielles, méthodes de calcul intégral,
calcul de transformées de Fourier, traitement d’images…). L'interpolation est l'opération permettant de construire une courbe à partir de la donnée
d'un nombre fini de points, ou une fonction à partir de la donnée d'un nombre fini de valeurs. Sous Python, cette opération est réalisée à l'aide du
module $scipy.interpolate$. Nous utiliserons en particulier la fonction $interp1d$ qui permet d'interpoler des courbes à une dimension, c’est‐à‐dire
des nuages de points dont on connaît les valeurs des abscisses et des ordonnées.
3. Refaire la même question en utilisant un sous programme fonction Lagrange. Afficher le graphe du polynôme d'interpolation de Lagrange
.
In [19]:
import numpy as np
from scipy.interpolate import lagrange
import matplotlib.pyplot as plt
x=np.array([0,20,40,60,80,100],float)
y=np.array([26.0,48.6,61.6,71.2,74.8,75.2],float)
poly = lagrange(x, y)
xp = np.linspace(x[0], x[5], 1000)
yp = poly(xp)
plt.scatter(x, y, marker='s', c='r')
plt.plot(xp, yp)
Out[19]:
[<matplotlib.lines.Line2D at 0x222ff096ec8>]
1. On considére $x_i = [0,1,2,3,4,5,6,7,8,9,10]$ et $f(x) = \cos(\frac{x^2}{8})+1$.
Ajouter les instructions pour afficher les $(x_i, y_i)$.
Définir la fonction $y =f(x)$.
Affiche le graphe de polynôme d’interpolation linéaire en rouge .
Affiche le graphe de polynôme d’interpolation cubique en vert.
In [20]:
import scipy.interpolate as sp
x=np.array([0,1,2,3,4,5,6,7,8,9,10])
y=np.cos(x**2.0/8.0)+1
f_interp=sp.interp1d(x,y)
xx=np.linspace(0,10,1000)
yy=np.cos(xx**2.0/8.0)+1
xp=xx
yp=f_interp(xp)
plt.plot(x,y, 'o', label='points originaux')
plt.plot(xx,f_interp(xp),':',label='interpolation linaire')
plt.plot(xx,yy,'-' ,label='interpolation cubique')
plt.xlabel('x')
plt.ylabel('y')
plt.ylim([-0.1,3])
plt.legend(loc='best', frameon = False, fontsize=12)
Out[20]:
<matplotlib.legend.Legend at 0x222fedfdb08>
In [103]:
import scipy.interpolate as sp
#from scipy.interpolate import interp1d
x=np.array([0,1,2,3,4,5,6,7,8,9,10])
y=np.cos(x**2.0/8.0)+1
f_interp=interp1d(x,y)
#xx=np.linspace(0,10,1000)
#yy=np.cos(xx**2.0/8.0)+1
yp=f_interp(xp)
xp=0.5
print(yp)
1.9960988336146646
In [100]:
x = np.array([0,1,2,3,4,5,6,7,8,9,10])
y = np.cos(x**2.0/8.0) + 1
plt.rc('font', size=16)
plt.plot(x, y, 'o:')
plt.plot([2.5,2.5],[-0.1,1.6], '--', color='gray')
plt.plot([-0.1,2.5],[1.6,1.6], '--', color='gray')
plt.plot([2.5], [1.6], '*', markersize=20)
plt.xlim([-0.1,11]); plt.ylim([-0.1,2.2])
plt.xlabel('x'); plt.ylabel('y')
plt.text(2.6,0, r"$x_p$", fontsize=16); plt.text(0,1.7, r"$y_p$", fontsize=16)
Out[100]:
Text(0, 1.7, '$y_p$')
Exercice 2 : Méthode de Newton
Ecrire un programme permettant de calculer le polynôme $P_2$ par la méthode de Newton associé aux points $(x_i,y_i)= \{ (0,1) \ ; \ (2,5) \ ; \ (4,17)
\}$.
In [104]:
import matplotlib.pyplot as plt
import numpy as np
def diff_div(x,y):
F=np.zeros((n+1,n+1))
F[:,0]=y
for i in range(1,n+1):
for j in range(1,i+1):
F[i,j]=( F[i,j-1]- F[i-1,j-1])/(x[i]-x[i-j])
return F
xi=[0,2,4]
yi=[1,5,17]
n=len(xi)-1
plt.plot(xi,yi,'gs')
F=diff_div(xi,yi)
print(F)
plt.show()
[[ 1. 0. 0.]
[ 5. 2. 0.]
[17. 6. 1.]]
Soit $x=[-3,-2,-1,0,1,2,3]$ et $y =\sin(x)$.
In [138]:
import matplotlib.pyplot as plt
import numpy as np
def diff_div(x,y):
F=np.zeros((n+1,n+1))
F[:,0]=y
for i in range(1,n+1):
for j in range(1,i+1):
F[i,j]=( F[i,j-1]- F[i-1,j-1])/(x[i]- x[i-j])
return F
def Pn(x):
s=0
for i in range(n+1):
p=1
for j in range(i):
p *= (x - xi[j])
s+= a[i]*p
return s
xi=[-3,-2,-1,0,1,2,3]
yi=np.sin(xi)
n=len(xi)-1
plt.plot(xi,yi,'go')
F=diff_div(xi,yi)
print(F)
a = np.diag(F)
print(a)
X=np.linspace(xi[0],xi[-1],100)
Y= Pn(X)
plt.plot(X,Y,'r--')
Y= np.sin(X)
plt.plot(X,Y,'g')
plt.show()
[[-0.14112001 0. 0. 0. 0. 0.
0. ]
[-0.90929743 -0.76817742 0. 0. 0. 0.
0. ]
[-0.84147098 0.06782644 0.41800193 0. 0. 0.
0. ]
[ 0. 0.84147098 0.38682227 -0.01039322 0. 0.
0. ]
[ 0.84147098 0.84147098 0. -0.12894076 -0.02963688 0.
0. ]
[ 0.90929743 0.06782644 -0.38682227 -0.12894076 0. 0.00592738
0. ]
[ 0.14112001 -0.76817742 -0.41800193 -0.01039322 0.02963688 0.00592738
0. ]]
[-0.14112001 -0.76817742 0.41800193 -0.01039322 -0.02963688 0.00592738
0. ]
Exercice 3 : Phénomène de Runge
Prenons maintenant l'exemple de la function $x \mapsto \frac{1}{1 + 10 x^2}$ sur l'intervalle $[-1, 1]$. Nous augmentons alors
progressivement le degé d'interpolation.
In [59]:
x=np.linspace(-1,1,100)
f=1/(1+10*x**2)
plt.plot(x, f,'r')
Out[59]:
[<matplotlib.lines.Line2D at 0x2aefb3add48>]
In [65]:
#Interpolation d’ordre 2 à 3 points équidistants
from scipy import interpolate
xi=np.linspace(-1,1,3) # 3 points
fi=1/(1+10*xi**2)
p= lagrange(xi,fi)
fig, ax1= plt.subplots()
ax1.plot(x,f,'r')
ax1.plot(xi,fi,'ro')
ax1.plot(x,np.polyval(p,x),label='Ordre 2')
ax1.legend()
Out[65]:
<matplotlib.legend.Legend at 0x2aefb43cb48>
In [66]:
# Interpolation d’ordre 4 à 5 points équidistants:
xi=np.linspace(-1,1,5) # 5 points
fi=1/(1+10*xi**2)
p=lagrange(xi,fi)
fig, ax1= plt.subplots()
ax1.plot(x,f,'r')
ax1.plot(xi,fi,'ro')
ax1.plot(x,np.polyval(p,x),label='Ordre 4')
ax1.legend()
Out[66]:
<matplotlib.legend.Legend at 0x2aefb3ed708>
In [67]:
#Interpolation d’ordre 6 à 7 points équidistants:
xi=np.linspace(-1,1,7) # 5 points
fi=1/(1+10*xi**2)
p=lagrange(xi,fi)
fig, ax1= plt.subplots()
ax1.plot(x,f,'r')
ax1.plot(xi,fi,'ro')
ax1.plot(x,np.polyval(p,x),label='Ordre 6')
ax1.legend()
Out[67]:
<matplotlib.legend.Legend at 0x2aefb2debc8>
In [68]:
#Et enfin interpolation d’ordre 8 à 9 points équidistants:
#Interpolation d’ordre 6 `a 7 points ´equidistants:
xi=np.linspace(-1,1,9) # 5 points
fi=1/(1+10*xi**2)
p=lagrange(xi,fi)
fig, ax1= plt.subplots()
ax1.plot(x,f,'r')
ax1.plot(xi,fi,'ro')
ax1.plot(x,np.polyval(p,x),label='Ordre 10')
ax1.legend()
Out[68]:
<matplotlib.legend.Legend at 0x2aefb237108>
Un phénomène d’oscillation apparaît et s’amplifie lorsque n augmente. Ce phénomène a été clairement mis en évidence et expliqué par
Carl Runge en 1901.
Exercice 4 : Polynômes de Chebyshev et atténuation du phénomène de Runge
In [72]:
x=np.linspace(-1,1,100); fig, ax1=plt.subplots(); i=1; chebObj_=list(); chebPol_=list()
while i<5:
chebOrd_ = np.array([0]*i+[1])
chebObj_.append(np.polynomial.chebyshev.Chebyshev(chebOrd_))
chebPol_.append(np.polynomial.chebyshev.cheb2poly(chebObj_[-1].coef))
ax1.plot(x,np.polyval(chebPol_[-1][::-1],x),label='T_'+str(i))
i +=1
ax1.legend()
In [ ]:
In [75]:
x=np.linspace(-1,1,100)
f=1/(1+10*x**2)
xi=np.polynomial.chebyshev.Chebyshev(np.array([0]*9+[1])).roots(); # Ordre 10, 9 racine
fi=1/(1+10*xi**2)
p=lagrange(xi,fi)
fig, ax1= plt.subplots()
ax1.plot(x,f,'r')
ax1.plot(xi,fi,'ro')
ax1.plot(x,np.polyval(p,x),label='Ordre 10')
ax1.legend()
Out[75]:
<matplotlib.legend.Legend at 0x2aefb4e1d48>
In [76]:
xi=np.polynomial.chebyshev.Chebyshev(np.array([0]*13+[1])).roots(); # Ordre 14, 13 racines
fi=1/(1+10*xi**2)
p=lagrange(xi,fi)
fig, ax1= plt.subplots()
ax1.plot(x,f,'r')
ax1.plot(xi,fi,'ro')
ax1.plot(x,np.polyval(p,x),label='Ordre'+str(len(xi)+1))
ax1.legend()
Out[76]:
<matplotlib.legend.Legend at 0x2aefb554f48>
In [ ]: