Académique Documents
Professionnel Documents
Culture Documents
ż 1
2 ?
I“ f ptqdt où f : x ÞÑ 1 ´ x2 .
0
1
Figure 1 – La courbe de f est un arc de cercle
żx
Calculons, pour x Ps ´ 1, 1r, la valeur de J “ f ptqdt. Une intégration par parties donne
0
żx
?
2
t2
Jpxq “ x 1 ´ x ` ? dt
0 1 ´ t2
? ż x żx?
1
“ x 1 ´ x2 ` ? dt ´ 1 ´ t2 dt
0 1 ´ t2 0
?
“ x 1 ´ x2 ` arcsinpxq ´ Jpxq
et donc
1´ ? ¯
Jpxq “ x 1 ´ x2 ` arcsinpxq .
2
ˆ ˙
1
Donc I “ J ´ Jp0q et on retrouve bien la valeur annoncée.
2
En fait, on pouvait trouver cette primitive en généralisant le raisonnement géométrique de la question
précédente.
4 Écrire une fonction rectangle, permettant d’obtenir la valeur approchée d’une intégrale par la
méthode des rectangles. Testez sur l’exemple, en changeant le nombre de points de la subdivision.
1 from numpy import sqrt, pi
2
3 def rectangle(f,a,b,n):
4 h = (b-a)/n
5 return ( sum ( f(a+k*h) for k in range(n) ) * h)
6
7 f = lambda x: sqrt(1-x**2)
8 print("valeur approchée par la méthode des rectangles:")
9 for n in [10,20,30,40,50,60]:
10 print( "\tavec n=",n,"\t", rectangle ( f , 0, 1/2, n ))
2
11
12 print()
13 v = pi/12 + sqrt(3)/8 # valeur exacte
14 print( "valeur exacte : ", v)
1 valeur approchée par la méthode des rectangles:
2 avec n= 10 0.481534849018
3 avec n= 20 0.479950352541
4 avec n= 30 0.479408829454
5 avec n= 40 0.479135562494
6 avec n= 50 0.478970800517
7 avec n= 60 0.478860625103
8
9 valeur exacte : 0.478305738745
Si on est moins à l’aise, on peut écrire une boucle gentille :
1 from numpy import sqrt, pi
2
3 def rectangle(f,a,b,n):
4 h = (b-a)/n
5 S=0
6 for k in range(n):
7 S=S+f(a+k*h)
8 return S*h
9
10 f = lambda x: sqrt(1-x**2)
11 for n in [10,20,30,40,50,60]:
12 print( "valeur approchée : ", rectangle ( f , 0, 1/2, n )," avec",n,"
intervalles" )
13
14 v = pi/12 + sqrt(3)/8 # valeur exacte
15 print( "valeur exacte : ", v)
En toute rigueur, ne multiplier par h qu’après avoir sommé, pour éviter des erreurs d’arrondi.
Par exemple, on désire acheter 1000 boulons, dont le prix unitaire est 0.92FF.
En multipliant d’abord par 1000, et en convertissant (et arrondissant) après : Un boulon coûte 6.03e.
Donc 1000 boulons, 60 300e.
En convertissant (et arrondissant) d’abord, et en multipliant par 1000 après : Il s’agit de convertir
9 200FF : on trouve 60 348.04e.
5 Mettez en œuvre les autres méthodes du cours pour calculer l’intégrale de l’exemple.
On peut remarquer que :
1 2
méthode Simpson “ méthode trapèzes ` méthode points milieux
3 3
1 import matplotlib.pyplot as plt
2 import numpy as np
3
4 n = 10 # nombre de points de la subdivision
5 f = lambda t : np.sqrt(1-t**2)
6
3
7 a,b=0,0.5
8 v = np.pi/12 + np.sqrt(3)/8 # valeur exacte
9
10 h = (b-a)/n
11 a1 = h * sum ( f ( a+k*h ) for k in range(n) )
12 a2 = h * ( (f(a)+f(b))/2 + sum ( f ( a+k*h ) for k in range(1, n) ))
13 a3 = h * sum ( f ( a+ k*h + h/2 ) for k in range(n) )
14 a4 = 1/3*a2 + 2/3*a3
15
16 print("n=",n)
17 print("méthode des rectangles:\t\t", a1 )
18 print("méthode des trapèzes:\t\t", a2 )
19 print("méthode des points-milieux:\t", a3 )
20 print("méthode de Simpson:\t\t", a4 )
21 print("valeur exacte ",v)
1 n= 10
2 méthode des rectangles: 0.481534849018
3 méthode des trapèzes: 0.478185484112
4 méthode des points-milieux: 0.478365856065
5 méthode de Simpson: 0.478305732081
6 valeur exacte 0.478305738745
6 ‹ Comment adapter les méthodes numériques de calcul d’intégrale pour approximer une primitive
F de f sur r0, 1s qui
ż aks’annule en 0 ? Faire un dessin.
On a F pak q “ f ptqdt qu’on approxime avec une des méthodes numériques. On approxime à chaque
0
fois F pak`1 q à partir de l’approximation de F pak q, ce qui est facile, car
ż ak`1
F pak`1 q ´ F pak q “ f ptqdt.
ak
1 import numpy as np
2 import matplotlib.pyplot as plt
3
4 a=0
5 b=1
6 n=10
7
8 f=lambda x:np.sqrt(1-x**2)
9
10 h = (b-a)/n
11
12 LX = np.linspace(a,b,n+1)
13 tmp_rec = [0]
14 tmp_sim = [0]
15
16 for k in range(n):
17 tmp_rec.append(tmp_rec[-1]+f(a+k*h))
18 tmp_sim.append(tmp_sim[-1]+1/6*(f(a+k*h)+4*f(a+k*h+h/2)+f(a+(k+1)*h)))
4
19
20 LYappro_rec = h*np.array(tmp_rec)
21 LYappro_sim = h*np.array(tmp_sim)
22
23 LXexact = np.linspace(0,1,100)
24 F=lambda x:1/2*(x*np.sqrt(1-x**2)+np.arcsin(x))
25 LYexact = F(LXexact)
26
27 plt.plot(LX,LYappro_rec,label=’méthode des rectangles’)
28 plt.plot(LX,LYappro_sim,label=’méthode de Simpson’)
29 plt.plot(LXexact,LYexact,label=’primitive exacte’,linewidth=3)
30 plt.legend(loc=4)
31 plt.show()
Dans le module scipy, il existe des méthodes qui permettent d’intégrer des fonctions.
Le plus simple est d’utiliser la fonction quad du sous-module scipy.integrate. Voici le début de l’aide
de cette fonction.
1 quad(func, a, b, args=(), full_output=0, epsabs=1.49e-08, epsrel=1.49e-08,
limit=50, points=None, weight=None, wvar=None, wopts=None, maxp1=50,
limlst=50)
2 Compute a definite integral.
3
4 Integrate func from ‘a‘ to ‘b‘ (possibly infinite interval) using a
5 technique from the Fortran library QUADPACK.
Quelle méthode numérique est utilisée ? Un peu obscur. . . hmmmm. . . Qu’importe. . . nous allons
utiliser la fonction quad comme une boı̂te noire.
7 Tester avec l’intégrale de l’exemple. Que sont les 2 nombres renvoyées par quad ?
Valeur de l’intégrale et précision.
1 import numpy as np
2 import scipy.integrate as sci
3 f = lambda t: np.sqrt(1-t**2)
4 print(sci.quad(f,0,1/2))
1 (0.47830573874525906, 5.310260439653314e-15)
Voir l’aide.
1 Returns
2 -------
3 y : float
4 The integral of func from ‘a‘ to ‘b‘.
5 abserr : float
6 An estimate of the absolute error in the result.
5
1.4 Méthode de Monte-Carlo
Par défaut, la commande plot du module matplotlib.pyplot relie des points pour former une ligne
brisée. Si vous préférez un nuage de points indiqués par un symbole, il suffit de rajouter une option
correspondant à ce symbole, par exemple '+' pour des petits `, 'o' pour des gros points, etc. Vous
pouvez aussi préciser la couleur : ainsi l’option '*g' signifie que les symboles sont des étoiles de couleur
verte. (Pour la liste des symboles et des couleurs, allez voir l’aide de plot.) L’option ms (abbréviation de
markersize) permet de régler la taille des points.
„
1
8 Tirez aléatoirement un grand nombre de points dans le rectangle 0, ˆ r0, 1s et visualisez le
2
résultat. Vous pourrez utiliser la fonction uniform du module random.
1 import numpy as np
2 import matplotlib.pyplot as plt
3 from random import uniform
4
5 n=1000
6 LXalea = [ uniform(0,1/2) for _ in range(n) ]
7 LYalea = [ uniform(0,1) for _ in range(n) ]
8 plt.plot(LXalea,LYalea,’o’,ms=4)
9
10 f = lambda t : np.sqrt(1-t**2)
11 LX = np.linspace(-1,1,100)
12 plt.plot(LX,f(LX),’r’,linewidth=5)
13 plt.fill([0,0,1/2,1/2,0],[1,0,0,1,1],edgecolor=’r’,facecolor=’#FBA16C’,linewidth=5)
14
15 plt.axis(’equal’)
16 plt.show()
6
Figure 2 – Algorithme de Monte-Carlo
10 ‹ ‹ ‹ Comparez les vitesses de convergence des différentes méthodes (à vous de donner du sens à cet
7
énoncé !).
Pour cela, représentez le log de l’erreur en fonction de log n. Dans le cas de la méthode de Monte-Carlo,
pour avoir un joli dessin, vous devrez faire la moyenne sur un grand nombre d’expériences.
En effet, il faudrait déjà définir ce que signifie qu’une variable aléatoire converge vers un nombre. . . Nous
ne le ferons pas ici, et nous contenterons d’un résultat intuitif.
1
Si En est de l’ordre de α , avec α ą 0, alors la courbe de logpEn q en fonction de logpnq est une droite
n
de pente ´α.
Pour les 4 méthodes déterministes, pour que les points en abscisse soient bien espacés, on choisit des
valeurs de x entières régulièrement espacées, et on trace la courbe sur les points n “ 2x .
Ce sont les courbes pour les différentes méthodes qu’on représente sur le dessin suivant, décalées
verticalement pour qu’elles partent du même point d’ordonnée nulle, afin de pouvoir comparer les pentes.
1 import matplotlib.pyplot as plt
2 import numpy as np
3
4 v = np.pi/12 + np.sqrt(3)/8 # valeur exacte
5
6
7 # méthodes déterministes
8 f = lambda t : np.sqrt(1-t**2)
9
10 a,b=0,0.5
11
12 N=11
13 Lx = np.arange(1,N+1)
14 Ln=2**Lx
15
16 Y1,Y2,Y3,Y4 = np.zeros(N),np.zeros(N),np.zeros(N),np.zeros(N)
17
18 for i in range(N):
19 n=Ln[i]
20 h = (b-a)/n
21 Y1[i] = h * sum ( f ( a+k*h ) for k in range(n) )
22 Y2[i] = h * ( (f(a)+f(b))/2 + sum ( f ( a+k*h ) for k in range(1, n) ))
23 Y3[i] = h * sum ( f ( a+ k*h + h/2 ) for k in range(n) )
24 Y4[i] = 1/3*Y2[i]+2/3*Y3[i]
25
26 Y1=abs(Y1-v)
27 Y2=abs(Y2-v)
28 Y3=abs(Y3-v)
29 Y4=abs(Y4-v)
30
31
32
33
34 # méthode de Monte-Carlo
35 from random import uniform
36 nexperiences=200
37 nmax=2**N
38 Ln2 = np.arange(1,nmax+1)
39 Lx2 = np.log2(Ln2)
8
40
41 T0 = np.zeros((nexperiences,nmax))
42 P = np.zeros(nexperiences)
43
44 for n in Ln2: # boucle sur le nombre de points aléatoires
45 for i in range(nexperiences):
46 if uniform(0,1/2)**2+uniform(0,1)**2<1: P[i]+=1
47 T0[i,n-1] = abs(1/2*P[i]/n-v)
48
49 Y5=np.array([ sum(T0[:,n-1]) for n in Ln2 ])/nexperiences
50
51
52
53 # tracé
54 plt.plot(Lx,np.log(Y1/Y1[0]),label=’rectangles’,linewidth=3)
55 plt.plot(Lx,np.log(Y2/Y2[0]),label=’trapezes’,linewidth=3)
56 plt.plot(Lx,np.log(Y3/Y3[0]),label=’points milieux’,linewidth=3)
57 plt.plot(Lx,np.log(Y4/Y4[0]),label=’Simpson’,linewidth=3)
58
59 plt.plot(Lx2,np.log(Y5/Y5[0]),linewidth=3,label=’Monte-Carlo’)
60
61 plt.legend(loc=3)
62 plt.title("etude de l’erreur, avec maximum "+str(nmax)+"\nintervalles pour les mé
thodes déterministes/points pour Monte-Carlo,\nmoyenne sur "+str(nexperiences)+"
expériences")
63 plt.show()
ˆ ˙
1
Sur le dessin, on conjecture une convergence en O ? . Bien plus mauvais que les méthodes
n
déterministes (pour cet exemple du moins. . . ).
9
2 Régression et interpolation
2.1 Un échantillon de points
12 Dessiner le nuage de points de la question précédente (comme vous avez représenté les points de la
méthode de Monte-Carlo).
1 import matplotlib.pyplot as plt
2 plt.plot(Xechant,Yechant,"o",ms=10)
3 plt.show()
10
14 En appelant P le résultat calculé par lagrange, que renvoient P[2] ? et P(3) ?
P[i] est le coefficient de degré i. P(x) est l’évaluation en x.
1 >>> P[7]
2 1199.0497563592905
3 >>> P(3)
4 23.663747379993854
17 ‹ Ecrire votre propre fonction monlagrange qui renvoie la fonction polynômiale en prenant les
mêmes arguments que la fonction lagrange prédéfinie (je ne demande quand même pas de renvoyer un
polynôme du type poly1d, mais je veux quand même une fonction qui renvoie une fonction).
Remarque pour les optionnaires : en Caml, avec la curryfication, on aurait pu définir une fonction
monlagrange X Y x, qu’il est possible d’appeler avec un seul argument (sans préciser le deuxième) ; on
obtient alors une fonction de x !
1 def monlagrange(X,Y):
2 """ renvoie la fonction polyn^
omiale associée au polyn^
ome d’interpolation de
Lagrange """
3 n = len(X)
4
5 def fonction(x):
6 res=0
7 for i in range(n):
8 terme=1
9 for j in range(n):
10 if i!=j:
11 terme*=(x-Xechant[j])/(Xechant[i]-Xechant[j])
12 res+=Yechant[i]*terme
13
11
14 return( res)
15
16 return fonction
17
18 LX=np.linspace(0,3,100)
19 plt.plot(LX,monlagrange(Xechant,Yechant)(LX),linewidth=3,label=’monlagrange’)
20 import scipy.interpolate as interpol
21 plt.plot(LX,interpol.lagrange(Xechant,Yechant)(LX),linewidth=3,label=’fonction de
scipy’)
22 plt.legend()
23 plt.show()
18 La commande polyfit du module numpy (sur lequel vous regarderez l’aide) permet d’obtenir un
polynôme de degré fixé passant au plus près d’une famille de points (au sens des moindres carrés, hors-
programme, on ne cherchera pas à comprendre l’algorithme). Calculer le polynôme de degré 2 approchant
au mieux vos 10 points. Quel est le type du résultat renvoyé ?
Voici l’aide correspondante.
1 polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False)
2 Least squares polynomial fit.
3
4 Fit a polynomial ‘‘p(x) = p[0] * x**deg + ... + p[deg]‘‘ of degree ‘deg‘
5 to points ‘(x, y)‘. Returns a vector of coefficients ‘p‘ that minimises
6 the squared error.
La fonction renvoie un tableau numpy de coefficients d’un polynôme (d’abord le coefficient dominant,
etc., et à la fin le terme constant).
1 import numpy as np
2 Xechant = np.linspace(0,3,10)
3 Yechant = (2*Xechant**2 + Xechant + 3) + np.random.uniform(-2,2,10)
4
5 L=np.polyfit(Xechant,Yechant,2)
6 print(L,type(L))
1 [ 1.9518499 0.80298038 3.8147304 ] <class ’numpy.ndarray’>
2 2
3 1.952 x + 0.803 x + 3.815 <class ’numpy.lib.polynomial.poly1d’>
12
6 plt.plot(TX,P(TX),linewidth=3)
7
8 plt.plot(Xechant,Yechant,"o",ms=10)
9 plt.show()
20 ‹ Ecrivez vous-même une fonction transform_poly qui transforme un polynôme donné sous forme
de liste ou de tableaux numpy (d’abord le coefficient dominant, etc., et à la fin le terme constant) en
fonction polynomiale.
1 import numpy as np
2
3 def transform_poly(L):
4 d=len(L)-1
5 return lambda x:sum( x**(d-i)*L[i] for i in range(len(L)) )
6 print(transform_poly([1,2,3])(4)) # x**2+2*x+3 avec x=4
7
8 # ou alors:
9 def transform_poly2(L):
10 d=len(L)-1
11 def fonction(x):
12 res=0
13 for i in range(len(L)):
14 res+= x**(d-i)*L[i]
15 return res
16 return fonction
17 print(transform_poly2([1,2,3])(4)) # x**2+2*x+3 avec x=4
2.4 Comparaison
21 Faire apparaı̂tre sur un même dessin les points d’interpolation et le graphe des deux polynômes de
régression et d’interpolation.
1 import numpy as np
2 import scipy.interpolate as interpol
3 import matplotlib.pyplot as plt
4
5 for position in [221,222,223,224]:
6 plt.subplot(position)
7
8 Xechant = np.linspace(0,3,10)
9 Yechant = (2*Xechant**2 + Xechant + 3) + np.random.uniform(-2,2,10)
10 # la fonction polynomiale des moindres carres
11 # polynome est le polynome donne par ses coefficients
12 polynome=np.poly1d(np.polyfit(Xechant,Yechant,2))
13 print("polyn^
ome de régression:\n",polynome)
14
15 # polynome interpolateur de Lagrange
16 polynome2=interpol.lagrange(Xechant,Yechant)
17 print("polyn^
ome interpolateur de Lagrange:\n",polynome2)
13
18 print(polynome2(Xechant),Yechant)
19
20 # dessins
21 X=np.linspace(0,30,1000)
22 print(polynome2(Xechant),Yechant)
23 plt.plot(X,polynome(X),’g’,linewidth=5,label=’moindres carrés’)
24 plt.plot(X, polynome2(X),’b’,linewidth=5,label=’Lagrange’)
25 plt.plot(Xechant,Yechant,’or’,ms=20,label=’echantillon’)
26
27 plt.axis([0,3,0,25])
28
29 plt.legend(loc=2)
30
31 plt.show()
Figure 4 – Polynôme de régression et polynôme d’interpolation sur un même dessin, pour différents jeux
de points
14