• Aucun résultat trouvé

Séries formelles

Dans le document Calcul mathématique avec Sage (Page 154-159)

Corps finis et théorie élémentaire des 6

7.6 Séries formelles

Une série formelle est une série entière vue comme une simple suite de coefficients, sans considérations de convergence. Plus précisément, siA est un anneau commutatif, on appelle séries formelles (en anglais formal power series) d’indéterminéex à coefficients dans A les sommes formelles P

n=0anxn où (an) est une suite quelconque d’éléments deA. Munies des opérations d’addition et de multiplication naturelles

les séries formelles forment un anneau notéA[[x]].

Dans un système de calcul formel, ces séries sont utiles pour représenter des fonctions analytiques dont on n’a pas d’écriture exacte. Comme toujours, l’ordinateur fait les calculs, mais c’est à l’utilisateur de leur donner un sens mathématique. À lui par exemple de s’assurer que les séries qu’il manipule sont convergentes.

Les séries formelles interviennent aussi abondamment en combinatoire, en tant que séries génératrices. Nous verrons un exemple de ce type en §15.1.2.

7.6.1 Opérations sur les séries tronquées L’anneau de séries formelles Q[[x]] s’obtient par sage: R.<x> = PowerSeriesRing(QQ)

ou en abrégéR.<x> = QQ[[]]6. Les éléments de A[['x']] sont des séries tronquées, c’est-à-dire des objets de la forme

f =f0+f1x+· · ·+fn−1xn−1+O(xn).

6. Ou d’ailleurs à partir deQ[x], parQQ['x'].completion('x').

BR

OUILLON

Ils jouent le rôle d’approximations des séries « mathématiques » infinies, tout comme les éléments deRRreprésentent des approximations de réels. L’anneau A[['x']]est donc un anneau inexact.

Chaque série possède son propre ordre de troncature7, et la précision est suivie automatiquement au cours des calculs :

sage: R.<x> = QQ[[]]

sage: f = 1 + x + O(x^2); g = x + 2*x^2 + O(x^4) sage: f + g

1 + 2*x + O(x^2) sage: f * g

x + 3*x^2 + O(x^3)

Il existe des séries de précision infinie, qui correspondent exactement aux polynômes :

sage: (1 + x^3).prec() +Infinity

Une précision par défaut est utilisée quand il est nécessaire de tronquer un résultat exact. Elle se règle à la création de l’anneau, ou ensuite par sa méthode set_default_prec:

sage: R.<x> = PowerSeriesRing(Reals(24), default_prec=4) sage: 1/(1 + RR.pi() * x)^2

1.00000 - 6.28319*x + 29.6088*x^2 - 124.025*x^3 + O(x^4) Tout cela entraîne qu’il n’est pas possible de tester l’égalité mathématique de deux séries. C’est une différence conceptuelle importante entre celles-ci et les autres classes d’objets vues dans ce chapitre. Sage considère donc deux éléments de A[['x']] comme égaux dès qu’ils coïncident jusqu’à la plus faiblede leurs précisions :

sage: R.<x> = QQ[[]]

sage: 1 + x + O(x^2) == 1 + x + x^2 + O(x^3) True

Attention : cela implique par exemple que le testO(x^2) == 0renvoie vrai, puisque la série nulle a une précision infinie.

Les opérations arithmétiques de base sur les séries fonctionnent comme sur les polynômes. On dispose aussi de quelques fonctions usuelles, par exemplef.exp() lorsquef(0) = 0, ainsi que des opérations de dérivation et d’intégration. Ainsi, un développement asymptotique quandx→0 de

1 x2 exp

Z x 0

s 1 1 +t dt est donné par

7. D’un certain point de vue, c’est la principale différence entre un polynôme moduloxk et une série tronquée à l’ordrek: les opération sur ces deux sortes d’objets sont analogues, mais les éléments deA[[x]]/hxkiont, eux, tous la même « précision ».

BR

OUILLON

sage: (1/(1+x)).sqrt().integral().exp()/x^2 + O(x^4)

x^-2 + x^-1 + 1/4 + 1/24*x - 1/192*x^2 + 11/1920*x^3 + O(x^4) Ici, même si seuls quatre termes apparaissent dans le résultat, chaque opé-ration est effectuée à la précision par défaut 20, qui suffit largement pour obtenir un reste final enO(x4). Pour obtenir plus de vingt termes, il faudrait augmenter la précision des calculs intermédiaires.

Cet exemple montre aussi que sif, g∈K[[x]] et g(0) = 0, le quotientf /g renvoie un objet série de Laurent formelle. Contrairement aux séries de Laurent de l’analyse complexe, de la formePn=−∞anxn, les séries de Laurent formelles sont des sommes du type Pn=−Nanxn, avec un nombre fini de termes d’exposant négatif. Cette restriction est nécessaire pour donner un sens au produit de deux séries formelles : sans elle, chaque coefficient du produit s’exprime comme une somme de série infinie.

7.6.2 Développement de solutions d’équations

Face à une équation différentielle dont les solutions exactes sont trop compliquées à calculer ou à exploiter une fois calculées, ou tout simplement qui n’admet pas de solution en forme close, un recours fréquent consiste à chercher des solutions sous forme de séries. On commence habituellement par déterminer les solutions de l’équation dans l’espace des séries formelles, et si nécessaire, on conclut ensuite par un argument de convergence que les solutions formelles construites ont un sens analytique. Sagepeut être d’une aide précieuse pour la première étape.

Considérons par exemple l’équation différentielle

y0(x) =p1 +x2y(x) + exp(x), y(0) = 1.

Cette équation admet une unique solution en série formelle, dont on peut calculer les premiers termes par

sage: (1+x^2).sqrt().solve_linear_de(prec=6, b=x.exp()) 1 + 2*x + 3/2*x^2 + 5/6*x^3 + 1/2*x^4 + 7/30*x^5 + O(x^6) De plus, le théorème de Cauchy d’existence de solutions d’équations diffé-rentielles linéaires à coefficients analytiques assure que cette série converge pour|x|<1 : sa somme fournit donc une solution analytique sur le disque unité complexe.

Cette approche n’est pas limitée aux équations différentielles. L’équation fonctionnelleexf(x)=f(x) est plus compliquée, ne serait-ce que parce qu’elle n’est pas linéaire. Mais c’est une équation de point fixe, nous pouvons essayer de raffiner une solution (formelle) par itération :

sage: S.<x> = PowerSeriesRing(QQ, default_prec=5) sage: f = S(1)

sage: for i in range(5):

... f = (x*f).exp()

... print f

BR

forme Φn(a) converge, sa limite est nécessairement solution de l’équation.

Inversement, posons f(x) = Pn=0fnxn, et développons en série les deux membres : il vient

Peu importent les détails de la formule ; l’essentiel est que fn se calcule en fonction des coefficients précédents f0, . . . , fn−1, comme on le voit en identifiant les coefficients des deux membres. Chaque itération de Φ fournit donc un nouveau terme correct.

Exercice 28. Calculer le développement limité à l’ordre 15 de tanx au voisinage de zéro à partir de l’équation différentielle tan0 = 1 + tan2. 7.6.3 Séries paresseuses

Ce phénomène motive l’introduction d’une autre sorte de séries formelles appelées séries paresseuses (en anglais lazy). Ce ne sont pas des séries tronquées, mais bien des séries infinies ; l’adjectif paresseux signifie que les coefficients ne sont calculés que quand ils sont explicitement demandés. En contrepartie, on ne peut représenter que des séries dont on sait calculer les coefficients : essentiellement, des combinaisons de séries de base et certaines solutions d’équations pour lesquelles existent des relations comme (7.2). Par exemple, la série paresseuselazy_exp définie par

sage: L.<x> = LazyPowerSeriesRing(QQ) sage: lazy_exp = x.exponential(); lazy_exp O(1)

est un objet qui contient dans sa représentation interne toutes les informations nécessaires pour calculer le développement en série de expxà n’importe quel ordre. Elle s’affiche initialement commeO(1)car aucun coefficient n’a encore été calculé. Tenter d’accéder au coefficient dex5 déclenche le calcul, et les coefficients calculés sont alors mémorisés :

sage: lazy_exp[5]

1/120

BR

OUILLON

sage: lazy_exp

1 + x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + 1/120*x^5 + O(x^6) Reprenons l’exemple de l’équation exf(x) =f(x) pour voir comment il se simplifie. Nous pouvons d’abord essayer de reproduire le calcul fait plus haut dans l’anneau QQ[['x']]:

sage: f = L(1) # la série paresseuse constante 1 sage: for i in range(5):

... f = (x*f).exponential()

... f.compute_coefficients(5) # force le calcul des

... print f # premiers coefficients

1 + x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + 1/120*x^5 + O(x^6) 1 + x + 3/2*x^2 + 5/3*x^3 + 41/24*x^4 + 49/30*x^5 + O(x^6) 1 + x + 3/2*x^2 + 8/3*x^3 + 101/24*x^4 + 63/10*x^5 + O(x^6) 1 + x + 3/2*x^2 + 8/3*x^3 + 125/24*x^4 + 49/5*x^5 + O(x^6) 1 + x + 3/2*x^2 + 8/3*x^3 + 125/24*x^4 + 54/5*x^5 + O(x^6) Les développements obtenus sont bien sûr les mêmes que précédemment8. Mais la valeur defà chaque itération est maintenant une série infinie, dont on peut calculer des coefficients à la demande. Toutes ces séries intermédiaires sont conservées en mémoire. Le calcul de chacune d’entre elles est automati-quement poussé à la précision requise de manière à fournir, par exemple, le coefficient dex7 dans le dernier itéré lorsque l’on tente d’y accéder :

sage: f[7]

28673/630

Avec le code de la §7.6.2, l’accès àf[7]aurait provoqué une erreurIndexError, l’indice 7 étant supérieur à l’ordre de troncature de la sérief.

Cependant, la valeur renvoyée parf[7]n’est que le coefficient dex7 dans l’itéré Φ5(1), et non dans la solution. La force des séries paresseuses est la possibilité de passer directement à la limite, en codantf elle-même comme une série paresseuse :

sage: from sage.combinat.species.series import LazyPowerSeries sage: f = LazyPowerSeries(L, name='f')

sage: f.define((x*f).exponential()) sage: f.coefficients(8)

[1, 1, 3/2, 8/3, 125/24, 54/5, 16807/720, 16384/315]

Ce qui « faisait marcher » le calcul itératif est la relation (7.2). En coulisses, Sage déduit de la définition récursive f.define((x*f).exponential()) une formule du même genre, qui permet de calculer les coefficients par récurrence.

8. On constate cependant que Sage emploie parfois des conventions incohérentes : la méthode qui s’appelait exp pour les séries tronquées s’appelle ici exponential, et compute_coefficients(5) calcule les coeffcients jusqu’à l’ordre 5 inclus tandis que default_prec=5donnait des séries tronquées après le coefficient dex4.

BR

OUILLON

Dans le document Calcul mathématique avec Sage (Page 154-159)