Lyc´ee Thiers - MPSI-3

publicité
Lycée Thiers
TP PYTHON - 10
Les fonctions polynomiales, c’est la classe !
1. Introduction
Si n est un entier naturel non nul et a0 , ..., an−1 sont des réels, on appelle fonction polynomiale ou, plus
briévement, polynôme, associé aux coefficients a0 , ..., an−1 , l’application P de R dans R définie par :
∀x ∈ R, P(x) =
n−1
X
ak xk .
k=0
Si l’on note X la fonction x 7→ x de R dans R, on peut alors écrire : P =
n−1
X
ak Xk . Xk désigne ici la
k=0
fonction x 7→ xk .
On montre que la somme, le produit, la composée de deux fonctions polynomiales est une fonction
polynomiale, la dérivée, les primitives d’une fonction polynomiale sont polynomiales.
Ces propriétés suffisent à justifier l’intérèt de définir une classe polynome qui modélise ces fonctions.
2. Définition d’une classe polynome
On souhaite construire un objet de la classe polynome à partir d’un tuple de nombres. L’entête de la
définition de cette classe sera class polynome ou class polynome(object).
[Qu. 1] Compléter la définition de cette classe avec la surchage de la méthode spéciale __init__, qui
servira à créer et modifier l’attribut coeffs des objets de cette classe. On pourra débuter l’implémentation de la surcharge par :
def __init__ (self ,*a)
où a est le tuple des coefficients qui définissent le polynôme.
Faisons quelques essais :
>>>P= polynome (1 ,1 ,1)
>>>P. coeffs
[1, 1, 1]
>>> P
<__main__ . polynome object at 0 x1029fb850 >
TP PYTHON - 10
2
[Qu. 2]
1) Tester les commandes suivantes :
>>> P= polynome (1 ,1)
>>> Q= polynome (1 ,1)
>>> P==Q
Comment expliquer la réponse de Python ?
2) Soit P et Q deux polynômes associés aux coefficients a0 , ..., an−1 et b0 , ..., bm−1 respectivement. Si
n ≤ m, on montre que P = Q si et seulement si, pour tout k ∈ [[0, n − 1]], ak = bk et pour tout
k ∈ [[n, m − 1]], bk = 0.
L’exemple précédent montre qu’il est donc indispensable de surcharger la fonction spéciale __eq__
pour obtenir une réponse en accord avec la théorie.
Ecrire cette méthode __eq__ pour obtenir par exemple :
>>> P= polynome (1 ,1 ,0 , -2)
>>> Q= polynome (1 ,1 ,0 , -2 ,0)
>>> P==Q
True
On débutera la définition de cette surcharge par :
def __eq__ (self ,Q):
le paramètre self désignant le premier polynôme du test d’égalité et Q le second.
[Qu. 3] On voudrait un affichage des polynomes assez proche de l’habitude mathématique. Cela doit
donner pour le polynome précédent, l’affichage suivant :
>>> P
1+X+X**2
et
>>>Q= polynome (1 ,0 , -1 ,0 ,2)
>>> Q
1-X**2+2 X**4
Pour cela on doit surcharger la méthode spéciale __repr__. Une première version de cette méthode
pourrait ressembler à ceci :
def __repr__ (self):
n=len(self. coeffs )
res=’’
k=0
while (k<n):
while (k<n)and(self. coeffs [k ]==0) :
k+=1
if (k<n):
res=res+’+’ +str(self. coeffs [k])+’X** ’+str(k)
TP PYTHON - 10
3
k+=1
if res == ’’:
res=’0’
return res
Essayons cette représentation :
>>> P= polynome (1 ,0 , -1 ,0 ,2)
>>> P
+1X**0+ -1X **2+2 X**4
1) Identifier au moins trois aspects non satisfaisants de cette représentation.
2) Modifier cette surchage pour obtenir la représentation souhaitée.
3) Ecrire une fonction polyGeo de n qui affiche le polynôme associé aux coefficients ak = (−1)n−k
pour k ∈ [[0, n]].
Vous devez obtenir :
>>> polyGeo (10)
1-X+X**2 -X**3+X**4 -X**5+X**6 -X**7+X**8 -X**9+X**10
3. Les opérations arithmétiques
L’addition. Soit P et Q deux polynômes tels que P =
n−1
X
ak Xk et Q =
k=0

n−1
m−1

X
X


 (a + b )Xk +

bk X k
k
k



 k=0
k=n
P+Q=
m−1
n−1

X
X




(ak + bk )Xk +
ak X k



k=0
m−1
X
bk Xk . On a alors :
k=0
si n ≤ m
sinon.
k=m
[Qu. 4]
1) Essayer les commandes suivantes :
>>> P= polynome (1 ,1)
>>> Q= polynome (1 ,1 ,0 , -2)
>>> P+Q
2) Le résultat ne correspond pas à ce que l’on souhaite, d’où la nécessité de redéfinir l’opérateur
d’addition via la méthode __add__. Implémenter cette surcharge. Vérifier la validité de votre
méthode en obtenant l’affichage suivant dans le shell :
>>>P= polynome (1 ,2 ,3 , -4)
>>> P
1+2X+3X**2 -4X**3
>>> Q= polynome (3 , -2 ,1)
>>> Q
3-2X+X**2
>>> P+Q
4+4X**2 -4X**3
TP PYTHON - 10
4
ou
>>> P= polyGeo (5)
>>> P
-1+X-X**2+X**3 -X**4+X**5
>>> Q= polyGeo (8)
>>> Q
1-X+X**2 -X**3+X**4 -X**5+X**6 -X**7+X**8
>>> P+Q
X**6 -X**7+X**8
3) La méthode spéciale __sub__ permet de redéfinir la soustraction. Le faire et tester cet opérateur.
Un exemple :
>>>P= polynome (1 ,2 ,3 , -4)
>>> P
1+2X+3X**2 -4X**3
>>> Q= polynome (3 , -2 ,1)
>>> Q
3-2X+X**2
>>> P-Q
-2+4X+2X**2 -4X**3
>>> P-P
0
La multiplication scalaire. Si P est un polynôme et α un réel, la fonction x 7→ αP(x) est un polynôme
et se note αP.
Python fournit une méthode spéciale __rmul__ ( pour right multiplication), qui, si P est un objet et a
un objet d’une autre classe, déclenche cette méthode de P lorsque l’objet a*P est créé.
Voici un exemple d’utilisation de cette multiplication scalaire :
>>> P= polynome (1 , -2 ,1)
>>> -2*P
-2+4X-2X**2
[Qu. 5] Ecrire la définition de cette méthode pour que, si l’objet P représente le polynôme P et a le
réel α, l’objet a*P représente le polynôme αP.
Le produit. Reprenons nos deux polynômes, P =
n−1
X
ak X et Q =
k
k=0
m−1
X
bk Xk . Naturellement, la fonction
k=0
produit, PQ, c’est à dire celle qui à tout x réel associe P(x)Q(x) est une fonction polynomiale et vérifie :
PQ =
n+m−2
X
ck Xk
k=0
les réels ck s’exprimant à partir des réels a0 , ..., an et b0 , ..., bm . Précisément :
∀k ∈ [[0, n + m − 2]] , ck =
min(n−1,k)
X
ai bk−i
i=max(k−m+1,0)
Par exemple, pour k = 0, c0 = a0 b0 et pour k = n + m − 2, cn+m−2 = an−1 bm−1 .
TP PYTHON - 10
5
[Qu. 6]
1) C’est la méthode spéciale __mul__ qui va nous permettre de définir notre produit de polynômes.
Redéfinir cette méthode pour qu’elle donne le résultat attendu lorsqu’on effectue le produit de
deux polynômes. Vous devriez obtenir, par exemple :
>>> Q= polynome (1 , -2 ,1)
>>> Q
1-2X+X**2
>>> P= polynome (1 ,1)
>>> P
1+X
>>> P*Q
1-X-X**2+X**3
>>>P*Q==Q*P
True
2) Si n est un entier et P un polynôme, Pn est encore un polynôme. Python permet avec la méthode
__pow__ ( power) d’obtenir Pn en écrivant P**n, si P est un objet de type polynôme et n un entier
naturel. Bien entendu, pour cela il faut surcharger, un fois de plus, cette méthode. Implémenter
cette méthode dont la première ligne prendra la forme suivante :
def __pow__ (self ,n):
On utilisera, évidemment, la produit défini dans la question qui précède.
Par exemple :
>>> P= polynome (1 ,1)
>>> P**5
1+5X+10X **2+10 X **3+5 X**4+X**5
3) Il existe aussi deux méthodes __radd__ et __rsub__ qui vont permettre d’ajouter ou de retrancher
un polynôme quelconque à un réel représentant un polynôme constant. Si l’on surchage ces
méthodes, on peut alors écrire :
>>>X= polynome (0 ,1)
>>> (1+X+X**2) *(1+X)
1+2X+2X**2+X**3
>>> (1+X)**5
1+5X+10X **2+10 X **3+5 X**4+X**5
>>> (1-X)**5
1-5X+10X**2 -10X **3+5 X**4 -X**5
A vous de jouer !
4. Une première application
Les polynômes de Tchébichev, (Tn )n≥0 , sont définis par la propriété suivante :
∀x ∈ R, Tn (cos(x)) = cos(nx)
(1)
On rappelle que deux polynômes qui coïncident en une infinité de valeurs de la variable x sont égaux
pour tout x réel.
TP PYTHON - 10
6
[Qu. 7]
1) Montrer que s’il existe un polynôme Tn vérifiant la propriété (1) alors il est unique.
2) On définit la suite (Tn )n≥0 par : T0 = 1, T1 = X et pour tout n ≥ 1, Tn+1 = 2XTn − Tn−1 . Montrer que
les polynômes de cette suite vérifient (1).
3) Ecrire une fonction tchebichev d’argument un entier n et qui renvoie le n-ième polynôme de
Tchébichev. Vérifier que :
T10 = −1 + 50X2 − 400X4 + 1120X6 − 1280X8 + 512X10
1
4) En utilisant la relation cos(nx) = [(cos(x) + i sin(x))n + (cos(x) − i sin(x))n ] et la formule du bi2
nôme de Newton, montrer que :
b n2 c X
n
Xn−2k (X2 − 1)k
Tn =
2k
k=0
Ecrire une fonction tchebichevDirect d’argument un entier n et qui renvoie le n-ième polynôme de
Tchébichev. Comparer tchebichevDirect(10) et tchebichev(10).
Rem. On pourra utiliser la fonction binomial du module sympy pour calculer les coefficients binomiaux.
5. Composition et évaluation en un point
La composition des fonctions appliquée aux polynômes donne encore une opération qui retourne des
polynômes. Si P et Q désignent deux polynômes, on notera P(Q) la fonction polynomiale qui à x réel
associe P(Q(x)).
La méthode spéciale __call__ permet d’utiliser la notation des fonctions pour les objets d’une classe.
Si la surcharge de cette méthode, pour la classe polynôme, comporte par exemple, un paramètre a,
alors pour éxecuter cette méthode du polynôme P, sur l’objet Q, on écrira P(Q).
Si P =
n−1
X
ak Xk , l’algorithme de Hörner permet de calculer P en effectuant moins d’opérations que
k=0
par la méthode naïve.
Posons, P1 = an−1 et pour tout k ∈ [[1, n − 1]], Pk+1 = an−1−k + XPk . On a alors Pn = P.
Pour calculer P(Q) il suffit remplacer dans la suite précédente, X par Q. Si l’on veut calculer P(a) où a
est un réel, on remplace X par a.
Le polymorphisme des opérateurs d’addition et de multiplication, permet de calculer aussi bien P(a)
que P(Q), sans se soucier du type du paramètre.
[Qu. 8]
1) Montrer par récurrence sur k ∈ [[1, n]], Pk =
k
X
an−i Xk−i et en déduire que Pn = P.
i=1
2) Ecrire la surcharge de la méthode __call__ pour qu’elle retourne P(Q) si Q est un polynôme et
P(a) si a est un réel, sans toutefois distinguer les deux cas.
Vérifier la validité de votre méthode en obtenant l’affichage suivant dans le shell :
>>> X= polynome (0 ,1)
>>> P=(1+X)**3
>>> P(2)
27
>>> Q=P(1-X**2)
>>> Q
8-12X **2+6 X**4 -X**6
TP PYTHON - 10
7
!
2k + 1
3) Si Tn est le n-ième polynôme de Tchébichev, vérifier que les cos
π pour k ∈ [[0, n − 1]], sont,
2n
à peu près, des racines de Pn .
6. Une deuxième application
On dit que le polynôme P est de degré p si P =
p
X
ak Xk avec ap , 0. Une famille (Pn )n≥1 est qualifiée
k=0
de famille de polynômes commutants si pour tout n ≥ 1, le degré de Pn vaut n et pour tout couple
(n, m), Pn (Pm ) = Pm (Pn ).
Soit a non nul, b un réel, on définit, d’une part, les polynômes Pn par,
Pn = an−1 (X − b)n + b
et, d’autre part, les polynômes Qn par :
Qn = aTn
1
(X − b) + b
a
où Tn désigne le n-ième polynôme de Tchébichev.
[Qu. 9]
1) Montrer que les familles (Pn )n≥1 et (Qn )n≥1 ainsi définies sont des familles de polynômes commutants.
2) Ecrire une fonction polyP(n,a,b) qui renvoie Pn pour les valeurs de n, a et b transmises en
paramètres et une fonction polyQ(n,a,b) qui fait de même pour Qn .
Note. Pour éviter les erreurs d’arrondi, on utilisera le module fractions et Fraction(1,a) pour
1
.
a
3) Vérifier que l’on a bien :
>>>
>>>
>>>
0
>>>
>>>
>>>
0
>>>
>>>
>>>
0
P= polyP (5 ,3 ,6)
Q= polyP (9 ,3 ,6)
P(Q)-Q(P)
Q= polyQ (5 ,7 ,4)
P= polyQ (8 ,7 ,4)
P(Q)-Q(P)
Q= polyQ (7 ,3 ,6)
P= polyQ (5 ,3 ,6)
P(Q)-Q(P)
On peut montrer que seules les suites de ces deux formes sont commutantes.
Téléchargement