|
|
Soit un polynôme de degré :
On cherche ici à évaluer la valeur du polynôme pour une valeur donnée .
Pour ce faire, on peut factoriser le polynôme sous la forme :
 |
(1) |
où est un polynôme de degré et une constante scalaire.
Sous cette forme on voit que et que
.
Le polynôme est bien sur différent du polynôme mais leur valeurs
coïncident quand prends la valeur .
Soit les coefficients du polynôme :
 |
(2) |
en développant l'équation (1) on obtient facilement une équation récurrente
permettant de calculer les coefficients du polynôme :
pour |
(3) |
La valeur de est donnée par . On notera que l'on peut initialiser la récurrence
par
ou quitte à rajouter un point par .
Cet Algorithme s'appelle algorithme d'Horner, il revient à évaluer la valeur du polynôme
en le factorisant sous la forme :
Nous avons noté que la dérivée de au point s'obtient en évaluant
. Il suffit donc de réappliquer l'algorithme d'Horner au polynôme
pour évaluer .
->function [Q,R]=Horner(P,xi)
 Évalue le polynôme P au point xi
-> [lhs,rhs]=argn(0);
-> a=coeff(P);
 Les coefficients du polynôme
-> na=size(a,'*');
-> b=ones(a);
 Espace pour stocker les coefficient du polynôme Q et la valeur R=P(xi)
-> b($)=a($);
 Initialisation
-> for i=na-1:-1:1
-> b(i)= b(i+1)*xi+ a(i)
 Les coefficients du polynôme Q
-> end
-> if lhs==2 then
-> R = b(1);
-> Q=poly(b(2:$),'x','coeffs');
 Construction de Q
-> else
-> Q= b(1)
-> end
->endfunction
->P=poly(1:3,'x','coeffs');
->xi=0.5;
->[Q,R]=Horner(P,xi);
->P2= Q*poly(xi,'x','roots')+R
 On vérifie le lien entre P, Q et R
P2 =
2
1 + 2x + 3x
->if norm(coeff(P-P2)) > %eps then pause;end
->if norm( R - horner(P,xi)) > %eps then pause;end
 Contrôle avec la fonction Scilab horner
->[Pprimxi]=Horner(Q,xi);
 Calcul de
->if norm( Pprimxi - horner(derivat(P),xi)) > %eps then pause;end
 Contrôle avec les fonctions Scilab horner et derivat
En fait, on peut calculer directement les valeurs et sans
passer par l'intermédiaire de la construction du polynôme , c'est à dire sans
stocker les coefficients du polynôme . On écrit conjointement les
deux algorithmes de Horner et pour faciliter la gestion des indices on initialise
le deuxième avec plutôt que
. Ainsi les deux vecteurs de
coefficients à calculer auront même taille :
le calcul du couple permet d'obtenir le couple de valeurs
.
En généralisant cette idée on peut calculer les -dérivées successives du polynôme
en un point . Posons
avec
.
Par un algorithme de Horner on peut calculer en procédant comme dans (3)
les valeurs pour
. Il est ensuite facile de voir par
dérivation composées que :
pour |
(4) |
et d'obtenir ainsi les dérivées successives de en .
->function [val]=Hornerp(P,xi,p)
 Évalue
 pour
-> V=zeros(p,1);
-> a=coeff(P);
-> V(1)=a($);
 Initialisation
-> M=diag(xi*ones(1,p))+ diag(ones(1,p-1),-1);
-> n=size(a,'*');
-> for i=1:n-1
-> V=M*V + [a(n-i);zeros(p-1,1)],
 Horner simultané
-> end
-> F=ones(p,1);
-> for i=2:p-1 do F(i+1)=F(i)*i ; end
 Calcul des
-> val = V.* F;
 Les dérivées de P en
->endfunction
->P=poly(1:8,'x','coeffs');
->xi=1.5 ;
->p=10;
->val=Hornerp(P,xi,p);
->Q=P;
->for i=1:p-1, Q=[Q;derivat(Q($))];end
 Les dérivées succéssives de P
->if norm(val -horner(Q,xi)) > %eps then pause;end
 Vérifions le résultat
Supposons que l'on ait estimé un zéro du polynôme ,
dans la décomposition de
on doit avoir et la méthode de
Horner permet d'éliminer la racine du polynôme puisqu'elle donne
les coefficients du polynôme . Mais si est une racine de on
doit aussi avoir dans l'algorithme de Horner.
On peut donc utiliser la récurrence (3) à partir de de
(méthode forward) ou à partir de méthode backward.
Si l'on cherche à éliminer successivement les racines d'un polynôme en éliminant
à chaque fois la plus grande racine, la méthode backward donne une meilleur stabilité
numérique.
On peut comparer les deux méthodes avec le polynôme
en utilisant
la fonction roots de Scilab pour estimer les valeurs des racines.
->function [Q]=deflate_forward(P,xi)
 Élimine la racine xi méthode forward
-> a=coeff(P);
 Les coefficients du polynôme
-> na=size(a,'*');
-> b=ones(a);
 Espace pour stocker les coefficient du polynôme Q et la valeur R=P(xi)
-> b($)=a($);
 Initialisation
-> for i=na-1:-1:1
-> b(i)= b(i+1)*xi+ a(i)
 Les coefficients du polynôme Q
-> end
-> Q=poly(b(2:$),'x','coeffs');
 Construction de Q
->endfunction
->function [Q]=deflate_backward(P,xi)
 Élimine la racine xi méthode backward
-> a=coeff(P);
 Les coefficients du polynôme
-> na=size(a,'*');
-> b=ones(a);
 Espace pour stocker les coefficient du polynôme Q et la valeur R=P(xi)
-> b(1)=0;
 Initialisation
-> for i=1:na-1
-> b(i+1)= (b(i)-a(i))/xi
 Les coefficients du polynôme Q
-> end
-> Q=poly(b(2:$),'x','coeffs');
 Construction de Q
->endfunction
->n=13;
->r= 2.^(-[0:n]);
->P=poly(r,'x','roots');
->rr=roots(P)
rr =
! 0.0001221 !
! 0.0002441 !
! 0.0004883 !
! 0.0009766 !
! 0.0019531 !
! 0.0039062 !
! 0.0078125 !
! 0.015625 !
! 0.03125 !
! 0.0625 !
! 0.125 !
! 0.25 !
! 0.5 !
! 1. !
->maxi(abs(rr'-r($:-1:1)))
ans =
4.441D-16
->P1=P;
->r3=zeros(r);
->for i=1:n+1
-> r3(i)=maxi(real(roots(P1)));
-> P1=deflate_backward(P1,r3(i));
 On élimine la plus grande racine
->end
->maxi(abs(r3-r))
 Test du résultat
ans =
6.661D-16
->P1=P;
->r4=zeros(r);
->for i=1:n+1
-> r4(i)=maxi(real(roots(P1)));
-> P1=deflate_forward(P1,r4(i));
 On élimine la plus grande racine
->end
->maxi(abs(r4-r))
 Test du résultat
ans =
0.0408097
L'équation (3) permettant de calculer les coefficients
du polynôme peut-être vu comme un système dynamique discret.
La stabilité de ce système ou de celui obtenu pour le calcul simultané de
et de ses dérivées au point dépend de . Pour le
système est instable et on va donc pour des polynômes de grande taille
amplifier les erreurs de calcul si l'on utilise (3).
Mais on peut remarquer que s'écrit aussi :
avec |
(5) |
Pour une valeur de telle que . on se ramène à un système dynamique
stable en utilisant l'algorithme de Horner pour l'évaluation de et de ses dérivées en et
on utilise la relation (5) pour les relier aux valeurs de et de ses
dérivées en .
On utilise ici la méthode de Newton pour trouver les zéros d'un polynôme.
Soit un polynôme de degré , on utilise pour trouver les
zéros l'algorithme de Newton qui consiste à effectuer les itérations suivantes :
 |
(6) |
Il faut pouvoir évaluer la valeur du polynôme et de sa dérivée au point courant
et nous avons vu qu'un algorithme d'Horner permet d'évaluer ces deux
quantités.
La convergence de l'algorithme de Newton dans ce cas particulier est donnée
par le théorème suivant :
Théorème 1
Soit  un polynôme de degré  dont toutes les racines
sont réelles. La méthode de Newton donne une suite strictement décroissante pour
 où  est la plus grande racine de  .
On trouvera la preuve de la convergence dans [1].
Pour implémenter cet algorithme il faut trouver un majorant de . Plusieurs
formules de majoration sont données dans la littérature. Par exemple :
si |
(7) |
si |
(8) |
->function xn=newton(P,x,prec)
-> while %t
-> val=Hornerp(P,x,2);
val=[P(x),P'(x)]
-> xn= x -val(1)/val(2);
-> if norm(xn-x) <= prec*norm(x) then
-> break;
-> end
-> x=xn;
-> end
->endfunction
->n=13;
->r= 2.^(-[0:n]);
->P=poly(r,'x','roots');
 Le polynôme test
->a=coeff(P);
->xd=max([1+abs(a(2:$-1)/a($)),abs(a(1)/a($))]) ;
 Un majorant de la plus grande racine
->y1=newton(P,xd,%eps)
y1 =
1.
En éliminant à chaque fois la plus grande racine trouvée on peut chercher
toutes les racines du polynôme . On peut constater dans le code
qui suit que la méthode d'élimination choisie (forward ou backward)
n'est pas anodine !
y1 =
1.
->y=y1; rnf= zeros(r); rnf(1)=y; Q=P;
->for i=2:4
 Problème au dela de
-> Q=deflate_forward(Q,y);
 On élimine la plus grande racine
-> y=newton(Q,y,%eps);
 Évaluation de la plus grande racine
-> rnf(i)=y;
->end
->y=y1;rnb= zeros(r); rnb(1)=y; Q=P;
->for i=2:(n+1)
-> Q=deflate_backward(Q,y);
 On élimine la plus grande racine
-> y=newton(Q,y,%eps);
-> rnb(i)=y;
->end
->if norm(abs(r-rnb)) > 10*%eps then pause;end
Plutôt que d'essayer de simplifier le polynôme on peut utiliser
la méthode de Maehly (1954) qui consiste à appliquer la méthode de
Newton à la fraction rationnelle
plutôt que d'éliminer la
racine du polynôme . Ainsi si l'on a estimé les premières
racines du polynôme, notées ,
on cherche la -ème racine par l'algorithme de Newton :
avec |
(9) |
Pour initialiser l'algorithme, on peut utiliser la dernière racine trouvée (à epsilon près
pour éviter une division par zéro).
->function y=newton(P,x,r,prec)
-> while %t
-> val=Hornerp(P,x,2);
-> if r<>[] then
-> w=sum(val(1)./(x-r));
r
-> else
-> w=0.0;
-> end
-> xn= x -val(1)/(val(2)-w);
-> if norm(xn-x) <= prec*norm(x) then
-> break;
-> end
-> x=xn;
-> end
-> y=xn;
->endfunction
->n=13;r= 2.^(-[0:n]);P=poly(r,'x','roots');
->y=newton(P,10,[],%eps);
->rn= zeros(r); rn(1)=y;
->for i=2:n+1
-> y=newton(P,y-100*%eps,rn(1:i-1),10*%eps);
-> rn(i)=y;
->end
->if maxi(abs(rn-r)) > 10*%eps then pause;end
- 1
-
J. Stoer and R. Burlisch.
Introduction to Numerical Analysis.
Springer-Verlag, 1980.
|