intt_romberg(f,a,b,n):={ local l,l0,l1,puis,k,j; l:=trapezel(f,a,b,n); //debut de l'acceleration de Romberg l0:=[l[0]]; //on fait n accelerations for (k:=1;k<=n;k++) { l1:=[l[k]]; //calcul des T_{k,j} (j=1..k) dans l1 for (j:=1;j<=k;j++) { puis:=2^(2*j); l1[j]:=(puis*l1[j-1]-l0[j-1])/(puis-1); } l0:=l1; } return l1; }On applque l'algorithme de Romberg à
ptmilieul(f,a,b,n):={ local s,puiss3,k,lt,s1,j; s:=evalf(f((a+b)/2)); puiss3:=1; lt:=[s*(b-a)]; for (k:=1;k<=n;k++) { s1:=0.0; for (j:=0;j<puiss3;j++) { s1:=s1+f(a+(6*j+1)*(b-a)/(6*puiss3))+f(a+(6*j+5)*(b-a)/(6*puiss3)); } s:=s+s1; puiss3:=3*puiss3; lt:=concat(lt,s*(b-a)/puiss3); } return lt; }On procède comme précédemment en remplacant les puissances de 2 par des puissances de 3 et le calcul de T(h) par celui de M(h).
intm_romberg(f,a,b,n):={ local l,l0,l1,puis,k,j; l:=milieul(f,a,b,n); //debut de l'acceleration de Romberg l0:=[l[0]]; //on fait n accelerations for (k:=1;k<=n;k++) { l1:=[l[k]]; //calcul des M_{k,j} (j=1..k) dans l1 for (j:=1;j<=k;j++) { puis:=3^(2*j); l1[j]:=(puis*l1[j-1]-l0[j-1])/(puis-1); } l0:=l1; } return l1; }
On peut raffiner en
calculant
dans la boucle (en rajoutant puis:=1;
avant for (j:=1;j<=k;j++).. et en remplacant
par puis:=puis*4;) et aussi
en n'utilisant qu'une seule liste...
On met ces programmes successivement
dans un niveau éditeur de programmes (que l'on ouvre avec Alt+p), puis
on les teste et on les valide avec OK.
On tape (on partage [0;1] en 23=8 parties égales) :
intt_romberg(x->x^
2+1,0,1,3)
On obtient :
[[1.3359375,1.33333333333,1.33333333333,1.33333333333]
On sait que int(x^
2+1,x,0,1)=
=1.3333333333
On tape (on partage [0;1] en 24=16 parties égales) :
intt_romberg(exp,0,1,4)
On obtient :
1.71884112858,1.71828197405,1.71828182868,
1.71828182846,1.71828182846]
On sait que int(exp(x),x,0,1)=e-1=1.71828182846.
Dans la pratique, l'utilisateur ne connait pas la valeur de n qui donnera un
résultat correct sans faire trop de calculs. C'est pourquoi, on va
faire le calcul de la méthode des trapèzes au fur et à mesure
et changer le test d'arrêt : on s'arrête quand la différence de
deux termes consécutifs est en valeur absolue plus petit que epsi.
intrap_romberg(f,a,b,epsi):={ local l0,l1,puis,puiss2,k,j,s,s1,test; //initialisation on a 1 intervalle s:=evalf((f(a)+f(b))/2); puiss2:=1; l0:=[s*(b-a)]; k:=1; test:=1; while (test>epsi) { //calcul de la methode des trapezes avec 2^k intervalles s1:=0; for (j:=0;j<puiss2;j++) { s1:=s1+f(a+(2*j+1)*(b-a)/(2*puiss2)); } s:=s+s1; puiss2:=2*puiss2; l1:=[s*(b-a)/puiss2]; //debut de l'acceleration de Romberg //calcul des T_{k,j} (j=1..k) dans l1 j:=1; while ((test>epsi) and (j<=k)) { puis:=2^(2*j); l1[j]:=(puis*l1[j-1]-l0[j-1])/(puis-1); test:=abs(l1[j]-l1[j-1]); j:=j+1; } l0:=l1; k:=k+1; } return [k-1,j-1,l1[j-1]]; }On renvoie la liste [p, q, val] où val = Tq, p (p=le nombre d'accélérations).
On peut aussi appliquer l'algorithme de Romberg à M(h) on le même programme en remplacant les puissances de 2 par des puissances de 3 et le calcul de T(h) par celui de M(h).
intmili_romberg(f,a,b,epsi):={ local l0,l1,puis,puiss3,k,j,s,s1,test; //initialisation on a 1 intervalle s:=evalf(f((a+b)/2)); puiss3:=1; l0:=[s*(b-a)]; k:=1; test:=1; while (test>epsi) { //calcul de la methode du point milieu avec 3^k intervalles s1:=0; for (j:=0;j<puiss3;j++) { s1:=s1+f(a+(6*j+1)*(b-a)/(6*puiss3))+ f(a+(6*j+5)*(b-a)/(6*puiss3)); } s:=s+s1; puiss3:=3*puiss3; l1:=[s*(b-a)/puiss3]; //debut de l'acceleration de Romberg //calcul des T_{k,j} (j=1..k) dans l1 j:=1; while ((test>epsi) and (j<=k)) { puis:=3^(2*j); l1[j]:=(puis*l1[j-1]-l0[j-1])/(puis-1); test:=abs(l1[j]-l1[j-1]); j:=j+1; } l0:=l1; k:=k+1; } return [k-1,j-1,l1[j-1]]; }On tape :