Romberg PDF
Romberg PDF
Romberg PDF
1. Introduction
On s’intéresse au calcul approchée d’une intégrale d’une fonction d’une variable réelle,
sur un intervalle fini où la fonction est définie en tout point. On verra dans un premier
temps la méthode des trapèzes itérative, qui consiste à appliquer la méthode des trapèzes
pour des intervalles de plus en petits jusqu’à satisfaire une tolérance demandée. Dans
un second temps, nous aborderons la méthode de Romberg, qui consiste à faire une
extrapolation polynomiale à partir des approximations obtenues par la méthode des
trapèzes pour différentes largeurs d’intervalles. La méthode de Romberg permet, pour des
fonctions assez régulières, d’obtenir une accélération très importante de la convergence.
N = 2p p = 0, 1, 2, . . .
b−a
hp =
N
x0 = a
xN = b
xk = x0 + kh k = 0, 1, 2, . . . N
f4
f3
f1 f2
f0
x
x0 x1 x2 x3 x4
a b
La formule des trapèzes consiste à approximer l’intégrale sur chaque intervalle par l’aire
du trapèze :
Z xk+1
1 1
f (x) dx ' hfk + h (fk+1 − fk ) = h (fk + fk+1 ) (2)
xk 2 2
On obtient ainsi une approximation de l’intégrale, pour un indice p :
1 1
Ip = hp f0 + f1 + f2 + . . . + fN −2 + fN −1 + fN = hp Sp (3)
2 2
Mis à part le premier et le dernier terme, correspondant à x = a et x = b, il s’agit de
calculer la somme des fk .
Cette approximation de l’intégrale étant calculée, on obtient une meilleure approxi-
mation en divisant h par deux, c’est-à-dire en ajoutant les points milieux des intervalles.
La figure suivante montre le passage de p = 2 à p = 3 :
Frédéric Legrand Licence Creative Commons 3
f8
f7
f6
f2 f3 f4 f5
f1
f0
x3 x4 x5 x6 x7 x
x0 x1 x2 x8
a b
On remarque que la somme Sp peut être réutilisée pour calculer Sp+1 . Il suffit d’ajouter
les points milieux, encadrés sur la figure.
Pour calculer une approximation de l’intégrale, on choisit une tolérance puis on
procède par itérations. La première somme à calculer est :
1
S0 = (f (a) + f (b)) (4)
2
Connaissant la somme Sp , on calcule la somme Sp+1 en ajoutant la somme des fk des
points milieux. L’itération est stoppée lorsque la valeur absolue de la différence des deux
évaluations consécutives de l’intégrale est inférieure à la tolérance :
2.b. Implémentation
Les fonctions sont définies dans une classe :
class Romberg:
def __init__(self,f,a,b):
self.f = f
self.a = a
self.b = b
self.p = 0
self.N = 1
self.S = 0.5*(f(a)+f(b))
self.h = (b-a)
self.I = self.S*self.h
self.I_last = self.I
self.n_eval = 0
def iteration(self):
Frédéric Legrand Licence Creative Commons 4
self.n_eval += self.N
x = self.a+self.h*0.5
somme = self.f(x)
for k in range(self.N-1):
x += self.h
somme += f(x)
self.N *= 2
self.p += 1
self.S += somme
self.h *= 0.5
self.I_last = self.I
self.I = self.h*self.S
def iterations(self,P):
I = [self.I]
h = [self.h]
while self.p<P:
self.iteration()
I.append(self.I)
h.append(self.h)
return (numpy.array(h),numpy.array(I))
def trapezes(self,epsilon):
I = [self.I]
h = [self.h]
self.iteration()
while abs(self.I-self.I_last)>epsilon:
self.iteration()
I.append(self.I)
h.append(self.h)
return (numpy.array(h),numpy.array(I))
def romberg(self,epsilon):
jmax = 20
A=numpy.zeros((jmax+1,jmax+1))
A[0][0] = self.I
self.iteration()
A[1][0] = self.I
correction = (A[1][0]-A[0][0])/3
A[1][1] = A[1][0] + correction
j = 2
while abs(correction) > epsilon:
self.iteration()
A[j][0] = self.I
for i in range(1,j+1):
correction = (A[j][i-1]-A[j-1][i-1])/(4**i-1)
A[j][i] = A[j][i-1] + correction
j += 1
Frédéric Legrand Licence Creative Commons 5
return (A[0:j-1,0:j-1],A[j-1][j-1])
Voici l’erreur :
print(I[-1]-1.0/6)
--> 2.4835268314093994e-08
print(romberg.n_eval)
--> 4095
3. Méthode de Romberg
3.a. Principe
Considérons l’application de la méthode des trapèzes jusqu’au rang p, par exemple
p = 3, et traçons l’estimation de l’intégrale en fonction de h2 .
romberg = Romberg(f,0,1)
(h,I) = romberg.iterations(3)
figure(figsize=(8,6))
plot(h*h,I,"o")
xlabel("$h^2$",fontsize=18)
ylabel("$I$",fontsize=18)
axis([0,1.5,0,1])
grid()
Frédéric Legrand Licence Creative Commons 7
A0,0
A1,0 A1,1
(7)
A2,0 A2,1 A2,2
A3,0 A3,1 A3,2 A3,3
Le premier terme correspond à la première estimation de l’intégrale A0,0 = I0 . Le premier
élément de la deuxième ligne est la seconde estimation de l’intégrale A1,0 = I1 . À partir
des deux points (h20 , A0,0 ) et (h21 , A1,0 ), on effectue une extrapolation en h2 = 0 par un
Frédéric Legrand Licence Creative Commons 8
def f(x):
return x**5
romberg = Romberg(f,0,1)
(h,I) = romberg.trapezes(1e-7)
print(I[-1]-1.0/6)
--> 2.4835268314093994e-08
print(romberg.n_eval)
--> 4095
romberg = Romberg(f,0,1)
(A,I) = romberg.romberg(1e-7)
print(I-1.0/6)
--> 0.0
Frédéric Legrand Licence Creative Commons 9
print(romberg.n_eval)
--> 7
Avec la méthode des Trapèzes itérative, 4095 évaluations de la fonction sont né-
cessaires pour arriver à une erreur de l’ordre de 10−8 . Avec la méthode de Romberg,
seulement 7 évaluations sont nécessaires pour arriver à une erreur inférieure à la préci-
sion des nombres flottants (il s’agit bien sûr d’un cas très favorable). Voici la matrice A,
qui permet de voir les extrapolations effectuées :
print(A)
--> array([[ 0.5 , 0. , 0. ],
[ 0.265625 , 0.1875 , 0. ],
[ 0.19238281, 0.16796875, 0.16666667]])
Le premier élément de la troisième ligne est obtenu avec la formule des trapèzes pour
N = 4. L’extrapolation à 3 points, par un polynôme de degré 2, permet d’obtenir la
valeur exacte (à la précision des flottants près). Sur cet exemple, l’expression de Ip en
fonction de h2 est probablement un polynome de degré 2.
Voyons un autre exemple plus intéressant, où l’on ne connaît pas d’expression analy-
tique de la primitive :
Z z
2
erf(z) = √ exp(−x2 ) dx (11)
π 0
La fonction scipy.special.erf(z) fournit sa valeur. On fait le test pour z = 1.
print(I[-1]-numpy.sqrt(numpy.pi)/2*erf(1))
--> -1.4618215860018324e-08
print(romberg.n_eval)
--> 2047
romberg = Romberg(f,0,1)
(A,I) = romberg.romberg(1e-7)
print(I-numpy.sqrt(numpy.pi)/2*erf(1))
--> 2.8266744500626828e-10
print(romberg.n_eval)
--> 15
print(A)
--> array([[ 0.68393972, 0. , 0. , 0. ],
[ 0.73137025, 0.74718043, 0. , 0. ],
[ 0.7429841 , 0.74685538, 0.74683371, 0. ],
[ 0.74586561, 0.74682612, 0.74682417, 0.74682402]])
Le résultat est obtenu avec une extrapolation par un polynôme de degré 3.
Considérons l’intégrale suivante :
Z 1√
π
1 − x2 dx = (12)
0 4
from scipy.special import erf
def f(x):
return numpy.sqrt(1-x*x)
romberg = Romberg(f,0,1)
(h,I) = romberg.trapezes(1e-7)
print(I[-1]-numpy.pi/4)
--> -4.9563892989823444e-08
print(romberg.n_eval)
--> 32767
romberg = Romberg(f,0,1)
(A,I) = romberg.romberg(1e-7)
print(I-numpy.pi/4)
--> -0.00018949376813126584
print(romberg.n_eval)
--> 63
Pour cette intégrale, l’erreur finale obtenue avec la méthode de Romberg est beaucoup
plus grande que la tolérance demandée, ce qui signifie que l’extrapolation ne fonctionne
pas bien. On peut essayer de réduire la tolérance :
romberg = Romberg(f,0,1)
(A,I) = romberg.romberg(1e-15)
print(I-numpy.pi/4)
--> -4.6233250450278263e-08
print(romberg.n_eval)
--> 16383
On arrive à la même erreur que la méthode des trapèzes, mais le nombre d’évaluations
n’est que deux fois moindre. Pour cette fonction, la méthode de Romberg est donc peu
efficace.
En principe, la méthode de Romberg fonctionne avec une grande efficacité lorsque la
fonction à intégrer est infiniment dérivable sur l’intervalle d’intégration. Ce n’est pas le
cas du dernier exemple, dont la dérivée n’est pas définie en x = 1.