Vous êtes sur la page 1sur 474

Calcul mathmatique avec

SAGE
Calcul mathmatique avec Sage

Alexandre Casamayou Nathann Cohen


Guillaume Connan Thierry Dumont Laurent Fousse
Franois Maltey Matthias Meulien Marc Mezzarobba
Clment Pernet Nicolas M. Thiry Paul Zimmermann
C
Cette uvre est mise disposition selon les termes de la licence Creative Commons
Paternit Partage dans les mmes conditions 3.0 France (cc by-sa 3.0 fr).
Extrait de http://creativecommons.org/licenses/by-sa/3.0/fr/deed.fr :
Ceci est le rsum explicatif lisible par les humains du Code Juridique (la version
intgrale de la licence).
Vous tes libre de :
partager reproduire, distribuer et communiquer luvre
remixer adapter luvre
dutiliser cette uvre des fins commerciales
Selon les conditions suivantes :
b Attribution Vous devez attribuer luvre de la manire indique par
lauteur de luvre ou le titulaire des droits (mais pas dune manire qui
suggrerait quils vous approuvent, vous ou votre utilisation de luvre).
a Partage dans les Mmes Conditions Si vous modifiez, transformez ou
adaptez cette uvre, vous navez le droit de distribuer votre cration que
sous une licence identique ou similaire celle-ci.
comprenant bien que :
Renonciation Nimporte laquelle des conditions ci-dessus peut tre leve
si vous avez lautorisation du titulaire de droits.
Domaine Public L o luvre ou un quelconque de ses lments est dans
le domaine public selon le droit applicable, ce statut nest en aucune faon
affect par la licence.
Autres droits Les droits suivants ne sont en aucune manire affects par
la licence :
Vos prrogatives issues des exceptions et limitations aux droits exclusifs
ou fair use ;
Les droits moraux de lauteur ;
Droits quautrui peut avoir soit sur luvre elle-mme soit sur la faon
dont elle est utilise, comme le droit limage ou les droits la vie
prive.
Remarque A chaque rutilisation ou distribution de cette uvre, vous
devez faire apparatre clairement au public la licence selon laquelle elle est
mise disposition. La meilleure manire de lindiquer est un lien vers cette
page web.

Des parties de cet ouvrage sont inspires de louvrage Calcul formel : mode
demploi. Exemples en Maple de Philippe Dumas, Claude Gomez, Bruno Salvy
et Paul Zimmermann [DGSZ95], diffus sous la mme licence, notamment les
sections 2.1.5, 2.3.5 et 5.3.
Une partie des exemples Sage du chapitre 15 sont tirs du tutoriel des logiciels
MuPAD-Combinat [HT04] et Sage-combinat. Le dnombrement des arbres binaires
complets de 15.1.2 est en partie inspir dun sujet de TP de Florent Hivert.
Lexercice 9 sur le problme de Gauss est tir dun problme de Franois
Pantigny et lexercice 17 sur leffet Magnus est extrait dun TD de Jean-Guy
Stoliaroff.
Les graphiques de la figure 4.9 et leur interprtation reproduisent une partie du
paragraphe III.4 du Que sais-je ? Les nombres premiers de Grald Tenenbaum
et Michel Mends France [TMF00].
Prface

Ce livre est destin tous ceux qui dsirent utiliser efficacement un systme
de calcul mathmatique, en particulier le logiciel Sage. Ces systmes offrent une
multitude de fonctionnalits, et trouver comment rsoudre un problme donn
nest pas toujours facile. Un manuel de rfrence fournit une description analytique
et en dtail de chaque fonction du systme ; encore faut-il savoir le nom de la
fonction que lon cherche ! Le point de vue adopt ici est complmentaire, en
donnant une vision globale et synthtique, avec un accent sur les mathmatiques
sous-jacentes, les classes de problmes que lon sait rsoudre et les algorithmes
correspondants.
La premire partie, plus spcifique au logiciel Sage, constitue une prise en
main du systme. Cette partie se veut accessible tous les tudiants scientifiques
(BTS, IUT, classes prparatoires, licence), et dans une certaine mesure aux lves
des lyces. Les autres parties sadressent des tudiants au niveau agrgation.
Contrairement un manuel de rfrence, les concepts mathmatiques sont claire-
ment noncs avant dillustrer leur mise en uvre avec Sage. Ce livre est donc
aussi un livre sur les mathmatiques.
Pour illustrer cet ouvrage, le choix sest port naturellement vers Sage, car cest
un logiciel libre, que tout un chacun peut utiliser, modifier et redistribuer loisir.
Ainsi llve qui a appris Sage au lyce pourra lutiliser quelle que soit sa voie
professionnelle : en licence, master, doctorat, en cole dingnieur, en entreprise,
etc. Sage est un logiciel encore jeune par rapport aux logiciels concurrents, et
malgr ses capacits dj tendues, il comporte encore de nombreux bogues. Mais
par sa communaut trs active de dveloppeurs, Sage volue trs vite. Chaque
utilisateur de Sage peut rapporter un bogue et ventuellement sa solution
sur trac.sagemath.org ou via la liste sage-support.
Pour rdiger ce livre, nous avons utilis la version 5.9 de Sage. Nanmoins, les
exemples doivent fonctionner avec toute version ultrieure. Par contre, certaines
affirmations pourraient ne plus tre vrifies, comme par exemple le fait que Sage
utilise Maxima pour valuer des intgrales numriques.
Quand jai propos en dcembre 2009 Alexandre Casamayou, Guillaume
Connan, Thierry Dumont, Laurent Fousse, Franois Maltey, Matthias Meulien,
Marc Mezzarobba, Clment Pernet et Nicolas Thiry dcrire un livre sur Sage,
tous ont rpondu prsent, malgr une charge de travail dj importante, comme
Nathann Cohen qui nous a rejoint dans cette aventure. Je tiens les remercier, no-
tamment pour le respect du planning serr que javais fix, et plus particulirement
iv

Nathann Cohen, Marc Mezzarobba et Nicolas Thiry pour leur investissement


dcisif dans la dernire ligne droite.
Tous les auteurs remercient les personnes suivantes qui ont relu des versions
prliminaires de ce livre : Gatan Bisson, Franoise Jung, Hugh Thomas, Anne
Vaugon, Sbastien Desreux, Pierrick Gaudry, Maxime Huet, Jean Thiry, Muriel
Shan Sei Fan, Timothy Walsh, Daniel Duparc, Kvin Rowanet et Kamel Naroun
(une mention spciale tous les deux qui ont relev des coquilles qui avaient
rsist 17 relectures) ; ainsi quEmmanuel Thom pour son aide prcieuse lors
de la ralisation de ce livre, Sylvain Chevillard, Gatan Bisson et Jrmie Detrey
pour leurs conseils typographiques aviss et les erreurs quils ont releves. Le
dessin de la couverture a t ralis par Corinne Thiry, sur une ide originale
dAlbane Saintenoy.
En rdigeant ce livre, nous avons beaucoup appris sur Sage, nous avons bien
sr rencontr quelques bogues, dont certains sont dj corrigs. Nous esprons
que ce livre sera utile dautres, lycens, tudiants, professeurs, ingnieurs, cher-
cheurs ou amateurs ! Cet ouvrage comportant certainement encore de nombreuses
imperfections, nous attendons en retour du lecteur quil nous fasse part de toute
erreur, critique ou suggestion pour une version ultrieure ; merci dutiliser pour
cela la page sagebook.gforge.inria.fr.

Nancy, France
Paul Zimmermann
Mai 2013
Table des matires

I Prise en main de Sage 1

1 Premiers pas 3
1.1 Le logiciel Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1 Un outil pour les mathmatiques . . . . . . . . . . . . . 3
1.1.2 Accs Sage . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.3 Ressources . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2 Sage comme calculatrice . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.1 Premiers calculs . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.2 Fonctions lmentaires et constantes usuelles . . . . . . . . 11
1.2.3 Aide en ligne et compltion automatique . . . . . . . . . 13
1.2.4 Variables Python . . . . . . . . . . . . . . . . . . . . . . 13
1.2.5 Variables symboliques . . . . . . . . . . . . . . . . . . . . 15
1.2.6 Premiers graphiques . . . . . . . . . . . . . . . . . . . . . 16

2 Analyse et algbre 17
2.1 Expressions symboliques et simplification . . . . . . . . . . . . . 17
2.1.1 Expressions symboliques . . . . . . . . . . . . . . . . . . 17
2.1.2 Transformation dexpressions . . . . . . . . . . . . . . . . 18
2.1.3 Fonctions mathmatiques usuelles . . . . . . . . . . . . . 20
2.1.4 Hypothses sur une variable symbolique . . . . . . . . . . 22
2.1.5 Quelques dangers . . . . . . . . . . . . . . . . . . . . . . 22
2.2 quations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.2.1 Rsolution explicite . . . . . . . . . . . . . . . . . . . . . 24
2.2.2 quations sans solution explicite . . . . . . . . . . . . . . 26
2.3 Analyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.3.1 Sommes . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.3.2 Limites . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.3.3 Suites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.3.4 Dveloppements limits . . . . . . . . . . . . . . . . . . . 30
2.3.5 Sries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.3.6 Drivation . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.3.7 Drives partielles . . . . . . . . . . . . . . . . . . . . . . 33
2.3.8 Intgration . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.4 Algbre linaire lmentaire . . . . . . . . . . . . . . . . . . . . . 35
2.4.1 Rsolution de systmes linaires . . . . . . . . . . . . . . 36
vi TABLE DES MATIRES

2.4.2 Calcul vectoriel . . . . . . . . . . . . . . . . . . . . . . . 36


2.4.3 Calcul matriciel . . . . . . . . . . . . . . . . . . . . . . . 37
2.4.4 Rduction dune matrice carre . . . . . . . . . . . . . . 38

3 Programmation et structures de donnes 41


3.1 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.1.1 Syntaxe gnrale . . . . . . . . . . . . . . . . . . . . . . . 42
3.1.2 Appel de fonctions . . . . . . . . . . . . . . . . . . . . . 43
3.1.3 Complments sur les variables . . . . . . . . . . . . . . . 43
3.2 Algorithmique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.2.1 Les boucles . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.2.2 Les tests . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.2.3 Les procdures et les fonctions . . . . . . . . . . . . . . . 53
3.2.4 Exemple : exponentiation rapide . . . . . . . . . . . . . . 56
3.2.5 Affichage et saisie . . . . . . . . . . . . . . . . . . . . . . 59
3.3 Listes et structures composes . . . . . . . . . . . . . . . . . . . 60
3.3.1 Dfinition des listes et accs aux lments . . . . . . . . . 60
3.3.2 Oprations globales sur les listes . . . . . . . . . . . . . . 62
3.3.3 Principales mthodes sur les listes . . . . . . . . . . . . . 66
3.3.4 Exemples de manipulation de listes . . . . . . . . . . . . 68
3.3.5 Chanes de caractres . . . . . . . . . . . . . . . . . . . . 69
3.3.6 Structure partage ou duplique . . . . . . . . . . . . . . 70
3.3.7 Donnes modifiables ou immuables . . . . . . . . . . . . 72
3.3.8 Ensembles finis . . . . . . . . . . . . . . . . . . . . . . . 73
3.3.9 Dictionnaires . . . . . . . . . . . . . . . . . . . . . . . . . 74

4 Graphiques 77
4.1 Courbes en 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.1.1 Reprsentation graphique de fonctions . . . . . . . . . . 77
4.1.2 Courbe paramtre . . . . . . . . . . . . . . . . . . . . . 80
4.1.3 Courbe en coordonnes polaires . . . . . . . . . . . . . . 80
4.1.4 Courbe dfinie par une quation implicite . . . . . . . . . . 81
4.1.5 Trac de donnes . . . . . . . . . . . . . . . . . . . . . . 83
4.1.6 Trac de solution dquation diffrentielle . . . . . . . . . 87
4.1.7 Dveloppe dune courbe . . . . . . . . . . . . . . . . . . . 91
4.2 Courbes en 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

5 Domaines de calcul 97
5.1 Sage est orient objet . . . . . . . . . . . . . . . . . . . . . . . . 97
5.1.1 Objets, classes et mthodes . . . . . . . . . . . . . . . . . 97
5.1.2 Objets et polymorphisme . . . . . . . . . . . . . . . . . . 99
5.1.3 Introspection . . . . . . . . . . . . . . . . . . . . . . . . . 100
5.2 lments, parents, catgories . . . . . . . . . . . . . . . . . . . . . 101
5.2.1 lments et parents . . . . . . . . . . . . . . . . . . . . . . 101
5.2.2 Constructions . . . . . . . . . . . . . . . . . . . . . . . . 102
5.2.3 Complment : catgories . . . . . . . . . . . . . . . . . . 103
TABLE DES MATIRES vii

5.3 Domaines de calcul reprsentation normale . . . . . . . . . . . 103


5.3.1 Domaines de calcul lmentaires . . . . . . . . . . . . . . 105
5.3.2 Domaines composs . . . . . . . . . . . . . . . . . . . . . 109
5.4 Expressions versus domaines de calcul . . . . . . . . . . . . . . . . 111
5.4.1 Les expressions comme domaine de calcul . . . . . . . . . . 111
5.4.2 Exemples : polynmes et formes normales . . . . . . . . 112
5.4.3 Exemple : factorisation des polynmes . . . . . . . . . . 113
5.4.4 Synthse . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

II Algbre et calcul formel 117

6 Corps finis et thorie des nombres 119


6.1 Anneaux et corps finis . . . . . . . . . . . . . . . . . . . . . . . . 119
6.1.1 Anneau des entiers modulo n . . . . . . . . . . . . . . . . 119
6.1.2 Corps finis . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
6.1.3 Reconstruction rationnelle . . . . . . . . . . . . . . . . . 122
6.1.4 Restes chinois . . . . . . . . . . . . . . . . . . . . . . . . 123
6.2 Primalit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
6.3 Factorisation et logarithme discret . . . . . . . . . . . . . . . . . 127
6.4 Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
6.4.1 La constante . . . . . . . . . . . . . . . . . . . . . . . . 128
6.4.2 Calcul dintgrale multiple via reconstruction rationnelle 129

7 Polynmes 131
7.1 Anneaux de polynmes . . . . . . . . . . . . . . . . . . . . . . . 132
7.1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 132
7.1.2 Construction danneaux de polynmes . . . . . . . . . . 132
7.1.3 Polynmes . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7.2 Arithmtique euclidienne . . . . . . . . . . . . . . . . . . . . . . 137
7.2.1 Divisibilit . . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.2.2 Idaux et quotients . . . . . . . . . . . . . . . . . . . . . 140
7.3 Factorisation et racines . . . . . . . . . . . . . . . . . . . . . . . . 141
7.3.1 Factorisation . . . . . . . . . . . . . . . . . . . . . . . . . 142
7.3.2 Recherche de racines . . . . . . . . . . . . . . . . . . . . 143
7.3.3 Rsultant . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.3.4 Groupe de Galois . . . . . . . . . . . . . . . . . . . . . . 146
7.4 Fractions rationnelles . . . . . . . . . . . . . . . . . . . . . . . . 147
7.4.1 Construction et proprits lmentaires . . . . . . . . . . 147
7.4.2 Dcomposition en lments simples . . . . . . . . . . . . 147
7.4.3 Reconstruction rationnelle . . . . . . . . . . . . . . . . . 149
7.5 Sries formelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
7.5.1 Oprations sur les sries tronques . . . . . . . . . . . . . 152
7.5.2 Dveloppement de solutions dquations . . . . . . . . . . 154
7.5.3 Sries paresseuses . . . . . . . . . . . . . . . . . . . . . . 155
7.6 Reprsentation informatique des polynmes . . . . . . . . . . . . 156
viii TABLE DES MATIRES

8 Algbre linaire 159


8.1 Constructions et manipulations lmentaires . . . . . . . . . . . 159
8.1.1 Espaces de vecteurs, de matrices . . . . . . . . . . . . . . 159
8.1.2 Construction des matrices et des vecteurs . . . . . . . . . . 161
8.1.3 Manipulations de base et arithmtique sur les matrices . 162
8.1.4 Oprations de base sur les matrices . . . . . . . . . . . . 164
8.2 Calculs sur les matrices . . . . . . . . . . . . . . . . . . . . . . . 164
8.2.1 limination de Gauss, forme chelonne . . . . . . . . . . 165
8.2.2 Rsolution de systmes ; image et base du noyau . . . . . 172
8.2.3 Valeurs propres, forme de Jordan et transformations de
similitude . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

9 Systmes polynomiaux 183


9.1 Polynmes plusieurs indtermines . . . . . . . . . . . . . . . . 183
9.1.1 Les anneaux A[x1 , . . . , xn ] . . . . . . . . . . . . . . . . . 183
9.1.2 Polynmes . . . . . . . . . . . . . . . . . . . . . . . . . . 185
9.1.3 Oprations de base . . . . . . . . . . . . . . . . . . . . . 187
9.1.4 Arithmtique . . . . . . . . . . . . . . . . . . . . . . . . . 187
9.2 Systmes polynomiaux et idaux . . . . . . . . . . . . . . . . . . 188
9.2.1 Un premier exemple . . . . . . . . . . . . . . . . . . . . . 188
9.2.2 Quest-ce que rsoudre ? . . . . . . . . . . . . . . . . . . 192
9.2.3 Idaux et systmes . . . . . . . . . . . . . . . . . . . . . 192
9.2.4 limination . . . . . . . . . . . . . . . . . . . . . . . . . 197
9.2.5 Systmes de dimension zro . . . . . . . . . . . . . . . . 203
9.3 Bases de Grbner . . . . . . . . . . . . . . . . . . . . . . . . . . 207
9.3.1 Ordres monomiaux . . . . . . . . . . . . . . . . . . . . . 208
9.3.2 Division par une famille de polynmes . . . . . . . . . . 209
9.3.3 Bases de Grbner . . . . . . . . . . . . . . . . . . . . . . 210
9.3.4 Proprits des bases de Grbner . . . . . . . . . . . . . . 214
9.3.5 Calcul . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217

10 quations diffrentielles et rcurrences 221


10.1 quations diffrentielles . . . . . . . . . . . . . . . . . . . . . . . . 221
10.1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . 221
10.1.2 quations diffrentielles ordinaires dordre 1 . . . . . . . 222
10.1.3 quations dordre 2 . . . . . . . . . . . . . . . . . . . . . 230
10.1.4 Transforme de Laplace . . . . . . . . . . . . . . . . . . . . 231
10.1.5 Systmes diffrentiels linaires . . . . . . . . . . . . . . . 233
10.2 Suites dfinies par une relation de rcurrence . . . . . . . . . . . 235
10.2.1 Suites dfinies par un+1 = f (un ) . . . . . . . . . . . . . . 235
10.2.2 Suites rcurrentes linaires . . . . . . . . . . . . . . . . . 237
10.2.3 Suites rcurrentes avec second membre . . . . . . . . 238
TABLE DES MATIRES ix

III Calcul numrique 239

11 Nombres virgule flottante 241


11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
11.1.1 Dfinition . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
11.1.2 Proprits, exemples . . . . . . . . . . . . . . . . . . . . 242
11.1.3 Normalisation . . . . . . . . . . . . . . . . . . . . . . . . 242
11.2 Les nombres flottants . . . . . . . . . . . . . . . . . . . . . . . . 243
11.2.1 Quel type de nombres choisir ? . . . . . . . . . . . . . . . 245
11.3 Proprits des nombres virgule flottante . . . . . . . . . . . . . 245
11.3.1 Des ensembles pleins de trous . . . . . . . . . . . . . . . 245
11.3.2 Larrondi . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
11.3.3 Quelques proprits . . . . . . . . . . . . . . . . . . . . . 246
11.3.4 Nombres flottants complexes . . . . . . . . . . . . . . . . . 251
11.3.5 Mthodes . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
11.4 En guise de conclusion . . . . . . . . . . . . . . . . . . . . . . . . 253

12 quations non linaires 255


12.1 quations algbriques . . . . . . . . . . . . . . . . . . . . . . . . 255
12.1.1 Mthode Polynomial.roots() . . . . . . . . . . . . . . . 255
12.1.2 Reprsentation des nombres . . . . . . . . . . . . . . . . 256
12.1.3 Thorme de dAlembert . . . . . . . . . . . . . . . . . . 257
12.1.4 Distribution des racines . . . . . . . . . . . . . . . . . . . 257
12.1.5 Rsolution par radicaux . . . . . . . . . . . . . . . . . . . 258
12.1.6 Mthode Expression.roots() . . . . . . . . . . . . . . . 260
12.2 Rsolution numrique . . . . . . . . . . . . . . . . . . . . . . . . . 261
12.2.1 Localisation des solutions des quations algbriques . . . 262
12.2.2 Mthodes dapproximations successives . . . . . . . . . . 264

13 Algbre linaire numrique 277


13.1 Calculs inexacts en algbre linaire . . . . . . . . . . . . . . . . . 278
13.1.1 Normes de matrices et conditionnement . . . . . . . . . . 278
13.2 Matrices pleines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
13.2.1 Rsolution de systmes linaires . . . . . . . . . . . . . . . 281
13.2.2 Rsolution directe . . . . . . . . . . . . . . . . . . . . . . 282
13.2.3 La dcomposition LU . . . . . . . . . . . . . . . . . . . . 282
13.2.4 La dcomposition de Cholesky des matrices relles sym-
triques dfinies positives . . . . . . . . . . . . . . . . . . 283
13.2.5 La dcomposition QR . . . . . . . . . . . . . . . . . . . . 283
13.2.6 La dcomposition en valeurs singulires . . . . . . . . . . 284
13.2.7 Application aux moindres carrs . . . . . . . . . . . . . . 285
13.2.8 Valeurs propres, vecteurs propres . . . . . . . . . . . . . 288
13.2.9 Ajustement polynomial : le retour du diable . . . . . . . 293
13.2.10 Implantation et performances . . . . . . . . . . . . . . . 295
13.3 Matrices creuses . . . . . . . . . . . . . . . . . . . . . . . . . . . 296
13.3.1 Origine des systmes creux . . . . . . . . . . . . . . . . . 297
13.3.2 Sage et les matrices creuses . . . . . . . . . . . . . . . . 298
x TABLE DES MATIRES

13.3.3 Rsolution de systmes linaires . . . . . . . . . . . . . . 298


13.3.4 Valeurs propres, vecteurs propres . . . . . . . . . . . . . 300
13.3.5 Thme de rflexion : rsolution de trs grands systmes
non linaires . . . . . . . . . . . . . . . . . . . . . . . . . . 301

14 Intgration numrique 303


14.1 Intgration numrique . . . . . . . . . . . . . . . . . . . . . . . . 303
14.1.1 Fonctions dintgration disponibles . . . . . . . . . . . . 309
14.2 Rsolution dquations diffrentielles . . . . . . . . . . . . . . . . 315
14.2.1 Exemple de rsolution . . . . . . . . . . . . . . . . . . . . 317
14.2.2 Fonctions de rsolution disponibles . . . . . . . . . . . . 318

IV Combinatoire 321

15 Dnombrement et combinatoire 323


15.1 Premiers exemples . . . . . . . . . . . . . . . . . . . . . . . . . 324
15.1.1 Jeu de poker et probabilits . . . . . . . . . . . . . . . . 324
15.1.2 Dnombrement darbres par sries gnratrices . . . . . 326
15.2 Ensembles numrs usuels . . . . . . . . . . . . . . . . . . . . . 333
15.2.1 Exemple : les sous-ensembles dun ensemble . . . . . . . 333
15.2.2 Partitions dentiers . . . . . . . . . . . . . . . . . . . . . 334
15.2.3 Quelques autres ensembles finis numrs . . . . . . . . . 336
15.2.4 Comprhensions et itrateurs . . . . . . . . . . . . . . . . 339
15.3 Constructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
15.4 Algorithmes gnriques . . . . . . . . . . . . . . . . . . . . . . . 347
15.4.1 Gnration lexicographique de listes dentiers . . . . . . 347
15.4.2 Points entiers dans les polytopes . . . . . . . . . . . . . . 349
15.4.3 Espces, classes combinatoires dcomposables . . . . . . 350
15.4.4 Graphes un isomorphisme prs . . . . . . . . . . . . . . 352

16 Thorie des graphes 355


16.1 Construire un graphe . . . . . . . . . . . . . . . . . . . . . . . . 355
16.1.1 partir de zro . . . . . . . . . . . . . . . . . . . . . . . 355
16.1.2 Les constructeurs disponibles . . . . . . . . . . . . . . . . 357
16.1.3 Unions disjointes . . . . . . . . . . . . . . . . . . . . . . 360
16.1.4 Affichage des graphes . . . . . . . . . . . . . . . . . . . . . 361
16.2 Mthodes de la classe Graph . . . . . . . . . . . . . . . . . . . . 364
16.2.1 Modification de la structure dun graphe . . . . . . . . . 365
16.2.2 Oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . 365
16.2.3 Parcours de graphes et distances . . . . . . . . . . . . . . 366
16.2.4 Flots, connectivit, couplage (matching) . . . . . . . . . 367
16.2.5 Problmes NP-complets . . . . . . . . . . . . . . . . . . . 368
16.2.6 Reconnaissance et test de proprits . . . . . . . . . . . . 370
16.3 Graphes en action . . . . . . . . . . . . . . . . . . . . . . . . . . 372
16.3.1 Coloration gloutonne des sommets dun graphe . . . . . . 372
16.3.2 Gnrer des graphes sous contraintes . . . . . . . . . . . 374
TABLE DES MATIRES xi

16.3.3 Appliquer un algorithme probabiliste pour trouver un


grand ensemble indpendant . . . . . . . . . . . . . . . . 375
16.3.4 Trouver un sous-graphe induit dans un graphe alatoire . 376
16.4 Quelques problmes modliss par des graphes . . . . . . . . . . 378
16.4.1 Une nigme du journal Le Monde 2 . . . . . . . . . . 378
16.4.2 Affectation de tches . . . . . . . . . . . . . . . . . . . . 379
16.4.3 Planifier un tournoi . . . . . . . . . . . . . . . . . . . . . 380

17 Programmation linaire 383


17.1 Dfinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
17.2 Programmation entire . . . . . . . . . . . . . . . . . . . . . . . 384
17.3 En pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
17.3.1 La classe MixedIntegerLinearProgram . . . . . . . . . . 384
17.3.2 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
17.3.3 Problmes infaisables ou non borns . . . . . . . . . . . . 386
17.4 Premires applications la combinatoire . . . . . . . . . . . . . 387
17.4.1 Sac dos . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
17.4.2 Couplages . . . . . . . . . . . . . . . . . . . . . . . . . . 388
17.4.3 Flot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
17.5 Gnration de contraintes et application . . . . . . . . . . . . . . . 391

Annexes 399

A Solutions des exercices 399


A.1 Premiers pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
A.2 Analyse et algbre avec Sage . . . . . . . . . . . . . . . . . . . . 399
A.4 Graphiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
A.5 Domaines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
A.6 Corps finis et thorie lmentaire des nombres . . . . . . . . . . 412
A.7 Polynmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
A.8 Algbre linaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
A.9 Systmes polynomiaux . . . . . . . . . . . . . . . . . . . . . . . . 422
A.10 quations diffrentielles et rcurrences . . . . . . . . . . . . . . . 426
A.11 Nombres virgule flottante . . . . . . . . . . . . . . . . . . . . . 427
A.12 quations non linaires . . . . . . . . . . . . . . . . . . . . . . . 430
A.13 Algbre linaire numrique . . . . . . . . . . . . . . . . . . . . . 433
A.14 Intgration numrique . . . . . . . . . . . . . . . . . . . . . . . . 434
A.15 Dnombrement et combinatoire . . . . . . . . . . . . . . . . . . . 435
A.16 Thorie des graphes . . . . . . . . . . . . . . . . . . . . . . . . . . 441
A.17 Programmation linaire . . . . . . . . . . . . . . . . . . . . . . . 442

B Bibliographie 445

C Index 449
xii TABLE DES MATIRES
Premire partie

Prise en main de Sage


1
Premiers pas

Ce chapitre dintroduction prsente la tournure desprit du logiciel mathma-


tique Sage. Les autres chapitres de cette partie dveloppent les notions de base de
Sage : effectuer des calculs numriques ou symboliques en analyse, oprer sur des
vecteurs et des matrices, crire des programmes, manipuler des listes de donnes,
construire des graphiques, etc. Les parties suivantes de cet ouvrage approfon-
dissent quelques branches des mathmatiques dans lesquelles linformatique fait
preuve dune grande efficacit.

1.1 Le logiciel Sage


1.1.1 Un outil pour les mathmatiques
Sage est un logiciel qui implante des algorithmes mathmatiques dans des
domaines varis. En premier lieu, le systme opre sur diffrentes sortes de
nombres : les nombres entiers ou rationnels, les approximations numriques des
rels et des complexes, avec une prcision variable, ou encore les lments des corps
finis. Lutilisateur peut trs rapidement se servir de Sage comme de nimporte
quelle calculette scientifique ventuellement graphique.
Mais le calcul mathmatique ne se limite pas aux nombres. Les collgiens
apprennent par exemple rsoudre des quations affines, dvelopper, simplifier,
et parfois factoriser des expressions contenant des variables. Sage est aussi et
surtout un systme de calcul formel, capable deffectuer les calculs algbriques
de ce genre y compris, pour une utilisation plus avance, dans un anneau de
polynmes ou un corps de fractions rationnelles prcis.
Ct analyse, Sage reconnat les fonctions usuelles comme la racine carre,
la puissance, lexponentielle, le logarithme ou les fonctions trigonomtriques, et
4 CHAP. 1. PREMIERS PAS

Objectifs et dveloppement de Sage

William Stein, un enseignant-chercheur amricain, commence le dveloppe-


ment de Sage en 2005 dans le but dcrire un logiciel de calcul mathmatique
dont tout le code source soit accessible et lisible. Le logiciel est dabord centr
sur le domaine de recherche de son auteur, la thorie des nombres. Progres-
sivement se forme une communaut internationale de plusieurs centaines
de dveloppeurs, la plupart enseignants ou chercheurs. Au fur et mesure
des contributions, les fonctionnalits stendent pour couvrir bien dautres
domaines des mathmatiques, ce qui fait de Sage le logiciel gnraliste quil
est aujourdhui.
Non seulement Sage est tlchargeable et utilisable gratuitement, mais
cest un logiciel libre. Ses auteurs nimposent aucune restriction sa diffusion,
son installation et mme sa modification, pourvu que les versions modifies
soient, elles aussi, libres. Si Sage tait un livre, il pourrait tre emprunt et
photocopi sans limite dans toutes les bibliothques ! Cette licence est en
harmonie avec la diffusion des connaissances vise par lenseignement et la
recherche.
Le dveloppement de Sage est relativement rapide car il privilgie la
rutilisation de logiciels libres existants. Sage lui-mme est crit en Python,
un langage de programmation largement utilis et rput facile apprendre.
Ce code Python fait abondamment appel aux logiciels mathmatiques pr-
existants fournis avec Sage.
Comme presque tous les logiciels de calcul mathmatique, Sage sutilise en
saisissant des commandes crites dans un langage informatique. Mais il ny a
pas proprement parler de langage Sage : cest Python qui joue ce rle, avec
quelques raccourcis syntaxiques pour allger les notations mathmatiques. Les
instructions entres par lutilisateur sont values par linterprteur Python.
Il est possible, pour faire des calculs complexes ou simplement rptitifs,
dcrire de vritables programmes au lieu de simples commandes dune ligne,
voire, pourquoi pas, de les proposer pour inclusion dans Sage !

Figure 1.1 La premire apparition du nom de Sage, sur un carnet de W. Stein. Ori-
ginellement Sage tait aussi un acronyme ; lorsque le systme sest largi lensemble
des mathmatiques, seul le nom de la sauge sage en anglais est rest.
1.1. LE LOGICIEL SAGE 5

Figure 1.2 Une feuille de travail dans le bloc-notes de Sage.

les expressions formes partir de celles-ci. Il effectue drivations, intgrations


et calculs de limites, simplifie les sommes, dveloppe en sries, rsout certaines
quations diffrentielles...
Sage effectue les oprations usuelles de lalgbre linaire sur les vecteurs, les
matrices et les sous-espaces vectoriels. Il permet aussi daborder, dillustrer et de
traiter de diffrentes faons les probabilits, les statistiques et les questions de
dnombrement.
Ainsi, les domaines mathmatiques traits par Sage sont multiples, de la thorie
des groupes lanalyse numrique. Il peut aussi reprsenter graphiquement les
rsultats obtenus sous la forme dune image, dun volume, ou dune animation.
Utiliser un mme logiciel pour aborder ces diffrents aspects des mathmatiques
libre le mathmaticien, quel que soit son niveau, des problmes de transfert de
donnes entre divers outils et de lapprentissage des syntaxes de plusieurs langages
informatiques. Sage se veut homogne entre ces diffrents domaines.

1.1.2 Accs Sage


Pour utiliser Sage, il suffit dun navigateur web tel que Firefox. Le plus
simple dans un premier temps est de se connecter sur un serveur de calcul Sage
public comme http://sagenb.org/. On a alors accs une interface utilisateur
riche constitue dun bloc-notes (notebook en anglais) permettant dditer
et partager des feuilles de travail (worksheets, voir figure 1.2). De nombreuses
universits et institutions mettent de tels serveurs la disposition de leurs
utilisateurs ; renseignez-vous autour de vous. Pour un usage plus intensif, on
6 CHAP. 1. PREMIERS PAS

Figure 1.3 Sage en ligne de commande.

installe gnralement Sage sur sa propre machine 1 . On peut alors toujours


lutiliser avec linterface bloc-notes dans le navigateur web. Alternativement, on
peut lutiliser en ligne de commande, comme une calculatrice (voir figure 1.3).
Les figures 1.4 et 1.5 illustrent pas pas les tapes pour accder un serveur
Sage public et lutiliser pour faire un calcul :
1. Ouvrez votre navigateur web et connectez-vous au site http://sagenb.org
(figure 1.4). Vous pouvez ds prsent consulter les feuilles de travail
publiques accessibles par le lien Browse published Sage worksheets.
2. Pour travailler sur vos propres feuilles de travail, vous devez vous authenti-
fier ; pour cela sagenb.org utilise le systme OpenID 2 . Si vous avez dj, par
exemple, un compte Google ou Yahoo, il vous suffit de suivre les liens corres-
pondants. Sinon, vous devez dabord crer un compte OpenID 3 . Ensuite, il
ne restera qu revenir sur la page daccueil, suivre le lien OpenID, et entrer
votre identifiant OpenID (par exemple http://votre-nom.myopenid.com/).
3. Vous tes maintenant sur la page principale de linterface web de Sage, depuis
laquelle vous pouvez grer vos feuilles de travail. Crez-en une nouvelle
(Create worksheet) et donnez-lui un nom (Rename worksheet).
4. Saisissez ensuite 1 + 1 dans la cellule de calcul, puis cliquez sur evaluate
ou formez la combinaison de touches hAlti+hEntrei (figure 1.5).
Bravo, vous avez fait votre premier calcul avec Sage !
1. Sage est disponible pour la plupart des systmes dexploitation : Linux, Windows, Mac
os x et Solaris.
2. Voir http://fr.wikipedia.org/wiki/OpenID.
3. ladresse https://www.myopenid.com/signup ou auprs de nimporte lequel des fournis-
seurs indiqus sur http://openid.net/get-an-openid/.
1.1. LE LOGICIEL SAGE 7

Figure 1.4 Connectez-vous sur http://sagenb.org...

Figure 1.5 Saisissez une commande, puis cliquez sur evaluate...


8 CHAP. 1. PREMIERS PAS

1.1.3 Ressources
Si vous lisez langlais, cest maintenant le bon moment pour jeter un coup dil
longlet Help (figure 1.6). Vous y trouverez en particulier toutes les commandes
pour diter votre feuille de travail ainsi quun tutoriel interactif (Tutorial). Les
adresses suivantes pointent vers le site internet de rfrence de Sage et quelques
autres pages dinformations, dont une traduction franaise de ce tutoriel.
http://www.sagemath.org/ site officiel
http://www.sagemath.org/fr/ site officiel en franais
http://www.sagemath.org/doc/ documentation
http://www.sagemath.org/fr/html/tutorial/ tutoriel en franais
http://wiki.sagemath.org/quickref fiches de commandes
http://ask.sagemath.org/ forum daide
Par ailleurs, plusieurs listes de diffusion accueillent les discussions des utilisa-
teurs. La liste sage-support@googlegroups.com, en langue anglaise, est la plus
adapte aux questions techniques. Les francophones peuvent aussi dialoguer sur la
liste sagemath-edu@irem.univ-mrs.fr, consacre principalement lutilisation
de Sage dans lenseignement.

1.2 Sage comme calculatrice


1.2.1 Premiers calculs
Dans la suite du livre, nous prsentons les calculs sous la forme suivante, qui
imite lallure dune session Sage en ligne de commande :
sage: 1+1
2
Le texte sage: au dbut de la premire ligne est linvite du systme. Linvite (qui
napparat pas dans linterface bloc-notes) indique que Sage attend une commande
de lutilisateur. La suite de la ligne correspond la commande saisir, puis
valider en appuyant sur hEntrei. Les lignes suivantes correspondent la rponse
du systme, cest--dire en gnral au rsultat du calcul. Certaines instructions
stendent sur plusieurs lignes (voir chapitre 3). Les lignes de commande sup-
plmentaires sont alors indiques par ... en dbut de ligne. Une commande
sur plusieurs lignes doit tre saisie en respectant la position des retours la
ligne et lventuelle indentation (dcalage par des espaces par rapport la ligne
qui prcde) des lignes supplmentaires, sans recopier la marque ... qui les
introduit.
Dans le bloc-notes, on entre directement la commande indique dans une cellule
de calcul, et on valide en cliquant sur evaluate ou en appuyant sur hMaji+hEntrei.
La combinaison de touches hAlti+hEntrei cre une nouvelle cellule au-dessous
de la cellule courante en plus de valider la commande. On peut aussi ajouter une
cellule en cliquant dans lespace vertical juste au-dessus dune cellule existante ou
au-dessous de la dernire cellule.
Sage interprte les formules simples comme une calculatrice scientifique. Les
oprations +, , etc. ont leur priorit usuelle, et les parenthses leur rle habituel :
1.2. SAGE COMME CALCULATRICE 9

Figure 1.6 Laide du bloc-notes.

sage: ( 1 + 2 * (3 + 5) ) * 2
34
Ci-dessus, le signe * reprsente la multiplication. Il ne doit pas tre omis, mme
dans des expressions comme 2x. La puissance se note ^ ou ** :
sage: 2^3
8
sage: 2**3
8
et la division par / :
sage: 20/6
10/3
Observons que le calcul est fait de manire exacte : le rsultat de la division, aprs
simplification, est le nombre rationnel 10/3 et non une approximation comme
3,33333. Il ny a pas de limite 4 la taille des nombres entiers ou rationnels
manipuls :
sage: 2^10
1024
sage: 2^100
1267650600228229401496703205376
sage: 2^1000

4. Hormis celle lie la mmoire de lordinateur utilis.


10 CHAP. 1. PREMIERS PAS

Oprateurs arithmtiques de base


quatre oprations a+b, a-b, a*b, a/b
puissance a^b ou a**b
racine carre sqrt(a)
racine n-ime a^(1/n)

Oprations sur les entiers


division entire a // b
modulo a % b
factorielle n!
 factorial(n)
coefficients binomiaux n k
binomial(n,k)

Fonctions usuelles sur les rels, les complexes...


partie entire floor(a)
valeur absolue, module abs(a)
fonctions lmentaires sin, cos, ... (voir tableau 2.2)

Tableau 1.1 Quelques oprations usuelles.

1071508607186267320948425049060001810561404811705533607443750\
3883703510511249361224931983788156958581275946729175531468251\
8714528569231404359845775746985748039345677748242309854210746\
0506237114187795418215304647498358194126739876755916554394607\
7062914571196477686542167660429831652624386837205668069376
Pour obtenir une approximation numrique, il suffit dcrire au moins lun des
nombres avec un point dcimal (on pourrait remplacer 20.0 par 20. ou 20.000) :
sage: 20.0 / 14
1.42857142857143
Par ailleurs, la fonction numerical_approx prend le rsultat dun calcul exact et
en donne une approximation numrique :
sage: numerical_approx(20/14)
1.42857142857143
sage: numerical_approx(2^1000)
1.07150860718627e301
Il est possible de calculer des approximations prcision arbitrairement grande.
Augmentons par exemple celle-ci 60 chiffres pour bien mettre en vidence la
priodicit du dveloppement dcimal dun nombre rationnel :
sage: numerical_approx(20/14, digits=60)
1.42857142857142857142857142857142857142857142857142857142857
Nous revenons sur les diffrences entre calcul exact et numrique dans lencadr
page 12.
Les oprateurs // et % donnent le quotient et le reste de la division de deux
entiers :
1.2. SAGE COMME CALCULATRICE 11

sage: 20 // 6
3
sage: 20 % 6
2
De nombreuses autres fonctions sappliquent aux entiers. Parmi celles qui leur
sont spcifiques, citons par exemple la factorielle ou les coefficients binomiaux
(voir tableau 1.1) :
sage: factorial(100)
93326215443944152681699238856266700490715968264381621\
46859296389521759999322991560894146397615651828625369\
7920827223758251185210916864000000000000000000000000
Voici enfin une manire de dcomposer un entier en facteurs premiers. Nous
reviendrons sur ce problme au chapitre 5, puis nouveau au chapitre 6.
sage: factor(2^(2^5)+1)
641 * 6700417
n
Fermat avait conjectur que tous les nombres de la forme 22 + 1 taient premiers.
Lexemple ci-dessus est le plus petit qui invalide sa conjecture.

1.2.2 Fonctions lmentaires et constantes usuelles


On retrouve les fonctions et constantes usuelles (voir tableaux 1.1 et 1.2), y
compris pour les nombres complexes. L encore, les calculs sont exacts :
sage: sin(pi)
0
sage: tan(pi/3)
sqrt(3)
sage: arctan(1)
1/4*pi
sage: exp(2 * I * pi)
1
quitte renvoyer des formules plutt que des valeurs numriques :
sage: arccos(sin(pi/3))
arccos(1/2*sqrt(3))
sage: sqrt(2)
sqrt(2)
sage: exp(I*pi/6)
e^(1/6*I*pi)
Les formules que lon obtient ne sont pas toujours celles que lon attend. En
effet, peu de simplifications sont faites automatiquement. Quand un rsultat
semble trop compliqu, on peut essayer dappeler explicitement une fonction de
simplification :
sage: simplify(arccos(sin(pi/3)))
12 CHAP. 1. PREMIERS PAS

Calcul formel et mthodes numriques

Un systme de calcul formel est un logiciel qui a pour but de manipuler,


de simplifier et de calculer des formules mathmatiques en appliquant unique-
ment des transformations exactes. Le terme formel soppose ici numrique ;
il signifie que les calculs sont effectus sur des formules, de faon algbrique,
en manipulant formellement des symboles. Pour cette raison lexpression
calcul symbolique est parfois employe la place de calcul formel. En anglais,
on dit computer algebra ou parfois symbolic computation.
Les calculatrices manipulent de faon exacte les nombres entiers ayant
moins dune douzaine de chiffres ; les nombres plus grands sont arrondis, ce
qui entrane des erreurs. Ainsi une calculatrice numrique value de faon
errone lexpression suivante en obtenant 0 la place de 1 :

(1 + 1050 ) 1050 .

De telles erreurs sont difficilement dtectables si elles se produisent lors dun


calcul intermdiaire sans tre prvues ni facilement prvisibles par une
tude thorique. Les systmes de calcul formel, au contraire, sappliquent
repousser ces limites et ne faire aucune approximation sur les nombres
entiers pour que les oprations qui en dcoulent soient exactes : ils rpondent 1
au calcul prcdent.
Les mthodes danalyse numrique approchent une prcision donne R (par
une mthode des trapzes, de Simpson, de Gauss, etc.) lintgrale 0 cos t dt
pour obtenir un rsultat numrique plus ou moins proche de zro ( 1010
prs par exemple) sans pouvoir affirmer si le rsultat est le nombre entier 0
de faon exacte ou au contraire est proche de zro mais est non nul.
Un systme formelR transforme par une manipulation de symboles math-
matiques lintgrale 0 cos t dt en la formule sin sin 0 qui est ensuite value
R
de faon exacte en 0 0 = 0. Cette mthode prouve donc 0 cos t dt = 0.
Cependant les transformations uniquement algbriques ont aussi des
limites. La plupart des expressions manipules par les systmes formels sont
des fractions rationnelles et lexpression a/a est automatiquement simplifie
en 1. Ce mode de calcul algbrique ne convient pas la rsolution des
quations ; dans ce cadre, la solution de lquation ax = a est x = a/a qui
est simplifie en x = 1 sans distinguer suivant la valeur de a par rapport 0,
valeur particulire pour laquelle tout nombre x est solution (voir aussi 2.1.5).
1.2. SAGE COMME CALCULATRICE 13

Quelques valeurs spciales


valeurs de vrit vrai et faux True, False
unit imaginaire i I ou i
infini infinity ou oo

Constantes mathmatiques usuelles


constante dArchimde pi
base du logarithme naturel e = exp(1) e

constante dEuler-Mascheroni euler_gamma
nombre dor = (1 + 5)/2 golden_ratio
constante de Catalan catalan

Tableau 1.2 Constantes prdfinies.

1/6*pi
sage: simplify(exp(i*pi/6))
1/2*sqrt(3) + 1/2*I
Nous verrons en 2.1 comment contrler plus finement la simplification des
expressions. Naturellement, on peut aussi calculer des approximations numriques
(le plus souvent, prcision aussi grande que lon veut) des rsultats :
sage: numerical_approx(6*arccos(sin(pi/3)), digits=60)
3.14159265358979323846264338327950288419716939937510582097494
sage: numerical_approx(sqrt(2), digits=60)
1.41421356237309504880168872420969807856967187537694807317668

1.2.3 Aide en ligne et compltion automatique


On peut accder interactivement au manuel de rfrence de toute fonction,
constante ou commande en la faisant suivre dun point dinterrogation ? :
sage: sin?
La page de documentation (en anglais) contient la description de la fonction, sa
syntaxe et des exemples dutilisation.
La touche tabulation hTabi la suite dun dbut de mot montre quelles sont
les commandes commenant par ces lettres : arc suivi de la touche hTabi affiche
ainsi le nom de toutes les fonctions trigonomtriques rciproques :
sage: arc<tab>
Possible completions are:
arc arccos arccosh arccot arccoth arccsc arccsch
arcsec arcsech arcsin arcsinh arctan arctan2 arctanh

1.2.4 Variables Python


Lorsque lon veut conserver le rsultat dun calcul, on peut laffecter une
variable :
14 CHAP. 1. PREMIERS PAS

sage: y = 1 + 2

pour le rutiliser par la suite :


sage: y
3
sage: (2 + y) * y
15

Noter que le rsultat du calcul nest pas affich par dfaut lors dune affectation.
Aussi, nous utiliserons souvent le raccourci suivant :
sage: y = 1 + 2; y
3

le signe ; permettant de sparer plusieurs instructions sur la mme ligne. Le


calcul du rsultat est effectu avant laffectation. On peut donc rutiliser la mme
variable :
sage: y = 3 * y + 1; y
10
sage: y = 3 * y + 1; y
31
sage: y = 3 * y + 1; y
94

Enfin Sage conserve le rsultat des trois calculs prcdents dans les variables
spciales _, __ et ___ :
sage: 1 + 1
2
sage: _ + 1
3
sage: __
2

Les variables que nous venons de manipuler sont des variables au sens de la
programmation Python ; nous y reviendrons plus en dtail en 3.1.3. Mentionnons
seulement quil est recommand de ne pas craser les constantes ni les fonctions
prdfinies de Sage. Le faire ne perturbe pas le fonctionnement interne de Sage,
mais les rsultats ultrieurs de vos calculs ou de vos programmes pourraient tre
troublants :
sage: pi = -I/2
sage: exp(2*i*pi)
e

Pour restaurer la valeur dorigine, on peut utiliser une instruction comme :


sage: from sage.all import pi
1.2. SAGE COMME CALCULATRICE 15

1.2.5 Variables symboliques


Nous
navons jusquici manipul que des expressions constantes telles que
sin( 2). Sage permet aussi et surtout de calculer avec des expressions contenant
des variables, comme x + y + z ou encore sin(x) + cos(x). Les variables symboliques
du mathmaticien x, y, z apparaissant dans ces expressions diffrent, en Sage,
des variables du programmeur que nous avons rencontres dans la section
prcdente. Sage diffre notablement, sur ce point, dautres systmes de calcul
formel comme Maple ou Maxima.
Les variables symboliques doivent tre explicitement dclares avant dtre
employes 5 :
sage: z = SR.var('z')
sage: 2*z + 3
2*z + 3
Dans cet exemple, la commande SR.var(z) construit et renvoie une variable
symbolique dont le nom est z. Cette variable symbolique est un objet Sage
comme un autre : elle nest pas traite diffremment dexpressions plus complexes
comme sin(x) + 1. Ensuite, cette variable symbolique est affecte la variable
du programmeur z, ce qui permet de sen servir comme de nimporte quelle
expression pour construire des expressions plus complexes.
On aurait pu tout aussi bien affecter z une autre variable que z :
sage: y = SR.var('z')
sage: 2*y + 3
2*z + 3
Affecter systmatiquement la variable symbolique z la variable z nest donc
quune simple convention, mais elle est recommande pour viter les confusions.
Inversement, la variable z ninterfre en rien avec la variable symbolique z :
sage: c = 2 * y + 3
sage: z = 1
sage: 2*y + 3
2*z + 3
sage: c
2*z + 3
Comment faire alors pour donner une valeur une variable symbolique qui
apparat dans une expression ? On utilise lopration de substitution, comme
dans
sage: x = SR.var('x')
sage: expr = sin(x); expr
sin(x)
sage: expr(x=1)
sin(1)

5. En fait, la variable symbolique x est prdfinie dans Sage. Mais cest la seule.
16 CHAP. 1. PREMIERS PAS

La substitution dans les expressions symboliques est prsente en dtail au chapitre


suivant.
Exercice 1. Expliquer pas pas ce quil se passe lors de la squence dinstructions :
sage: u = SR.var('u')
sage: u = u+1
sage: u = u+1
sage: u
u + 2

Comme il serait un peu laborieux de crer un grand nombre de variables


symboliques de cette manire, il existe un raccourci var(x) qui est quivalent
x = SR.var(x). Plus gnralement on peut faire par exemple :
sage: var('a, b, c, x, y')
(a, b, c, x, y)
sage: a * x + b * y + c
a*x + b*y + c
Si la dclaration explicite des variables symboliques est juge trop lourde,
il est aussi possible dmuler le comportement de systmes comme Maxima ou
Maple. Pour linstant (Sage 5.9), cette fonctionnalit nest disponible que dans le
bloc-notes. Dans celui-ci, aprs un appel :
sage: automatic_names(True)

toute utilisation dune variable non affecte dclenche implicitement la cration


dune variable symbolique du mme nom et son affectation :
sage: 2 * bla + 3
2*bla + 3
sage: bla
bla

1.2.6 Premiers graphiques


La commande plot permet de tracer facilement la courbe reprsentative dune
fonction relle sur un intervalle donn. La commande plot3d sert aux tracs
en trois dimensions, comme le graphe dune fonction relle de deux variables.
Voici les commandes utilises pour produire les graphiques qui apparaissent sur
la capture dcran en figure 1.3 (page 6) :
sage: plot(sin(2*x), x, -pi, pi)
sage: plot3d(sin(pi*sqrt(x^2 + y^2))/sqrt(x^2+y^2),
....: (x,-5,5), (y,-5,5))
Les capacits graphiques de Sage vont bien au-del de ces exemples. Nous les
explorerons plus en dtail au chapitre 4.
Analyse et algbre
2
Ce chapitre prsente travers des exemples simples les fonctions de base
utiles en analyse et en algbre. Les lycens et tudiants trouveront matire
remplacer le crayon et le papier par le clavier et lcran tout en relevant le mme
dfi intellectuel de comprhension des mathmatiques.
Cet expos des principales commandes de calcul avec Sage se veut accessible
aux lves de lyce ; figurent galement des complments signals par un ast-
risque (*) pour les tudiants de premire anne de licence. On renvoie aux autres
chapitres pour plus de dtails.

2.1 Expressions symboliques et simplification


2.1.1 Expressions symboliques
Sage permet deffectuer toutes sortes de calculs danalyse partir dexpressions
symboliques combinant des nombres, des variables symboliques, les quatre opra-
tions, et des fonctions usuelles comme sqrt, exp, log, sin, cos, etc. Une expression
symbolique peut tre reprsente par un arbre comme ceux de la figure 2.1. Il est
important de comprendre quune expression symbolique est une formule et non pas
une valeur ou une fonction mathmatique. Ainsi, Sage ne reconnat pas que les deux
expressions suivantes sont gales 1 :
sage: bool(arctan(1+abs(x)) == pi/2 - arctan(1/(1+abs(x))))
False
1. Le test dgalit == nest par pour autant une simple comparaison syntaxique des formules :
par exemple, avec Sage 5.9, les expressions arctan(sqrt(2)) et pi/2-arctan(1/sqrt(2)) sont
considres comme gales. En fait, quand on compare deux expressions avec bool(x==y), Sage
tente de prouver que leur diffrence est nulle, et renvoie True si cela russit.
18 CHAP. 2. ANALYSE ET ALGBRE

+ *

^ * 2 + +

x 2 3 x x 1 x 2

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

Figure 2.1 Deux expression symboliques qui reprsentent le mme objet mathmatique.

Cest lutilisateur de transformer les expressions quil manipule afin de les mettre
sous la forme souhaite, grce aux commandes prsentes dans ce chapitre.
Lopration peut-tre la plus commune consiste valuer une expression en
donnant une valeur un ou plusieurs des paramtres qui y apparaissent. La
mthode subs qui peut tre sous-entendue effectue cette manipulation :
sage: a, x = var('a, x'); y = cos(x+a) * (x+1); y
(x + 1)*cos(a + x)
sage: y.subs(a=-x); y.subs(x=pi/2, a=pi/3); y.subs(x=0.5, a=2.3)
x + 1
-1/4*(pi + 2)*sqrt(3)
-1.41333351100299
sage: y(a=-x); y(x=pi/2, a=pi/3); y(x=0.5, a=2.3)
x + 1
-1/4*(pi + 2)*sqrt(3)
-1.41333351100299
Par rapport la notation mathmatique usuelle x 7 f (x), le nom de la variable
substitue doit tre indiqu. La substitution avec plusieurs paramtres est faite
de faon parallle, alors que plusieurs substitutions effectuent des rcritures
squentielles, comme le montrent les deux exemples ci-dessous :
sage: x, y, z = var('x, y, z') ; q = x*y + y*z + z*x
sage: bool(q(x=y, y=z, z=x) == q), bool(q(z=y)(y=x) == 3*x^2)
(True, True)
Notons que pour remplacer une sous-expression plus complexe quune variable,
on dispose de la fonction subs_expr :
sage: y, z = var('y, z'); f = x^3 + y^2 + z
sage: f.subs_expr(x^3 == y^2, z==1)
2*y^2 + 1

2.1.2 Transformation dexpressions


Les expressions avec variables les plus simples sont les polynmes et les
fractions rationnelles une ou plusieurs variables. Les fonctions qui permettent
de les rcrire sous diverses formes ou de les mettre en forme normale sont
2.1. EXPRESSIONS SYMBOLIQUES ET SIMPLIFICATION 19

Fonctions symboliques

Sage permet aussi de dfinir des fonctions symboliques pour la manipula-


tion dexpressions :
sage: f(x)=(2*x+1)^3 ; f(-3)
-125
sage: f.expand()
x |--> 8*x^3 + 12*x^2 + 6*x + 1
Une fonction symbolique nest autre quune expression que lon peut appeler
comme une commande et o lordre des variables est fix. Pour convertir une
expression symbolique en fonction symbolique, on utilise soit la syntaxe dj
mentionne, soit la mthode function :
sage: y = var('y'); u = sin(x) + x*cos(y)
sage: v = u.function(x, y); v
(x, y) |--> x*cos(y) + sin(x)
sage: w(x, y) = u; w
(x, y) |--> x*cos(y) + sin(x)
Les fonctions symboliques servent modliser des fonctions mathma-
tiques. Elles nont pas le mme rle que les fonctions (ou procdures) Python,
qui sont des constructions de programmation dcrites dans le chapitre 3. La
diffrence entre les deux est analogue celle entre variable symbolique et
variable Python, prsente en 1.2.5.
Une fonction symbolique sutilise pratiquement de la mme manire
quune expression, ce qui nest pas le cas dune fonction Python ; par exemple,
la mthode expand ne sapplique pas ces dernires.

rsumes dans le tableau 2.1. Par exemple, la mthode expand sert dvelopper
les polynmes :
sage: x, y = SR.var('x,y')
sage: p = (x+y)*(x+1)^2
sage: p2 = p.expand(); p2
x^3 + x^2*y + 2*x^2 + 2*x*y + x + y
tandis que la mthode collect regroupe les termes suivant les puissances dune
variable donne :
sage: p2.collect(x)
(y + 2)*x^2 + x^3 + (2*y + 1)*x + y
Ces fonctions sappliquent aussi des expressions qui sont polynomiales non
pas en des variables symboliques, mais en des sous-expressions plus compliques
comme sin x :
sage: ((x+y+sin(x))^2).expand().collect(sin(x))
2*(x + y)*sin(x) + x^2 + 2*x*y + y^2 + sin(x)^2
20 CHAP. 2. ANALYSE ET ALGBRE

Polynme p = zx2 + x2 (x2 + y 2 )(ax 2by) + zy 2 + y 2


p.expand().collect(x) ax3 axy 2 + 2 by 3 + (2 by + z + 1)x2 + y 2 z + y 2
p.collect(x).collect(y) 2 bx2 y + 2 by 3 (ax z 1)x2 (ax z 1)y 2
p.expand() ax3 axy 2 2 3 2 2
 + 2 bx y + 2 by + x z + y z + x + y
2 2

p.factor() 2 2
x + y (ax 2 by z 1)
 2  
p.factor_list() x + y 2 , 1 , (ax 2 by z 1, 1) , (1, 1)

x3 +x2 y+3 x2 +3 xy+2 x+2 y


Fraction rationnelle r= x3 +2 x2 +xy+2 y
(x+1)y+x2 +x
r.simplify_rational() x2 +y
(x+1)(x+y)
r.factor() x2 +y
x2
r.factor().expand() x2 +y
+ x2xy
+y
+ x
x2 +y
+ y
x2 +y

(x1)x y2 b c 1
Fraction rationnelle r= x2 7
+ x2 7
+ a
+ a
+ x+1
(x1)x+y 2
r.combine() x2 7
+ b+c
a
+ 1
x+1

1
Fraction rationnelle r=
(x3 +1)y2
(x2)
r.partial_fraction(x) + 1
3 (x+1)y 2
3 (x2 x+1)y 2

Tableau 2.1 Polynmes et fractions rationnelles.

Concernant les fractions rationnelles, la fonction combine permet de regrouper


les termes qui ont mme dnominateur. Quant la fonction partial_fraction,
elle effectue la dcomposition en lments simples dans Q. (Pour prciser le corps
dans lequel il faut effectuer la dcomposition en lments simples, on se reportera
au chapitre 7.4.)
Les reprsentations les plus usites sont la forme dveloppe pour un polynme,
et la forme rduite P/Q avec P et Q dvelopps dans le cas dune fraction
rationnelle. Lorsque deux polynmes ou deux fractions rationnelles sont crits
sous une de ces formes, il suffit de comparer leur coefficients pour dcider sils
sont gaux : on dit que ces formes sont des formes normales.

2.1.3 Fonctions mathmatiques usuelles


La plupart des fonctions mathmatiques se retrouvent en Sage, en particulier les
fonctions trigonomtriques, le logarithme et lexponentielle : elles sont rassembles
dans le tableau 2.2.
La simplification de telles fonctions est cruciale. Pour simplifier une expression
ou une fonction symbolique, on dispose de la commande simplify :
sage: (x^x/x).simplify()
x^(x - 1)
Cependant, pour des simplifications plus subtiles, on doit prciser le type de
simplification attendue :
2.1. EXPRESSIONS SYMBOLIQUES ET SIMPLIFICATION 21

Fonctions mathmatiques usuelles


Exponentielle et logarithme exp, log
Logarithme de base a log(x, a)
Fonctions trigonomtriques sin, cos, tan
Fonctions trigonomtriques rciproques arcsin, arccos, arctan
Fonctions hyperboliques sinh, cosh, tanh
Fonctions hyperboliques rciproques arcsinh, arccosh, arctanh
Partie entire, etc. floor, ceil, trunc, round
Racine carre et n-ime sqrt, nth_root

Transformation des expressions trigonomtriques


Simplification simplify_trig
Linarisation reduce_trig
Anti-linarisation expand_trig

Tableau 2.2 Fonctions usuelles et simplification.

sage: f = (e^x-1) / (1+e^(x/2)); f.simplify_exp()


e^(1/2*x) - 1
Ainsi, pour simplifier des expressions trigonomtriques, on utilise la commande
simplify_trig :
sage: f = cos(x)^6 + sin(x)^6 + 3 * sin(x)^2 * cos(x)^2
sage: f.simplify_trig()
1
Pour linariser (resp. anti-linariser) une expression trigonomtrique, on utilise
reduce_trig (resp. expand_trig) :
sage: f = cos(x)^6; f.reduce_trig()
15/32*cos(2*x) + 3/16*cos(4*x) + 1/32*cos(6*x) + 5/16
sage: f = sin(5 * x); f.expand_trig()
sin(x)^5 - 10*sin(x)^3*cos(x)^2 + 5*sin(x)*cos(x)^4
On peut galement simplifier des expressions faisant intervenir des factorielles :

sage: n = var('n'); f = factorial(n+1)/factorial(n)


sage: f.simplify_factorial()
n + 1
La fonction simplify_rational, quant elle, cherche simplifier une fraction
rationnelle en dveloppant ses membres. Pour simplifier des racines carres, des
logarithmes ou des exponentielles, on utilise simplify_radical :
sage: f = sqrt(abs(x)^2); f.simplify_radical()
abs(x)
sage: f = log(x*y); f.simplify_radical()
log(x) + log(y)
22 CHAP. 2. ANALYSE ET ALGBRE

La commande simplify_full applique (dans lordre) les fonctions simplify_


factorial, simplify_trig, simplify_rational et simplify_radical.
Tout ce qui concerne le classique tableau de variation de la fonction (calcul
des drives, des asymptotes, des extremums, recherche des zros et trac de la
courbe) peut tre facilement ralis laide dun systme de calcul formel. Les
principales oprations Sage qui sappliquent une fonction sont prsentes dans
la section 2.3.

2.1.4 Hypothses sur une variable symbolique


Lors des calculs, les variables symboliques qui apparaissent dans les expressions
sont en gnral considres comme pouvant prendre nimporte quelle valeur
complexe. Cela pose problme quand un paramtre reprsente une quantit
restreinte un domaine particulier (par exemple, relle positive) dans lapplication
que lutilisateur a en tte.
Un cas typique est la simplification de lexpression x2 . Pour simplifier de
telles expressions, la bonne solution consiste utiliser la fonction assume qui
permet de prciser les proprits dune variable. Si on souhaite annuler cette
hypothse, on emploie linstruction forget :
sage: assume(x > 0); bool(sqrt(x^2) == x)
True
sage: forget(x > 0); bool(sqrt(x^2) == x)
False
sage: n = var('n'); assume(n, 'integer'); sin(n*pi).simplify()
0

2.1.5 Quelques dangers


Soit c une expression un tout petit peu complique :
sage: a = var('a')
sage: c = (a+1)^2 - (a^2+2*a+1)
et cherchons rsoudre lquation en x donne par cx = 0 :
sage: eq = c * x == 0
Lutilisateur imprudent pourrait tre tent de simplifier cette quation par c avant
de la rsoudre :
sage: eq2 = eq / c; eq2
x == 0
sage: solve(eq2, x)
[x == 0]
Heureusement, Sage ne fait pas cette erreur :
sage: solve(eq, x)
[x == x]
2.1. EXPRESSIONS SYMBOLIQUES ET SIMPLIFICATION 23

Le problme de la simplification

Les exemples de la section 2.1.5 illustrent limportance des formes nor-


males, et en particulier du test de nullit. Sans lui, tout calcul faisant intervenir
une division devient hasardeux.
Certaines familles dexpressions, limage des polynmes, admettent
une procdure de dcision pour la nullit. Cela signifie que pour ces classes
dexpressions, un programme peut dterminer si une expression donne est
nulle ou non. Dans de nombreux cas, cette dcision se fait par rduction
la forme normale : lexpression est nulle si et seulement si sa forme normale
est 0.
Malheureusement, toutes les classes dexpressions nadmettent pas une
forme normale, et pour certaines classes, on peut dmontrer quil ny a pas
de mthode gnrale pour vrifier en un temps fini si une expression est nulle.
Un exemple dune telle classe est fourni par les expressions composes partir
des rationnels, des nombres et log 2 et dune variable, par utilisation rpte
de laddition, de la soustraction, du produit, de lexponentielle et du sinus.
Une utilisation rpte de numerical_approx en augmentant la prcision
permet certes souvent de conjecturer si une expression particulire est nulle
ou non ; mais il a t montr quil est impossible dcrire un programme
prenant en argument une expression de cette classe et renvoyant le rsultat
vrai si celle-ci est nulle, et faux sinon.
Cest dans ces classes que se pose avec le plus dacuit le problme de
la simplification. Sans forme normale, les systmes ne peuvent que donner
un certain nombre de fonctions de rcriture avec lesquelles lutilisateur doit
jongler pour parvenir un rsultat. Pour y voir plus clair, il faut identifier
des sous-classes dexpressions qui admettent des formes normales et savoir
quelles fonctions appeler pour calculer ces dernires. Lapproche de Sage face
ces difficults est prsente plus en dtail au chapitre 5.

Ici, Sage a pu rsoudre correctement le systme car le coefficient c est une


expression polynomiale. Il est donc facile de tester si c est nul ; il suffit de le
dvelopper :
sage: expand(c)
0
et dutiliser le fait que deux polynmes sous forme dveloppe identiques sont
gaux, autrement dit, que la forme dveloppe est une forme normale.
En revanche, sur un exemple peine plus compliqu, Sage commet une erreur :
sage: c = cos(a)^2 + sin(a)^2 - 1
sage: eq = c*x == 0
sage: solve(eq, x)
[x == 0]
alors mme quil sait faire la simplification et mme le test zro correctement :
24 CHAP. 2. ANALYSE ET ALGBRE

quations numriques
Rsolution symbolique solve
Rsolution (avec multiplicit) roots
Rsolution numrique find_root

quations vectorielles et quations fonctionnelles


Rsolution dquations linaires right_solve, left_solve
Rsolution dquations diffrentielles desolve
Rsolution de rcurrences rsolve

Tableau 2.3 Rsolution dquations.

sage: c.simplify_trig()
0
sage: c.is_zero()
True

2.2 quations
Nous abordons maintenant les quations et leur rsolution ; les principales
fonctions sont rsumes dans le tableau 2.3.

2.2.1 Rsolution explicite


Considrons lquation dinconnue z et de paramtre suivante :

2 5 i h
z2 z+ 4 = 0, avec , .
cos cos2 2 2

Elle scrit :
sage: z, phi = var('z, phi')
sage: eq = z**2 - 2/cos(phi)*z + 5/cos(phi)**2 - 4 == 0; eq
z^2 - 2*z/cos(phi) + 5/cos(phi)^2 - 4 == 0

On peut en extraire le membre de gauche (resp. de droite) laide de la mthode


lhs (resp. rhs) :
sage: eq.lhs()
2z
z 2 cos() + cos()
5
2 4

sage: eq.rhs()
0

puis la rsoudre avec solve :


sage: solve(eq, z)
2.2. QUATIONS 25

 
2 cos()2 11 2 cos()2 1+1
z= cos() , z = cos()

Soit maintenant rsoudre lquation y 6 = y.


sage: y = var('y'); solve(y^6==y, y)
[y == e^(2/5*I*pi), y == e^(4/5*I*pi), y == e^(-4/5*I*pi),
y == e^(-2/5*I*pi), y == 1, y == 0]
Les solutions peuvent tre renvoyes sous la forme dun objet du type dictionnaire
(cf. 3.3.9) :
sage: solve(x^2-1, x, solution_dict=True)
[{x: -1}, {x: 1}]
La commande solve permet galement de rsoudre des systmes :
sage: solve([x+y == 3, 2*x+2*y == 6], x, y)
[[x == -r1 + 3, y == r1]]
Ce systme linaire tant indtermin, linconnue secondaire qui permet de para-
mtrer lensemble des solutions est un rel dsign par r1, r2, etc. Si le paramtre
est implicitement un entier, il est dsign sous la forme z1, z2, etc. (ci-dessous
z... dsigne z36, z60, ou autre suivant la version de Sage) :
sage: solve([cos(x)*sin(x) == 1/2, x+y == 0], x, y)
[[x == 1/4*pi + pi*z..., y == -1/4*pi - pi*z...]]
Enfin, la fonction solve peut tre utilise pour rsoudre des inquations :
sage: solve(x^2+x-1 > 0, x)
[[x < -1/2*sqrt(5) - 1/2], [x > 1/2*sqrt(5) - 1/2]]
Il arrive que les solutions dun systme renvoyes par la fonction solve soient
sous forme de flottants. Soit, par
exemple, rsoudre dans C3 le systme suivant :
x yz = 18,
2

xy 3 z = 24,
xyz 4 = 3.

sage: x, y, z = var('x, y, z')


sage: solve([x^2 * y * z == 18, x * y^3 * z == 24,\
....: x * y * z^4 == 3], x, y, z)
[[x == (-2.76736473308 - 1.71347969911*I), y == (-0.570103503963 +
2.00370597877*I), z == (-0.801684337646 - 0.14986077496*I)], ...]
Sage renvoie ici 17 triplets de solutions complexes approches. Pour obtenir une
solution symbolique, on se reportera au chapitre 9.
Pour effectuer des rsolutions numriques dquations, on utilise la fonction
find_root qui prend en argument une fonction dune variable ou une galit
symbolique, et les bornes de lintervalle dans lequel il faut chercher une solution.
sage: expr = sin(x) + sin(2 * x) + sin(3 * x)
sage: solve(expr, x)
[sin(3*x) == -sin(2*x) - sin(x)]
26 CHAP. 2. ANALYSE ET ALGBRE

Sage ne trouve pas de solution symbolique cette quation. Deux choix sont alors
possibles : soit on passe une rsolution numrique,
sage: find_root(expr, 0.1, pi)
2.0943951023931957
soit on transforme au pralable lexpression.
sage: f = expr.simplify_trig(); f
2*(2*cos(x)^2 + cos(x))*sin(x)
sage: solve(f, x)
[x == 0, x == 2/3*pi, x == 1/2*pi]
Enfin la fonction roots permet dobtenir les solutions exactes dune quation,
avec leur multiplicit. On peut prciser en outre lanneau dans lequel on souhaite
effectuer la rsolution ; si on choisit RR R ou CC C on obtient les rsultats
sous forme de nombres virgule flottante : la mthode de rsolution sous-jacente
est spcifique lquation considre, contrairement find_roots qui utilise une
mthode gnrique.
Considrons lquation du troisime degr x3 + 2 x + 1 = 0. Cette quation
est de discriminant ngatif, donc elle possde une racine relle et deux racines
complexes, que lon peut obtenir grce la fonction roots :
sage: (x^3+2*x+1).roots(x)
" ( 13 )
1   1 1 I 31

I 3+1 3 59 +  1 ,1 ,
2 18 2 1 (3)

3 18 3 59 2
1

(3)
1
1   1 1 I 3 1
  
I 3 + 1 3 59 +  1 ,1 ,
2 18 2 1 (3)

3 18 3 59 2
1

( 13 )

1 1

2
3 59 +  1 ,1
18 2 1 (3)

3 18 3 59 2
1

sage: (x^3+2*x+1).roots(x, ring=RR)


[(0.453397651516404, 1)]

sage: (x^3+2*x+1).roots(x, ring=CC)


(0.453397651516404, 1), (0.226698825758202 1.46771150871022 I, 1),


(0.226698825758202 + 1.46771150871022 I, 1)


2.2.2 quations sans solution explicite


Dans la plupart des cas, ds que le systme devient trop compliqu, il nest
pas possible de calculer une solution explicite :
sage: solve(x^(1/x)==(1/x)^x, x)
[(1/x)^x == x^(1/x)]
2.3. ANALYSE 27

Contrairement ce que lon pourrait penser, cela nest pas forcment une
limitation ! De fait, un leitmotiv du calcul formel est que lon peut trs bien
manipuler des objets dfinis par des quations, et en particulier calculer leurs
proprits, sans passer par la rsolution explicite de celles-ci. Mieux encore,
lquation dfinissant un objet est souvent la meilleure description algorithmique
de cet objet.
Ainsi, une fonction dfinie par une quation diffrentielle linaire et des
conditions initiales est parfaitement prcise. Lensemble des solutions dquations
diffrentielles linaires est clos par somme et produit (entre autres) et forme ainsi
une importante classe o lon peut dcider de la nullit. En revanche, si lon rsout
une telle quation, la solution, prive de son quation de dfinition, tombe dans
une classe plus grande o bien peu est dcidable :
sage: y = function('y', x)
sage: desolve(diff(y,x,x) + x*diff(y,x) + y == 0, y, [0,0,1])
-1/2*I*sqrt(pi)*sqrt(2)*e^(-1/2*x^2)*erf(1/2*I*sqrt(2)*x)
Nous reviendrons sur ces considrations plus en dtail au chapitre 14 et au
15.1.2 du chapitre 15.

2.3 Analyse
Dans cette section, nous prsentons succinctement les fonctions couramment
utiles en analyse relle. Pour une utilisation avance ou des complments, on
renvoie aux chapitres suivants notamment ceux qui traitent de lintgration
numrique (ch. 14), de la rsolution des quations non linaires (ch. 12), et des
quations diffrentielles (ch. 10).

2.3.1 Sommes
Pour calculer des sommes symboliques on utilise la fonction sum. Calculons
par exemple la somme des n premiers entiers non nuls :
sage: k, n = var('k, n')
sage: sum(k, k, 1, n).factor()
2 (n + 1)n
1

La fonction sum permet deffectuer des simplifications partir du binme de


Newton :
sage: n, k, y = var('n, k, y')
sage: sum(binomial(n,k) * x^k * y^(n-k), k, 0, n)
n
(x + y)
Voici dautres exemples, dont la somme des cardinaux des parties dun ensemble
n lments :
sage: k, n = var('k, n')
28 CHAP. 2. ANALYSE ET ALGBRE

sage: sum(binomial(n,k), k, 0, n),\


....: sum(k * binomial(n, k), k, 0, n),\
....: sum((-1)^k*binomial(n,k), k, 0, n)
2n , n2n1 , 0


Enfin, quelques exemples de sommes gomtriques :


sage: a, q, k, n = var('a, q, k, n')
sage: sum(a*q^k, k, 0, n)
aq n+1 a
q1

Pour calculer la srie correspondante, il faut prciser que le module de la


raison est infrieur 1 :
sage: assume(abs(q) < 1)
sage: sum(a*q^k, k, 0, infinity)
a
q1

sage: forget(); assume(q > 1); sum(a*q^k, k, 0, infinity)


Traceback (most recent call last):
...
ValueError: Sum is divergent.
Exercice 2 (Un calcul de somme par rcurrence). Calculer sans utiliser lalgorithme
de Sage la somme des puissances p-imes des entiers de 0 n, pour p = 1, ..., 4 :
n
X
Sn (p) = kp .
k=0

Pour calculer cette somme, on peut utiliser la formule de rcurrence suivante :


p1   !
1 X p+1
Sn (p) = (n + 1)p+1 Sn (j) .
p+1 j
j=0

Cette relation de
P rcurrence stablit facilement en calculant de deux manires la somme
tlescopique (k + 1)p+1 kp+1 .
06k6n

2.3.2 Limites
Pour calculer une limite, on utilise la commande limit ou son alias lim. Soient
calculer les limites suivantes :
3
x2
a) lim ;
x8 3
x + 19 3
cos 4 x tan x

b) lim  .
x 4 1 sin 4 + x

sage: limit((x**(1/3) - 2) / ((x + 19)**(1/3) - 3), x = 8)


9/4
sage: f(x) = (cos(pi/4-x)-tan(x))/(1-sin(pi/4 + x))
2.3. ANALYSE 29

sage: limit(f(x), x = pi/4)


Infinity
La dernire rponse indique que lune des limites gauche ou droite est infinie.
Pour prciser le rsultat, on tudie les limites gauche (minus) et droite (plus),
en utilisant loption dir :
sage: limit(f(x), x = pi/4, dir='minus')
+Infinity
sage: limit(f(x), x = pi/4, dir='plus')
-Infinity

2.3.3 Suites
Les fonctions prcdentes permettent deffectuer des tudes de suites. On
donne un exemple dtude de croissance compare entre une suite exponentielle
et une suite gomtrique.
100
Exemple. (Une tude de suite) On considre la suite un = 100 n
n . Calculer les

10 premiers termes de la suite. Quelle est la monotonie de la suite ? Quelle est la


limite de la suite ? partir de quel rang a-t-on un 0, 108 ?
 

1. Pour dfinir le terme de la suite un , on utilise une fonction symbolique. On


effectue le calcul des 10 premiers termes la main (en attendant davoir
vu les boucles au chapitre 3) :
sage: u(n) = n^100 / 100^n
sage: u(2.);u(3.);u(4.);u(5.);u(6.);u(7.);u(8.);u(9.);u(10.)
1.26765060022823e26
5.15377520732011e41
1.60693804425899e52
7.88860905221012e59
6.53318623500071e65
3.23447650962476e70
2.03703597633449e74
2.65613988875875e77
1.00000000000000e80

On pourrait en conclure htivement que un tend vers linfini...


2. Pour avoir une ide de la monotonie, on peut tracer la fonction laide de
laquelle on a dfini la suite un (cf. figure 2.2).
sage: plot(u(x), x, 1, 40)

On conjecture que la suite va dcrotre partir du rang 22.


sage: v(x) = diff(u(x), x); sol = solve(v(x) == 0, x); sol
[x == 100/log(100), x == 0]
sage: floor(sol[0].rhs())
21
30 CHAP. 2. ANALYSE ET ALGBRE

1.6e90
1.4e90
1.2e90
1e90
8e89
6e89
4e89
2e89
0 5 10 15 20 25 30 35 40
Figure 2.2 Graphe de x 7 x100 /100x .

La suite est donc croissante jusquau rang 21, puis dcroissante partir du
rang 22.
3. On effectue ensuite le calcul de la limite :
sage: limit(u(n), n=infinity)
0
sage: n0 = find_root(u(n) - 1e-8 == 0, 22, 1000); n0
105.07496210187252
La suite tant dcroissante partir du rang 22, on en dduit qu partir du
rang 106, la suite reste confine lintervalle 0, 108 .

2.3.4 Dveloppements limits (*)


Pour calculer un dveloppement limit dordre n au sens fort 2 en x0 , on
dispose de la fonction f(x).series(x==x0, n). Si lon ne sintresse qu la
partie rgulire du dveloppement limit lordre n (au sens faible), on peut aussi
utiliser la fonction taylor(f(x), x, x0, n).
Dterminons le dveloppement limit des fonctions suivantes :
1
a) (1 + arctan x) x lordre 3, en x0 = 0 ;

b) ln(2 sin x) lordre 3, en x0 =


6.

sage: taylor((1+arctan(x))**(1/x), x, 0, 3)
16 x e + 8 x e 2 xe + e
1 3 1 2 1

2. On appelle dveloppement limit en 0 au sens fort une galit de la forme f (x) =


P (x)+O(xn+1 ) avec P polynme de degr au plus n, par opposition la notion de dveloppement
limit au sens faible qui dsigne une galit de la forme f (x) = P (x) + o(xn ).
2.3. ANALYSE 31

Fonctions et oprateurs
Drivation diff(f(x), x)
Drive n-ime diff(f(x), x, n)
Intgration integrate(f(x), x)
Intgration numrique integral_numerical(f(x), a, b)
Somme symbolique sum(f(i), i, imin, imax)
Limite limit(f(x), x=a)
Polynme de Taylor taylor(f(x), x, a, n)
Dveloppement limit f.series(x==a, n)
Trac dune courbe plot(f(x), x, a, b)

Tableau 2.4 Rcapitulatif des fonctions utiles en analyse.

sage: (ln(2*sin(x))).series(x==pi/6, 3)
2

3

( 3)( 16 + x) + (2)( 16 + x) + O 216
1
( 6 x)

Pour extraire la partie rgulire dun dveloppement limit obtenu laide de


series, on utilise la fonction truncate :
sage: (ln(2*sin(x))).series(x==pi/6, 3).truncate()
2
1
18 ( 6 x) 16 ( 6 x) 3
La commande taylor permet galement dobtenir des dveloppements asymp-
totiques. Par exemple, pour obtenir un quivalent au voisinage de + de la
1 1
fonction (x3 + x) 3 (x3 x) 3 :
sage: taylor((x**3+x)**(1/3) - (x**3-x)**(1/3), x, infinity, 2)
2/3/x
Exercice 3 (Un calcul symbolique de limite). Soit f de classe C 3 au voisinage de
a R. Calculer
1
lim (f (a + 3h) 3f (a + 2h) + 3f (a + h) f (a))
h0 h3
Gnralisation ?
Exemple (*). (La formule de Machin) Montrer la formule suivante :
1 1
= 4 arctan arctan .
4 5 239
Cest laide de cette formule et du dveloppement darctan en srie entire,
que lastronome John Machin (1680-1752) calcula cent dcimales de en 1706.
Dduire de cette formule une valeur approche de en utilisant sa mthode.
On commence par remarquer que 4 arctan 15 et 4 + arctan 239 1
ont mme
tangente :
sage: tan(4*arctan(1/5)).simplify_trig()
120/119
sage: tan(pi/4+arctan(1/239)).simplify_trig()
120/119
32 CHAP. 2. ANALYSE ET ALGBRE

Or les rels 4 arctan 15 et 4 +arctan 239


1
appartiennent tous les deux lintervalle
ouvert ]0, [, donc ils sont gaux. Pour obtenir une valeur approche de , on
peut procder de la manire suivante :
sage: f = arctan(x).series(x, 10); f
1*x + (-1/3)*x^3 + 1/5*x^5 + (-1/7)*x^7 + 1/9*x^9 + Order(x^10)
sage: (16*f.subs(x==1/5) - 4*f.subs(x==1/239)).n(); pi.n()
3.14159268240440
3.14159265358979
Exercice 4 (Une formule due Gauss). La formule suivante ncessite le calcul de
20 pages de tables de factorisations dans ldition des uvres de Gauss (cf. Werke, ed.
Kngl. Ges. de Wiss. Gttingen, vol. 2, p. 477-502) :

1 1 1 1
= 12 arctan + 20 arctan + 7 arctan + 24 arctan .
4 38 57 239 268
1 1 1 1
1. On pose = 12 arctan 38 + 20 arctan 57 + 7 arctan 239
+ 24 arctan 268
.
Vrifier laide de Sage, que tan = 1.
, tan x 6

 4
2. Prouver lingalit : x 0, 4
x. En dduire la formule de Gauss.
3. En approchant la fonction arctan par son polynme de Taylor dordre 21 en 0,
donner une nouvelle approximation de .

2.3.5 Sries (*)


On peut utiliser les commandes prcdentes pour effectuer des calculs sur les
sries. Donnons quelques exemples.
Exemple. (Calcul de la somme de sries de Riemann)
sage: k = var('k')
sage: sum(1/k^2, k, 1, infinity),\
....: sum(1/k^4, k, 1, infinity),\
....: sum(1/k^5, k, 1, infinity)
1 2 1 4

6 , 90 , (5)

Exemple. (Une formule due Ramanujan) En utilisant la somme partielle


des 12 premiers termes de la srie suivante, donnons une approximation de et
comparons-la avec la valeur donne par Sage.
+
1 2 2 X (4k)! (1103 + 26390 k)
= .
9801 (k!)4 3964k
k=0

sage: s = 2*sqrt(2)/9801*(sum((factorial(4*k)) * (1103+26390*k) /


....: ((factorial(k)) ^ 4 * 396 ^ (4 * k)) for k in (0..11)))
sage: (1/s).n(digits=100)
3.141592653589793238462643383279502884197169399375105820974...
sage: (pi-1/s).n(digits=100).n()
-4.36415445739398e-96
2.3. ANALYSE 33

On remarque que la somme partielle des 12 premiers termes donne dj 95


dcimales significatives de !
Exemple. (Convergence dune srie) Soit tudier la nature de la srie
X  p 
sin 4 n2 + 1 .
n>0

Pour effectuer un dveloppement asymptotique du terme gnral, on utilise la


2-priodicit de la fonction sinus pour que largument du sinus tende vers 0 :
 p  h p i
un = sin 4 n2 + 1 = sin 4 n2 + 1 2n .

On peut alors appliquer la fonction taylor cette nouvelle expression du terme


gnral :
sage: n = var('n'); u = sin(pi*(sqrt(4*n^2+1)-2*n))
sage: taylor(u, n, infinity, 3)
6 + 3
4 n 384 n3

On en dduit un P4n . Donc, daprs les rgles de comparaison aux sries de


Riemann, la srie un diverge.
n>0
Exercice 5 (Dveloppement asymptotique dune suite). Il est ais de montrer (en
utilisant par exemple le thorme de la bijection monotone) que pour tout n N,
lquation tan x = x admet une et une seule solution xn dans lintervalle [n, n + 2 [.
Donner un dveloppement asymptotique de xn lordre 6 en +.

2.3.6 Drivation
La fonction derivative (qui a pour alias diff) permet de driver une expres-
sion symbolique ou une fonction symbolique.
sage: diff(sin(x^2), x)
2*x*cos(x^2)
sage: function('f', x); function('g', x); diff(f(g(x)), x)
f(x)
g(x)
D[0](f)(g(x))*D[0](g)(x)
sage: diff(ln(f(x)), x)
D[0](f)(x)/f(x)

2.3.7 Drives partielles (*)


La commande diff permet galement de calculer des drives n-imes ou des
drives partielles.
sage: f(x,y) = x*y + sin(x^2) + e^(-x); derivative(f, x)
(x, y) |--> 2*x*cos(x^2) + y - e^(-x)
sage: derivative(f, y)
34 CHAP. 2. ANALYSE ET ALGBRE

(x, y) |--> x

Exemple. Soit vrifier que la fonction suivante est harmonique 3 :


f (x, y) = 21 ln(x2 + y 2 ) pour tout (x, y) 6= (0, 0).
sage: x, y = var('x, y'); f = ln(x**2+y**2) / 2
sage: delta = diff(f,x,2) + diff(f,y,2)
sage: delta.simplify_full()
0
Exercice 6 (Un contre-exemple d Peano au thorme de Schwarz). Soit f
lapplication de R2 dans R dfinie par :
( 2 2
xy xx2 y
+y 2
si (x, y) 6= (0, 0),
f (x, y) =
0 si (x, y) = (0, 0).

A-t-on 1 2 f (0, 0) = 2 1 f (0, 0) ?

2.3.8 Intgration
Pour calculer une primitive ou une intgrale, on utilise la fonction integrate
(ou son alias integral) :
sage: sin(x).integral(x, 0, pi/2)
1
sage: integrate(1/(1+x^2), x)
arctan(x)
sage: integrate(1/(1+x^2), x, -infinity, infinity)
pi
sage: integrate(exp(-x**2), x, 0, infinity)
1/2*sqrt(pi)

sage: integrate(exp(-x), x, -infinity, infinity)


Traceback (most recent call last):
...
ValueError: Integral is divergent.
+
x cos u
Z
Exemple. Soit calculer, pour x R, lintgrale (x) = du.
0 u2 + x2
sage: u = var('u'); f = x * cos(u) / (u^2 + x^2)
sage: assume(x>0); f.integrate(u, 0, infinity)
1/2*pi*e^(-x)
sage: forget(); assume(x<0); f.integrate(u, 0, infinity)
-1/2*pi*e^x

On a donc : x R , (x) =
2 sgn(x) e|x| .

3. Une fonction f est dite harmonique lorsque son Laplacien f = 12 f + 22 f est nul.
2.4. ALGBRE LINAIRE LMENTAIRE 35

Pour effectuer une intgration numrique sur un intervalle, on dispose de


la fonction integral_numerical qui renvoie un tuple deux lments, dont la
premire composante donne une valeur approche de lintgrale, et la deuxime
une estimation de lerreur effectue.
sage: integral_numerical(sin(x)/x, 0, 1)
(0.94608307036718287, 1.0503632079297086e-14)
sage: g = integrate(exp(-x**2), x, 0, infinity)
sage: g, g.n()
(1/2*sqrt(pi), 0.886226925452758)
sage: approx = integral_numerical(exp(-x**2), 0, infinity)
sage: approx
(0.88622692545275705, 1.7147744320162414e-08)
sage: approx[0]-g.n()
-8.88178419700125e-16
Exercice 7 (La formule BBP (*)). On cherche tablir par un calcul symbolique
la formule BBP (ou Bailey-Borwein-Plouffe) ; cette formule permet de calculer le n-ime
chiffre aprs la virgule de en base 2 (ou 16) sans avoir en calculer les prcdents, et
en utilisant trs peu de mmoire et de temps. Pour N N, on pose
N  n
4 2 1 1 1
X 
SN = .
8n + 1 8n + 4 8n + 5 8n + 6 16
n=0

1. Soit la fonction f : t 7 4 2 8t3 4 2t4 8t5 . Pour N N, exprimer en
fonction de SN lintgrale suivante :
!
Z 1/ 2 N
X 8n
IN = f (t) t dt.
0 n=0


Z 1/ 2
f (t)
2. Pour N N, on pose J = dt. Montrer lim SN = J.
0
1 t8 N +

3. Montrer la formule BBP :


+  n
4 2 1 1 1
X 
= .
8n + 1 8n + 4 8n + 5 8n + 6 16
n=0

Cette formule remarquable a t obtenue le 19 septembre 1995 par Simon Plouffe


en collaboration avec David Bailey et Peter Borwein. Grce une formule drive
de la formule BBP, le 4 000 000 000 000 000e chiffre de en base 2 a t obtenu en
2001.

2.4 Calcul matriciel (*)


Dans cette section, on dcrit les fonctions de base utiles en algbre linaire :
oprations sur les vecteurs, puis sur les matrices. Pour plus de dtails, on renvoie
au chapitre 8 pour le calcul matriciel symbolique et au chapitre 13 pour le calcul
matriciel numrique.
36 CHAP. 2. ANALYSE ET ALGBRE

Fonctions usuelles sur les vecteurs


Dclaration dun vecteur vector
Produit vectoriel cross_product
Produit scalaire dot_product
Norme dun vecteur norm

Tableau 2.5 Calcul vectoriel.

2.4.1 Rsolution de systmes linaires


Pour rsoudre un systme linaire, on peut utiliser la fonction solve dj
rencontre.
Exercice 8 (Approximation polynomiale du sinus). Dterminer le polynme de
degr au plus 5 qui ralise la meilleure approximation, au sens des moindres carrs, de
la fonction sinus sur lintervalle [, ] :
Z 
5 = min |sin x P (x)|2 dx P R5 [x] .

2.4.2 Calcul vectoriel


Les fonctions de base utiles pour la manipulation des vecteurs sont rsumes
dans le tableau 2.5.
On peut se servir de ces fonctions pour traiter lexercice suivant.
Exercice 9 (Le problme de Gauss). On considre un satellite en orbite autour de
la Terre et on suppose que lon connat trois points de son orbite : A1 , A2 et A3 . On
souhaite dterminer partir de ces trois points les paramtres de lorbite de ce satellite.
On note O le centre de la Terre. Les points O, A1 , A2 et A3 sont videmment situs
dans un mme plan, savoir le plan de lorbite du satellite. Lorbite du satellite est
une ellipse dont O est un foyer. On peut choisir un repre (O; ,
) de telle sorte que
lquation de lellipse en coordonnes polaires soit dans ce repre r = 1epcos o e

dsigne lexcentricit de lellipse et p son paramtre. On notera
r = OA et r = k
i i

r k
i i
pour i {1, 2, 3}. On considre alors les trois vecteurs suivants qui se dduisent de la
connaissance de A1 , A2 et A3 :


D =r1

r2 +
r2

r3 +
r3
r1 ,


S = (r1 r3 ) r2 + (r3 r2 )


r1 + (r2 r1 )

r3 ,








N = r (r r ) + r (r r ) + r (r r ) .
3 1 2 1 2 3 2 3 1




1. Montrer que

D = 1e S et en dduire lexcentricit e de lellipse.


2. Montrer que

est colinaire au vecteur S D .



3. Montrer que

N = pe S et en dduire le paramtre p de lellipse.
4. Exprimer le demi-grand axe a de lellipse en fonction du paramtre p et de
lexcentricit e.
2.4. ALGBRE LINAIRE LMENTAIRE 37

5. Application numrique : dans le plan rapport un repre orthonorm direct, on


considre les points suivants :

A1 ( 01 ) , A2 ( 22 ) , A3 ( 3.5
0 ), O ( 00 ) .

Dterminer numriquement les caractristiques de lunique ellipse dont O est un


foyer et qui passe par les trois points A1 , A2 et A3 .

2.4.3 Calcul matriciel


Pour dfinir une matrice, on utilise linstruction matrix en prcisant ventuel-
lement lanneau (ou le corps) de base :

sage: A = matrix(QQ, [[1,2],[3,4]]); A


[1 2]
[3 4]

Pour trouver une solution particulire lquation matricielle Ax = b (resp.


xA = b), on utilise la fonction solve_right (resp. solve_left). Pour trouver
toutes les solutions dune quation matricielle, il faut ajouter une solution
particulire la forme gnrale de lquation homogne associe. Pour rsoudre une
quation homogne de la forme Ax = 0 (resp. xA = 0), on utilisera la fonction
right_kernel (resp. left_kernel), comme dans lexercice suivant.

Exercice 10 (Bases de sous-espaces vectoriels). 1. Dterminer une base de les-


pace des solutions du systme linaire homogne associ la matrice :

3 12

2 2 33
6 1 26 16 69
A= .
10 29 18 53 32
2 0 8 18 84

2. Dterminer une base de lespace F engendr par les colonnes de A.


3. Caractriser F par une ou plusieurs quations.
Exercice 11 (Une quation matricielle). On rappelle le lemme de factorisation des
applications linaires. Soient E, F, G des K-espaces vectoriels de dimension finie. Soient
u L(E, F ) et v L(E, G). Alors les assertions suivantes sont quivalentes :

i) il existe w L(F, G) tel que v = w u,


ii) Ker(u) Ker(v).

On cherche toutes les solutions ce problme dans un cas concret. Soient


 2 1 1
  1 2 1

A= 8 1 5 et C= 2 1 1 .
4 3 3 5 0 3

Dterminer toutes les solutions B M3 (R) de lquation A = BC.


38 CHAP. 2. ANALYSE ET ALGBRE

Fonctions usuelles sur les matrices


Dclaration dune matrice matrix
Rsolution dune quation matricielle solve_right, solve_left
Noyau droite, gauche right_kernel, left_kernel
Rduction sous forme chelonne en ligne echelon_form
Sous-espace engendr par les colonnes column_space
Sous-espace engendr par les lignes row_space
Concatnation de matrices matrix_block

Rduction des matrices


Valeurs propres dune matrice eigenvalues
Vecteurs propres dune matrice eigenvectors_right
Rduction sous forme normale de Jordan jordan_form
Polynme minimal dune matrice minimal_polynomial
Polynme caractristique dune matrice characteristic_polynomial

Tableau 2.6 Calcul matriciel.

2.4.4 Rduction dune matrice carre


Pour tudier les lments propres dune matrice, on dispose des fonctions
rsumes dans le tableau 2.6.
Ces fonctions seront dtailles dans le chapitre 8. On se contente de donner
ici quelques exemples simples dutilisation.
 2 4 3 
Exemple. La matrice A = 4 6 3 est-elle diagonalisable ? trigonali-
3 3 1
sable ?
On commence par dfinir la matrice A en indiquant le corps de base (QQ=Q),
puis on dtermine les lments propres.
sage: A = matrix(QQ, [[2,4,3],[-4,-6,-3],[3,3,1]])
sage: A.characteristic_polynomial()
x^3 + 3*x^2 - 4
sage: A.eigenvalues()
[1, -2, -2]
sage: A.minimal_polynomial().factor()
(x - 1) * (x + 2)^2
Le polynme minimal de A possde une racine simple et une racine double ; donc
A nest pas diagonalisable. Par contre, le polynme minimal de A est scind donc
A est trigonalisable.
sage: A.eigenvectors_right()
[(1, [(1, 1, 1)] , 1) , (2, [(1, 1, 0)] , 2)]

sage: A.jordan_form(transformation=True)
1 0 0 1 1 1

0 2 1 , 1 1 0
0 0 2 1 0 1
2.4. ALGBRE LINAIRE LMENTAIRE 39

 
1 1/2
Exemple. Soit diagonaliser la matrice A = 1/2 1 . On peut essayer
de diagonaliser cette matrice en utilisant la fonction jordan_form :
sage: A = matrix(QQ, [[1,-1/2],[-1/2,-1]])
sage: A.jordan_form()
Traceback (most recent call last):
...
RuntimeError: Some eigenvalue does not exist in Rational Field.
Mais, ici une petite difficult apparat : les valeurs propres ne sont pas rationnelles.
sage: A = matrix(QQ, [[1,-1/2],[-1/2,-1]])
sage: A.minimal_polynomial()
x^2 - 5/4
Il faut donc changer de corps de base.
sage: R = QQ[sqrt(5)]
sage: A = A.change_ring(R)
sage: A.jordan_form(transformation=True, subdivide=False)
1
sqrt5 0 
1 1

2 ,
1 sqrt + 2 sqrt + 2
0 sqrt5 5 5
2
Ce qui sinterprte ainsi :
 1
2 5 0 1 1
  
,
0 12 5 5+2 5+2
 
2 6 2
Exemple. Soit diagonaliser la matrice A = 6 3 3
2 3 1
Cette fois-ci, il faut travailler dans une extension de degr 4 du corps Q. On
peut alors procder comme suit.
sage: K.<sqrt2> = NumberField(x^2 - 2)
sage: L.<sqrt3> = K.extension(x^2 - 3)
sage: A = matrix(L, [[2, sqrt2*sqrt3, sqrt2], \
....: [sqrt2*sqrt3, 3, sqrt3], \
....: [sqrt2, sqrt3, 1]])
sage: A.jordan_form(transformation=True)
6 0 0 1 1 0


0 0 0 , 1 2 3
0 1

2
0 0 0 2 2 2 3
1
40 CHAP. 2. ANALYSE ET ALGBRE
Programmation et
3
structures de donnes

Nous avons vu dans les chapitres prcdents comment effectuer des calculs
mathmatiques par des commandes Sage isoles, mais le systme autorise aussi la
programmation dune suite dinstructions.
Le systme de calcul formel Sage est en fait une extension du langage infor-
matique Python 1 et permet, quelques changements de syntaxe prs, dexploiter
les mthodes de programmation de ce langage.
Les commandes dcrites dans les chapitres prcdents prouvent quil nest
pas ncessaire de connatre le langage Python pour utiliser Sage ; ce chapitre
montre au contraire comment employer dans Sage les structures lmentaires
de programmation de Python. Il se limite aux bases de la programmation et
peut tre survol par les personnes connaissant Python ; les exemples sont choisis
parmi les plus classiques rencontrs en mathmatiques pour permettre au lecteur
dassimiler rapidement la syntaxe de Python par analogie avec les langages de
programmation quil connat.
Ce chapitre prsente la mthode algorithmique de programmation structure
avec les instructions de boucles et de tests, et expose ensuite les fonctions oprant
sur les listes et les autres structures composes de donnes. Le livre Apprendre
programmer avec Python de G. Swinnen [Swi09, Swi12] (disponible sous licence
libre) et le Syllabus en ligne de T. Massart [Mas13] prsentent de faon plus
approfondie le langage Python.

1. La version 5.9 de Sage utilise Python 2.7 ; la syntaxe de Python change lgrement
partir de la version 3.
42 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

Mots-cls du langage Python


while, for...in, if...elif...else boucles et tests
continue, break sortie anticipe dun bloc de code
try...except...finally, raise traitement et dclenchement dexceptions
assert condition de dbogage
pass instruction sans effet
def, lambda dfinition dune fonction
return, yield renvoi dune valeur
global, del porte et destruction des variables et fonctions
and, not, or oprations logiques
print affichage de texte
class, with programmation objet, application dun contexte
from...import...as accs une bibliothque
exec...in valuation dynamique de code

Tableau 3.1 Syntaxe gnrale du code Sage.

3.1 Syntaxe
3.1.1 Syntaxe gnrale
Les instructions lmentaires sont en gnral traites ligne par ligne. Python
considre le caractre croisillon # comme un dbut de commentaire et ignore le
texte saisi jusqu la fin de la ligne. Le point-virgule ; spare les instructions pla-
ces sur une mme ligne :
sage: 2*3; 3*4; 4*5 # un commentaire, 3 rsultats
6
12
20
Dans le terminal, une commande peut tre saisie sur plusieurs lignes en faisant
prcder les retours la ligne intermdiaires dune contre-oblique \ ; ces retours
la ligne sont considrs comme de simples blancs :
sage: 123 + \
....: 345
468
Un identificateur cest--dire un nom de variable, de fonction, etc. est
constitu uniquement de lettres, de chiffres ou du caractre de soulignement _
et ne peut commencer par un chiffre. Les identificateurs doivent tre diffrents
des mots-clefs du langage. Ces mots-clefs, rpertoris dans le tableau 3.1, forment
le noyau du langage Python 2.7. De faon anecdotique, on peut obtenir la liste de
ces mots-cls avec :
sage: import keyword; keyword.kwlist
['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del',
'elif', 'else', 'except', 'exec', 'finally', 'for', 'from',
'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass',
'print', 'raise', 'return', 'try', 'while', 'with', 'yield']
3.1. SYNTAXE 43

Les caractres spciaux de Sage et leurs principales utilisations


,
; sparateurs darguments et dinstructions
: ouverture dun bloc dinstructions, comprhension
. sparateur dcimal, accs aux champs dun objet
= affectation dune valeur une variable
+ - * / oprations arithmtiques lmentaires
^ ** puissance
% // quotient et reste dune division euclidienne
+= -= *= /= **= oprations arithmtiques avec modification dune variable
== != <> is tests dgalit
< <= > >= comparaisons
& | ^^ << >> oprations ensemblistes et oprations logiques bit bit
# commentaire (jusqu la fin de la ligne)
[...] construction dune liste, accs un lment par son indice
(...) appel de fonction ou de mthode, tuples immuables
{...:...} construction de dictionnaires
\ chappement dun caractre spcial (et algbre linaire)
@ application dun dcorateur une fonction
? accs laide
_ __ ___ rappel des trois derniers rsultats obtenus

Tableau 3.2 Syntaxe gnrale du code Sage (suite).

ces mots clefs sajoutent les constantes None (valeur vide , quivalent
approximatif de NULL dans dautres langages), True et False, ainsi que de nom-
breuses fonctions prdfinies par Python et Sage comme len, cos et integrate.
Il est prfrable de ne pas utiliser les identificateurs correspondants comme noms
de variables, sous peine de rendre difficile laccs aux fonctionnalits du systme.
Linterprteur accepte quelques commandes supplmentaires, comme quit pour
quitter la session Sage en cours. Nous en dcouvrirons dautres comme time ou
timeit au fur et mesure.
Certains caractres jouent un rle spcial dans Sage. Ils sont numrs dans
le tableau 3.2.

3.1.2 Appel de fonctions


Lvaluation dune fonction impose de placer ses ventuels arguments entre
parenthses, comme dans cos(pi) ou dans la fonction sans argument reset().
Cependant ces parenthses sont superflues pour les arguments dune commande :
les instructions print(6*7) et print 6*7 sont quivalentes 2 . Le nom dune
fonction sans argument ni parenthse reprsente la fonction elle-mme et neffectue
aucun calcul.

3.1.3 Complments sur les variables


Comme nous lavons vu, Sage note par le signe gal = la commande
daffectation dune valeur une variable. La partie situe droite du caractre
2. En Python 3.0, print est une fonction et impose de placer ses arguments entre parenthses.
44 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

= est dabord value puis sa valeur est mmorise dans la variable dont le
nom est gauche. Ainsi, on a :
sage: y = 3; y = 3 * y + 1; y = 3 * y + 1; y
31
Les affectations prcdentes modifient la valeur de la variable y sans afficher de
rsultat intermdiaire, la dernire de ces quatre commandes affiche la valeur de la
variable y la fin de ces calculs.
La commande del x supprime laffectation de la variable x, et la fonction
sans paramtre reset() rinitialise lensemble des variables.
Laffectation de plusieurs variables de faon parallle, ou synchronise, est
aussi possible ; elle diffre des affectations successives a = b; b = a :
sage: a, b = 10, 20 # (a, b) = (10, 20) et [10, 20] possibles
sage: a, b = b, a
sage: a, b
(20, 10)
Laffectation a, b = b, a est quivalente lchange des valeurs des variables a
et b en utilisant une variable intermdiaire :
sage: temp = a; a = b; b = temp # est quivalent : a, b = b, a
Cet autre exemple change les valeurs de deux variables a et b sans variable
intermdiaire ni affectation parallle, mais en utilisant des sommes et diffrences :
sage: x, y = var('x, y'); a = x ; b = y
sage: a, b
(x, y)
sage: a = a + b ; b = a - b ; a = a - b
sage: a, b
(y, x)
Laffectation multiple affecte la mme valeur plusieurs variables, avec une
syntaxe de la forme a = b = c = 0 ; les instructions x += 5 et n *= 2 sont
respectivement quivalentes x = x+5 et n = n*2.
Le test de comparaison entre deux objets se note par le double signe dgalit
== :
sage: 2 + 2 == 2^2, 3 * 3 == 3^3
(True, False)

3.2 Algorithmique
La programmation structure consiste dcrire un programme informatique
comme une suite finie dinstructions effectues les unes la suite des autres. Ces
instructions peuvent tre lmentaires ou composes :
une instruction lmentaire correspond par exemple laffectation dune
valeur une variable (cf. 1.2.4), ou laffichage dun rsultat ;
3.2. ALGORITHMIQUE 45

une instruction compose, comme une boucle ou une structure conditionnelle,


est construite partir de plusieurs instructions qui peuvent tre elles-mmes
simples ou composes.

3.2.1 Les boucles


Les boucles dnumration. Une boucle dnumration effectue les mmes
calculs pour toutes les valeurs entires dun indice k {a, . . . , b} ; lexemple
suivant 3 affiche le dbut de la table de multiplication par 7 :
sage: for k in [1..5]:
....: print 7*k # bloc qui contient une seule instruction
7
14
21
28
35
Les deux-points : la fin de la premire ligne introduisent le bloc dinstructions
qui est valu pour chaque valeur successive 1, 2, 3, 4 et 5 de la variable k.
chaque itration Sage affiche le produit 7 k par lintermdiaire de la commande
print.
Sur cet exemple, le bloc des instructions rptes contient une seule instruction
(print) qui est saisie de faon dcale par rapport au mot-clef for. Un bloc
compos de plusieurs instructions est caractris par des instructions saisies les
unes sous les autres avec la mme indentation.
La dfinition des blocs est importante : les deux programmes ci-dessous
diffrent uniquement par lindentation dune ligne, et aboutissent des rsultats
diffrents.
sage: S = 0 sage: S = 0
sage: for k in [1..3]: sage: for k in [1..3]:
... S = S+k ... S = S+k
sage: S = 2*S ... S = 2*S
sage: S sage: S

gauche linstruction S = 2*S est effectue une seule fois la fin de la boucle,
alors qu droite elle est effectue chaque itration, do des rsultats diffrents :

S = (0 + 1 + 2 + 3) 2 = 12 S = ((((0 + 1) 2) + 2) 2 + 3) 2 = 22.

Cette boucle sert entre autre calculer un terme donn dune suite rcurrente et
est illustre dans les exemples placs la fin de cette section.
Cette syntaxe de boucle dnumration est la plus directe et peut tre utilise
sans inconvnient pour 104 ou 105 itrations ; elle a cependant linconvnient de
3. Lorsque lon utilise Sage dans un terminal, la saisie dun tel bloc doit se terminer par
une ligne vide supplmentaire. Cette condition nest pas ncessaire en utilisant Sage par
lintermdiaire dun navigateur web et sera sous-entendue dans la suite.
46 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

Fonctions ditrations de la forme ..range pour a, b, c entiers


for k in [a..b]: ... construit la liste des entiers a 6 k 6 b de Sage
for k in srange (a, b): ... construit la liste des entiers a 6 k < b de Sage
for k in range (a, b): ... construit une liste dentiers int de Python
for k in xrange (a, b): ... numre des entiers int de Python sans
construire explicitement la liste correspondante
for k in sxrange (a, b): ... numre des nombres de Sage sans construire de liste
[a,a+c..b], [a..b, step=c] nombres Sage a, a + c, a + 2c, . . . jusqu a + kc 6 b
..range (b) est quivalent ..range (0, b)
..range (a, b, c) fixe lincrment dnumration c la place de 1

Tableau 3.3 Les diffrentes boucles dnumration.

construire explicitement la liste de toutes les valeurs de la variable de boucle avant


de rpter les instructions itres, mais a lavantage de manipuler les entiers de
Sage de type Integer (voir 5.3.1). Plusieurs fonctions ..range permettent aussi
ces itrations avec deux choix indpendants possibles. Le premier choix consiste
soit construire la liste des valeurs en mmoire avant le dbut de la boucle, soit
dterminer ces valeurs au fur et mesure des itrations. Le second choix est
faire entre entiers Integer de Sage 4 et entiers de type int de Python, ces deux
types dentiers nont pas exactement les mmes proprits informatiques. Dans le
doute, la forme [a..b] est celle qui rserve le moins de surprises.

Boucles tant que. Lautre famille de boucles est constitue des boucles tant que.
Comme les boucles dnumration for, celles-ci valuent un certain nombre de
fois les mmes instructions ; en revanche le nombre de rptitions nest pas fix
au dbut de la boucle mais dpend de la ralisation dune condition.
La boucle tant que, comme son nom lindique, excute des instructions tant
quune condition est ralise. Lexemple suivant 5 calcule la somme des carrs des
entiers naturels dont lexponentielle est infrieure ou gale 106 , soit 12 + 22 +
+ 132 :
sage: S = 0 ; k = 0 # La somme S commence 0
sage: while e^k <= 10^6: # e^13 <= 10^6 < e^14
....: S = S + k^2 # ajout des carrs k^2
....: k = k + 1

sage: S
819
La dernire instruction renvoie la valeur de la variable S et affiche le rsultat :
13
e13 442413 6 106 < e14 1202604.
X X
S= k2 = k 2 = 819,
kN k=0
ek 6106

4. Les commandes srange, sxrange et [...] oprent aussi sur les nombres rationnels et
flottants : que donne [pi,pi+5..20] ?
5. Lors de la saisie dans un terminal une ligne vide est ncessaire pour clore la dfinition du
bloc dinstructions de la boucle, avant de demander la valeur de la variable S.
3.2. ALGORITHMIQUE 47

Le bloc dinstructions ci-dessus comporte deux instructions daffectation, la


premire additionne le nouveau terme, et la seconde passe lindice suivant. Ces
deux instructions sont bien places les unes sous les autres et indentes de la
mme faon lintrieur de la structure while.
Lexemple suivant est un autre exemple typique de la boucle tant que. Il
consiste rechercher, pour un nombre x > 1, lunique valeur n N vrifiant
2n1 6 x < 2n , cest--dire le plus petit entier vrifiant x < 2n . Le programme
ci-dessous compare x 2n dont la valeur est successivement 1, 2, 4, 8, etc. ; il
effectue ce calcul pour x = 104 :
sage: x = 10^4; u = 1; n = 0 # invariant : u = 2^n
sage: while u <= x: n = n+1; u = 2*u # ou n += 1; u *= 2
sage: n
14

Tant que la condition 2n 6 x est vrifie, ce programme calcule les nouvelles


valeurs n + 1 et 2n+1 = 2 2n des deux variables n et u et les mmorise la
place de n et 2n . Cette boucle se termine lorsque la condition nest plus vrifie,
cest--dire pour x < 2n :

x = 104 , min{n N | x 6 2n } = 14, 213 = 8192, 214 = 16384.

Le corps dune boucle tant que nest pas excut lorsque le test est faux ds la
premire valuation.
Les blocs de commandes simples peuvent aussi tre saisis sur une ligne la
suite des deux-points : sans dfinir un nouveau bloc indent partir de la
ligne suivante.

Exemples dapplication aux suites et aux sries. La boucle for permet de


calculer facilement un terme donn dune suite rcurrente. Soit par exemple (un )
la suite dfinie par

1
u0 = 1, n N un+1 = .
1 + u2n

Le programme ci-dessous dtermine une approximation numrique du terme un


pour n = 20 ; la variable U est modifie chaque itration de la boucle pour passer
de la valeur un1 un en suivant la formule de rcurrence. La premire itration
calcule u1 partir de u0 pour n = 1, la deuxime fait de mme de u1 u2 quand
n = 2, et la dernire des n itrations modifie la variable U pour passer de un1
un :
sage: U = 1.0 # ou U = 1. ou U = 1.000
sage: for n in [1..20]:
....: U = 1 / (1 + U^2)
sage: U
0.682360434761105
48 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

Interruption de lexcution dune boucle

Les boucles while et for rptent un certain nombre de fois les mmes
instructions. La commande break lintrieur dune boucle termine de faon
prmature cette boucle, et la commande continue passe directement
litration suivante. Ces commandes permettent ainsi deffectuer lvaluation
de la condition nimporte quel endroit du corps de la boucle.
Les quatre exemples ci-dessous dterminent le plus petit nombre entier
strictement positif vrifiant log(x + 1) 6 x/10. Le premier met en avant une
boucle for dau maximum 100 essais qui se termine de faon prmature
la premire solution, le deuxime prsente la recherche du plus petit
entier vrifiant cette condition et risque de ne pas se terminer si cette
condition nest jamais vrifie, le troisime est quivalent au premier avec
une condition de boucle plus complexe, enfin le quatrime exemple possde
une structure inutilement complique qui a pour unique but dillustrer la
commande continue. Dans tous ces cas la valeur finale de x est 37.0.
for x in [1.0..100.0]: x=1.0
if log(x+1)<=x/10: break while log(x+1)>x/10:
x=x+1

x=1.0 x=1.0
while log(x+1)>x/10 and x<100: while True:
x=x+1 if log(x+1)>x/10:
x=x+1
continue
break

La commande return (qui termine lexcution dune fonction et dfinit


son rsultat, cf. 3.2.3) offre une autre manire dinterrompre prmaturment
un bloc dinstructions.

Le mme programme avec lentier U = 1 la place de lapproximation numrique


U = 1.0 sur la premire ligne fait des calculs exacts sur les nombres rationnels ;
le rsultat exact u10 est une fraction avec plus dune centaine de chiffres, et u20
en comporte plusieurs centaines de milliers. Les calculs exacts sont intressants
lorsque les erreurs darrondi se cumulent dans les approximations numriques.
Sinon, la main comme la machine, les oprations sur les approximations
numriques dune dizaine de dcimales sont plus rapides que celles sur des entiers
ou des rationnels faisant intervenir 500, 1 000 chiffres, ou plus.
Les sommes ou les produits peuvent tre mis sous forme de suites rcurrentes
et se calculent de la mme manire :
n
X
Sn = (2k)(2k + 1) = 2 3 + 4 5 + + (2n)(2n + 1),
k=1
S0 = 0, Sn = Sn1 + (2n)(2n + 1) pour n N .
3.2. ALGORITHMIQUE 49

La mthode de programmation de cette srie est celle des suites rcurrentes ; le


programme effectue des sommes successives partir de 0 en additionnant les
termes pour k = 1, k = 2, jusqu k = n :
sage: S = 0 ; n = 10
sage: for k in [1..n]:
....: S = S + (2*k) * (2*k+1)
sage: S
1650

Cet exemple illustre une mthode gnrale de programmation dune somme, mais,
dans ce cas simple, le calcul formel aboutit au rsultat en toute gnralit :
sage: n, k = var('n, k') ; res = sum(2*k*(2*k+1), k, 1, n)
sage: res, factor(res) # rsultat dvelopp puis factoris
(4/3*n^3 + 3*n^2 + 5/3*n, 1/3*(n + 1)*(4*n + 5)*n)

Ces rsultats peuvent aussi tre obtenus avec un papier et un crayon partir de
sommes bien connues :
n n
X n(n + 1) X n(n + 1)(2n + 1)
k= , k2 = ,
2 6
k=1 k=1
n n n
X X 2 n (n + 1)(2n + 1)
X
2k (2k + 1) = 4 k2 + 2 k= + n(n + 1)
3
k=1 k=1 k=1
n(n + 1) (4n + 2) + 3 n(n + 1)(4n + 5)

= = .
3 3

Exemples dapproximation de limites de suites. La boucle dnumration


permet de calculer un terme donn dune suite ou dune srie, la boucle tant que
est quant elle bien adapte pour approcher numriquement une limite de suite.
Si une suite (an )nN converge vers ` R, les termes an sont voisins de `
pour n assez grand. Il est donc possible dapprocher ` par un certain terme an ,
et le problme mathmatique consiste alors majorer plus ou moins facilement
lerreur |` an |. Cette majoration est immdiate pour des suites (un )nN et
(vn )nN adjacentes, cest--dire telles que

(un )nN est croissante,

(vn )nN est dcroissante,
lim vn un = 0.

n+

Dans ce cas,

les deux suites convergent vers la mme limite `,




p N up 6 lim un = ` = lim vn 6 vp ,
n+ n+
` up +vp 6 vp up .


2 2
50 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

Une tude mathmatique


prouve que les deux suites ci-dessous sont adjacentes et
convergent vers ab lorsque 0 < a < b :
2 un vn un + vn
u0 = a, v0 = b > a, un+1 = , vn+1 = .
un + vn 2
La limite commune de ces deux suites porte le nom de moyenne arithmtico-
harmoniquedu fait que la moyenne arithmtique de deux nombres a et b est la
moyenne au sens usuel (a + b)/2 et la moyenne harmonique h est linverse de la
moyenne des inverses : 1/h = (1/a+1/b)/2 = (a+b)/(2ab). Le programme suivant
vrifie que la limite est la mme pour des valeurs numriques particulires :
sage: U = 2.0; V = 50.0;
sage: while V-U >= 1.0e-6: # 1.0e-6 signifie 1.0*10^-6
....: temp = U
....: U = 2 * U * V / (U + V)
....: V = (temp + V) / 2
sage: U, V
(9.99999999989..., 10.0000000001...)
Les valeurs de un+1 et de vn+1 dpendent de un et vn ; pour cette raison la boucle
principale de ce programme fait intervenir une variable intermdiaire appele ici
temp de faon ce que les nouvelles valeurs un+1 , vn+1 de U, V dpendent des
deux valeurs prcdentes un , vn . Les deux blocs de gauche ci-dessous dfinissent
les mmes suites alors que celui de droite construit deux autres suites (u0n )n et
(vn0 )n ; laffectation parallle vite dutiliser une variable intermdiaire :

temp = 2*U*V/(U+V) U,V = 2*U*V/(U+V),(U+V)/2 U = 2*U*V/(U+V)


V = (U+V)/2 V = (U+V)/2
2u0n vn
0
U = temp (affectation parallle) u0n+1 = u0 +v 0
n n
u0n+1 +vn
0
0
vn+1 = 2
Pn
La srie Sn = k=0 (1)k ak est alterne ds que la suite (an )nN est dcroissante
et de limite nulle. Dire que S est alterne signifie que les deux suites extraites
(S2n )nN et (S2n+1 )nN sont adjacentes de mme limite note `. La suite (Sn )nN
converge donc aussi vers cette limite et lon a S2p+1 6 ` = limn+ Sn 6 S2p .
Le programme suivant illustre ce rsultat pour la suite ak = 1/k 3 partir de
k = 1, en mmorisant dans deux variables U et V les sommes partielles successives
S2n et S2n+1 de la srie qui encadrent la limite :
sage: U = 0.0 # la somme S0 est vide, de valeur nulle
sage: V = -1.0 # S1 = -1/1^3
sage: n = 0 # U et V contiennent S(2n) et S(2n+1)
sage: while U-V >= 1.0e-6:
....: n = n+1 # n += 1 est quivalent
....: U = V + 1/(2*n)^3 # passage de S(2n-1) S(2n)
....: V = U - 1/(2*n+1)^3 # passage de S(2n) S(2n+1)
sage: V, U
3.2. ALGORITHMIQUE 51

(-0.901543155458595, -0.901542184868447)

La boucle principale du programme modifie la valeur de n pour passer lindice


suivant tant que les deux valeurs S2n et S2n+1 ne sont pas assez proches lune de
lautre. Les deux variables U et V mmorisent ces deux termes successifs ; le corps
de la boucle dtermine partir de S2n1 successivement S2n et S2n+1 , do les
affectations croises U et V.
Le programme se termine lorsque deux termes conscutifs S2n+1 et S2n qui
encadrent la limite sont suffisamment proches lun de lautre, lerreur dapproxi-
mation (sans tenir compte des erreurs darrondi) vrifie alors 0 6 a2n+1 =
S2n S2n+1 6 106 .
La programmation de ces quatre sries alternes est similaire :
X (1)n X (1)n X (1)n
, , ,
log n n n2
n>2 n>1 n>1
X (1)n X X (1)n
, (1)n en ln n = .
n4 nn
n>1 n>1 n>1

Les termes gnraux de ces sries tendent plus ou moins vite vers 0 et les
approximations des limites demandent, selon les cas, plus ou moins de calculs.
La recherche dune prcision de 3, 10, 20 ou 100 dcimales sur les limites de
ces sries consiste rsoudre les inquations suivantes :
3
1/ log n 6 103 n > e(10 ) 1.97 10434
1/n 6 103 n > 10

3
1/n 6 1010 n > 1010
1/n2 6 103 n > 103 32 1/n2 6 1010 n > 105
1/n4 6 103 n > (103 )1/4 6 1/n4 6 1010 n > 317
e n log n
6 103 n > 5 e n log n
6 1010 n > 10
1/n2 6 1020 n > 1010 1/n2 6 10100 n > 1050
1/n4 6 1020 n > 105 1/n4 6 10100 n > 1025
e n log n
6 1020 n > 17 e n log n
6 10100 n > 57

Dans les cas les plus simples la rsolution de ces inquations dtermine donc un
indice n partir duquel la valeur Sn permet approcher la limite ` de la srie, ainsi
une boucle dnumration for est aussi possible. Au contraire une boucle while
est ncessaire ds que la rsolution algbrique en n de linquation an 6 10p
savre impossible.
Certaines approximations des limites prcdentes demandent trop de calculs
pour tre obtenues directement, notamment ds que lindice n dpasse un ordre de
grandeur de 1010 ou 1012 . Une tude mathmatique plus approfondie peut parfois
permettre de dterminer la limite ou de lapprocher par dautres mthodes ; ainsi
en est-il des sries de Riemann :
n n
X (1)k 3 X 1
lim = (3), avec (p) = lim ,
n+ k3 4 n+ kp
k=1 k=1
52 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

n n
X (1)k X (1)k 2
lim = log 2, lim = ,
n+ k n+ k2 12
k=1 k=1
n
X (1)k 7 4
lim = .
n+ k4 6!
k=1

Par ailleurs Sage peut calculer formellement certaines de ces sries et dterminer
une approximation de (3) avec 1200 dcimales en quelques secondes en effectuant
bien moins doprations que les 10400 ncessaires par lapplication directe de la
dfinition :
sage: k = var('k') ; sum((-1)^k/k, k, 1, +oo)
-log(2)
sage: sum((-1)^k/k^2, k, 1, +oo), sum((-1)^k/k^3, k, 1, +oo)
(-1/12*pi^2, -3/4*zeta(3))
sage: -3/4 * zeta (N(3, digits = 1200))
-0.901542677369695714049803621133587493073739719255374161344\
203666506378654339734817639841905207001443609649368346445539\
563868996999004962410332297627905925121090456337212020050039\
...
019995492652889297069804080151808335908153437310705359919271\
798970151406163560328524502424605060519774421390289145054538\
901961216359146837813916598064286672255343817703539760170306262

3.2.2 Les tests


Lautre instruction compose importante est le test : les instructions excutes
dpendent de la valeur boolenne dune condition. La structure et deux syntaxes
possibles de cette instruction sont les suivantes :

if une condition: if une condition:


une suite dinstructions une suite dinstructions
else:
sinon dautres instructions

La suite de Syracuse est dfinie selon une condition de parit :


(
un /2 si un est pair,
u0 N
un+1 =
3un + 1 si un est impair.

La conjecture tchque nonce sans preuve connue en 2012 que pour


toutes les valeurs initiales u0 N il existe un rang n pour lequel un = 1. Les
termes suivants sont alors 4, 2, 1, 4, 2, etc. Calculer chaque terme de cette suite
se fait par lintermdiaire dun test. Ce test est plac lintrieur dune boucle
tant que qui dtermine la plus petite valeur de n N vrifiant un = 1 :
sage: u = 6 ; n = 0
3.2. ALGORITHMIQUE 53

sage: while u != 1: # test "diffrent de" <> aussi possible


....: if u % 2 == 0: # l'oprateur % donne le reste euclidien
....: u = u//2 # // : quotient de la division euclidienne
....: else:
....: u = 3*u+1
....: n = n+1
sage: n
8
Tester si un est pair se fait en comparant 0 le reste de la division par 2 de un .
Le nombre ditrations effectues est la valeur de la variable n la fin du bloc.
Cette boucle se termine ds que la valeur calcule de un est 1 ; par exemple si
u0 = 6 alors u8 = 1 et 8 = min{p N |up = 1} :

p= 0 1 2 3 4 5 6 7 8 9 10
up = 6 3 10 5 16 8 4 2 1 4 2

La vrification pas--pas du bon fonctionnement de ces lignes peut se faire par


un print-espion de la forme print u, n plac dans le corps de la boucle.
Linstruction if permet en outre des tests imbriqus dans la branche else
laide du mot-clef elif. Ces deux structures sont quivalentes :

if une condition cond1: if cond1:


une suite dinstructions inst1 inst1
else: elif cond2:
if une condition cond2: inst2
une suite dinstructions inst2 elif cond3:
else: inst3
if une condition cond3: else:
une suite dinstructions inst3 instn
else:
dans les autres cas instn

Comme pour les boucles, les instructions simples associes aux tests peuvent tre
places la suite des deux-points et non dans un bloc en dessous.

3.2.3 Les procdures et les fonctions


Syntaxe gnrale. Comme bien dautres langages informatiques, Sage permet
lutilisateur de dfinir des fonctions ou des instructions sur mesure. La commande
def dont la syntaxe est dtaille ci-dessous autorise la dfinition de procdures et
de fonctions, cest--dire de sous-programmes (respectivement qui ne renvoient pas
de rsultat et qui en renvoient un), avec un ou plusieurs arguments. Ce premier
exemple dfinit la fonction (x, y) 7 x2 + y 2 :
sage: def fct2 (x, y):
....: return x^2 + y^2
sage: a = var('a')
sage: fct2 (a, 2*a)
54 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

5*a^2
Lvaluation de la fonction se termine par la commande return dont largument,
ici x2 + y 2 , est le rsultat de la fonction.
Une procdure est dfinie de la mme faon sans renvoyer explicitement de
rsultat, et en labsence de linstruction return le bloc dinstructions dfinissant
le programme est valu jusquau bout. En fait la procdure renvoie la valeur
None qui veut bien dire ce quelle veut dire.
Par dfaut, Sage considre que toutes les variables intervenant dans une
fonction sont locales. Ces variables sont cres chaque appel de la fonction,
dtruites la fin, et sont indpendantes dautres variables de mme nom pouvant
dj exister. Les variables globales ne sont pas modifies par lvaluation dune
fonction ayant des variables locales du mme nom :
sage: def essai (u):
....: t = u^2
....: return t*(t+1)
sage: t = 1 ; u = 2
sage: essai(3), t, u
(90, 1, 2)
Pour modifier une variable globale depuis une fonction, il faut la dclarer explici-
tement grce au mot-cl global :
sage: a = b = 1
sage: def f(): global a; a = b = 2
sage: f(); a, b
(2, 1)
Lexemple suivant reprend le calcul de la moyenne arithmtico-harmonique de
deux nombres supposs strictement positifs :
sage: def MoyAH (u, v):
....: u, v = min(u, v), max(u, v)
....: while v-u > 2.0e-8:
....: u, v = 2*u*v/(u+v), (u+v)/2
....: return (u+v) / 2

sage: MoyAH (1., 2.)


1.41421...
sage: MoyAH # correspond une fonction
<function MoyAH at ...>
La fonction MoyAH comporte deux paramtres nots u et v qui sont des variables
locales dont les valeurs initiales sont fixes lors de lappel de cette fonction ; par
exemple MoyAH(1., 2.) dbute lexcution de cette fonction avec les valeurs 1.
et 2. des variables u et v.
La programmation structure conseille de dfinir une fonction de faon ce
que return soit la dernire instruction du bloc de celle-ci. Place au milieu du
bloc dinstructions dune fonction, cette commande return termine lexcution
3.2. ALGORITHMIQUE 55

de la fonction en interrompant avant la fin lvaluation complte de ce bloc ; en


outre il peut y en avoir plusieurs dans diffrentes branches des tests.
La traduction informatique de ltat desprit des mathmatiques suggre
de programmer des fonctions renvoyant chacune un rsultat partir de leurs
arguments, plutt que des procdures affichant ces rsultats par une commande
print. Le systme de calcul formel Sage repose dailleurs sur de trs nombreuses
fonctions, par exemple exp ou solve, qui renvoient toutes un rsultat, par exemple
un nombre, une expression, une liste de solutions, etc.

Mthode itrative et mthode rcursive. Une fonction dfinie par lutilisa-


teur est construite comme une suite dinstructions. Une fonction est dite rcursive
lorsque son valuation ncessite dans certains cas dexcuter cette mme fonction
avec dautres paramtres. La suite factorielle (n!)nN en est un exemple simple :

0! = 1, (n + 1)! = (n + 1) n! pour tout n N.

Les deux fonctions suivantes aboutissent au mme rsultat partir dun argument
entier naturel n ; la premire fonction utilise la mthode itrative avec une boucle
for, et la seconde la mthode rcursive traduisant mot pour mot la dfinition
rcurrente prcdente :
sage: def fact1 (n):
....: res = 1
....: for k in [1..n]: res = res*k
....: return res

sage: def fact2 (n):


....: if n == 0: return 1
....: else: return n*fact2(n-1)
La suite de Fibonacci est une suite rcurrente dordre 2 car la valeur de un+2
dpend uniquement de celles de un et de un+1 :

u0 = 0, u1 = 1, un+2 = un+1 + un pour tout n N.

La fonction fib1 ci-dessous applique une mthode de calcul itratif des termes
de la suite de Fibonacci en utilisant deux variables intermdiaires U et V pour
mmoriser les deux valeurs prcdentes de la suite avant de passer au terme
suivant :
sage: def fib1 (n):
....: if n == 0 or n == 1: return n
....: else:
....: U = 0 ; V = 1 # les termes initiaux u0 et u1
....: for k in [2..n]: W = U+V ; U = V ; V = W
....: return V
sage: fib1(8)
21
56 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

La boucle applique partir de n = 2 la relation un = un1 + un2 . Par ailleurs


laffectation parallle U,V = V,U+V la place de W=U+V ; U=V ; V=W vite lutilisa-
tion de la variable W et traduit litration de la suite vectorielle Xn = (un , un+1 )
rcurrente dordre 1 dfinie par Xn+1 = f (Xn ) quand f (a, b) = (b, a + b). Ces
mthodes itratives sont efficaces mais leur programmation doit transformer la
dfinition de la suite de faon ladapter aux manipulations des variables.
Au contraire la fonction rcursive fib2 suit de beaucoup plus prs la d-
finition mathmatique de cette suite, ce qui facilite sa programmation et sa
comprhension :

sage: def fib2 (n):


....: if 0 <= n <= 1: return n # pour n = 0 ou n = 1
....: else: return fib2(n-1) + fib2(n-2)

Le rsultat de cette fonction est la valeur renvoye par linstruction conditionnelle :


0 et 1 respectivement pour n = 0 et n = 1, et la somme fib2(n-1)+fib2(n-2)
sinon ; chaque branche du test comporte une instruction return.
Cette mthode est cependant moins efficace car beaucoup de calculs sont
inutilement rpts. Par exemple fib2(5) value fib2(3) et fib2(4) qui sont
eux aussi calculs de la mme manire. Ainsi Sage value deux fois fib2(3) et
trois fois fib2(2). Ce processus se termine lors de lvaluation de fib2(0) ou de
fib2(1), de valeur 0 ou 1, et lvaluation de fib2(n) consiste calculer finalement
un en additionnant un uns et un1 zros. Le nombre total dadditions effectues
pour dterminer un est donc gal un+1 1 ; ce nombre est considrable et crot
trs rapidement. Aucun ordinateur, aussi rapide soit-il, ne peut calculer de cette
manire u100 .
Dautres mthodes sont aussi possibles, par exemple mmoriser les calculs
intermdiaires grce au dcorateur @cached_function, ou exploiter une proprit
des puissances de matrices : le paragraphe suivant sur lexponentiation rapide
montre comment calculer le millionime terme de cette suite.

3.2.4 Exemple : exponentiation rapide


Une mthode nave de calcul de an consiste effectuer n N multiplications
par a dans une boucle for :

sage: a = 2; n = 6; res = 1 # 1 est le neutre du produit


sage: for k in [1..n]: res = res*a
sage: res # La valeur de res est 2^6
64

Les puissances entires interviennent sous de trs nombreux aspects en mathma-


tique et en informatique ; ce paragraphe tudie une mthode gnrale de calcul
dune puissance entire an plus rapide que celle ci-dessus. La suite (un )nN dfinie
ci-aprs vrifie un = an ; ce rsultat se dmontre par rcurrence partir des
3.2. ALGORITHMIQUE 57

2
galits a2k = (ak ) et ak+1 = a ak :

1
si n = 0,
un = un/2 2
si n est pair et strictement positif, (3.1)
a un1 si n est impair.

Par exemple, pour u11 :

u11 = a u10 , u10 = u25 , u5 = a u4 , u4 = u22 ,


u2 = u21 , u1 = a u0 = a ;

ainsi :

u2 = a 2 , u4 = u22 = a4 , u5 = a a4 = a5 ,
u10 = u25 = a10 , u11 = a a10 = a11 .

Le calcul de un ne fait intervenir que des termes uk avec k {0 n 1}, et


donc celui-ci est bien dcrit en un nombre fini doprations.
En outre cet exemple montre que la valeur de u11 est obtenue par lvaluation
des 6 termes u10 , u5 , u4 , u2 , u1 et u0 , et effectue uniquement 6 multiplications.
Le calcul de un ncessite entre log n / log 2 et 2 log n / log 2 multiplications car
aprs une ou deux tapes selon que n est pair ou impair un sexprime en
fonction de uk , avec k 6 n/2. Cette mthode est donc incomparablement plus
rapide que la mthode nave quand n est grand ; une vingtaine de termes pour
n = 104 et non 104 produits :

indices traits : 10 000 5 000 2 500 1 250 625 624 312 156 78
39 38 19 18 9 8 4 2 1

Cette mthode nest cependant pas toujours la plus rapide ; les calculs suivants
sur b, c, d et f effectuent 5 produits pour calculer a15 , alors que par cette mthode
les oprations sur u, v, w, x et y ncessitent 6 multiplications sans compter le
produit par 1 :

b = a2 c = ab = a3 d = c2 = a6 f = cd = a9 df = a15 : 5 produits ;
u = a2 v = au = a3 w = v 2 = a6
x = aw = a7 y = x2 = a14 ay = a15 : 6 produits.

La fonction rcursive puiss1 calcule la suite rcurrente (3.1) avec uniquement


des multiplications pour programmer loprateur dlvation une puissance :
sage: def puiss1 (a, n):
....: if n == 0: return 1
....: elif n % 2 == 0: b = puiss1 (a, n//2); return b*b
....: else: return a * puiss1(a, n-1)

sage: puiss1 (2, 11) # a pour rsultat 2^11


2048
58 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

Le nombre doprations effectues par cette fonction est le mme que celui fait
par un calcul la main en reprenant les rsultats dj calculs. Au contraire si les
instructions b = puiss(a, n//2);return b*b faites aprs le test de parit de
n taient remplaces par puiss1(a, n//2)*puiss1(a, n//2) Sage effectuerait
beaucoup plus de calculs car, comme pour la fonction rcursive fib2 calculant la
suite de Fibonacci, certaines oprations seraient inutilement rptes. Il y aurait
en dfinitive de lordre de n multiplications, autant que via la mthode nave.
Par ailleurs la commande return puiss1(a*a, n//2) peut remplacer de
faon quivalente ces deux instructions.
Le programme ci-dessous effectue le mme calcul par une mthode itrative :
sage: def puiss2 (u, k):
....: v = 1
....: while k != 0:
....: if k % 2 == 0: u = u*u ; k = k//2
....: else: v = v*u ; k = k-1
....: return v

sage: puiss2 (2, 10) # a pour rsultat 2^10


1024
Le fait que la valeur de puiss2(a, n) est an se dmontre en vrifiant quitration
aprs itration les valeurs des variables u, v et k sont lies par lgalit v uk = an ,
que lentier k soit pair ou impair. la premire itration v = 1, u = a et k = n ;
aprs la dernire itration k = 0, donc v = an .
Les valeurs successives de la variable k sont entires et positives, et elles
forment une suite strictement dcroissante. Cette variable ne peut donc prendre
quun nombre fini de valeurs avant dtre nulle et de terminer ainsi linstruction
de boucle.
En dpit des apparences la fonction puiss1 est programme rcursivement,
et puiss2 de faon itrative ces deux fonctions traduisent presque le mme
2
algorithme : la seule diffrence est que la premire value a2k par (ak ) alors que
k
la seconde calcule a2k par (a2 ) lors de la modification de la variable u.
Cette mthode ne se limite pas au calcul des puissances positives de nombres
partir de la multiplication, mais sadapte toute loi de composition interne
associative. Cette loi doit tre associative afin de vrifier les proprits usuelles des
produits itrs. Ainsi en remplaant le nombre 1 par la matrice unit 1n les deux
fonctions prcdentes valueraient les puissances positives de matrices carres. Ces
fonctions illustrent comment programmer efficacement loprateur puissance
partir de la multiplication, et ressemblent la mthode implante dans Sage.
Par exemple une puissance de matrice permet dobtenir des termes dindices
encore plus grands que prcdemment de la suite de Fibonacci :

0 1
   
un
A= , Xn = , AXn = Xn+1 An X0 = Xn .
1 1 un+1

Le programme Sage correspondant tient en deux lignes, et le rsultat recherch est


la premire coordonne du produit matriciel An X0 , ce qui fonctionne effectivement
3.2. ALGORITHMIQUE 59

mme pour n = 107 ; ces deux programmes sont quivalents et leur efficacit
provient du fait que Sage applique essentiellement une mthode dexponentiation
rapide :
sage: def fib3 (n):
....: A = matrix ([[0, 1], [1, 1]]) ; X0 = vector ([0, 1])
....: return (A^n*X0)[0]

sage: def fib4 (n):


....: return (matrix([[0,1], [1,1]])^n * vector([0,1]))[0]

3.2.5 Affichage et saisie


Linstruction print est la principale commande daffichage. Par dfaut, les
arguments sont affichs les uns la suite des autres spars par un espace ; Sage
passe automatiquement la ligne la fin de la commande :
sage: print 2^2, 3^3, 4^4 ; print 5^5, 6^6
4 27 256
3125 46656
Une virgule la fin de la commande print omet ce passage la ligne, et la
prochaine instruction print continue sur la mme ligne :
sage: for k in [1..10]: print '+', k,
+ 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
Il est possible dafficher des rsultats sans espace intermdiaire en transformant
ceux-ci en une chane de caractres par la fonction str(..), et en effectuant la
concatnation des chanes de caractres par loprateur + :
sage: print 10, 0.5 ; print 10+0.5 ; print 10.0, 5
10 0.500000000000000
10.5000000000000
10.0000000000000 5
sage: print 10+0, 5 ; print str(10)+str(0.5)
10 5
100.500000000000000
La dernire section de ce chapitre sur les listes et les structures prsente les chanes
de caractres de manire plus approfondie.
La commande print permet aussi de formater laffichage des nombres pour les
prsenter en tableaux, lexemple suivant partir du motif %.d et de loprateur %
affiche la table des puissances quatrimes les unes sous les autres :
sage: for k in [1..6]: print '%2d^4 = %4d' % (k, k^4)
1^4 = 1
2^4 = 16
3^4 = 81
4^4 = 256
5^4 = 625
6^4 = 1296
60 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

Loprateur % insre les nombres placs sa droite dans la chane de caractres


sa gauche la place des signes de conversion comme %2d ou %.4f. Dans lexemple
prcdent le terme %4d complte gauche par des espaces la chane de caractres
reprsentant lentier k 4 de faon occuper au minimum quatre caractres. De
mme le motif %.4f dans pi = %.4f % n(pi) affiche pi = 3.1416 avec quatre
chiffres aprs le sparateur dcimal.
Dans un terminal, la fonction raw_input(message) affiche le texte message,
attend une saisie au clavier valide par un passage la ligne, et renvoie la chane
de caractres correspondante.

3.3 Listes et structures composes


Cette section dtaille les structures de donnes composes de Sage : les chanes
de caractres, les listes de type modifiable ou immuable , les ensembles et
les dictionnaires.

3.3.1 Dfinition des listes et accs aux lments


La notion de liste en informatique et celle de n-uplet en mathmatiques
permettent lnumration dobjets mathmatiques. Cette notion de couple avec
(a, b) 6= (b, a) et de n-uplet prcise la position de chaque lment au contraire
de la notion densemble.
On dfinit une liste en plaant ses lments entre crochets [...] spars par
des virgules. Laffectation du triplet (10, 20, 30) la variable L seffectue de la
manire suivante, et la liste vide, sans lment, est simplement dfinie ainsi :
sage: L = [10, 20, 30]
sage: L
[10, 20, 30]
sage: [] # [] est la liste vide
[]
Les coordonnes des listes sont numres dans lordre partir de lindice 0, puis
1, 2, etc. Laccs la coordonne de rang k dune liste L seffectue par L[k],
mathmatiquement ceci correspond la projection canonique de la liste considre
comme un lment dun produit cartsien sur la coordonne dordre k. La fonction
len renvoie le nombre dlments dune liste 6 :
sage: L[1], len(L), len([])
(20, 3, 0)
La modification dune coordonne est obtenue de la mme manire, par affectation
de la coordonne correspondante. Ainsi la commande suivante modifie le troisime
terme de la liste indic par 2 :
sage: L[2] = 33
6. Le rsultat de la fonction len est de type int propre Python, la composition
Integer(len(..)) renvoie un entier Integer de Sage.
3.3. LISTES ET STRUCTURES COMPOSES 61

sage: L
[10, 20, 33]
Les indices ngatifs accdent aux lments de la liste compts partir du dernier
terme :
sage: L = [11, 22, 33]
sage: L[-1], L[-2], L[-3]
(33, 22, 11)
La commande L[p:q] extrait la sous-liste [L[p], L[p+1], ..., L[q-1]] qui
est vide si q 6 p. Des indices ngatifs permettent dextraire les derniers termes
de la liste ; enfin la rfrence L[p:] construit la sous-liste L[p:len(L)] partir
de lindice p jusqu la fin, et L[:q] = L[0:q] numre les lments partir du
dbut jusqu lindice q exclu :
sage: L = [0, 11, 22, 33, 44, 55]
sage: L[2:4]
[22, 33]
sage: L[-4:4]
[22, 33]
sage: L[2:-2]
[22, 33]
sage: L[:4]
[0, 11, 22, 33]
sage: L[4:]
[44, 55]
De la mme manire que la commande L[n] = ... modifie un lment de la liste,
laffectation L[p:q] = [...] remplace la sous-liste entre les indices p compris et
q exclu :
sage: L = [0, 11, 22, 33, 44, 55, 66, 77]
sage: L[2:6] = [12, 13, 14] # remplace [22, 33, 44, 55]
Ainsi L[:1] = [] et L[-1:] = [] suppriment respectivement le premier et le
dernier terme dune liste, et rciproquement L[:0] = [a] et L[len(L):] =
[a] insrent un lment a respectivement en tte et la fin de la liste. Plus
gnralement les termes dune liste vrifient ces galits :

L = [`0 , `1 , `2 , . . . , `n1 ] = [`n , `1n , . . . `2 , `1 ] avec n = len(L),


`k = `kn pour 0 6 k < n, `j = `n+j pour n 6 j < 0.

Loprateur in teste lappartenance dun lment une liste. Sage effectue le


test dgalit de deux listes par == qui compare les lments un par un. Ces
deux sous-listes avec des indices positifs ou ngatifs sont gales :
sage: L = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
sage: L[3:len(L)-5] == L[3-len(L):-5]
True
sage: [5 in L, 6 in L]
62 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

[True, False]
Les exemples ci-dessus concernent des listes dentiers, mais les lments des listes
peuvent tre nimporte quels objets Sage, nombres, expressions, autres listes, etc.

3.3.2 Oprations globales sur les listes


Loprateur daddition + effectue la concatnation de deux listes, et lop-
rateur de multiplication * associ un entier itre cette concatnation :
sage: L = [1, 2, 3] ; L + [10, 20, 30]
[1, 2, 3, 10, 20, 30]
sage: 4 * [1, 2, 3]
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
La concatnation des deux sous-listes L[:k] et L[k:] reconstruit la liste initiale.
Ceci explique pourquoi la borne gauche dindice p dune sous-liste L[p:q] est
comprise, alors que la borne droite dindice q est exclue :

L = L[:k]+L[k:] = [`0 , `1 , `2 , . . . , `n1 ]


= [`0 , `1 , `2 , . . . , `k1 ] + [`k , `k+1 , `k+2 , . . . , `n1 ].

Lexemple suivant illustre cette proprit :


sage: L = 5*[10, 20, 30] ; L[:3]+L[3:] == L
True
Loprateur compos de deux points .. automatise la construction des listes
dentiers sans numrer explicitement tous leurs lments. Lexemple suivant
construit une liste faite dnumrations dentiers et dlments isols :
sage: [1..3, 7, 10..13]
[1, 2, 3, 7, 10, 11, 12, 13]
La suite de ce paragraphe dcrit comment construire limage dune liste par
une application et une sous-liste dune liste. Les fonctions associes sont map et
filter, et la construction [..for..x..in..]. Les mathmatiques font souvent
intervenir des listes constitues des images par une application f de ses lments :

(a0 , a1 , a2 , . . . , an1 ) 7 (f (a0 ), f (a1 ), . . . , f (an1 )).

La commande map construit cette image ; lexemple suivant applique la fonction


trigonomtrique cos une liste dangles usuels :
sage: map (cos, [0, pi/6, pi/4, pi/3, pi/2])
[1, 1/2*sqrt(3), 1/2*sqrt(2), 1/2, 0]
Il est aussi possible dutiliser une fonction de lutilisateur dfinie par def, ou
de dclarer directement une fonction par lambda ; la commande ci-dessous est
quivalente la prcdente et applique la fonction dfinie par t 7 cos t :
sage: map (lambda t: cos(t), [0, pi/6, pi/4, pi/3, pi/2])
[1, 1/2*sqrt(3), 1/2*sqrt(2), 1/2, 0]
3.3. LISTES ET STRUCTURES COMPOSES 63

La commande lambda est suivie de la dclaration du ou des paramtres spars


par des virgules, et ne peut comporter aprs le deux-points quune et une seule
expression qui est le rsultat de la fonction, sans utiliser linstruction return.
Cette fonction lambda peut aussi comporter un test ; les codes suivants sont
quivalents :

fctTest1 = lambda x: res1 if cond else res2


def fctTest2 (x):
if cond: return res1
else: return res2

Les trois commandes map suivantes sont quivalentes, la composition des


applications N cos tant effectue dune faon ou dune autre :
sage: map (lambda t: N(cos(t)), [0, pi/6, pi/4, pi/3, pi/2])
[1.00000000000000, 0.866025403784439, 0.707106781186548,
0.500000000000000, 0.000000000000000]

sage: map (N, map (cos, [0, pi/6, pi/4, pi/3, pi/2]))
[1.00000000000000, 0.866025403784439, 0.707106781186548,
0.500000000000000, 0.000000000000000]

sage: map (compose(N, cos), [0, pi/6, pi/4, pi/3, pi/2])


[1.00000000000000, 0.866025403784439, 0.707106781186548,
0.500000000000000, 0.000000000000000]
La commande filter construit une sous-liste des lments vrifiant une condi-
tion. Cet exemple applique le test de primalit is_prime aux entiers 1, ..., 55 :
sage: filter (is_prime, [1..55])
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]
La fonction de test peut aussi tre dfinie lintrieur de la commande filter.
Lexemple ci-dessous, par des essais exhaustifs, dtermine toutes les racines
quatrimes de 7 modulo le nombre premier 37 ; cette quation comporte quatre
solutions 3, 18, 19 et 34 :
sage: p = 37 ; filter (lambda n: n^4 % p == 7, [0..p-1])
[3, 18, 19, 34]
Par ailleurs, la commande [..for..x..in..] construit par comprhension
une liste ; ces deux commandes numrent de faon quivalente les entiers impairs
de 1 31 :
sage: map(lambda n:2*n+1, [0..15])
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
sage: [2*n+1 for n in [0..15]]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
Cette commande est indpendante de la commande de boucle for. La condition
if associe for aboutit cette construction quivalente la fonction filter :
64 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

sage: filter (is_prime, [1..55])


[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]
sage: [p for p in [1..55] if is_prime(p)]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]
Les deux exemples suivants combinent les tests if et filter avec for pour
dterminer une liste de nombres premiers qui sont congrus 1 modulo 4, puis
une liste de carrs de nombres premiers :
sage: filter (is_prime, [4*n+1 for n in [0..20]])
[5, 13, 17, 29, 37, 41, 53, 61, 73]
sage: [n^2 for n in [1..20] if is_prime(n)]
[4, 9, 25, 49, 121, 169, 289, 361]
Dans le premier cas le test is_prime est effectu aprs le calcul 4n + 1 alors que
dans le second le test est effectu avant le calcul du carr n2 .
La fonction reduce opre par associativit de la gauche vers la droite sur les
lments dune liste. Dfinissons ainsi la loi de composition interne ? :

x ? y = 10x + y, alors ((1 ? 2) ? 3) ? 4 = (12 ? 3) ? 4 = 1234.

Le premier argument de reduce est une fonction deux paramtres et le deuxime


est la liste des arguments :
sage: reduce (lambda x, y: 10*x+y, [1, 2, 3, 4])
1234
Un troisime argument optionnel donne le rsultat sur une liste vide :
sage: reduce (lambda x, y: 10*x+y, [9, 8, 7, 6], 1)
19876
Il correspond gnralement llment neutre de lopration applique. Ainsi,
lexemple ci-dessous calcule un produit dentiers impairs :
sage: L = [2*n+1 for n in [0..9]]
sage: reduce (lambda x, y: x*y, L, 1)
654729075
Les fonctions add 7 et prod de Sage appliquent directement loprateur reduce
pour calculer des sommes et des produits ; le rsultat est le mme dans les trois
exemples ci-dessous, et la commande sur une liste autorise en outre dajouter un
second terme optionnel reprsentant llment neutre, 1 pour le produit et 0 pour
la somme, ou une matrice unit pour un produit matriciel :
sage: prod ([2*n+1 for n in [0..9]], 1) # une liste avec for
654729075
sage: prod ( 2*n+1 for n in [0..9]) # sans liste
654729075
sage: prod (n for n in [0..19] if n%2 == 1)
654729075
7. ne pas confondre avec sum, qui cherche une expression symbolique pour une somme.
3.3. LISTES ET STRUCTURES COMPOSES 65

La fonction any associe loprateur or et la fonction all loprateur and


sont de principe et de syntaxe quivalents. Cependant lvaluation se termine ds
que le rsultat True ou False dun des termes impose ce rsultat sans effectuer
lvaluation des termes suivants :
sage: def fct (x): return 4/x == 2
sage: all (fct(x) for x in [2, 1, 0])
False
sage: any (fct(x) for x in [2, 1, 0])
True
En revanche la construction de la liste [fct(x) for x in [2, 1, 0]] et la
commande all([fct(x) for x in [2, 1, 0]]) provoquent des erreurs car
tous les termes sont valus, y compris le dernier avec x = 0.
Limbrication de plusieurs commandes for permet de construire le produit
cartsien de deux listes ou de dfinir des listes de listes. Lexemple suivant
montre que si lon combine plusieurs oprateurs for dans la mme dfinition par
comprhension, le plus gauche correspond la boucle la plus extrieure :
sage: [[x, y] for x in [1..2] for y in [6..8]]
[[1, 6], [1, 7], [1, 8], [2, 6], [2, 7], [2, 8]]
Lordre ditration est donc diffrent de celui obtenu en imbriquant plusieurs
dfinitions par comprhension :
sage: [[[x, y] for x in [1..2]] for y in [6..8]]
[[[1, 6], [2, 6]], [[1, 7], [2, 7]], [[1, 8], [2, 8]]]
La commande map avec plusieurs listes en argument avance de faon synchro-
nise dans ces listes.
sage: map (lambda x, y: [x, y], [1..3], [6..8])
[[1, 6], [2, 7], [3, 8]]
Enfin la commande flatten permet de concatner des listes sur un ou plusieurs
niveaux :
sage: L = [[1, 2, [3]], [4, [5, 6]], [7, [8, [9]]]]
sage: flatten (L, max_level = 1)
[1, 2, [3], 4, [5, 6], 7, [8, [9]]]
sage: flatten (L, max_level = 2)
[1, 2, 3, 4, 5, 6, 7, 8, [9]]
sage: flatten (L) # quivaut flatten (L, max_level = 3)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Ces manipulations lmentaires de listes interviennent de faon trs utile
dans les autres branches de Sage ; lexemple suivant calcule les premires drives
itres de x ex ; le premier argument de diff est lexpression driver, et le ou les
suivants correspondent la variable de drivation, ces paramtres pouvant aussi
tre la liste des variables par rapport auxquelles les drivations sont effectues :
sage: x = var('x')
66 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

sage: factor(diff(x*exp(x), [x, x]))


(x + 2)*e^x
sage: map(lambda n: factor(diff(x*exp(x), n*[x])), [0..6])
[x*e^x, (x + 1)*e^x, (x + 2)*e^x, (x + 3)*e^x, (x + 4)*e^x,
(x + 5)*e^x, (x + 6)*e^x]
sage: [factor (diff (x*exp(x), n*[x])) for n in [0..6]]
[x*e^x, (x + 1)*e^x, (x + 2)*e^x, (x + 3)*e^x, (x + 4)*e^x,
(x + 5)*e^x, (x + 6)*e^x]
La commande diff possde plusieurs syntaxes. Les paramtres suivant la fonc-
tion f peuvent aussi bien tre la liste des variables de drivation que lnumration
de ces variables, ou lordre de la drive :

diff(f(x), x, x, x), diff(f(x), [x, x, x]), diff(f(x), x, 3).

On peut aussi employer diff(f(x), 3) pour les fonctions une seule variable.
Ces rsultats se vrifient directement par la formule de Leibniz de drive itre
dun produit de deux termes o les drives dordre 2 ou plus de x sont nulles :
n  
X n
(xe )
x (n)
= x(k) (ex )(nk) = (x + n)ex .
k
k=0

3.3.3 Principales mthodes sur les listes


La mthode reverse renverse lordre des lments dune liste, et la mthode
sort transforme la liste initiale en une liste trie :
sage: L = [1, 8, 5, 2, 9] ; L.reverse() ; L
[9, 2, 5, 8, 1]
sage: L.sort() ; L
[1, 2, 5, 8, 9]
sage: L.sort(reverse = True) ; L
[9, 8, 5, 2, 1]
Ces deux mthodes modifient la liste L, et lancienne valeur est perdue.
Un premier argument optionnel sort permet de choisir la relation dordre
applique sous la forme dune fonction Ordre(x, y) deux paramtres. Le
rsultat doit tre du type int des entiers Python ; il est strictement ngatif, nul
ou positif, par exemple 1, 0 ou 1, selon que x y, x = y ou x  y. La liste
transforme (x0 , x1 , . . . , xn1 ) vrifie x0  x1   xn1 .
Lordre lexicographique de deux listes de nombres de mme longueur est
similaire lordre alphabtique et est dfini par cette quivalence en ignorant les
premiers termes lorsquils sont gaux deux deux :

P = (p0 , p1 , . . . pn1 ) lex Q = (q0 , q1 , . . . qn1 )


r {0, . . . , n 1} (p0 , p1 , . . . , pr1 ) = (q0 , q1 , . . . , qr1 ) et pr < qr .

La fonction suivante compare deux listes supposes de mme longueur. Malgr la


boucle a priori sans fin while True, les commandes return sortent directement
3.3. LISTES ET STRUCTURES COMPOSES 67

de cette boucle et terminent la fonction. Le rsultat est 1, 0 ou 1 selon que


P lex Q, P = Q ou P lex Q :
sage: def alpha (P, Q): # len(P) = len(Q) par hypothse
....: i = 0
....: while True:
....: if i == len(P): return int(0)
....: elif P[i] < Q[i]: return int(-1)
....: elif P[i] > Q[i]: return int(1)
....: else: i = i+1
sage: alpha ([2, 3, 4, 6, 5], [2, 3, 4, 5, 6])
1

La commande suivante trie une liste de listes de mme longueur en suivant lordre
lexicographique. Cette fonction correspond par ailleurs lordre implant dans
Sage pour comparer deux listes ; la commande L.sort() sans paramtre optionnel
est quivalente :
sage: L = [[2, 2, 5], [2, 3, 4], [3, 2, 4], [3, 3, 3],\
....: [1, 1, 2], [1, 2, 7]]
sage: L.sort (cmp = alpha) ; L
[[1, 1, 2], [1, 2, 7], [2, 2, 5], [2, 3, 4], [3, 2, 4], [3, 3, 3]]

La dfinition de lordre lexicographique homogne consiste dabord comparer


les termes de mme poids avant dappliquer lordre lexicographique, o le poids
est la somme des coefficients :

P = (p0 , p1 , . . . pn1 ) lexH Q = (q0 , q1 , . . . qn1 )


n1
X n1
X  n1
X n1
X 
pk < qk ou pk = qk et P lex Q
k=0 k=0 k=0 k=0

Le code ci-dessous implante cet ordre homogne :


sage: def homogLex (P, Q):
....: sp = sum (P) ; sq = sum (Q)
....: if sp < sq: return int(-1)
....: elif sp > sq: return int(1)
....: else: return alpha (P, Q)

sage: homogLex ([2, 3, 4, 6, 4], [2, 3, 4, 5, 6])


-1

La fonction sorted de Sage est une fonction au sens mathmatique du terme ;


elle prend une liste comme premier argument et, sans la modifier, renvoie comme
rsultat une liste trie, contrairement la mthode sort qui modifie la liste en
place.
Sage propose dautres mthodes sur les listes, insertion dun lment en fin de
liste, concatnation en fin de liste, et dnombrement du nombre de rptitions
68 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

dun lment :

L.append(x) est quivalent L[len(L):] = [x]


L.extend(L1) est quivalent L[len(L):] = L1
L.insert(i, x) est quivalent L[i:i] = [x]
L.count(x) est quivalent len (select (lambda t : t == x, L))

Les commandes L.pop(i) et L.pop() suppriment llment dindice i ou le dernier


lment dune liste, et renvoient la valeur de cet lment ; les deux fonctions ci-
dessous dcrivent leur fonctionnement respectif :

def pop1 (L, i): def pop2 (L):


a = L[i] return pop1 (L, len(L)-1)
L[i:i+1] = []
return a

Par ailleurs L.index(x) renvoie lindice du premier terme gal x, et L.remove(x)


supprime le premier lment de valeur x de la liste. Ces commandes provoquent
une erreur si x nappartient pas la liste. Enfin la commande del L[p:q] est
quivalente L[p:q] = [], et del L[i] supprime llment dindice i.
Contrairement ce quil se produit dans de nombreux autres langages infor-
matiques, ces fonctions modifient la liste L sans crer de nouvelle liste.

3.3.4 Exemples de manipulation de listes


Lexemple suivant construit la liste des termes pairs et celle des termes impairs
dune liste donne. Cette premire solution parcourt deux fois la liste et effectue
deux fois ces tests :
sage: def fct1(L):
....: return [filter (lambda n: n % 2 == 0, L),
....: filter (lambda n: n % 2 == 1, L)]

sage: fct1([1..10])
[[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]
Cette deuxime solution parcourt une seule fois la liste initiale et construit petit
petit ces deux listes rsultats :
sage: def fct2 (L):
....: res0 = [] ; res1 = []
....: for k in L:
....: if k%2 == 0: res0.append(k) # ou res0[len(res0):] = [k]
....: else: res1.append(k) # ou res1[len(res1):] = [k]
....: return [res0, res1]
Ce programme remplace la boucle for et les variables auxiliaires par un appel
rcursif et un paramtre supplmentaire :
3.3. LISTES ET STRUCTURES COMPOSES 69

sage: def fct3a (L, res0, res1):


....: if L == []: return [res0, res1]
....: elif L[0]%2 == 0: return fct3a(L[1:], res0+[L[0]], res1)
....: else: return fct3a (L[1:], res0, res1+[L[0]])

sage: def fct3 (L): return fct3a (L, [], [])


Les paramtres res0 et res1 contiennent les premiers lments dj tris, et la
liste paramtre L perd un terme chaque appel rcursif.
Le deuxime exemple ci-dessous extrait toutes les suites croissantes dune
liste de nombres. Trois variables sont utilises, la premire res mmorise les
suites croissantes dj obtenues, la variable debut indique la position o la suite
croissante en cours commence, et la variable k est lindice de boucle :
sage: def sousSuites (L):
....: if L == []: return []
....: res = [] ; debut = 0 ; k = 1
....: while k < len(L): # 2 termes conscutifs sont dfinis
....: if L[k-1] > L[k]:
....: res.append (L[debut:k]) ; debut = k
....: k = k+1
....: res.append (L[debut:k])
....: return res

sage: sousSuites([1, 4, 1, 5])


[[1, 4], [1, 5]]
sage: sousSuites([4, 1, 5, 1])
[[4], [1, 5], [1]]
Le corps de la boucle permet de passer au terme suivant de la liste. Si le test est
vrifi, alors la sous-suite croissante en cours se termine, et il faut passer une
nouvelle sous-suite, sinon elle se prolonge au terme suivant.
Linstruction aprs la boucle ajoute au rsultat final la sous-suite croissante
en cours de parcours qui possde au moins un lment.

3.3.5 Chanes de caractres


Les chanes de caractres sont dlimites par des guillemets anglais droits,
simples '...' ou doubles "...". Les chanes dlimites par des guillemets simples
peuvent contenir des guillemets doubles, et rciproquement. Les chanes peuvent
aussi tre dlimites par des triples guillemets '''...''' et, dans ce cas peuvent
tre saisies sur plusieurs lignes et contenir des guillemets simples ou doubles.
sage: S = 'Ceci est une chane de caractres.'
Le caractre dchappement est le signe \, il permet dinclure des passages la
ligne par \n, des guillemets par \" ou par \', le caractre de tabulation par \t,
le signe dchappement par \\. Les chanes de caractres peuvent contenir des
caractres accentus, et plus gnralement des caractres Unicode quelconques :
70 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

sage: S = 'Ceci est une chane de caractres.'; S


'Ceci est une cha\xc3\xaene de caract\xc3\xa8res.'
sage: print S
Ceci est une chane de caractres.
La comparaison des chanes de caractres seffectue en fonction du code interne
de chaque caractre. La longueur dune chane est obtenue par la fonction len, et la
concatnation de chanes se fait par les signes daddition + et de multiplication
* .
Laccs une sous-chane de caractres de S seffectue comme pour les listes
par des crochets S[n], S[p:q], S[p:] et S[:q], et le rsultat est une chane
de caractres. Le langage ne permet pas de modifier la chane initiale par une
affectation de cette forme, pour cette raison le type chane de caractres est dit
immuable.
La fonction str convertit son argument en une chane de caractres. La
mthode split dcoupe une chane de caractres en listes de sous-chanes au
niveau des espaces :
sage: S='un deux trois quatre cinq six sept'; L=S.split(); L
['un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept']
La bibliothque trs complte re des expressions rgulires de Python peut aussi
tre utilise pour la recherche des sous-chanes et la reconnaissance de motifs et
de mots.

3.3.6 Structure partage ou duplique


Une liste entre crochets [...] peut tre modifie par des affectations sur ses
lments, par un changement du nombre de termes de la liste, ou des mthodes
comme le tri sort ou le renversement reverse.
Laffectation dune liste une variable ne duplique pas la structure mais
partage les mmes donnes. Dans lexemple suivant les listes L1 et L2 restent
identiques ; elles correspondent deux alias du mme objet, et la modification de
lune est visible sur lautre :
sage: L1 = [11, 22, 33] ; L2 = L1
sage: L1[1] = 222 ; L2.sort() ; L1, L2
([11, 33, 222], [11, 33, 222])
sage: L1[2:3] = []; L2[0:0] = [6, 7, 8]
sage: L1, L2
([6, 7, 8, 11, 33], [6, 7, 8, 11, 33])
Au contraire les images de listes par map, les constructions de sous-listes par
L[p:q], filter ou [..for..if..], la concatnation par + et *, et laplatissement
de listes par flatten dupliquent la structure des donnes.
Dans lexemple prcdent remplacer sur la premire ligne L2 = L1 par lune
des six commandes ci-aprs change compltement les rsultats suivants car les
modifications dune liste ne se propagent pas lautre. Les deux structures
deviennent indpendantes, les deux listes sont distinctes mme si elles ont la
3.3. LISTES ET STRUCTURES COMPOSES 71

mme valeur ; ainsi laffectation L2 = L1[:] recopie la sous-liste de L1 du premier


au dernier terme, et donc duplique la structure complte de L1 :

L2 = [11, 22, 33] L2 = copy(L1) L2 = L1[:]


L2 = []+L1 L2 = L1+[] L2 = 1*L1

Le test du partage des structures de Sage seffectue par loprateur binaire


is ; si la rponse au test est vraie, alors toutes les modifications portent sur les
deux variables la fois :
sage: L1 = [11, 22, 33] ; L2 = L1 ; L3 = L1[:]
sage: [L1 is L2, L2 is L1, L1 is L3, L1 == L3]
[True, True, False, True]

Les oprations de copie oprent sur un seul niveau de listes. Ainsi la modification
lintrieur dune liste de listes se propage malgr la copie de la structure au
premier niveau :
sage: La = [1, 2, 3] ; L1 = [1, La] ; L2 = copy(L1)
sage: L1[1][0] = 5 # [1, [5, 2, 3]] pour L1 et L2
sage: [L1 == L2, L1 is L2, L1[1] is L2[1]]
[True, False, True]

Linstruction suivante recopie la structure sur deux niveaux :


sage: map (copy, L)

alors que la fonction copyRec duplique rcursivement les listes tous les niveaux :
sage: def copyRec (L):
....: if type (L) == list: return map (copyRec, L)
....: else: return L

Lordre lexicographique inverse est dfini partir de lordre lexicographique


sur des n-uplets numrs lenvers en renversant lordre appliqu chaque
lment :

P = (p0 , p1 , . . . pn1 ) lexInv Q = (q0 , q1 , . . . qn1 )


r {0, . . . , n 1}, (pr+1 , . . . , pn1 ) = (qr+1 , . . . , qn1 ) et pr > qr .

La programmation de lordre lexicographique inverse peut se faire partir de la


fonction alpha dfinie prcdemment qui implante lordre lexicographique. La
recopie des listes P et Q est ncessaire pour effectuer linversion sans modifier les
donnes. Plus prcisment la fonction lexInverse renverse lordre des n-uplets
par reverse et renverse lordre final par le rsultat renvoy (P1 lex Q1 ) :
sage: def lexInverse (P, Q):
....: P1 = copy(P) ; P1.reverse()
....: Q1 = copy(Q) ; Q1.reverse()
....: return - alpha (P1, Q1)
72 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

Les modifications sur une liste passe en argument dune fonction se rpercutent
de faon globale sur la liste car les fonctions ne recopient pas les structures de
listes passes en argument. Ainsi une fonction effectuant uniquement P.reverse()
la place de P1 = copy(P) et P1.reverse() modifie dfinitivement la liste P ;
cet effet, appel effet de bord, nest gnralement pas souhait.
La variable P est une variable locale de la fonction indpendamment de
tout autre variable globale de mme nom P , mais cela est sans rapport avec les
modifications apportes lintrieur dune liste passe en argument.
Les listes terme employ dans Python et Sage sont en fait implantes
dans ces systmes sous la forme de tableau dynamique, et nont pas la mme
structure que celles du Lisp et dOcaml dfinies par un lment de tte t et
une liste de queue Q. La commande Lisp lmentaire cons(t,Q) renvoie une
liste avec le terme t en tte sans modifier la liste Q ; au contraire ajouter un
lment e un tableau T par T.append(e) en Python modifie le tableau T . Les
deux reprsentations de donnes ont chacune leurs avantages et le passage dune
reprsentation des donnes lautre est possible, mais lefficacit des algorithmes
nest pas la mme dans les deux cas.

3.3.7 Donnes modifiables ou immuables


Les listes permettent de structurer et de manipuler des donnes pouvant tre
modifies. Pour cette raison ces structures sont qualifies de modifiables ou de
mutables.
Au contraire, Python permet aussi de dfinir des donnes figes ou immuables.
La structure immuable correspondant aux listes est appele squence ou tuple
daprs son nom anglais, et est note avec des parenthses (...) la place
des crochets [...]. Une squence un seul argument est dfinie en plaant
explicitement une virgule aprs son argument.
sage: S0 = (); S1 = (1, ); S2 = (1, 2)
sage: [1 in S1, 1 == (1)]
[True, True]
Les oprations daccs aux squences sont essentiellement les mmes que celles sur
les listes, par exemple la construction dimage de squence par map ou dextraction
de sous-squence par filter. Dans tous les cas le rsultat est une liste, et cette
commande for transforme une squence en liste :
sage: S1 = (1, 4, 9, 16, 25); [k for k in S1]
[1, 4, 9, 16, 25]
La commande zip regroupe terme terme plusieurs listes ou squences de
faon quivalente la commande map suivante :
sage: L1 = [0..4]; L2 = [5..9]
sage: zip(L1, L2)
[(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]
sage: map(lambda x, y:(x, y), L1, L2)
[(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]
3.3. LISTES ET STRUCTURES COMPOSES 73

3.3.8 Ensembles finis


Contrairement aux listes, la notion densemble tient uniquement compte de la
prsence ou non dun lment, sans dfinir sa position ni le nombre de rptitions
de cet lment. Sage manipule les ensembles de cardinal fini partir de la fonction
Set applique la liste des lments. Le rsultat est affich entre accolades :
sage: E = Set([1, 2, 4, 8, 2, 2, 2]); F = Set([7, 5, 3, 1]); E, F
({8, 1, 2, 4}, {1, 3, 5, 7})
Loprateur dappartenance in teste lappartenance dun lment un ensemble,
et Sage autorise les oprations de runion densembles par + ou |, dintersection
par &, de diffrence par -, et de diffrence symtrique par ^^ :
sage: E = Set([1, 2, 4, 8, 2, 2, 2]); F = Set([7, 5, 3, 1])
sage: 5 in E, 5 in F, E + F == F | E
(False, True, True)
sage: E & F, E - F, E ^^ F
({1}, {8, 2, 4}, {2, 3, 4, 5, 7, 8})
La fonction len(E) renvoie le cardinal dun tel ensemble fini. Les oprations
map, filter et for..if... sappliquent aux ensembles comme aux squences, et
les rsultats sont des listes. Laccs un lment seffectue par E[k]. Les deux
commandes ci-dessous construisent de faon quivalente la liste des lments dun
ensemble :
sage: E = Set([1, 2, 4, 8, 2, 2, 2])
sage: [E[k] for k in [0..len(E)-1]], [t for t in E]
([8, 1, 2, 4], [8, 1, 2, 4])
La fonction suivante teste linclusion dun ensemble E dans F partir de la
runion :
sage: def inclus (E, F): return E+F == F
Contrairement aux listes, les ensembles sont de type immuable et ne sont
donc pas modifiables ; leurs lments doivent aussi tre immuables. Les ensembles
de tuples et les ensembles densembles sont donc possibles mais on ne peut pas
construire des ensembles de listes :
sage: Set([Set([]), Set([1]), Set([2]), Set([1, 2])])
{{1, 2}, {}, {2}, {1}}
sage: Set([ (), (1, ), (2, ), (1, 2) ])
{(1, 2), (2,), (), (1,)}
Cette fonction numre tous les sous-ensembles dun ensemble par une mthode
rcursive :
sage: def Parties (EE):
....: if EE == Set([]): return Set([EE])
....: else:
....: return avecOuSansElt (EE[0], Parties(Set(EE[1:])))
74 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES

sage: def avecOuSansElt (a, E):


....: return Set (map (lambda F: Set([a])+F, E)) + E

sage: Parties(Set([1, 2, 3]))


{{3}, {1, 2}, {}, {2, 3}, {1}, {1, 3}, {1, 2, 3}, {2}}
La fonction avecOuSansElt(a, E) prend un ensemble E de sous-ensembles, et
construit lensemble ayant deux fois plus dlments qui sont ces mmes sous-
ensembles et ceux auxquels llment a a t ajout. La construction rcursive
commence avec lensemble un lment E = {}.

3.3.9 Dictionnaires
Enfin Python, et donc Sage, intgre la notion de dictionnaire. Comme un
annuaire, un dictionnaire associe une valeur chaque entre.
Les entres dun dictionnaire sont de nimporte quel type immuable, nombres,
chanes de caractres, squences, etc. La syntaxe est comparable celle des listes
par des affectations partir du dictionnaire vide dict() pouvant tre abrg
en {} :
sage: D={}; D['un']=1; D['deux']=2; D['trois']=3; D['dix']=10
sage: D['deux'] + D['trois']
5
Lexemple prcdent dtaille donc comment ajouter une entre dans un diction-
naire, et comment accder un champ par D[...].
Loprateur in teste si une entre fait partie dun dictionnaire, et les com-
mandes del D[x] ou D.pop(x) effacent lentre x de ce dictionnaire.
Lexemple suivant indique comment un dictionnaire peut reprsenter une
application sur un ensemble fini :

E = {a0 , a1 , a2 , a3 , a4 , a5 }, f (a0 ) = b0 , f (a1 ) = b1 , f (a2 ) = b2 ,


f (a3 ) = b0 , f (a4 ) = b3 , f (a5 ) = b3 .

Les mthodes sur les dictionnaires sont comparables celles portant sur les
autres structures numres. Le code ci-dessous implante la fonction prcdente
et construit lensemble de dpart E et lensemble image Im f = f (E) par les
mthodes keys et values :
sage: D = {'a0':'b0', 'a1':'b1', 'a2':'b2', 'a3':'b0',\
....: 'a4':'b3', 'a5':'b3'}
sage: E = Set(D.keys()) ; Imf = Set(D.values())
sage: Imf == Set(map (lambda t:D[t], E)) # est quivalent
True
Cette dernire commande traduit directement la dfinition mathmatique Im f =
{f (x)|x E}. Les dictionnaires peuvent aussi tre construits partir de listes ou
de couples [cl, valeur] par la commande suivante :

dict([a0, b0], [a1, b1], ...)


3.3. LISTES ET STRUCTURES COMPOSES 75

Les deux commandes suivantes appliques aux entres du dictionnaire ou au dic-


tionnaire lui-mme sont, par construction, quivalentes la mthode D.values() :

map (lambda t:D[t], D) map (lambda t:D[t], D.keys())

Le test suivant sur le nombre dlments dtermine si lapplication reprsente


par D est injective, len(D) tant le nombre dentres dans le dictionnaire :
sage: def injective(D):
....: return len(D) == len (Set(D.values()))
Les deux premires commandes ci-dessous construisent limage directe f (F )
et limage rciproque f 1 (G) des sous-ensembles F et G dune application dfinie
par le dictionnaire D ; la dernire dfinit un dictionnaire DR correspondant
lapplication rciproque f 1 dune application f suppose bijective :
sage: Set([D[t] for t in F])
sage: Set([t for t in D if D[t] in G])
sage: DR = dict((D[t], t) for t in D)
76 CHAP. 3. PROGRAMMATION ET STRUCTURES DE DONNES
4
Graphiques

La visualisation de fonctions dune ou deux variables, dune srie de donnes,


facilite la perception de phnomnes mathmatiques ou physiques et permet
de conjecturer des rsultats efficacement. Dans ce chapitre, on illustre sur des
exemples les capacits graphiques de Sage.

4.1 Courbes en 2D
Une courbe plane peut tre dfinie de plusieurs faons : comme graphe dune
fonction dune variable, par un systme dquations paramtriques, par une
quation en coordonnes polaires, ou par une quation implicite. Nous prsentons
ces quatre cas, puis donnons quelques exemples de tracs de donnes.

4.1.1 Reprsentation graphique de fonctions


Pour tracer le graphe dune fonction symbolique ou dune fonction Python
sur un intervalle [a, b], on dispose de deux syntaxes : plot(f(x), a, b) ou
plot(f(x), x, a, b).
sage: plot(x * sin(1/x), x, -2, 2, plot_points=500)
Parmi les nombreuses options de la fonction plot, citons :
plot_points (valeur par dfaut 200) : nombre minimal de points calculs ;
xmin et xmax : bornes de lintervalle sur lequel est trace la fonction ;
color : couleur du trac, un triplet RGB, une chane de caractres (par ex.
'blue'), ou une couleur HTML (par ex. '#aaff0b') ;
78 CHAP. 4. GRAPHIQUES

0.8

0.6

0.4

0.2

-2 -1.5 -1 -0.5 0.5 1 1.5 2


-0.2

1
Figure 4.1 Graphe de x 7 x sin x
.

detect_poles (valeur par dfaut False) : permet de tracer ou non lasymp-


tote verticale aux ples dune fonction ;
alpha : transparence du trait ;
thickness : paisseur du trait ;
linestyle : nature du trait, trac en pointills (':'), traits et pointills
('-.'), trait continu ('-'), qui est la valeur par dfaut.
Pour visualiser le trac, on peut placer lobjet graphique dans une variable,
disons g, puis utiliser la commande show, en prcisant par exemple les valeurs
minimales et maximales de lordonne (g.show(ymin=-1, ymax=3)) ou alors
en choisissant le rapport daffinit (g.show(aspect_ratio=1) pour un trac en
repre orthonorm).
La figure produite peut tre exporte grce la commande save vers diffrents
formats indiqus par les suffixes .pdf, .png, .ps, .eps, .svg et .sobj :
g.save(nom, aspect_ratio=1, xmin=-1, xmax=3, ymin=-1, ymax=3)
Pour inclure une telle figure dans un document LATEX laide de la commande
includegraphics, on choisit lextension eps (PostScript encapsul) si le document
est compil avec latex, et lextension pdf ( prfrer png, pour obtenir une
meilleure rsolution) si le document est compil avec pdflatex.
Traons sur un mme graphique la fonction sinus et ses premiers polynmes
de Taylor en 0.
sage: def p(x, n):
....: return(taylor(sin(x), x, 0, n))
sage: xmax = 15 ; n = 15
sage: g = plot(sin(x), x, -xmax, xmax)
sage: for d in range(n):
....: g += plot(p(x, 2 * d + 1), x, -xmax, xmax,\
....: color=(1.7*d/(2*n), 1.5*d/(2*n), 1-3*d/(4*n)))
sage: g.show(ymin=-2, ymax=2)
On aurait galement pu effectuer une animation, pour observer comment le
polynme de Taylor approche de mieux en mieux la fonction sinus lorsque le
degr augmente. Si lon souhaite sauvegarder lanimation, il suffit de lenregistrer
au format gif.
4.1. COURBES EN 2D 79

2 4
1.5 3
1 2
0.5 1

-10 -5 5 10 -20 -10 10 20


-0.5 -1
-1 -2
-1.5 -3
-2 -4

Figure 4.2 Quelques polynmes de Taylor de sinus en 0.

sage: a = animate([[sin(x), taylor(sin(x), x, 0, 2*k+1)]\


....: for k in range(0, 14)], xmin=-14, xmax=14,\
....: ymin=-3, ymax=3, figsize=[8, 4])
sage: a.show(); a.save('chemin/animation.gif')

Revenons la fonction plot pour observer, par exemple, le phnomne de


Gibbs. Traons la somme partielle dordre 20 de la srie de Fourier de la fonction
crneau.
sage: f2(x) = 1; f1(x) = -1
sage: f = piecewise([[(-pi,0),f1],[(0,pi),f2]])
sage: S = f.fourier_series_partial_sum(20,pi)
sage: g = plot(S, x, -8, 8, color='blue')
sage: scie(x) = x - 2 * pi * floor((x + pi) / (2 * pi))
sage: g += plot(scie(x) / abs(scie(x)), x, -8, 8, color='red')
sage: g

0.5

-8 -6 -4 -2 2 4 6 8

-0.5

-1

Figure 4.3 Dcomposition de la fonction crneau en srie de Fourier.

Dans le code ci-dessus, f est une fonction par morceaux dfinie sur [; ]
laide de linstruction piecewise. Pour reprsenter le prolongement de f par
2-priodicit, le plus simple est den chercher une expression valable pour tout
rel (en loccurrence scie/abs(scie)). La somme des 20 premiers termes de la
80 CHAP. 4. GRAPHIQUES

srie de Fourier vaut :


4 sin(3x) sin(5x) sin(19)
 
S= sin(x) + + + + .
3 5 19

4.1.2 Courbe paramtre


Les tracs de courbes paramtres (x = f (t), y = g(t)) sont raliss par la com-
mande parametric_plot((f(t), g(t)), (t, a, b)) o [a, b] est lintervalle
parcouru par le paramtre.
Reprsentons par exemple la courbe paramtre dquations :
1 1

x(t) = cos(t) + cos(7t) + sin(17t),

2 3
1 1
y(t) = sin(t) + sin(7t) + cos(17t).

2 3

sage: t = var('t')
sage: x = cos(t) + cos(7*t)/2 + sin(17*t)/3
sage: y = sin(t) + sin(7*t)/2 + cos(17*t)/3
sage: g = parametric_plot((x, y), (t, 0, 2*pi))
sage: g.show(aspect_ratio=1)

1.5

0.5

-1.5 -1 -0.5 0.5 1 1.5

-0.5

-1

-1.5

1 1
Figure 4.4 Courbe paramtre dquation x(t) = cos(t) + 2
cos(7t) + 3
sin(17t), y(t) =
sin(t) + 12 sin(7t) + 13 cos(17t).

4.1.3 Courbe en coordonnes polaires


Les tracs de courbes en coordonnes polaires = f () sont raliss par
la commande polar_plot(rho(theta),(theta,a,b)) o [a, b] est lintervalle
parcouru par le paramtre.
4.1. COURBES EN 2D 81

Reprsentons par exemple les conchodes de rosace dquation polaire () =


1 + e cos n lorsque n = 20/19 et e {2, 1/3}.

sage: t = var('t'); n = 20/19


sage: g1 = polar_plot(1+2*cos(n*t),(t,0,n*36*pi),plot_points=5000)
sage: g2 = polar_plot(1+1/3*cos(n*t),(t,0,n*36*pi),plot_points=5000)
sage: g1.show(aspect_ratio=1); g2.show(aspect_ratio=1)

1
2

1 0.5

-3 -2 -1 1 2 3 -1 -0.5 0.5 1

-1 -0.5

-2
-1

-3

Figure 4.5 Rosaces dquation () = 1 + e cos n.

Exercice 12. Reprsenter la famille de conchodes de Pascal dquation polaire


() = a + cos en faisant varier le paramtre a de 0 2 avec un pas de 0.1.

4.1.4 Courbe dfinie par une quation implicite

Pour reprsenter une courbe donne par une quation implicite, on utilise
la fonction implicit_plot(f(x, y), (x, a, b), (y, c, d)) ; cependant, on
peut aussi utiliser la commande complex_plot qui permet de visualiser en couleur
les lignes de niveau dune fonction  deux variables. Reprsentons la courbe
donne par lquation implicite C = z C , cos(z 4 ) = 1 .

sage: z = var('z')
sage: g1 = complex_plot(abs(cos(z^4))-1,
....: (-3,3), (-3,3), plot_points=400)
sage: f = lambda x, y : (abs(cos((x + I * y) ** 4)) - 1)
sage: g2 = implicit_plot(f, (-3, 3), (-3, 3), plot_points=400)
sage: g1.show(aspect_ratio=1); g2.show(aspect_ratio=1)
82 CHAP. 4. GRAPHIQUES

-3 -2 -1 1 2 3

-1

-2

-3

-3 -2 -1 1 2 3

-1

-2

-3


Figure 4.6 Courbe dfinie par lquation cos(z 4 ) = 1.

Voici un autre exemple de trac de fonc-


1
tion donne par une quation complexe :
sage: f(z) = z^5+z-1+1/z -3 -2 -1 1 2 3
sage: complex_plot(f,\
-1
....: (-3, 3), (-3, 3))
-2

-3
4.1. COURBES EN 2D 83

4.1.5 Trac de donnes


Pour tracer un diagramme en rectangles, on dispose de deux fonctions assez
diffrentes. Tout dabord, la commande bar_chart prend en argument une liste
dentiers et trace simplement des barres verticales dont la hauteur est donne par
les lments de la liste (dans leur ordre dapparition dans la liste). Notons que
loption width permet de choisir la largeur des rectangles.
sage: bar_chart([randrange(15) for i in range(20)])
sage: bar_chart([x^2 for x in range(1,20)], width=0.2)

9 350
8
300
7
6 250
5 200
4 150
3
100
2
1 50

2 4 6 8 10 5 10 15

Figure 4.7 Diagrammes en rectangles.

En revanche, pour tracer lhistogramme des frquences dune donne alatoire


partir dune liste de flottants, on utilise la fonction plot_histogram : les valeurs
de la liste sont tries et rparties dans des intervalles (le nombre dintervalles
tant fix par la variable bins dont la valeur par dfaut vaut 50) ; la hauteur de
la barre pour chaque intervalle tant gale la frquence correspondante.
sage: liste = [10 + floor(10*sin(i)) for i in range(100)]
sage: bar_chart(liste)
sage: finance.TimeSeries(liste).plot_histogram(bins=20)

0.16
0.14
15
0.12
0.1
10
0.08
0.06
5 0.04
0.02
10 20 30 40 50 5 10 15

(a) Trac avec bar_chart. (b) Trac avec plot_histogram.

Il est frquent que la liste statistique tudier soit stocke dans une feuille
de calcul obtenue laide dun tableur. Le module csv de Python permet alors
dimporter les donnes depuis un fichier enregistr au format csv. Par exemple,
supposons que lon souhaite tracer lhistogramme des notes dune classe se trouvant
dans la colonne 3 du fichier nomm ds01.csv. Pour extraire les notes de cette
colonne, on utilise les instructions suivantes (en gnral les premires lignes
84 CHAP. 4. GRAPHIQUES

50
40
30
20
10
-60 -40 -20 20 40
-10
-20
-30

Figure 4.8 Marche alatoire.

comportent du texte do la ncessit de grer les erreurs ventuelles lors de la


conversion en flottant grce linstruction try) :
sage: import csv
sage: reader = csv.reader(open("ds01.csv"))
sage: notes = []; liste = []
sage: for ligne in reader: 0.25
....: notes.append(ligne[3]) 0.2
....: for i in notes: 0.15
....: try: 0.1
....: f = float(i)
0.05
....: except ValueError:
0 2 4 6 8 10 12 14
....: pass
....: else:
....: liste.append(f)
sage: finance.TimeSeries(liste).plot_histogram(bins=20)
Pour tracer une liste de points relis (resp. un nuage de points), on utilise
la commande line(p) (resp. point(p)), p dsignant une liste de listes deux
lments donnant abscisse et ordonne des points tracer.
Exemple. (Marche alatoire) Partant dun point origine O, une particule se
dplace dune longueur `, intervalles de temps rguliers t, chaque fois dans une
direction quelconque, indpendante des directions prcdentes. Reprsentons un
exemple de trajectoire pour une telle particule. Le segment rouge relie la position
initiale la position finale.
sage: from random import *
sage: n, l, x, y = 10000, 1, 0, 0; p = [[0, 0]]
sage: for k in range(n):
....: theta = (2 * pi * random()).n(digits=5)
....: x, y = x + l * cos(theta), y + l * sin(theta)
....: p.append([x, y])
sage: g1 = line([p[n], [0, 0]], color='red', thickness=2)
sage: g1 += line(p, thickness=.4); g1.show(aspect_ratio=1)
4.1. COURBES EN 2D 85

Exemple. (Suites quirparties) tant donne une suite relle (un )nN , on
construit la ligne polygonale dont les sommets successifs sont les points daffixe
X
zN = e2iun .
n6N

Si la suite est quirpartie modulo 1, la ligne brise ne sloigne pas trop rapidement
de lorigine. On peut alors conjecturer la rgularit de la rpartition de la suite
partir du trac de la ligne brise. Traons la ligne polygonale dans les cas suivants :

un = n 2 et N = 200,

un = n ln(n) 2 et N = 10000,

un = E(n ln(n)) 2 et N = 10000 (o E dsigne la partie entire),

un = pn 2 et N = 10000 (ici pn est le n-ime nombre premier).

La figure 4.9 sobtient de la manire suivante (ici pour un = n 2) :

sage: length = 200; n = var('n')


sage: u = lambda n: n * sqrt(2)
sage: z = lambda n: exp(2 * I * pi * u(n)).n()
sage: vertices = [CC(0, 0)]
sage: for n in range(1, length):
....: vertices.append(vertices[n - 1] + CC(z(n)))
sage: line(vertices).show(aspect_ratio=1)

On remarque que la courbe 4.9a est particulirement rgulire, ce qui permet


de prvoir que lquirpartition
de n 2 est de nature dterministe. Dans le cas
de la suite un = n ln(n) 2, lexamen des valeurs prises donne limpression dun
engendrement alatoire. Cependant, la courbe associe 4.9b est remarquablement
bien structure. La courbe 4.9c prsente le mme type de structures que la
deuxime. Enfin, le trac de la courbe 4.9d
fait apparatre la nature profondment
diffrente de la rpartition modulo 1/ 2 de la suite des nombres premiers : les
spirales ont disparu et lallure ressemble la courbe que lon obtient dans le cas
dune suite de nombres alatoires un (figure 4.8). Il semble donc que les nombres
premiers occupent tout le hasard qui leur est imparti...
Pour une interprtation dtaille des courbes obtenues, on se reportera au
Que sais-je ? Les nombres premiers de Grald Tenenbaum et Michel Mends
France [TMF00].
Exercice 13 (Trac des termes dune suite rcurrente). On considre la suite
(un )nN dfinie par :
nu0 = a,

n N, un+1 = u2n 41 .

Reprsenter graphiquement
 le comportement de la suite en construisant une liste
forme des points [u0 , 0], [u0 , u1 ], [u1 , u1 ], [u1 , u2 ], [u2 , u2 ], . . . , avec a {0.4, 1.1, 1.3}.
86 CHAP. 4. GRAPHIQUES

60
0.6

0.4 40

0.2 20

-1 -0.8 -0.6 -0.4 -0.2 -50 -40 -30 -20 -10 10 20

-0.2
-20

-0.4

(a) Cas un = n 2. (b) Cas un = n ln(n) 2.

50

40
40
30 30
20
20
10

-80 -60 -40 -20 20 10


-10
-20 -30 -20 -10 10 20
-30 -10
-40

(c) Cas un = E(n ln(n)) 2. (d) Cas un = pn 2.

Figure 4.9 Suites quirparties.


4.1. COURBES EN 2D 87

4.1.6 Trac de solution dquation diffrentielle


On peut combiner les commandes prcdentes pour tracer des solutions dqua-
tions ou de systmes diffrentiels. Pour rsoudre symboliquement une quation
diffrentielle ordinaire, on utilise la fonction desolve dont ltude fait lobjet
du chapitre 10. Pour rsoudre numriquement une quation diffrentielle, Sage
nous fournit plusieurs outils : desolve_rk4 (qui utilise la mme syntaxe que la
fonction desolve et qui suffit pour rsoudre les quations diffrentielles ordinaires
rencontres en licence), odeint (qui utilise le module SciPy) et enfin ode_solver
(qui appelle la bibliothque GSL dont lutilisation est dtaille dans la section
14.2). Les fonctions desolve_rk4 et odeint renvoient une liste de points quil est
alors ais de tracer laide de la commande line ; cest celles que nous utiliserons
dans cette section pour tracer des solutions numriques.
Exemple. (quation diffrentielle linaire, du premier ordre, non rsolue)
Traons les courbes intgrales de lquation diffrentielle xy 0 2y = x3 .

sage: x = var('x'); y = function('y')


sage: DE = x*diff(y(x), x) == 2*y(x) + x^3
sage: desolve(DE, [y(x),x])
(c + x)*x^2
sage: sol = []
sage: for i in srange(-2, 2, 0.2):
....: sol.append(desolve(DE, [y(x), x], ics=[1, i]))
....: sol.append(desolve(DE, [y(x), x], ics=[-1, i]))
sage: g = plot(sol, x, -2, 2)
sage: y = var('y')
sage: g += plot_vector_field((x, 2*y+x^3), (x,-2,2), (y,-1,1))
sage: g.show(ymin=-1, ymax=1)
Pour diminuer le temps de calcul, il serait prfrable ici de saisir la main
la solution gnrale de lquation et de crer une liste de solutions particulires
(comme cela est fait dans la correction de lexercice 14) plutt que de rsoudre plu-
sieurs fois de suite lquation diffrentielle avec des conditions initiales diffrentes.
On aurait galement pu effectuer une rsolution numrique de cette quation (
laide de la fonction desolve_rk4) pour en tracer les courbes intgrales :

1 1

0.5 0.5

-2 -1.5 -1 -0.5 0.5 1 1.5 2 -2 -1.5 -1 -0.5 0.5 1 1.5 2


-0.5 -0.5

-1 -1
(a) Rsolution symbolique. (b) Rsolution numrique.

Figure 4.10 Trac des courbes intgrales de xy 0 2y = x3 .


88 CHAP. 4. GRAPHIQUES

10
8
6
4
2

-4 -2 2 4
-2
Figure 4.11 Trac des courbes intgrales de y 0 (t) + cos(y(t) t) = 0.

sage: x = var('x'); y = function('y')


sage: DE = x*diff(y(x), x) == 2*y(x) + x^3
sage: g = Graphics() # cre un graphique vide
sage: for i in srange(-2, 2, 0.2):
....: g += line(desolve_rk4(DE, y(x), ics=[1, i],\
....: step=0.05, end_points=[0,2]))
....: g += line(desolve_rk4(DE, y(x), ics=[-1, i],\
....: step=0.05, end_points=[-2,0]))
sage: y = var('y')
sage: g += plot_vector_field((x, 2*y+x^3), (x,-2,2), (y,-1,1))
sage: g.show(ymin=-1, ymax=1)
Comme on le voit sur lexemple prcdent, la fonction desolve_rk4 prend en
argument une quation diffrentielle (ou le membre de droite f de lquation crite
sous forme rsolue y 0 = f (y, x)), le nom de la fonction inconnue, la condition
initiale, le pas et lintervalle de rsolution. Largument optionnel output permet
de prciser la sortie de la fonction : la valeur par dfaut 'list' renvoie une liste
(ce qui est utile si on veut superposer des graphiques comme dans notre exemple),
'plot' affiche le trac de la solution et 'slope_field' y ajoute le trac des
pentes des courbes intgrales.
Exercice 14. Tracer les courbes intgrales de lquation x2 y 0 y = 0, pour 3 6
x 6 3 et 5 6 y 6 5.
Donnons prsent un exemple dutilisation de la fonction odeint du module
SciPy.
Exemple. (quation diffrentielle non linaire, rsolue, du premier ordre)
Traons les courbes intgrales de lquation y 0 (t) + cos(y(t) t) = 0.
4.1. COURBES EN 2D 89

sage: import scipy; from scipy import integrate


sage: f = lambda y, t: - cos(y * t)
sage: t = srange(0, 5, 0.1); p = Graphics()
sage: for k in srange(0, 10, 0.15):
....: y = integrate.odeint(f, k, t)
....: p += line(zip(t, flatten(y)))
sage: t = srange(0, -5, -0.1); q = Graphics()
sage: for k in srange(0, 10, 0.15):
....: y = integrate.odeint(f, k, t)
....: q += line(zip(t, flatten(y)))
sage: y = var('y')
sage: v = plot_vector_field((1, -cos(x*y)), (x,-5,5), (y,-2,11))
sage: g = p + q + v; g.show()
La fonction odeint prend en argument le second membre de lquation diffren-
tielle (crite sous forme rsolue), une ou plusieurs conditions initiales, et enfin
lintervalle de rsolution ; elle renvoie ensuite un tableau du type numpy.ndarray
que lon aplatit laide de la commande flatten 1 dj vue au 3.3.2 et que lon
runit avec le tableau t grce la commande zip avant deffectuer le trac de
la solution approche. Pour ajouter le champ des vecteurs tangents aux courbes
intgrales, on a utilis la commande plot_vector_field.
Exemple. (Modle proie-prdateur de Lokta-Volterra) On souhaite repr-
senter graphiquement lvolution dune population de proies et de prdateurs
voluant suivant un systme dquations du type Lokta-Volterra :
du


= au buv,
dt
dv = cv + dbuv,

dt
o u dsigne le nombre de proies (par ex. des lapins), v le nombre de prdateurs
(par ex. des renards). De plus, a, b, c, d sont des paramtres qui dcrivent
lvolution des populations : a caractrise la croissance naturelle du nombre de
lapins en labsence de renards, b la dcroissance du nombre de lapins due la
prsence de prdateurs, c la dcroissance du nombre de renards en labsence de
proies, enfin d indique combien il faut de lapins pour quapparaisse un nouveau
renard.
sage: import scipy; from scipy import integrate
sage: a, b, c, d = 1., 0.1, 1.5, 0.75
sage: def dX_dt(X, t=0): # renvoie l'augmentation des populations
....: return [a*X[0] - b*X[0]*X[1], -c*X[1] + d*b*X[0]*X[1]]
sage: t = srange(0, 15, .01) # chelle de temps
sage: X0 = [10, 5] # conditions initiales : 10 lapins et 5 renards
sage: X = integrate.odeint(dX_dt, X0, t) # rsolution numrique
sage: lapins, renards = X.T # raccourci de X.transpose()
1. On aurait pu utiliser galement la fonction ravel de NumPy qui vite de crer un nouvel
objet liste et donc optimise lutilisation de la mmoire.
90 CHAP. 4. GRAPHIQUES

sage: p = line(zip(t, lapins), color='red') # trac du nombre de lapins


sage: p += text("Lapins",(12,37), fontsize=10, color='red')
sage: p += line(zip(t, renards), color='blue') # idem pour les renards
sage: p += text("Renards",(12,7), fontsize=10, color='blue')
sage: p.axes_labels(["temps", "population"]); p.show(gridlines=True)
Les instructions ci-dessus tracent lvolution du nombre de lapins et de renards en
fonction du temps (figure 4.12 gauche), et celles ci-dessous le champ de vecteurs
(figure 4.12 droite) :
sage: n = 11; L = srange(6, 18, 12 / n); R = srange(3, 9, 6 / n)
sage: CI = zip(L, R) # liste des conditions initiales
sage: def g(x,y):
....: v = vector(dX_dt([x, y])) # pour un trac plus lisible,
....: return v/v.norm() # on norme le champ de vecteurs
sage: x, y = var('x, y')
sage: q = plot_vector_field(g(x, y), (x, 0, 60), (y, 0, 36))
sage: for j in range(n):
....: X = integrate.odeint(dX_dt, CI[j], t) # rsolution
....: q += line(X, color=hue(.8-float(j)/(1.8*n))) # graphique
sage: q.axes_labels(["lapins","renards"]); q.show()

population
renards
40
Lapins 35
35
30
30
25 25

20 20
15 15
10 10
Renards
5 5
temps lapins
0 2 4 6 8 10 12 14 10 20 30 40 50 60

Figure 4.12 tude dun systme proies-prdateurs.

Exercice 15 (Modle proie-prdateur). Refaire le graphe de gauche de la figure 4.12


en utilisant desolve_system_rk4 la place de odeint.
Exercice 16 (Un systme diffrentiel autonome). Tracer les courbes intgrales du
systme diffrentiel suivant :
x = y,
n
y = 0.5y x y 3 .
Exercice 17 (coulement autour dun cylindre avec effet Magnus). On superpose
un coulement simple autour dun cylindre de rayon a, un vortex de paramtre , ce
qui modifie la composante orthoradiale de vitesse. On se place dans un repre centr sur
le cylindre, et on travaille en coordonnes cylindriques dans le plan z = 0, autrement dit
en coordonnes polaires. Les composantes de la vitesse sont alors :
   
a2 a2 av0
vr = v0 cos() 1 2 et v = v0 sin() 1 + 2 +2 .
r r r
4.1. COURBES EN 2D 91

Les lignes de courant (confondues avec les trajectoires, car lcoulement est stationnaire)
sont parallles la vitesse. On cherche une expression paramtre des lignes de champs ;
il faut alors rsoudre le systme diffrentiel :
dr d v
= vr et = .
dt dt r
On utilise des coordonnes non dimensionnes, cest--dire rapportes a, rayon du
cylindre, ce qui revient supposer a = 1. Tracer les lignes de courant de cet coulement
pour {0.1, 0.5, 1, 1.25}.
Lutilisation de leffet Magnus a t propos pour mettre au point des systmes de
propulsion composs de gros cylindres verticaux en rotation capables de produire une
pousse longitudinale lorsque le vent est sur le ct du navire (ce fut le cas du navire
Baden-Baden mis au point par Anton Flettner qui traversa lAtlantique en 1926).

4.1.7 Dveloppe dune courbe


On donne prsent un exemple de trac de dveloppe dun arc paramtr (on
rappelle que la dveloppe est lenveloppe des normales ou, de manire quivalente,
le lieu des centres de courbure de la courbe).
Exemple. (Dveloppe de la parabole) Trouvons lquation de la dveloppe
de la parabole P dquation y = x2 /4 et traons sur un mme graphique la
parabole P, quelques normales P et sa dveloppe.
Pour dterminer un systme dquations paramtriques (x(t), y(t)) de lenve-
loppe dune famille de droites t dfinies par des quations cartsiennes de la
forme (t)X + (t)Y = (t), on exprime le fait que la droite t est tangente
lenveloppe au point (x(t), y(t)) :

(t)x(t) + (t)y(t) = (t), (4.1)


(t)x (t) + (t)y (t) = 0.
0 0
(4.2)

On drive lquation (4.1) et en combinant avec (4.2), on obtient le systme :

(t) x(t) + (t) y(t) = (t), (4.1)


0 (t)x(t) + 0 (t)y(t) = 0 (t). (4.3)

Dans notre cas, la normale (Nt ) la parabole P en M (t, t2 /4) a pour vecteur
normal
v = (1, t/2) (qui est le vecteur tangent la parabole) ; elle a donc pour
quation :
1 t3
   
xt t
= 0 x + y = t + ,
2
y t /4 t/2 2 8
autrement dit, ((t), (t), (t)) = (1, t/2, t + t3 /8). On peut alors rsoudre le
systme prcdent avec la fonction solve :
sage: x, y, t = var('x, y, t')
sage: alpha(t) = 1; beta(t) = t / 2; gamma(t) = t + t^3 / 8
sage: env = solve([alpha(t) * x + beta(t) * y == gamma(t),\
....: diff(alpha(t), t) * x + diff(beta(t), t) * y == \
....: diff(gamma(t), t)], [x,y])
92 CHAP. 4. GRAPHIQUES

1 3
 
x = t3 , y = t2 + 2
4 4
Do une reprsentation paramtrique de lenveloppe des normales :

x(t) = 41 t3 ,


y(t) = 2 + 34 t2 .

On peut alors effectuer le trac demand, en traant quelques normales la


parabole (plus prcisment, on trace des segments [M, M + 18

n ] o M (u, u2 /4)


est un point de P et n = (u/2, 1) un vecteur normal P) :
sage: f(x) = x^2 / 4
sage: p = plot(f, -8, 8, rgbcolor=(0.2,0.2,0.4)) # la parabole
sage: for u in srange(0, 8, 0.1): # normales la parabole
....: p += line([[u, f(u)], [-8*u, f(u) + 18]], thickness=.3)
....: p += line([[-u, f(u)], [8*u, f(u) + 18]], thickness=.3)
sage: p += parametric_plot((env[0][0].rhs(),env[0][1].rhs()),\
....: (t, -8, 8),color='red') # trace la dveloppe
sage: p.show(xmin=-8, xmax=8, ymin=-1, ymax=12, aspect_ratio=1)

12

10

-8 -6 -4 -2 2 4 6 8

Figure 4.13 La dveloppe de la parabole.

Comme rappel plus haut, la dveloppe dune courbe est aussi le lieu de ses
centres de courbures. laide de la fonction circle traons quelques cercles
osculateurs la parabole. On rappelle que le centre de courbure en un point
Mt = (x(t), y(t)) de la courbe a pour coordonnes :

x02 + y 02 x02 + y 02
x = x + y 0 , et y = y + x0 ,
x0 y 00 x00 y 0 x0 y 00 x00 y 0
4.2. COURBES EN 3D 93

et que le rayon de courbure en Mt vaut :


3
(x02 + y 02 ) 2
R= .
x0 y 00 x00 y 0

sage: t = var('t'); p = 2
sage: x(t) = t; y(t) = t^2 / (2 * p); f(t) = [x(t), y(t)]
sage: df(t) = [x(t).diff(t), y(t).diff(t)]
sage: d2f(t) = [x(t).diff(t, 2), y(t).diff(t, 2)]
sage: T(t) = [df(t)[0] / df(t).norm(), df[1](t) / df(t).norm()]
sage: N(t) = [-df(t)[1] / df(t).norm(), df[0](t) / df(t).norm()]
sage: R(t) = (df(t).norm())^3 / (df(t)[0]*d2f(t)[1]-df(t)[1]*d2f(t)[0])
sage: Omega(t) = [f(t)[0] + R(t)*N(t)[0], f(t)[1] + R(t)*N(t)[1]]
sage: g = parametric_plot(f(t), (t,-8,8), color='green',thickness=2)
sage: for u in srange(.4, 4, .2):
....: g += line([f(t=u), Omega(t=u)], color='red', alpha = .5)
....: g += circle(Omega(t=u), R(t=u), color='blue')
sage: g.show(aspect_ratio=1,xmin=-12,xmax=7,ymin=-3,ymax=12)

12

10

-10 -5 5
-2

Figure 4.14 Cercles osculateurs la parabole.

Le tableau 4.1 rsume les fonctions utilises dans cette section. On y signale
de plus la commande text qui permet de placer une chane de caractre dans un
graphique, ainsi que la commande polygon qui permet de tracer des polygones.

4.2 Courbes en 3D
On dispose de la commande plot3d(f(x,y),(x,a,b),(y,c,d)) pour le trac
de surfaces en trois dimensions. La surface obtenue est alors visualise par dfaut
94 CHAP. 4. GRAPHIQUES

Type de trac
Courbe reprsentative dune fonction plot
Courbe paramtre parametric_plot
Courbe dfinie par une quation polaire polar_plot
Courbe dfinie par une quation implicite implicit_plot
Lignes de niveau dune fonction complexe complex_plot
Objet graphique vide Graphics()
Courbes intgrales dquation diffrentielle odeint, desolve_rk4
Diagramme en btonnets bar_chart
Diagramme des frquences dune srie statistique plot_histogram
Trac dune ligne brise line
Trac dun nuage de points points
Cercle circle
Polygone polygon
Texte text

Tableau 4.1 Rcapitulatif des fonctions graphiques 2D.

grce lapplication Jmol ; cependant, on peut galement utiliser le Tachyon 3D


Ray Tracer grce largument optionnel viewer='tachyon' de la commande
show. Voici un premier exemple de trac dune surface paramtre (figure 4.15) :
sage: u, v = var('u, v')
sage: h = lambda u,v: u^2 + 2*v^2
sage: f = plot3d(h, (u,-1,1), (v,-1,1), aspect_ratio=[1,1,1])

Figure 4.15 La surface paramtre par (u, v) 7 u2 + 2v 2 .

La visualisation de la surface reprsentative dune fonction de deux variables


permet de guider ltude dune telle fonction, comme nous allons le voir dans
lexemple suivant.
Exemple. (Une fonction discontinue dont les drives directionnelles existent
partout !) tudier lexistence en (0, 0) des drives directionnelles et la continuit
de lapplication f de R2 dans R dfinie par :
( 2
x y
si (x, y) 6= (0, 0),
f (x, y) = x +y
4 2

0 si (x, y) = (0, 0).


4.2. COURBES EN 3D 95

Pour H = cossin , lapplication (t) = f (tH) = f (t cos , t sin ) est drivable en





t = 0 pour toute valeur de ; en effet,


sage: f(x, y) = x^2 * y / (x^4 + y^2)
sage: t, theta = var('t, theta')
sage: limit(f(t * cos(theta), t * sin(theta)) / t, t=0)
cos(theta)^2/sin(theta)
Donc f admet en (0, 0) des drives directionnelles suivant nimporte quel vecteur.
Pour mieux se reprsenter la surface reprsentative de f , on peut commencer par
chercher quelques lignes de niveau ; par exemple la ligne de niveau associe la
valeur 12 :
sage: solve(f(x,y) == 1/2, y)
[y == x^2]
sage: a = var('a'); h = f(x, a*x^2).simplify_rational(); h
a/(a^2 + 1)
Le long de la parabole dquation y = ax2 prive de lorigine, f est constante et
vaut f (x, ax2 ) = 1+a
a
2 . On trace alors la fonction h : a 7 1+a2 :
a

sage: plot(h, a, -4, 4)

0.4

0.2

-4 -3 -2 -1 1 2 3 4

-0.2

-0.4

Figure 4.16 Une coupe verticale de la surface tudie.

La fonction h atteint son maximum en a = 1 et son minimum en a = 1. La


restriction de f la parabole dquation y = x2 correspond la ligne de crte
qui se trouve laltitude 12 ; quant la restriction de f la parabole dquation
y = x2 , elle correspond au fond du thalweg qui se trouve laltitude 21 .
En conclusion, aussi proche que lon soit de (0, 0), on peut trouver des points en
lesquels f prend respectivement les valeurs 12 et 12 . Par consquent, la fonction
nest pas continue lorigine.
sage: p = plot3d(f(x,y),(x,-2,2),(y,-2,2),plot_points=[150,150])
On aurait galement pu tracer des plans horizontaux pour visualiser les lignes
de niveau de cette fonction en excutant :
sage: for i in range(1,4):
....: p += plot3d(-0.5 + i / 4, (x, -2, 2), (y, -2, 2),\
....: color=hue(i / 10), opacity=.1)
96 CHAP. 4. GRAPHIQUES

x2 y
Figure 4.17 La surface reprsentative de f : (x, y) 7 x4 +y 2
.

Parmi les autres commandes de trac 3D, citons implicit_plot3d qui permet
de tracer des surfaces dfinies par une quation implicite de la forme f (x, y, z) = 0.
Traons par exemple la surface de Cassini (figure 4.18a) dfinie par lquation
2
implicite : a2 + x2 + y 2 = 4 a2 x2 + z 4 .
sage: x, y, z = var('x, y, z'); a = 1
sage: h = lambda x, y, z:(a^2 + x^2 + y^2)^2 - 4*a^2*x^2-z^4
sage: f = implicit_plot3d(h, (x,-3,3), (y,-3,3), (z,-2,2),\
....: plot_points=100, adaptative=True)
Enfin donnons un exemple de trac de courbe dans lespace (figure 4.18b)
laide de la commande line3d :
sage: g1 = line3d([(-10*cos(t)-2*cos(5*t)+15*sin(2*t),\
....: -15*cos(2*t)+10*sin(t)-2*sin(5*t),\
....: 10*cos(3*t)) for t in srange(0,6.4,.1)],radius=.5)

(a) La surface de Cassini. (b) Un nud dans lespace.

Figure 4.18 Surface et courbe dans lespace.


Domaines de calcul
5
Lcriture des mathmatiques sur papier ou au tableau noir requiert, de
manire essentielle, la recherche dun bon compromis entre souplesse, lgret
des notations et rigueur. Cela nest pas diffrent pour lusage au quotidien dun
systme de calcul. Sage essaye de laisser le choix de ce compromis lutilisateur, en
particulier en permettant celui-ci de spcifier, plus ou moins rigoureusement, le
domaine de calcul : quelle est la nature des objets considrs, dans quel ensemble
vivent-ils, quelles oprations peut-on leur appliquer ?

5.1 Sage est orient objet


Python et Sage utilisent fortement la programmation oriente objet. Mme si
cela reste relativement transparent pour lutilisation ordinaire, il est utile den
savoir un minimum, dautant que celle-ci est trs naturelle dans un contexte
mathmatique.

5.1.1 Objets, classes et mthodes


La programmation oriente objet repose sur lide de modliser chaque entit
physique ou abstraite que lon souhaite manipuler dans un programme par une
construction du langage de programmation appele un objet. Le plus souvent, et
cest le cas en Python, chaque objet est instance dune classe. Ainsi, le nombre
rationnel 12/35 est modlis par un objet qui est une instance de la classe
Rational :
sage: o = 12/35
sage: print type(o)
98 CHAP. 5. DOMAINES DE CALCUL

<type 'sage.rings.rational.Rational'>
Notons que cette classe est vraiment associe lobjet 12/35, et non la variable
o qui le contient :
sage: print type(12/35)
<type 'sage.rings.rational.Rational'>
Prcisons les dfinitions. Un objet est une portion de la mmoire de lordinateur
qui contient linformation ncessaire pour reprsenter lentit quil modlise. La
classe quant elle dfinit deux choses :
1. la structure de donnes dun objet, cest--dire comment linformation est
organise dans le bloc mmoire. Par exemple, la classe Rational spcifie
quun nombre rationnel comme 12/35 est reprsent par deux nombres
entiers : son numrateur et son dnominateur ;
2. son comportement, et en particulier les oprations sur cet objet : par exemple
comment on extrait le numrateur dun nombre rationnel, comment on
calcule sa valeur absolue, comment on multiplie ou additionne deux nombres
rationnels. Chacune de ces oprations est implante par une mthode (ici
respectivement numer, abs, __mult__, __add__).
Pour factoriser un nombre entier, on va donc appeler la mthode factor avec
la syntaxe suivante 1 :
sage: o = 720
sage: o.factor()
2^4 * 3^2 * 5
que lon peut lire comme : prendre la valeur de o et lui appliquer la mthode
factor sans autre argument . Sous le capot, Python effectue le calcul suivant :
sage: type(o).factor(o)
2^4 * 3^2 * 5
De gauche droite : demander la classe de o (type(o)) la mthode approprie
de factorisation (type(o).factor), et lappliquer o .
Notons au passage que lon peut appliquer une mthode une valeur sans
passer par une variable :
sage: 720.factor()
2^4 * 3^2 * 5
et donc en particulier enchaner les oprations, de la gauche vers la droite. Ici, on
prend le numrateur dun nombre rationnel, que lon factorise ensuite :
sage: o = 720 / 133
sage: o.numerator().factor()
2^4 * 3^2 * 5

1. Pour le confort de lutilisateur, Sage fournit aussi une fonction factor, de sorte que
factor(o) est un raccourci pour o.factor(). Il en est de mme pour bon nombre de fonctions
dusage courant, et il est tout fait possible dajouter ses propres raccourcis.
5.1. SAGE EST ORIENT OBJET 99

5.1.2 Objets et polymorphisme


En quoi cela nous concerne-t-il ? Tout dabord, presque toutes les oprations en
Sage sont polymorphes, cest--dire quelles peuvent sappliquer diffrents types
dobjets. Ainsi, quelle que soit la nature de lobjet o que lon veut factoriser ,
on utilise la mme notation o.factor() (ou son raccourci factor(o)). Les
oprations effectuer ne sont pourtant pas les mmes dans le cas dun entier
et dun polynme ! Elles diffrent dailleurs aussi selon que le polynme est
coefficients rationnels ou coefficients dans un corps fini. Cest la classe de lobjet
qui dtermine quelle version de factor sera finalement excute.
De mme, calquant les notations mathmatiques usuelles, le produit de deux
objets a et b peut toujours tre not a*b mme si lalgorithme utilis dans chaque
cas est diffrent 2 . Voici un produit de deux nombres entiers :
sage: 3 * 7
21
un produit de deux nombres rationnels, obtenu par produit des numrateurs et
dnominateurs puis rduction :
sage: (2/3) * (6/5)
4/5
un produit de deux nombres complexes, utilisant la relation i2 = 1 :
sage: (1 + I) * (1 - I)
2
des produits commutatifs formels de deux expressions :
sage: (x + 2) * (x + 1)
(x + 1)*(x + 2)
sage: (x + 1) * (x + 2)
(x + 1)*(x + 2)
Outre la simplicit de notation, cette forme de polymorphisme permet dcrire
des programmes gnriques qui sappliquent tout objet admettant les oprations
utilises (ici la multiplication) :
sage: def puissance_quatre(a):
....: a = a * a
....: a = a * a
....: return a

sage: puissance_quatre(2)
16
sage: puissance_quatre(3/2)
2. Pour une opration arithmtique binaire comme le produit, la procdure de slection de
la mthode approprie est un peu plus complique que ce qui a t dcrit prcdemment. En
effet, elle doit grer des oprations mixtes comme la somme 2 + 3/4 dun entier et dun nombre
rationnel. En loccurrence, 2 sera converti en nombre rationnel 2/1 avant laddition. Les rgles
qui servent choisir quels oprandes convertir, et comment, sappellent le modle de coercition.
100 CHAP. 5. DOMAINES DE CALCUL

81/16
sage: puissance_quatre(I)
1
sage: puissance_quatre(x+1)
(x + 1)^4
sage: M = matrix([[0,-1],[1,0]]); M
[ 0 -1]
[ 1 0]
sage: puissance_quatre(M)
[1 0]
[0 1]

5.1.3 Introspection
Les objets Python, et donc Sage, ont des fonctionnalits dintrospection. Cela
signifie que lon peut, lexcution, interroger un objet sur sa classe, ses
mthodes, etc., et manipuler les informations obtenues via les constructions
habituelles du langage de programmation. Ainsi, la classe dun objet o est elle-
mme un objet Python (presque) comme les autres, que lon peut rcuprer avec
type(o) :
sage: t = type(5/1); print t
<type 'sage.rings.rational.Rational'>
sage: t == type(5)
False
Nous voyons ici que lexpression 5/1 construit le rationnel 5, qui est un objet
diffrent de lentier 5 !
Ce sont aussi les outils dintrospection qui permettent daccder laide en
ligne spcifique la factorisation des nombres entiers partir dun objet de type
entier :
sage: o = 720
sage: o.factor?
...
Definition: o.factor(self, algorithm='pari', proof=None, ...)
Docstring:
Return the prime factorization of this integer as a formal
Factorization object.
...
voire au code source de cette fonction :
sage: o.factor??
...
def factor(self, algorithm='pari', proof=None, ...)
...
if algorithm == 'pari':
...
5.2. LMENTS, PARENTS, CATGORIES 101

elif algorithm in ['kash', 'magma']:


...
En passant au-dessus des dtails techniques, on distingue quici Sage dlgue le
gros du calcul dautres logiciels (PARI, Kash, voire Magma).
Dans le mme ordre dide, on peut utiliser la compltion automatique pour
demander interactivement un objet o toutes les oprations que lon peut lui
appliquer. Ici, il y en a beaucoup ; voici celles qui commencent par n :
sage: o.n<tab>
o.n o.nbits o.ndigits
o.next_prime o.next_probable_prime o.nth_root
o.numerator o.numerical_approx
Il sagit encore dune forme dintrospection.

5.2 lments, parents, catgories


5.2.1 lments et parents
Dans la section prcdente, nous avons vu la notion de classe dun objet. Dans
la pratique, il est suffisant de savoir que cette notion existe ; on a rarement besoin
de regarder explicitement le type dun objet. En revanche Sage introduit une
contrepartie plus conceptuelle de cette notion que nous allons aborder maintenant :
celle de parent dun objet.
Supposons par exemple que lon veuille dterminer si un lment a est inversible.
La rponse ne va pas seulement dpendre de llment lui-mme, mais aussi de
lensemble A auquel il est considr appartenir (ainsi que son inverse potentiel).
Par exemple, le nombre 5 nest pas inversible dans lensemble Z des entiers, son
inverse 1/5 ntant pas un entier :
sage: a = 5; a
5
sage: a.is_unit()
False
En revanche, il est inversible dans lensemble des rationnels :
sage: a = 5/1; a
5
sage: a.is_unit()
True
Sage rpond diffremment ces deux questions car, comme nous lavons vu dans
la section prcdente, les lments 5 et 5/1 sont des instances de classes diffrentes.
Dans certains systmes de calcul formel orients objets, tels MuPAD ou Axiom,
lensemble X auquel x est considr appartenir (ici Z ou Q) est simplement
modlis par la classe de x. Sage suit lapproche de Magma et modlise X par un
objet supplmentaire associ x, appel son parent :
102 CHAP. 5. DOMAINES DE CALCUL

sage: parent(5)
Integer Ring
sage: parent(5/1)
Rational Field

On peut retrouver ces deux ensembles avec les raccourcis :


sage: ZZ
Integer Ring
sage: QQ
Rational Field

et les utiliser pour convertir aisment un lment de lun lautre lorsque cela a
un sens :
sage: QQ(5).parent()
Rational Field
sage: ZZ(5/1).parent()
Integer Ring
sage: ZZ(1/5)
Traceback (most recent call last):
...
TypeError: no conversion of this rational to integer

Dune manire gnrale, la syntaxe P(x) o P est un parent tente de convertir


lobjet x en un lment de P. Voici 1 en tant quentier 1 Z, en tant que nombre
rationnel 1 Q, et en tant quapproximation flottante relle 1,0 R ou complexe
1,0 + 0,0i C :
sage: ZZ(1), QQ(1), RR(1), CC(1)
(1, 1, 1.00000000000000, 1.00000000000000)
Exercice 18. Quelle est la classe de lanneau des entiers relatifs Z ?

5.2.2 Constructions
Les parents tant eux-mmes des objets, on peut leur appliquer des oprations.
Ainsi, on peut construire le produit cartsien Q2 :
sage: cartesian_product([QQ, QQ])
The cartesian product of (Rational Field, Rational Field)

retrouver Q comme corps des fractions de Z :


sage: ZZ.fraction_field()
Rational Field

construire lanneau des polynmes en x coefficients dans Z :


sage: ZZ['x']
Univariate Polynomial Ring in x over Integer Ring
5.3. DOMAINES DE CALCUL REPRSENTATION NORMALE 103

Par empilements successifs, on peut construire des structures algbriques


complexes comme lespace des matrices 3 3 coefficients polynomiaux sur un
corps fini :
sage: Z5 = GF(5); Z5
Finite Field of size 5
sage: P = Z5['x']; P
Univariate Polynomial Ring in x over Finite Field of size 5
sage: M = MatrixSpace(P, 3, 3); M
Full MatrixSpace of 3 by 3 dense matrices over
Univariate Polynomial Ring in x over Finite Field of size 5
dont voici un lment :
sage: M.random_element()
[2*x^2 + 3*x + 4 4*x^2 + 2*x + 2 4*x^2 + 2*x]
[ 3*x 2*x^2 + x + 3 3*x^2 + 4*x]
[ 4*x^2 + 3 3*x^2 + 2*x + 4 2*x + 4]

5.2.3 Complment : catgories


Un parent na, en gnral, pas lui-mme un parent, mais une catgorie qui
indique ses proprits :
sage: QQ.category()
Category of quotient fields
De fait Sage sait que Q est un corps :
sage: QQ in Fields()
True
et donc, par exemple, un groupe additif commutatif (voir figure 5.1) :
sage: QQ in CommutativeAdditiveGroups()
True
Il en dduit que Q[x] est un anneau euclidien :
sage: QQ['x'] in EuclideanDomains()
True
Toutes ces proprits sont utilises pour calculer rigoureusement et plus
efficacement sur les lments de ces ensembles.

5.3 Domaines de calcul reprsentation


normale
Passons maintenant en revue quelques-uns des parents que lon trouve dans
Sage.
Nous avons observ en 2.1 limportance pour le calcul symbolique des formes
normales, qui permettent de distinguer si deux objets sont mathmatiquement
104 CHAP. 5. DOMAINES DE CALCUL

fields

euclidean domains

principal ideal domains division rings

unique factorization domains

gcd domains

integral domains

commutative rings domains

rings

rngs semirings

commutative additive groups monoids

semigroups commutative additive monoids

commutative additive semigroups

magmas additive magmas

sets

sets with partial maps

objects

Figure 5.1 Un petit morceau du graphe des catgories dans Sage.


5.3. DOMAINES DE CALCUL REPRSENTATION NORMALE 105

Quelques types de base de Python


Entiers Python int
Flottants Python float
Boolens (vrai, faux) bool
Chanes de caractres str

Domaines numriques de base


Entiers Z ZZ ou IntegerRing()
Rationnels Q QQ ou RationalField()
Flottants prcision p Reals(p) ou RealField(p)
Flottants complexes prcision p Complexes(p) ou ComplexField(p)

Anneaux et corps finis


Rsidus modulo n, Z/nZ Integers(n) ou IntegerModRing(n)
Corps fini Fq GF(q) ou FiniteField(q)

Nombres algbriques
Nombres algbriques Q QQbar ou AlgebraicField()
Nombres algbriques rels AA ou AlgebraicRealField()
Corps de nombres Q[x]/hpi NumberField(p)

Calcul symbolique
Matrices m n coefficients dans A MatrixSpace(A, m, n)
Polynmes A[x, y] A['x,y'] ou PolynomialRing(A, 'x,y')
Sries A[[x]] A[['x']] ou PowerSeriesRing(A, 'x')
Expressions symboliques SR

Tableau 5.1 Principaux domaines de calcul et parents.

gaux en comparant leurs reprsentations. Chacun des parents fondamentaux


prsents ci-dessous correspond un domaine de calcul forme normale, cest-
-dire un ensemble dobjets mathmatiques qui admettent une forme normale.
Cela permet Sage de reprsenter sans ambigut les lments de chacun de ces
parents 3 .

5.3.1 Domaines de calcul lmentaires


Nous appelons domaines de calcul lmentaires les ensembles classiques de
constantes ne faisant pas intervenir de variable : entiers, rationnels, nombres
flottants, boolens, rsidus modulo n...

Entiers. Les entiers sont reprsents en base deux (en interne) et en base dix
( lcran). Comme nous lavons vu, les entiers Sage sont des objets de classe
Integer. Leur parent est lanneau Z :
3. La plupart des autres parents disponibles dans Sage correspondent des domaines de
calcul forme normale, mais ce nest pas le cas de tous. Il arrive aussi que, pour des raisons
defficacit, Sage ne reprsente les lments sous forme normale que sur demande explicite.
106 CHAP. 5. DOMAINES DE CALCUL

sage: 5.parent()
Integer Ring
Les entiers sont reprsents sous forme normale ; lgalit est donc facile tester.
Aussi, pour pouvoir reprsenter des entiers sous forme factorise, la commande
factor utilise une classe spcifique :
sage: print type(factor(4))
<class 'sage.structure.factorization_integer.IntegerFactorization'>
La classe Integer est propre Sage : par dfaut, Python utilise des entiers
de type int. En gnral la conversion de lun vers lautre est automatique, mais
il peut tre ncessaire dindiquer explicitement cette conversion par
sage: int(5)
5
sage: print type(int(5))
<type 'int'>
ou inversement
sage: Integer(5)
5
sage: print type(Integer(5))
<type 'sage.rings.integer.Integer'>

Rationnels. La proprit de forme normale stend aux nombres rationnels,


lments de QQ, qui sont toujours reprsents sous forme rduite. Ainsi, dans la
commande
sage: factorial(99) / factorial(100) - 1 / 50
-1/100
les factorielles sont dabord values, puis la fraction 1/100 obtenue est mise sous
forme irrductible. Sage construit ensuite le rationnel 1/50, effectue la soustraction,
puis rduit nouveau le rsultat (il ny a rien faire en loccurrence).

Flottants. Les nombres rels ne peuvent pas tre reprsents exactement. Leurs
valeurs numriques approches sont reprsentes sous forme de nombres virgule
flottante, appels aussi simplement flottants, prsents en dtail au chapitre 11.
Dans Sage, les flottants sont exprims en base deux. Une consquence est que
le flottant dnot par une constante dcimale comme 0.1 nest pas exactement
gal 1/10, car 1/10 nest pas reprsentable exactement en base deux ! Chaque
flottant a sa propre prcision. Le parent des flottants avec p bits significatifs est
not Reals(p). Celui des flottants la prcision par dfaut (p = 53) sappelle
aussi RR. Comme dans le cas des entiers, les flottants Sage diffrent de leurs
analogues Python.
Lorsquils interviennent dans une somme, un produit ou un quotient faisant
intervenir par ailleurs des entiers ou rationnels, les flottants sont contagieux :
toute lexpression est alors calcule en virgule flottante :
5.3. DOMAINES DE CALCUL REPRSENTATION NORMALE 107

sage: 72/53 - 5/3 * 2.7


-3.14150943396227
De mme, lorsque largument dune fonction usuelle est un flottant, le rsultat
est encore un flottant :
sage: cos(1), cos(1.)
(cos(1), 0.540302305868140)
La mthode numerical_approx (ou son alias n) sert valuer numriquement
les autres expressions. Un argument optionnel permet de prciser le nombre de
chiffres significatifs utiliss lors du calcul. Voici par exemple avec 50 chiffres
significatifs :
sage: pi.n(digits=50) # variante: n(pi,digits=50)
3.1415926535897932384626433832795028841971693993751

Nombres complexes. De mme, les approximations en virgule flottante de


nombres complexes prcision p sont lments de Complexes(p), ou CC la
prcision par dfaut. On peut construire un flottant complexe et calculer son
argument par
sage: z = CC(1,2); z.arg()
1.10714871779409

Expressions symboliques complexes

Lunit imaginaire i (note I ou i) dj rencontre dans les chapitres


prcdents nest pas un lment de CC, mais une expression symbolique
(voir 5.4.1) :
sage: I.parent()
Symbolic Ring
On peut lutiliser pour noter un flottant complexe moyennant une conversion
explicite :
sage: (1.+2.*I).parent()
Symbolic Ring
sage: CC(1.+2.*I).parent()
Complex Field with 53 bits of precision
Dans le monde des expressions symboliques, les mthodes real, imag et
abs donnent respectivement la partie relle, la partie imaginaire et le module
dun nombre complexe :
sage: z = 3 * exp(I*pi/4)
sage: z.real(), z.imag(), z.abs().simplify_exp()
(3/2*sqrt(2), 3/2*sqrt(2), 3)
108 CHAP. 5. DOMAINES DE CALCUL

Boolens. Les expressions logiques forment aussi un domaine de calcul forme


normale, mais la classe des valeurs de vrit, ou boolens, est un type de base de
Python sans parent Sage associ. Les deux formes normales sont True et False :
sage: a, b, c = 0, 2, 3
sage: a == 1 or (b == 2 and c == 3)
True
Dans les tests et les boucles, les conditions composes laide des oprateurs or
et and sont values de faon paresseuse de la gauche vers la droite. Ceci signifie
que lvaluation dune condition compose par or se termine aprs le premier
prdicat de valeur True, sans valuer les termes placs plus droite ; de mme
avec and et False. Ainsi le test ci-dessous dcrit la divisibilit a|b sur les entiers
et ne provoque aucune erreur mme si a = 0 :
sage: a = 0; b = 12; (a == 0) and (b == 0) or (a != 0) and (b%a == 0)
Loprateur not est prioritaire sur and qui est lui-mme prioritaire sur or, les tests
dgalit et de comparaison tant quant eux prioritaires sur tous les oprateurs
boolens. Les deux tests suivants sont donc quivalents au prcdent :
sage: ((a == 0) and (b == 0)) or ((a != 0) and (b%a == 0))
sage: a == 0 and b == 0 or not a == 0 and b%a == 0
En outre, Sage autorise les tests dencadrement et dgalits multiples de la mme
faon quils sont crits en mathmatiques :

x 6 y < z 6 t cod par x <= y < z <= t


x = y = z 6= t x == y == z != t

Dans les cas simples, ces tests sont effectus directement ; sinon il faut faire appel
la commande bool pour forcer lvaluation :
sage: x, y = var('x, y')
sage: bool( (x-y)*(x+y) == x^2-y^2 )
True

Rsidus modulo n. Pour dfinir un entier modulaire, on commence par cons-


truire son parent, lanneau Z/nZ :
sage: Z4 = IntegerModRing(4); Z4
Ring of integers modulo 4
sage: m = Z4(7); m
3
Comme dans le cas des flottants, les calculs faisant intervenir m seront faits
modulo 4 via des conversions automatiques. Ainsi, dans lexemple suivant, 3 et 1
sont automatiquement convertis en lments de Z/4Z :
sage: 3 * m + 1
2
5.3. DOMAINES DE CALCUL REPRSENTATION NORMALE 109

Lorsque p est premier, on peut aussi choisir de construire Z/pZ en tant que
corps :
sage: Z3 = GF(3); Z3
Finite Field of size 3

Il sagit dans les deux cas de domaines reprsentation normale : les rductions
modulo n ou p sont effectues automatiquement chaque cration dun lment.
Les calculs dans les anneaux et les corps finis sont dtaills au chapitre 6.

5.3.2 Domaines composs


partir de constantes bien dfinies, des classes dobjets symboliques faisant
intervenir des variables et admettant une forme normale peuvent tre construites.
Les plus importantes sont les matrices, les polynmes, les fractions rationnelles et
les sries tronques (dveloppements limits).
Les parents correspondants sont paramtrs par le domaine des coefficients.
Ainsi, par exemple, les matrices coefficients entiers diffrent des matrices
coefficients dans Z/nZ, et les rgles de calcul adquates sont appliques automa-
tiquement, sans quil y ait besoin de faire appel explicitement une fonction de
rduction modulo n.
La partie II de ce livre est consacre principalement ces objets.

Matrices. La forme normale dune matrice est obtenue lorsque tous ses coeffi-
cients sont eux-mmes sous forme normale. Aussi, toute matrice sur un corps ou
un anneau reprsentation normale est automatiquement sous forme normale :
sage: a = matrix(QQ, [[1,2,3],[2,4,8],[3,9,27]])
sage: (a^2 + 1) * a^(-1)
[ -5 13/2 7/3]
[ 7 1 25/3]
[ 2 19/2 27]

Lappel la fonction matrix est un raccourci. En interne, Sage construit le parent


correspondant, savoir lespace des matrices 3 3 coefficients dans Q (qui est
reprsentation normale), puis lutilise pour fabriquer la matrice :
sage: M = MatrixSpace(QQ,3,3); M
Full MatrixSpace of 3 by 3 dense matrices over Rational Field
sage: a = M([[1,2,3],[2,4,8],[3,9,27]])
sage: (a^2 + 1) * a^(-1)
[ -5 13/2 7/3]
[ 7 1 25/3]
[ 2 19/2 27]

Les oprations sur les matrices symboliques sont dcrites au chapitre 8, lalgbre
linaire numrique au chapitre 13.
110 CHAP. 5. DOMAINES DE CALCUL

Polynmes et fractions rationnelles. Tout comme les matrices, les poly-


nmes de Sage connaissent le type de leurs coefficients. Leurs parents sont
les anneaux de polynmes comme Z[x] ou C[x, y, z], prsents en dtail dans les
chapitres 7 et 9 de ce livre, et que lon peut construire comme suit :
sage: P = ZZ['x']; P
Univariate Polynomial Ring in x over Integer Ring
sage: F = P.fraction_field(); F
Fraction Field of Univariate Polynomial Ring in x over Integer Ring
sage: p = P(x+1) * P(x); p
x^2 + x
sage: p + 1/p
(x^4 + 2*x^3 + x^2 + 1)/(x^2 + x)
sage: parent(p + 1/p)
Fraction Field of Univariate Polynomial Ring in x over Integer Ring
Comme nous le verrons en 5.4.2, il ny a pas une reprsentation idale pour les
polynmes et les fractions rationnelles. Les lments des anneaux de polynmes
sont reprsents sous forme dveloppe. Ces anneaux sont donc reprsentation
normale ds que les coefficients sont eux-mmes dans un domaine de calcul
reprsentation normale.
Ces polynmes diffrent des expressions polynomiales que nous avons rencon-
tres au chapitre 2, qui nont pas de type bien dfini de coefficients ni de parent
qui reflte ce type. Celles-ci reprsentent une alternative aux vrais polynmes
qui peut tre utile, par exemple, pour mlanger polynmes et autres expressions
mathmatiques. Soulignons qu linverse de ce quil se passe avec les lments
des anneaux de polynmes, quand on travaille avec ces expressions, il faut appeler
explicitement une commande de rduction comme expand pour les mettre en
forme normale.

Sries. Les sries tronques sont des objets de la forme

a0 + a1 x + a2 x2 + + an xn + O(xn+1 )

utiliss par exemple pour reprsenter des dveloppements limits et dont la


manipulation avec Sage est dcrite en 7.5. Le parent des sries en x tronques
prcision n, coefficients dans A, est lanneau A[[x]], construit par PowerSeries
Ring(A, 'x', n).
Comme les polynmes, les sries tronques ont un analogue dans le monde des
expressions symboliques. La commande de rduction en forme normale associe
est series.
sage: f = cos(x).series(x == 0, 6); 1 / f
1
1+( 12 )x2 + 24
1 4
x +O(x6 )

sage: (1 / f).series(x == 0, 6)
1 + 12 x2 + 5 4
+ O x6

24 x
5.4. EXPRESSIONS VERSUS DOMAINES DE CALCUL 111

Nombres algbriques. Un nombre algbrique est dfini comme racine dun


polynme. Lorsque le degr du polynme est 5 ou plus, il nest, en gnral, pas
possible den crire explicitement les racines laide des oprations +, , , /, .
Cependant, de nombreux calculs sur les racines peuvent tre mens bien sans
autre information que le polynme lui-mme.
sage: k.<a> = NumberField(x^3 + x + 1); a^3; a^4+3*a
-a - 1
-a^2 + 2*a

La manipulation de nombres algbriques avec Sage nest pas traite en dtail


dans ce livre, mais on en trouvera plusieurs exemples dans les chapitres 7 et 9.

5.4 Expressions versus domaines de calcul


Plusieurs approches sont donc possibles pour manipuler avec Sage des objets
comme les polynmes. On peut soit les voir comme des expressions formelles
particulires, comme nous lavons fait dans les premiers chapitres de ce livre, soit
introduire un anneau de polynmes particulier et calculer avec ses lments. Pour
conclure ce chapitre, nous dcrivons brivement le parent des expressions formelles,
le domaine SR, puis nous illustrons travers quelques exemples limportance de
contrler le domaine de calcul et les diffrences entre les deux approches.

5.4.1 Les expressions comme domaine de calcul


Les expressions symboliques constituent elles-mmes un domaine de calcul !
Dans Sage, leur parent est lanneau symbolique :
sage: parent(sin(x))
Symbolic Ring

que lon peut aussi obtenir avec :


sage: SR
Symbolic Ring

Les proprits de cet anneau sont assez floues ; il est commutatif :


sage: SR.category()
Category of commutative rings

et les rgles de calcul font en gros lhypothse que toutes les variables symboliques
sont valeur dans C.
La forme des expressions que lon manipule dans SR (expressions polynomiales,
rationnelles, trigonomtriques) ntant pas apparente dans leur classe ou leur pa-
rent, le rsultat dun calcul ncessite le plus souvent des transformations manuelles
pour tre mis sous la forme dsire (voir 2.1), en utilisant par exemple expand,
combine, collect et simplify. Pour bien utiliser ces fonctions, il faut savoir
112 CHAP. 5. DOMAINES DE CALCUL

quel type de transformations elles effectuent, quelles sous-classes 4 dexpres-


sions formelles ces transformations sappliquent, et lesquelles de ces sous-classes
constituent des domaines de calcul forme normale. Ainsi, lusage aveugle de la
fonction simplify peut conduire des rsultats faux. Des variantes de simplify
permettent alors de prciser la simplification effectuer.

5.4.2 Exemples : polynmes et formes normales


Construisons lanneau Q[x1 , x2 , x3 , x4 ] des polynmes en 4 variables :
sage: R = QQ['x1,x2,x3,x4']; R
Multivariate Polynomial Ring in x1, x2, x3, x4 over Rational Field
sage: x1, x2, x3, x4 = R.gens()
Les lments de R sont automatiquement reprsents sous forme dveloppe :
sage: x1 * (x2 - x3)
x1*x2 - x1*x3
qui, comme nous lavons vu, est une forme normale. En particulier, le test zro
dans R est immdiat :
sage: (x1+x2)*(x1-x2) - (x1^2 - x2^2)
0
Ce nest pas toujours un avantage. Par exemple, si lon construit le dterminant
de Vandermonde 16i<j6n (xi xj ) :
Q

sage: prod( (a-b) for (a,b) in Subsets([x1,x2,x3,x4],2) )


x1^3*x2^2*x3 - x1^2*x2^3*x3 - x1^3*x2*x3^2 + x1*x2^3*x3^2
+ x1^2*x2*x3^3 - x1*x2^2*x3^3 - x1^3*x2^2*x4 + x1^2*x2^3*x4
+ x1^3*x3^2*x4 - x2^3*x3^2*x4 - x1^2*x3^3*x4 + x2^2*x3^3*x4
+ x1^3*x2*x4^2 - x1*x2^3*x4^2 - x1^3*x3*x4^2 + x2^3*x3*x4^2
+ x1*x3^3*x4^2 - x2*x3^3*x4^2 - x1^2*x2*x4^3 + x1*x2^2*x4^3
+ x1^2*x3*x4^3 - x2^2*x3*x4^3 - x1*x3^2*x4^3 + x2*x3^2*x4^3
on obtient 4! = 24 termes. La mme construction avec une expression reste sous
forme factorise, et est beaucoup plus compacte et lisible :
sage: x1, x2, x3, x4 = SR.var('x1, x2, x3, x4')
sage: prod( (a-b) for (a,b) in Subsets([x1,x2,x3,x4],2) )
(x3 - x4)*(x2 - x4)*(x2 - x3)*(x1 - x4)*(x1 - x3)*(x1 - x2)
De mme, une reprsentation factorise ou partiellement factorise permet des
calculs de pgcd plus rapides. Mais il ne serait pas judicieux non plus de mettre
automatiquement tout polynme sous forme factorise, mme sil sagit aussi
dune forme normale, car la factorisation est coteuse en temps de calcul et rend
compliques les additions.
De manire gnrale, selon le type de calcul voulu, la reprsentation idale dun
lment nest pas toujours sa forme normale. Cela amne les systmes de calcul
4. Au sens de familles, et non de classes dobjets Python.
5.4. EXPRESSIONS VERSUS DOMAINES DE CALCUL 113

formel un compromis avec les expressions. Un certain nombre de simplifications


basiques, comme la rduction des rationnels ou la multiplication par zro, y sont
effectues automatiquement ; les autres transformations sont laisses linitiative
de lutilisateur auquel des commandes spcialises sont proposes.

5.4.3 Exemple : factorisation des polynmes


Considrons la factorisation de lexpression polynomiale suivante :
sage: x = var('x')
sage: p = 54*x^4+36*x^3-102*x^2-72*x-12
sage: factor(p)
6*(3*x + 1)^2*(x^2 - 2)

Cette rponse est-elle satisfaisante ? Il sagit bien dune factorisation de p, mais


son optimalit dpend fortement du contexte ! Pour le moment Sage considre p
comme une expression symbolique, qui se trouve tre polynomiale. Il ne peut pas
savoir si lon souhaite factoriser p en tant que produit de polynmes coefficients
entiers ou coefficients rationnels (par exemple).
Pour prendre le contrle, nous allons prciser dans quel ensemble (domaine
de calcul) nous souhaitons considrer p. Pour commencer, nous allons considrer
p comme un polynme coefficients entiers. Nous dfinissons donc lanneau
R = Z[x] de ces polynmes :
sage: R = ZZ['x']; R
Univariate Polynomial Ring in x over Integer Ring

Puis nous convertissons p dans cet anneau :


sage: q = R(p); q
54*x^4 + 36*x^3 - 102*x^2 - 72*x - 12

laffichage on ne voit pas de diffrence, mais q sait quil est un lment de R :


sage: parent(q)
Univariate Polynomial Ring in x over Integer Ring

Du coup, sa factorisation est sans ambigut :


sage: factor(q)
2 * 3 * (3*x + 1)^2 * (x^2 - 2)

On procde de mme sur le corps des rationnels :


sage: R = QQ['x']; R
Univariate Polynomial Ring in x over Rational Field
sage: q = R(p); q
54*x^4 + 36*x^3 - 102*x^2 - 72*x - 12
sage: factor(q)
(54) * (x + 1/3)^2 * (x^2 - 2)
114 CHAP. 5. DOMAINES DE CALCUL

Dans ce nouveau contexte, la factorisation est encore non ambigu, mais diffrente
de la prcdente.
Cherchons maintenant une factorisation complte sur les nombres complexes.
Une premire option est de sautoriser une approximation numrique des nombres
complexes avec 16 bits de prcision :
sage: R = ComplexField(16)['x']; R
Univariate Polynomial Ring in x over Complex Field
with 16 bits of precision
sage: q = R(p); q
54.00*x^4 + 36.00*x^3 - 102.0*x^2 - 72.00*x - 12.00
sage: factor(q)
(54.00) * (x - 1.414) * (x + 0.3333)^2 * (x + 1.414)

Une autre est dagrandir un peu le corps des rationnels ; ici, on va ajouter 2.
sage: R = QQ[sqrt(2)]['x']; R
Univariate Polynomial Ring in x over Number Field in sqrt2
with defining polynomial x^2 - 2
sage: q = R(p); q
54*x^4 + 36*x^3 - 102*x^2 - 72*x - 12
sage: factor(q)
(54) * (x - sqrt2) * (x + sqrt2) * (x + 1/3)^2

Enfin, peut-tre souhaite-t-on que les coefficients soient considrs modulo 5 ?


sage: R = GF(5)['x']; R
Univariate Polynomial Ring in x over Finite Field of size 5
sage: q = R(p); q
4*x^4 + x^3 + 3*x^2 + 3*x + 3
sage: factor(q)
(4) * (x + 2)^2 * (x^2 + 3)

5.4.4 Synthse
Dans les exemples prcdents, nous avons illustr comment lutilisateur peut
contrler le niveau de rigueur dans ses calculs.
Dun ct il peut utiliser les expressions symboliques. Ces expressions vivent
dans lanneau SR. Elles offrent de nombreuses mthodes (prsentes au chapitre 2)
qui sappliquent bien certaines sous-classes dexpressions, telles que les expres-
sions polynomiales. Reconnatre quune expression appartient telle ou telle
classe permet de savoir quelles fonctions il est pertinent de lui appliquer. Un
problme pour lequel cette reconnaissance est essentielle est celui de la simplifica-
tion dexpressions. Cest autour de ce problme que sont dfinies les principales
classes dexpressions des systmes de calcul formel, et cest lapproche que nous
privilgierons le plus souvent dans la suite de cet ouvrage.
Dun autre ct, lutilisateur peut construire un parent qui va spcifier explicite-
ment le domaine de calcul. Cest particulirement intressant lorsque ce parent est
5.4. EXPRESSIONS VERSUS DOMAINES DE CALCUL 115

forme normale : cest--dire que deux objets lments sont mathmatiquement


gaux si et seulement sils ont la mme reprsentation.
Pour rsumer, la souplesse est lavantage principal des expressions : pas de
dclaration explicite du domaine de calcul, ajout au vol de nouvelles variables
ou fonctions symboliques, changement au vol du domaine de calcul (par exemple
lorsque lon prend le sinus dune expression polynomiale), utilisation de toute la
gamme des outils danalyse (intgration, etc.). Les avantages de la dclaration
explicite du domaine de calcul sont ses vertus pdagogiques, souvent une plus
grande rigueur 5 , la mise sous forme normale automatique (qui peut aussi tre
un inconvnient !), ainsi que la possibilit de constructions avances qui seraient
dlicates avec des expressions (calculs sur un corps fini ou une extension algbrique
de Q, dans un anneau non commutatif, etc.).

5. Sage nest pas un systme de calcul certifi ; il peut donc toujours y avoir un bogue
informatique ; mais il ny aura pas dutilisation dhypothse implicite.
116 CHAP. 5. DOMAINES DE CALCUL
Deuxime partie

Algbre et calcul formel


Dieu a cr les nombres entiers, tout le reste est fabriqu
par lhomme.
Leopold Kronecker (1823 - 1891)

Corps finis et thorie lmentaire des


6
nombres

Ce chapitre dcrit lutilisation de Sage en thorie lmentaire des nombres,


pour manipuler des objets sur des anneaux ou corps finis (6.1), pour tester
la primalit (6.2) ou factoriser un entier (6.3) ; enfin nous discutons quelques
applications (6.4).

6.1 Anneaux et corps finis


Les anneaux et corps finis sont un objet fondamental en thorie des nombres,
et en calcul symbolique en gnral. En effet, de nombreux algorithmes de calcul
formel se ramnent des calculs sur des corps finis, puis on exploite linformation
obtenue via des techniques comme la remonte de Hensel ou la reconstruction par
les restes chinois. Citons par exemple lalgorithme de Cantor-Zassenhaus pour
la factorisation de polynme univari coefficients entiers, qui commence par
factoriser le polynme donn sur un corps fini.

6.1.1 Anneau des entiers modulo n


En Sage, lanneau Z/nZ des entiers modulo n se dfinit laide du constructeur
IntegerModRing (ou plus simplement Integers). Tous les objets construits
partir de ce constructeur et leurs drivs sont systmatiquement rduits modulo
n, et ont donc une forme canonique, cest--dire que deux variables reprsentant
la mme valeur modulo n ont la mme reprsentation interne. Dans certains cas
bien particuliers, il est plus efficace de retarder les rductions modulo n, par
exemple si on multiplie des matrices avec de tels coefficients ; on prfrera alors
120 CHAP. 6. CORPS FINIS ET THORIE DES NOMBRES

travailler avec des entiers, et effectuer les rductions modulo n la main


via a % n. Attention, le module n napparat pas explicitement dans la valeur
affiche :
sage: a = IntegerModRing(15)(3); b = IntegerModRing(17)(3); a, b
(3, 3)
sage: a == b
False

Une consquence est que si lon copie-colle des entiers modulo n, on perd
linformation sur n. tant donne une variable contenant un entier modulo n, on
retrouve linformation sur n via les mthodes base_ring ou parent, et la valeur
de n via la mthode characteristic :
sage: R = a.base_ring(); R
Ring of integers modulo 15
sage: R.characteristic()
15

Les oprateurs de base (addition, soustraction, multiplication) sont surchargs


pour les entiers modulo n, et appellent les fonctions correspondantes, de mme
que les entiers sont automatiquement convertis, ds lors quun des oprandes est
un entier modulo n :
sage: a + a, a - 17, a * a + 1, a^3
(6, 1, 10, 12)

Quant linversion 1/a mod n ou la division b/a mod n, Sage leffectue quand
elle est possible, sinon il renvoie une erreur ZeroDivisionError, i.e., quand a et
n ont un pgcd non-trivial :
sage: 1/(a+1)
4
sage: 1/a
Traceback (most recent call last):
...
ZeroDivisionError: Inverse does not exist.

Pour obtenir la valeur de a en tant quentier partir du rsidu a mod n,


on peut utiliser la mthode lift ou bien ZZ :
sage: z = lift(a); y = ZZ(a); print y, type(y), y == z
3 <type 'sage.rings.integer.Integer'> True

Lordre additif de a modulo n est le plus petit entier k > 0 tel que ka =
0 mod n. Il vaut k = n/g o g = pgcd(a, n), et est donn par la mthode
additive_order (on voit au passage quon peut aussi utiliser Mod ou mod pour
dfinir les entiers modulo n) :
sage: [Mod(x,15).additive_order() for x in range(0,15)]
[1, 15, 15, 5, 15, 3, 5, 15, 15, 5, 3, 15, 5, 15, 15]
6.1. ANNEAUX ET CORPS FINIS 121

Lordre multiplicatif de a modulo n, pour a premier avec n, est le plus petit


entier k > 0 tel que ak = 1 mod n. (Si a a un diviseur commun p avec n, alors
ak mod n est un multiple de p quel que soit k.) Si cet ordre multiplicatif gale
(n), savoir lordre du groupe multiplicatif modulo n, on dit que a est un
gnrateur de ce groupe. Ainsi pour n = 15, il ny a pas de gnrateur, puisque
lordre maximal est 4 < 8 = (15) :
sage: [[x, Mod(x,15).multiplicative_order()]
....: for x in range(1,15) if gcd(x,15) == 1]
[[1, 1], [2, 4], [4, 2], [7, 4], [8, 4], [11, 2], [13, 4], [14, 2]]
Voici un exemple avec n = p premier, o 3 est gnrateur :
sage: p = 10^20 + 39; mod(2,p).multiplicative_order()
50000000000000000019
sage: mod(3,p).multiplicative_order()
100000000000000000038
Une opration importante sur Z/nZ est lexponentiation modulaire, qui consiste
calculer ae mod n. Le crypto-systme RSA repose sur cette opration. Pour
calculer efficacement ae mod n, les algorithmes les plus efficaces ncessitent de
lordre de log e multiplications ou carrs modulo n. Il est crucial de rduire
systmatiquement tous les calculs modulo n, au lieu de calculer dabord ae en
tant quentier, comme le montre lexemple suivant :
sage: n = 3^100000; a = n-1; e = 100
sage: %timeit (a^e) % n
5 loops, best of 3: 387 ms per loop
sage: %timeit power_mod(a,e,n)
125 loops, best of 3: 3.46 ms per loop

6.1.2 Corps finis


Les corps finis 1 se dfinissent laide du constructeur FiniteField (ou plus
simplement GF). On peut aussi bien construire les corps premiers GF(p) avec
p premier que les corps composs GF(q) avec q = pk , p premier et k > 1 un
entier. Comme pour les anneaux, les objets crs dans un tel corps ont une forme
canonique, par consquent une rduction est effectue chaque opration. Les
corps finis jouissent des mmes proprits que les anneaux (6.1.1), avec en plus
la possibilit dinverser un lment non nul :
sage: R = GF(17); [1/R(x) for x in range(1,17)]
[1, 9, 6, 13, 7, 3, 5, 15, 2, 12, 14, 10, 4, 11, 8, 16]
Un corps non premier Fpk avec p premier et k > 1 est isomorphe lanneau
quotient des polynmes de Fp [x] modulo un polynme f unitaire et irrductible
de degr k. Dans ce cas, Sage demande un nom pour le gnrateur du corps,
cest--dire la variable x :
1. En franais, le corps fini q lments est not usuellement Fq , alors quen anglais on
utilise plutt GF(q). On utilise ici la notation franaise pour dsigner le concept mathmatique,
et la notation anglaise pour dsigner du code Sage.
122 CHAP. 6. CORPS FINIS ET THORIE DES NOMBRES

sage: R = GF(9,name='x'); R
Finite Field in x of size 3^2
Ici, Sage a choisi automatiquement le polynme f :
sage: R.polynomial()
x^2 + 2*x + 2
Les lments du corps sont alors reprsents par des polynmes ak1 xk1 + +
a1 x + a0 , o les ai sont des lments de Fp :
sage: Set([r for r in R])
{0, 1, 2, x, x + 1, x + 2, 2*x, 2*x + 1, 2*x + 2}
On peut aussi imposer Sage le polynme irrductible f :
sage: Q.<x> = PolynomialRing(GF(3))
sage: R2 = GF(9, name='x', modulus=x^2+1); R2
Finite Field in x of size 3^2
Attention cependant, car si les deux instances R et R2 cres ci-dessus sont
isomorphes F9 , lisomorphisme nest pas explicite :
sage: p = R(x+1); R2(p)
Traceback (most recent call last):
...
TypeError: unable to coerce from a finite field other than the prime
subfield

6.1.3 Reconstruction rationnelle


Le problme de la reconstruction rationnelle constitue une jolie application
des calculs modulaires. tant donn un rsidu a modulo m, il sagit de trouver un
petit rationnel x/y tel que x/y a mod m. Si on sait quun tel petit rationnel
existe, au lieu de calculer directement x/y en tant que rationnel, on calcule x/y
modulo m, ce qui donne le rsidu a, puis on retrouve x/y par reconstruction
rationnelle. Cette seconde approche est souvent plus efficace, car on remplace
des calculs rationnels faisant intervenir de coteux pgcds par des calculs
modulaires.
Lemme. Soient a, m N, avec 0 < a < m. Il existe au plus une pairepdentiers
x, y Z premiers entre eux tels que x/y a mod m avec 0 < |x|, y 6 m/2.
Il nexiste pas toujours de telle paire x, y, par exemple pour a = 2 et m = 5.
Lalgorithme de reconstruction rationnelle est bas sur lalgorithme de pgcd tendu.
Le pgcd tendu de m et a calcule une suite dentiers ai = i m + i a, o les entiers
ai dcroissent, et les coefficientspi , i croissent en valeur absolue. Il suffit donc
de sarrter ds que |ai |, |i | 6 m/2, et la solution est alors x/y = ai /i . Cet
algorithme est disponible via la fonction rational_reconstruction de Sage, qui
renvoie x/y lorsquune telle solution existe, et une erreur sinon :
sage: rational_reconstruction(411,1000)
-13/17
6.1. ANNEAUX ET CORPS FINIS 123

sage: rational_reconstruction(409,1000)
Traceback (most recent call last):
...
ValueError: Rational reconstruction of 409 (mod 1000) does not exist.
Pour illustrer la reconstruction rationnelle, considrons le calcul du nombre
harmonique Hn = 1 + 1/2 + + 1/n. Le calcul naf avec des nombres rationnels
est le suivant :
sage: def harmonic(n):
....: return add([1/x for x in range(1,n+1)])
Or nous savons que Hn peut scrire sous la forme pn /qn avec pn , qn entiers, o
qn est le ppcm de 1, 2, . . . , n. On sait par ailleurs que Hn 6 log n + 1, ce qui
permet de borner pn . On en dduit la fonction suivante qui dtermine Hn par
calcul modulaire et reconstruction rationnelle :
sage: def harmonic_mod(n,m):
....: return add([1/x % m for x in range(1,n+1)])
sage: def harmonic2(n):
....: q = lcm(range(1,n+1))
....: pmax = RR(q*(log(n)+1))
....: m = ZZ(2*pmax^2)
....: m = ceil(m/q)*q + 1
....: a = harmonic_mod(n,m)
....: return rational_reconstruction(a,m)
La ligne
p m = ZZ(2*pmax^2) garantit que la reconstruction rationnelle va trouver
p 6 m/2, tandis que la ligne suivante garantit que m est premier avec x =
1, 2, . . . , n, sinon 1/x mod n provoquerait une erreur.
sage: harmonic(100) == harmonic2(100)
True
Sur cet exemple, la fonction harmonic2 nest pas plus efficace que la fonction
harmonic, mais elle illustre bien notre propos. Il nest pas toujours ncessaire de
connatre une borne rigoureuse sur x et y, une estimation la louche suffit si
on peut vrifier facilement par ailleurs que x/y est la solution cherche.
On peut gnraliser la reconstruction rationnelle avec un numrateur x et un
dnominateur y de tailles diffrentes (voir par exemple la section 5.10 du livre
[vzGG03]).

6.1.4 Restes chinois


Une autre application utile des calculs modulaires est ce quon appelle com-
munment les restes chinois . tant donns deux modules m et n premiers
entre eux, soit x un entier inconnu tel que x a mod m et x b mod n. Alors le
thorme des restes chinois permet de reconstruire de faon unique la valeur de x
modulo le produit mn. En effet, on dduit de x a mod m que x scrit sous la
forme x = a + m avec Z. En remplaant cette valeur dans x b mod n, on
124 CHAP. 6. CORPS FINIS ET THORIE DES NOMBRES

obtient 0 mod n, o 0 = (b a)/m mod n. Il en rsulte x = x0 + nm, o


x0 = a + 0 m, et est un entier quelconque.
On a dcrit ici la variante la plus simple des restes chinois . On peut
galement considrer le cas de plusieurs moduli m1 , m2 , . . . , mk . La commande
Sage pour trouver x0 partir de a, b, m, n est crt(a,b,m,n) :
sage: a = 2; b = 3; m = 5; n = 7; lambda0 = (b-a)/m % n; a + lambda0 * m
17
sage: crt(2,3,5,7)
17
Reprenons lexemple du calcul de Hn . Calculons dabord Hn mod mi pour i =
1, 2, . . . , k, ensuite nous dduisons Hn mod (m1 mk ) par restes chinois, enfin
nous retrouvons Hn par reconstruction rationnelle :
sage: def harmonic3(n):
....: q = lcm(range(1,n+1))
....: pmax = RR(q*(log(n)+1))
....: B = ZZ(2*pmax^2)
....: a = 0; m = 1; p = 2^63
....: while m < B:
....: p = next_prime(p)
....: b = harmonic_mod(n,p)
....: a = crt(a,b,m,p)
....: m = m*p
....: return rational_reconstruction(a,m)
sage: harmonic(100) == harmonic3(100)
True
La fonction crt de Sage fonctionne aussi quand les moduli m et n ne sont
pas premiers entre eux. Soit g = gcd(m, n), il y a une solution si et seulement si
a mod g b mod g :
sage: crt(15,1,30,4)
45
sage: crt(15,2,30,4)
Traceback (most recent call last):
...
ValueError: No solution to crt problem since gcd(30,4) does not divide
15-2
Une application plus complexe des restes chinois est prsente dans lexercice 22.

6.2 Primalit
Tester si un entier est premier est une des oprations fondamentales dun
logiciel de calcul symbolique. Mme si lutilisateur ne sen rend pas compte, de
tels tests sont effectus plusieurs milliers de fois par seconde par le logiciel. Par
6.2. PRIMALIT 125

Commandes les plus utiles


Anneau des entiers modulo n IntegerModRing(n)
Corps fini q lments GF(q)
Test de pseudo-primalit is_pseudoprime(n)
Test de primalit is_prime(n)

Tableau 6.1 Rcapitulatif.

exemple pour factoriser un polynme de Z[x] on commence par le factoriser dans


Fp [x] pour un nombre premier p, il faut donc trouver un tel p.
Deux grandes classes de tests de primalit existent. Les plus efficaces sont
des tests de pseudo-primalit, et sont en gnral bass sur des variantes du petit
thorme de Fermat, qui dit que si p est premier, alors tout entier 0 < a < p est
un gnrateur du groupe multiplicatif (Z/pZ) , donc ap1 1 mod p. On utilise
en gnral une petite valeur de a (2, 3, . . .) pour acclrer le calcul de ap1 mod p.
Si ap1 6 1 mod p, p nest certainement pas premier. Si ap1 1 mod p, on ne
peut rien conclure : on dit alors que p est pseudo-premier en base a. Lintuition est
quun entier p qui est pseudo-premier pour plusieurs bases a de grandes chances
dtre premier (voir cependant ci-dessous). Les tests de pseudo-primalit ont en
commun que quand ils renvoient False, le nombre est certainement compos, par
contre quand ils renvoient True, on ne peut rien conclure.
La seconde classe est constitue des tests de vraie primalit. Ces tests renvoient
toujours une rponse correcte, mais peuvent tre moins efficaces que les tests
de pseudo-primalit, notamment pour les nombres qui sont pseudo-premiers en
de nombreuses bases, et en particulier pour les nombres vraiment premiers. De
nombreux logiciels ne fournissent quun test de pseudo-primalit, voire pire le nom
de la fonction correspondante (isprime par exemple) laisse croire lutilisateur
que cest un test de (vraie) primalit. Sage fournit deux fonctions distinctes :
is_pseudoprime pour la pseudo-primalit, et is_prime pour la primalit :
sage: p = previous_prime(2^400)
sage: %timeit is_pseudoprime(p)
625 loops, best of 3: 1.07 ms per loop
sage: %timeit is_prime(p)
5 loops, best of 3: 485 ms per loop

Nous voyons sur cet exemple que le test de primalit est bien plus coteux ; quand
cest possible, on prfrera is_pseudoprime.
Certains algorithmes de primalit fournissent un certificat, qui peut tre vrifi
indpendamment, souvent de manire plus efficace que le test lui-mme. Sage ne
fournit pas de tel certificat dans la version actuelle, mais on peut en fabriquer un
avec le thorme de Pocklington :

Thorme. Soit n > 1 un entier tel que n 1 = F R, avec F > n. Si pour
tout facteur premier p de F , il existe a tel que an1 1 mod n et a(n1)/p 1
est premier avec n, alors n est premier.
126 CHAP. 6. CORPS FINIS ET THORIE DES NOMBRES

Soit par exemple n = 231 1. La factorisation de n1 est 232 71131151331.


On peut prendre F = 151 331 ; a = 3 convient pour les deux facteurs p = 151 et
p = 331. Il suffit ensuite de prouver la primalit de 151 et 331. Ce test utilise de
manire intensive lexponentiation modulaire.

Nombres de Carmichael

Les nombres de Carmichael sont des entiers composs qui sont pseudo-
premiers dans toutes les bases. Le petit thorme de Fermat ne permet donc
pas de les distinguer des nombres premiers, quel que soit le nombre de bases
essayes. Le plus petit nombre de Carmichael est 561 = 3 11 17. Un nombre
de Carmichael a au moins trois facteurs premiers. En effet, supposons que
n = pq soit un nombre de Carmichael, avec p, q premiers, p < q ; par dfinition
des nombres de Carmichael, on a pour tout 1 6 a < q lgalit an1 1
modulo n, et par suite modulo q, ce qui implique que n 1 est multiple de
q 1. Lentier n est ncessairement de la forme q + q(q 1), puisquil est
multiple de q, et n 1 est multiple de q 1, ce qui est incompatible avec
n = pq puisque p < q. Si n = pqr, alors il suffit que an1 1 mod p et de
mme pour q et r, puisque par restes chinois on aura alors an1 1 mod n.
Une condition suffisante est que n 1 soit multiple de p 1, q 1 et r 1 :
sage: [560 % (x-1) for x in [3,11,17]]
[0, 0, 0]

Exercice 19. crire une fonction Sage comptant les nombres de Carmichael n =
pqr 6 N , avec p, q, r premiers impairs distincts. Combien trouvez-vous pour N =
104 , 105 , 106 , 107 ? (Richard Pinch a compt 20138200 nombres de Carmichael infrieurs
1021 .)
Enfin, pour itrer une opration sur des nombres premiers dans un intervalle,
il vaut mieux utiliser la construction prime_range, qui construit une table via un
crible, plutt quune boucle avec next_probable_prime ou next_prime :
sage: def count_primes1(n):
....: return add([1 for p in range(n+1) if is_prime(p)])
sage: %timeit count_primes1(10^5)
5 loops, best of 3: 674 ms per loop

La fonction est plus rapide en utilisant is_pseudoprime au lieu de is_prime :


sage: def count_primes2(n):
....: return add([1 for p in range(n+1) if is_pseudoprime(p)])
sage: %timeit count_primes2(10^5)
5 loops, best of 3: 256 ms per loop

Sur cet exemple il vaut mieux utiliser une boucle qui vite de construire une liste
de 105 lments, et l encore is_pseudoprime est plus rapide que is_prime :
6.3. FACTORISATION ET LOGARITHME DISCRET 127

sage: def count_primes3(n):


....: s = 0; p = 2
....: while p <= n: s += 1; p = next_prime(p)
....: return s
sage: %timeit count_primes3(10^5)
5 loops, best of 3: 49.2 ms per loop
sage: def count_primes4(n):
....: s = 0; p = 2
....: while p <= n: s += 1; p = next_probable_prime(p)
....: return s
sage: %timeit count_primes4(10^5)
5 loops, best of 3: 48.6 ms per loop

Litrateur prime_range est quant lui bien plus rapide :


sage: def count_primes5(n):
....: s = 0
....: for p in prime_range(n): s += 1
....: return s
sage: %timeit count_primes5(10^5)
125 loops, best of 3: 2.67 ms per loop

6.3 Factorisation et logarithme discret


On dit quun entier a est un carr ou rsidu quadratique modulo n
sil existe x, 0 6 x < n, tel que a x2 mod n. Sinon, on dit que a est un
non-rsidu quadratique modulo n. Lorsque n = p est premier, ce test peut se
dcider efficacement grce au calcul du symbole de Jacobi de a et p, not (a|p),
qui peut prendre les valeurs {1, 0, 1}, o (a|p) = 0 signifie que a est multiple
de p, et (a|p) = 1 (respectivement (a|p) = 1) signifie que a est (respectivement
nest pas) un carr modulo p. La complexit du calcul du symbole de Jacobi
(a|n) est essentiellement la mme que celle du calcul du pgcd de a et n, savoir
O(M (`) log `) o ` est la taille de n, et M (`) est le cot du produit de deux entiers
de taille `. Cependant toutes les implantations du symbole de Jacobi voire du
pgcd nont pas cette complexit (a.jacobi(n) calcule (a|n)) :
sage: p = (2^42737+1)//3; a = 3^42737
sage: %timeit a.gcd(p)
125 loops, best of 3: 4.3 ms per loop
sage: %timeit a.jacobi(p)
25 loops, best of 3: 26.1 ms per loop

Lorsque n est compos, trouver les solutions de x2 a mod n est aussi difficile
que factoriser n. Toutefois le symbole de Jacobi, qui est relativement facile
calculer, donne une information partielle. En effet, si (a|n) = 1, il ny a pas de
solution, car une solution vrifie ncessairement (a|p) = 1 pour tous les facteurs
premiers p de n, donc (a|n) = 1.
128 CHAP. 6. CORPS FINIS ET THORIE DES NOMBRES

Le logarithme discret. Soit n un entier positif, g un gnrateur du groupe


multiplicatif modulo n et a premier avec n, 0 < a < n. Par dfinition du fait que
g est un gnrateur, il existe un entier x tel que g x = a mod n. Le problme du
logarithme discret consiste trouver un tel entier x. La mthode log permet de
rsoudre ce problme :
sage: p = 10^10+19; a = mod(17,p); a.log(2)
6954104378
sage: mod(2,p)^6954104378
17
Les meilleurs algorithmes connus pour calculer un logarithme discret sont de
mme ordre de complexit en fonction de la taille de n que ceux pour
factoriser n. Cependant limplantation actuelle en Sage du logarithme discret est
peu efficace :
sage: p = 10^20+39; a = mod(17,p)
sage: %time r = a.log(3)
CPU times: user 89.63 s, sys: 1.70 s, total: 91.33 s

Suites aliquotes

La suite aliquote associe un entier positif n est la suite (sk ) dfinie par
rcurrence : s0 = n et sk+1 = (sk ) sk , o (sk ) est la somme des diviseurs
de sk , i.e., sk+1 est la suite des diviseurs propres de sk , cest--dire sans sk
lui-mme. On arrte litration lorsque sk = 1 alors sk1 est premier
ou lorsque la suite (sk ) dcrit un cycle. Par exemple en partant de n = 30 on
obtient :
30, 42, 54, 66, 78, 90, 144, 259, 45, 33, 15, 9, 4, 3, 1.
Lorsque le cycle est de longueur un, on dit que lentier correspondant est
parfait, par exemple 6 = 1 + 2 + 3 et 28 = 1 + 2 + 4 + 7 + 14 sont parfaits.
Lorsque le cycle est de longueur deux, on dit que les deux entiers en question
sont amicaux, comme 220 et 284. Lorsque le cycle est de longueur trois ou
plus, les entiers formant ce cycle sont dits sociables.

Exercice 20. Calculer la suite aliquote commenant par 840, afficher les 5 premiers
et 5 derniers lments, et tracer le graphe de log10 sk en fonction de k (on pourra utiliser
la fonction sigma).

6.4 Applications
6.4.1 La constante
La constante est une gnralisation en dimension deux de la constante
dEuler. Elle est dfinie comme suit :
n
!
X 1
= lim log n , (6.1)
n rk2
k=2
6.4. APPLICATIONS 129

o rk est le rayon du plus petit disque du plan affine


R contenant au moins
2

k points de Z . Parexemple r2 = 1/2, r3 = r4 = 2/2, r5 = 1, r6 = 5/2,
2

r7 = 5/4, r8 = r9 = 2 :

Exercice 21 (Constante de Masser-Gramain). 1. crire une fonction qui prend


en entre un entier positif k, et renvoie le rayon rk et le centrep
(xk , yk ) dun plus petit
disque contenant au moins k points de Z2 . On admettra rk < k/.
2. crire une fonction dessinant le cercle de centre (xk , yk ) et de rayon rk , avec les
m > k points de Z2 inclus, comme ci-dessus.
3. En utilisant lencadrement
p r
(k 6) + 2 2 k1
< rk < , (6.2)

calculer une approximation de avec une erreur borne par 0.3.

6.4.2 Calcul dintgrale multiple via reconstruction


rationnelle
Cette application est inspire de larticle [Bea09]. Soient k et n1 , n2 , . . . , nk
des entiers positifs ou nuls. On veut calculer lintgrale
Z
I= xn1 1 xn2 2 xnk k dx1 dx2 . . . dxk ,
V

o le domaine dintgration est dfini par V = {x1 > x2 > > xk > 0, x1 +
+ xk 6 1}. Par exemple pour k = 2, n1 = 3, n2 = 5, on obtient la valeur
1/2 1x2
13
Z Z
I= x31 x52 dx1 dx2 = .
x2 =0 x1 =x2 258048
130 CHAP. 6. CORPS FINIS ET THORIE DES NOMBRES

Exercice 22. Sachant que I est un nombre rationnel, mettre au point un algorithme
utilisant la reconstruction rationnelle et/ou les restes chinois pour calculer I. On
implantera cet algorithme en Sage et on lappliquera au cas o [n1 , . . . , n31 ] =

[9, 7, 8, 11, 6, 3, 7, 6, 6, 4, 3, 4, 1, 2, 2, 1, 1, 1, 2, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0].


7
Polynmes

Ce chapitre est consacr aux polynmes une indtermine et aux objets


apparents, essentiellement les fractions rationnelles et les sries formelles. Nous
allons y voir tout dabord comment effectuer avec Sage des manipulations telles
que la division euclidienne de polynmes, la dcomposition en polynmes irr-
ductibles, la recherche de racines ou la dcomposition en lments simples de
fractions rationnelles. Ceci en tenant compte de lanneau ou du corps o vivent
les coefficients des polynmes considrs : Sage nous permet de calculer dans les
anneaux de polynmes A[x], leurs quotients A[x]/hP (x)i, les corps de fractions
rationnelles K(x) ou encore les anneaux de sries formelles A[[x]] pour toute une
gamme danneaux de base.
Mais les oprations sur les polynmes ont des applications plus inattendues.
Comment deviner automatiquement le terme suivant de la suite

1, 1, 2, 3, 8, 11, 39...?

Par exemple, grce lapproximation de Pad des fractions rationnelles, prsente


en section 7.4.3 ! Comment dvelopper aisment en srie les solutions de lquation
exf (x) = f (x) ? Rponse en section 7.5.3.
Nous supposons en gnral que le lecteur a lhabitude de manipuler les poly-
nmes et fractions rationnelles au niveau dun cours de premire anne duniversit.
Nous abordons cependant aussi quelques sujets plus avancs. (Comment prouver
que les solutions de lquation x5 x 1 ne sexpriment pas par radicaux ? Il
suffit de calculer son groupe de Galois comme expliqu en section 7.3.4.) Les
passages correspondants ne sont pas utiliss dans le reste du livre, et le lecteur
peut les sauter sans dommage. Enfin, ce chapitre donne une poigne dexemples
de manipulation de nombres algbriques et de nombres p-adiques.
Les polynmes plusieurs indtermines font quant eux lobjet du chapitre 9.
132 CHAP. 7. POLYNMES

7.1 Anneaux de polynmes


7.1.1 Introduction
Nous avons vu au chapitre 2 comment effectuer des calculs sur des expres-
sions formelles, lments de lanneau symbolique SR. Quelques-unes des
mthodes applicables ces expressions, par exemple degree, sont destines aux
polynmes :
sage: x = var('x'); p = (2*x+1)*(x+2)*(x^4-1)
sage: print p, "est de degr", p.degree(x)
(x + 2)*(2*x + 1)*(x^4 - 1) est de degr 6
Dans certains systmes de calcul formel, dont Maple et Maxima, reprsenter les
polynmes comme des expressions formelles particulires est la manire habituelle
de les manipuler. limage dAxiom, Magma ou MuPAD, Sage permet aussi
de traiter les polynmes de faon plus algbrique, et sait calculer dans des
anneaux comme Q[x] ou Z/4Z [x, y, z].
Ainsi, pour reproduire lexemple prcdent en travaillant dans un anneau de
polynmes bien dtermin, on affecte la variable Python x lindtermine de lan-
neau des polynmes en x coefficients rationnels, donne par polygen(QQ, 'x'),
au lieu de la variable symbolique x renvoye 1 par var('x') :
sage: x = polygen(QQ, 'x'); p = (2*x+1)*(x+2)*(x^4-1)
sage: print p, "est de degr", p.degree()
2*x^6 + 5*x^5 + 2*x^4 - 2*x^2 - 5*x - 2 est de degr 6
Observons que le polynme est automatiquement dvelopp. Les polynmes
algbriques sont toujours reprsents sous forme normale. Cest une diffrence
cruciale par rapport aux polynmes de SR. En particulier, lorsque deux polynmes
sont mathmatiquement gaux, leur reprsentation informatique est la mme, et
une comparaison coefficient par coefficient suffit tester lgalit.
Les fonctionnalits de calcul sur les polynmes algbriques sont beaucoup plus
tendues et performantes que celles sur les expressions polynomiales.

7.1.2 Construction danneaux de polynmes


En Sage, les polynmes, comme beaucoup dautres objets algbriques, sont
en gnral coefficients dans un anneau commutatif. Cest le point de vue que
nous adoptons, mais la plupart de nos exemples concernent des polynmes sur
un corps. Dans tout le chapitre, les lettres A et K dsignent respectivement un
anneau commutatif et un corps quelconques.
La premire tape pour mener un calcul dans une structure algbrique R est
souvent de construire R elle-mme. On construit Q[x] par
sage: R = PolynomialRing(QQ, 'x')
sage: x = R.gen()
1. Une petite diffrence : alors que var('x') a le mme effet que x = var('x') en utilisation
interactive, polygen(QQ, 'x') sans affectation ne change pas la valeur de la variable Python x.
7.1. ANNEAUX DE POLYNMES 133

Manipulation des anneaux de polynmes, R = A[x]


construction (repr. dense) R.<x> = A[] ou R.<x> = PolynomialRing(A, 'x')
ex. Z[x], Q[x], R[x], Z/nZ[x] ZZ['x'], QQ['x'], RR['x'], Integers(n)['x']
construction (repr. creuse) R.<x> = PolynomialRing(A, 'x', sparse=True)
accs lanneau de base A R.base_ring()
accs la variable x R.gen() ou R.0
tests (intgre, nthrien...) R.is_integral_domain(), R.is_noetherian(), ...

Tableau 7.1 Anneaux de polynmes.

Le 'x' qui apparat sur la premire ligne est une chane de caractres, le nom
de lindtermine, ou gnrateur de lanneau. Le x de la deuxime ligne est une
variable Python dans laquelle on rcupre le gnrateur ; employer le mme nom
facilite la lecture du code. Lobjet ainsi stock dans la variable x reprsente le
polynme x Q[x]. Il a pour parent (le parent dun objet Sage est la structure
algbrique do il est issu , voir 5.1) lanneau QQ['x'] :
sage: x.parent()
Univariate Polynomial Ring in x over Rational Field
Le polynme x Q[x] est considr comme diffrent la fois des polynmes
identit x A[x] danneau de base A = 6 Q et de ceux, comme t Q[t], dont
lindtermine porte un autre nom.
Lexpression PolynomialRing(QQ, 't') scrit aussi QQ['t']. On combine
souvent cette abrviation avec la construction S.<g> = ... , qui affecte simulta-
nment une structure la variable S et son gnrateur la variable g. La construc-
tion de lanneau Q[x] et de son indtermine se rduit alors R.<x> = QQ['x'],
ou mme simplement R.<x> = QQ[] en sous-entendant la variable x. La forme
x = polygen(QQ, 'x') vue en introduction quivaut
sage: x = PolynomialRing(QQ, 'x').gen()
Signalons en passant que lon peut choisir entre plusieurs reprsentations en
mmoire lorsque lon construit un anneau de polynmes. Les diffrences entre
reprsentations seront discutes en 7.6.
Exercice 23 (Variables et indtermines).
1. Comment dfinir x et y pour observer les rsultats suivants ?

sage: x^2 + 1
y^2 + 1
sage: (y^2 + 1).parent()
Univariate Polynomial Ring in x over Rational Field

2. Aprs les instructions


sage: Q.<x> = QQ[]; p = x + 1; x = 2; p = p + x

quelle est la valeur de p ?


134 CHAP. 7. POLYNMES

Polynmes coefficients polynomiaux

Nous pouvons dfinir en Sage des anneaux de polynmes coefficients


dans nimporte quel anneau commutatif, y compris un autre anneau de
polynmes. Mais attention, les anneaux du type A[x][y] construits suivant
ce procd sont distincts des vritables anneaux de polynmes plusieurs
indtermines comme A[x, y]. Ces derniers, prsents au chapitre 9, sont
mieux adapts aux calculs courants. En effet, travailler dans A[x][y][. . . ] fait
souvent jouer aux indtermines des rles trop dissymtriques.
Cependant, on souhaite parfois justement privilgier une variable en
voyant les autres comme des paramtres. La mthode polynomial des poly-
nmes multivaris permet disoler une variable, un peu comme la mthode
collect des expressions. Voici par exemple comment calculer le polynme
rciproque dun polynme donn par rapport une de ses indtermines :
sage: R.<x,y,z,t> = QQ[]; p = (x+y+z*t)^2
sage: p.polynomial(t).reverse()
(x^2 + 2*x*y + y^2)*t^2 + (2*x*z + 2*y*z)*t + z^2
Ici, p.polynomial(t) cre un polynme en la seule indtermine t et
coefficients dans QQ[x,y,z], auquel on applique ensuite la mthode reverse.
Les autres conversions entre A[x, y, . . . ] et A[x][y][. . . ] fonctionnent comme
on sy attend :
sage: x = polygen(QQ); y = polygen(QQ[x], 'y')
sage: p = x^3 + x*y + y + y^2; p
y^2 + (x + 1)*y + x^3
sage: q = QQ['x,y'](p); q
x^3 + x*y + y^2 + y
sage: QQ['x']['y'](q)
y^2 + (x + 1)*y + x^3

7.1.3 Polynmes
Cration et arithmtique de base. Aprs linstruction R.<x> = QQ[], les ex-
pressions construites partir de x et des constantes rationnelles par les oprations
+ et * sont des lments de Q[x]. Par exemple, dans p = x + 2, Sage dtermine
automatiquement que la valeur de la variable x et lentier 2 peuvent tous deux
sinterprter comme des lments de Q[x]. La routine daddition des polynmes
de Q[x] est donc appele ; elle fabrique et renvoie le polynme x + 2 Q[x].
Une autre faon de crer un polynme consiste numrer ses coefficients :
sage: def rook_polynomial(n, var='x'):
....: return ZZ[var]([binomial(n, k)^2 * factorial(k)
....: for k in (0..n) ])
La fonction ci-dessus fabrique des polynmes o le coefficient de xk sinterprte
comme le nombre de faons de placer k tours sur un chiquier n n sans quelles
7.1. ANNEAUX DE POLYNMES 135

Accs aux donnes, oprations syntaxiques


indtermine x p.variables(), p.variable_name()
coefficient de xk p[k]
coefficient dominant p.leading_coefficient()
degr p.degree()
liste des coefficients p.coeffs()
liste des coefficients non nuls p.coefficients()
dictionnaire degr 7 coefficient p.dict()
tests (unitaire, constant...) p.is_monic(), p.is_constant(), ...

Arithmtique de base
oprations p + q, p q, p q, pk p + q, p - q, p * q, p^k
substitution x := a p(a) ou p.subs(a)
drive p.derivative() ou diff(p)

Transformations
transformation des coefficients p.map_coefficients(f)
changement danneau de base A[x] B[x] p.change_ring(B) ou B['x'](p)
polynme rciproque p.reverse()

Tableau 7.2 Oprations de base sur les polynmes p, q A[x].

se menacent, do son nom. Les parenthses aprs ZZ[var] servent convertir


de force un objet donn en un lment de cet anneau. La conversion dune
liste [a0 , a1 , . . . ] en lment de ZZ['x'] renvoie le polynme a0 + a1 x + Z[x].

Vue densemble des oprations sur les polynmes. Les lments dun an-
neau de polynmes sont reprsents par des objets Python de la classe Polynomial
ou de classes drives. Les principales oprations 2 disponibles sur ces objets sont
rsumes dans les tableaux 7.2 7.5. Ainsi, on rcupre le degr dun polynme en
appelant sa mthode degree. De mme, p.subs(a) ou simplement p(a) donne
la valeur de p au point a, mais sert aussi calculer la compose p a lorsque a
est lui-mme un polynme, et plus gnralement valuer un polynme de A[x]
en un lment dune A-algbre :
sage: p = R.random_element(degree=4) # un polynme au hasard
sage: p
-4*x^4 - 52*x^3 - 1/6*x^2 - 4/23*x + 1
sage: p.subs(x^2)
-4*x^8 - 52*x^6 - 1/6*x^4 - 4/23*x^2 + 1
sage: p.subs(matrix([[1,2],[3,4]]))

2. Il y en a beaucoup dautres. Ces tableaux omettent les fonctionnalits trop pointues, les
variantes plus spcialises de mthodes mentionnes, et de nombreuses mthodes communes
tous les lments danneaux , voire tous les objets Sage, qui ne prsentent pas dintrt
particulier sur les polynmes. Notons cependant que les mthodes spcialises (par exemple
p.rescale(a), quivalent p(a*x)) sont souvent plus efficaces que les mthodes plus gnrales
qui peuvent les remplacer.
136 CHAP. 7. POLYNMES

[-375407/138 -273931/69]
[ -273931/46 -598600/69]
Nous reviendrons sur le contenu des deux derniers tableaux dans les sections 7.2.1
et 7.3.

Changement danneau. La liste exacte des oprations disponibles, leur effet


et leur efficacit dpendent fortement de lanneau de base. Par exemple, les
polynmes de ZZ['x'] possdent une mthode content qui renvoie leur contenu,
cest--dire le pgcd de leurs coefficients ; ceux de QQ['x'] non, lopration tant
triviale. La mthode factor existe quant elle pour tous les polynmes mais
dclenche une exception NotImplementedError pour un polynme coefficients
dans SR ou dans Z/4Z. Cette exception signifie que lopration nest pas disponible
dans Sage pour ce type dobjet bien quelle ait un sens mathmatiquement.
Il est donc trs utile de pouvoir jongler avec les diffrents anneaux de coefficients
sur lesquels on peut considrer un mme polynme. Applique un polynme
de A[x], la mthode change_ring renvoie son image dans B[x], quand il y a une
faon naturelle de convertir les coefficients. La conversion est souvent donne par
un morphisme canonique de A dans B : notamment, change_ring sert tendre
lanneau de base pour disposer de proprits algbriques supplmentaires. Ici par
exemple, le polynme p est irrductible sur les entiers, mais se factorise sur R :
sage: x = polygen(QQ)
sage: p = x^2 - 16*x + 3
sage: p.factor()
x^2 - 16*x + 3
sage: p.change_ring(RDF).factor()
(x - 15.8102496759) * (x - 0.189750324093)
Le domaine RDF est en fait celui des flottants machine , prsent au chapitre 11.
La factorisation obtenue nest quapproche ; elle ne suffit pas retrouver exac-
tement coup sr le polynme de dpart. Pour reprsenter les racines relles
de polynmes coefficients entiers dune manire qui permet les calculs exacts,
on utilise le domaine AA des nombres algbriques rels. Nous verrons quelques
exemples dans les sections suivantes.
La mme mthode change_ring permet de rduire un polynme de Z[x]
modulo un nombre premier :
sage: p.change_ring(GF(3))
x^2 + 2*x
Inversement, si B A et si les coefficients de p sont en fait dans B, cest aussi
change_ring que lon utilise afin de ramener p dans B[x].

Itration. Plus gnralement, on a parfois besoin dappliquer une transfor-


mation tous les coefficients dun polynme. La mthode map_coefficients
est l pour cela. Applique un polynme p A[x] avec comme paramtre
une fonction f , elle renvoie le polynme obtenu en appliquant f chacun des
coefficients non nuls de p. Le plus souvent, f est une fonction anonyme introduite
7.2. ARITHMTIQUE EUCLIDIENNE 137

Divisibilit et division euclidienne


test de divisibilit p | q p.divides(q)
multiplicit dun diviseur q k | p k = p.valuation(q)
division euclidienne p = qd + r q, r = p.quo_rem(d) ou q = p//d, r = p%d
pseudo-division ak p = qd + r q, r, k = p.pseudo_divrem(d)
plus grand commun diviseur p.gcd(q), gcd([p1, p2, p3])
plus petit commun multiple p.lcm(q), lcm([p1, p2, p3])
pgcd tendu g = up + vq g, u, v = p.xgcd(q) ou xgcd(p, q)
restes chinois c a mod p, c = crt(a, b, p, q)
c b mod q

Divers
interpolation p(xi ) = yi p = R.lagrange_polynomial([(x1,y1), ...])
contenu de p Z[x] p.content()

Tableau 7.3 Arithmtique des polynmes.

par la construction lambda (voir 3.3.2). Voici par exemple comment calculer le
conjugu dun polynme coefficients complexes :
sage: QQi.<myI> = QQ[I] # myi est le i de QQi, I celui de SR
sage: R.<x> = QQi[]; p = (x + 2*myI)^3; p
x^3 + 6*I*x^2 - 12*x - 8*I
sage: p.map_coefficients(lambda z: z.conjugate())
x^3 - 6*I*x^2 - 12*x + 8*I
Dans le cas prsent, on peut aussi crire p.map_coefficients(conjugate), car
conjugate(z) a le mme effet que z.conjugate pour z Q[i]. Appeler explici-
tement une mthode de lobjet z est plus sr : le code fonctionne ainsi avec tous
les objets dots dune mthode conjugate(), et seulement ceux-l.

7.2 Arithmtique euclidienne


Aprs la somme et le produit, les oprations les plus lmentaires sont ici la
division euclidienne et le calcul de plus grand commun diviseur. Les oprateurs
et mthodes correspondants (tableau 7.3) rappellent ceux sur les entiers. Bien
souvent cependant, ces oprations sont caches par une couche dabstraction
mathmatique supplmentaire : quotient danneaux (7.2.2) o chaque opration
arithmtique contient une division euclidienne implicite, fractions rationnelles
(7.4) dont la normalisation passe par des calculs de pgcd...

7.2.1 Divisibilit
Divisions. La division euclidienne fonctionne sur un corps, et plus gnralement
sur un anneau commutatif si le coefficient dominant du diviseur est inversible,
puisque ce coefficient est le seul lment de lanneau de base par lequel il est
ncessaire de diviser lors du calcul :
138 CHAP. 7. POLYNMES

Oprations sur les anneaux de polynmes

Les parents des objets polynmes, les anneaux A[x], sont eux-mmes des
objets Sage part entire. Voyons rapidement quoi ils peuvent servir.
Une premire famille de mthodes permet de construire des polynmes
remarquables, den tirer au hasard, ou encore dnumrer des familles de
polynmes, ici ceux de degr exactement 2 sur F2 :
sage: list(GF(2)['x'].polynomials(of_degree=2))
[x^2, x^2 + 1, x^2 + x, x^2 + x + 1]
Nous ferons appel quelques-unes de ces mthodes dans les exemples des
sections suivantes pour construire les objets sur lesquels travailler. Le cha-
pitre 15 explique de faon plus gnrale comment numrer les lments
densembles finis avec Sage.
Deuximement, le systme connat quelques faits de base propos
de chaque anneau de polynmes. On peut tester si un objet donn est un
anneau, sil est nthrien :
sage: A = QQ['x']
sage: A.is_ring() and A.is_noetherian()
True
ou encore si Z est sous-anneau de Q[x] et pour quelles valeurs de n lanneau
Z/nZ est intgre :
sage: ZZ.is_subring(A)
True
sage: [n for n in range(20)
....: if Integers(n)['x'].is_integral_domain()]
[0, 2, 3, 5, 7, 11, 13, 17, 19]
Ces possibilits reposent largement sur le systme de catgories de Sage
(voir aussi 5.2.3). Les anneaux de polynmes sont membres dun certain
nombre de catgories , comme la catgorie des ensembles, celle des anneaux
euclidiens, et bien dautres :
sage: R.categories()
[Category of euclidean domains,
Category of principal ideal domains,
...
Category of sets with partial maps, Category of objects]
Cela reflte que tout anneau de polynmes est aussi un ensemble, un anneau
euclidien, et ainsi de suite. Le systme peut ainsi transfrer automatiquement
aux anneaux de polynmes les proprits gnrales des objets de ces diffrentes
catgories.
7.2. ARITHMTIQUE EUCLIDIENNE 139

sage: R.<t> = Integers(42)[]; (t^20-1) % (t^5+8*t+7)


22*t^4 + 14*t^3 + 14*t + 6
Lorsque le coefficient dominant nest pas inversible, on peut encore dfinir une
pseudo-division euclidienne : soient A un anneau commutatif, p, d A[x], et a
le coefficient dominant de d. Alors il existe deux polynmes q, r A[x], avec
deg r < deg d, et un entier k 6 deg p deg d + 1 tels que

ak p = qd + r.

La pseudo-division euclidienne est donne par la mthode pseudo_divrem.


Pour effectuer une division exacte, on utilise galement loprateur de quotient
euclidien //. En effet, diviser par un polynme non constant avec / renvoie un
rsultat de type fraction rationnelle (voir 7.4), ou choue lorsque cela na pas de
sens :
sage: ((t^2+t)//t).parent()
Univariate Polynomial Ring in t over Ring of integers modulo 42
sage: (t^2+t)/t
Traceback (most recent call last):
...
TypeError: self must be an integral domain.
Exercice 24. Usuellement, en Sage, les polynmes de Q[x] sont reprsents sur
la base monomiale (xn )nN . Les polynmes de Tchebycheff Tn , dfinis par Tn (cos ) =
cos(n), constituent une famille de polynmes orthogonaux et donc une base de Q[x].
Les premiers polynmes de Tchebycheff sont
sage: x = polygen(QQ); [chebyshev_T(n, x) for n in (0..4)]
[1, x, 2*x^2 - 1, 4*x^3 - 3*x, 8*x^4 - 8*x^2 + 1]

crire une fonction qui prend en entre un lment de Q[x] et renvoie les coefficients de
sa dcomposition sur la base (Tn )nN .
Exercice 25 (Division suivant les puissances croissantes). Soient n N et u, v
A[x], avec v(0) inversible. Alors il existe un unique couple (q, r) de polynmes de A[x]
avec deg q 6 n tel que u = qv + xn+1 r. crire une fonction qui calcule q et r par un
analogue de lalgorithme de division euclidienne. Comment faire ce mme calcul le plus
simplement possible, laide de fonctions existantes ?

PGCD. Sage sait calculer le pgcd de polynmes sur un corps, grce la structure
euclidienne de K[x], mais aussi sur certains autres anneaux, dont les entiers :
sage: S.<x> = ZZ[]; p = 2*(x^10-1)*(x^8-1)
sage: p.gcd(p.derivative())
2*x^2 - 2
On peut prfrer lexpression plus symtrique gcd(p,q), qui donne le mme
rsultat que p.gcd(q). Elle est cependant un peu moins naturelle en Sage car
ce nest pas un mcanisme gnral : la routine appele par gcd(p,q) est une
fonction de deux arguments dfinie manuellement dans le code source de Sage
140 CHAP. 7. POLYNMES

et qui appelle son tour p.gcd. Seules quelques mthodes usuelles ont ainsi une
fonction associe.
Le pgcd tendu (en anglais extended gcd), cest--dire le calcul dune relation
de Bzout
g = pgcd(p, q) = ap + bq, g, p, q, a, b K[x]
est fourni quant lui par p.xgcd(q) :
sage: R.<x> = QQ[]; p = x^5-1; q = x^3-1
sage: print "le pgcd est %s = (%s)*p + (%s)*q" % p.xgcd(q)
le pgcd est x - 1 = (-x)*p + (x^3 + 1)*q
La mthode xgcd existe aussi pour les polynmes de ZZ['x'], mais attention :
lanneau Z[x] ntant pas principal, le rsultat nest pas en gnral une relation
de Bzout !

7.2.2 Idaux et quotients


Idaux de A[x]. Les idaux des anneaux de polynmes, et les quotients par
ces idaux, sont reprsents par des objets Sage construits partir de lanneau de
polynmes par les mthodes ideal et quo. Le produit dun tuple de polynmes
par un anneau de polynmes est interprt comme un idal :
sage: R.<x> = QQ[]
sage: J1 = (x^2 - 2*x + 1, 2*x^2 + x - 3)*R; J1
Principal ideal (x - 1) of Univariate Polynomial Ring in x
over Rational Field
On peut multiplier les idaux, et rduire un polynme modulo un idal :
sage: J2 = R.ideal(x^5 + 2)
sage: ((3*x+5)*J1*J2).reduce(x^10)
421/81*x^6 - 502/81*x^5 + 842/81*x - 680/81
Le polynme rduit demeure dans ce cas un lment de QQ['x']. Une autre
possibilit consiste construire le quotient par un idal et y projeter des lments.
Le parent du projet est alors lanneau quotient. La mthode lift des lments
du quotient sert les relever dans lanneau de dpart.
sage: B = R.quo((3*x+5)*J1*J2) # quo nomme automatiquement 'xbar'
sage: B(x^10) # le gnrateur de B image de x
421/81*xbar^6 - 502/81*xbar^5 + 842/81*xbar - 680/81
sage: B(x^10).lift()
421/81*x^6 - 502/81*x^5 + 842/81*x - 680/81
Si K est un corps, lanneau K[x] est principal : les idaux sont reprsents
dans les calculs par un gnrateur, et tout ceci nest gure quun langage plus
algbrique pour les oprations vues en 7.2.1. Son principal mrite est que les
anneaux quotients peuvent aisment tre utiliss dans de nouvelles constructions,
ici celle de F5 [t]/ht2 + 3i [x] :
sage: R.<t> = GF(5)[]; R.quo(t^2+3)['x'].random_element()
7.3. FACTORISATION ET RACINES 141

Construction didaux et danneaux quotients Q = R/J


idal hu, v, wi R.ideal(u, v, w) ou (u, v, w)*R
rduction de p modulo J J.reduce(p) ou p.mod(J)
anneau quotient R/J, R/hpi R.quo(J), R.quo(p)
anneau quotient pour obtenir Q Q.cover_ring()
corps de nombres isomorphe Q.number_field()

lments de K[x]/hpi
relev (section de R  R/J) u.lift()
polynme minimal u.minpoly()
polynme caractristique u.charpoly()
matrice u.matrix()
trace u.trace()

Tableau 7.4 Idaux et quotients.

(3*tbar + 1)*x^2 + (2*tbar + 3)*x + 3*tbar + 4


Sage permet aussi de construire des idaux danneaux non principaux comme Z[x],
mais les oprations disponibles sont alors limites sauf dans le cas des polynmes
plusieurs indtermines sur un corps, qui font lobjet du chapitre 9.
Exercice 26. On dfinit la suite (un )nN par les conditions initiales un = n + 7
pour 0 6 n < 1000 et la relation de rcurrence linaire

un+1000 = 23un+729 5un+2 + 12un+1 + 7un (n > 0).

Calculer les cinq derniers chiffres de u1010000 . Indication : on pourra sinspirer de


lalgorithme de 3.2.4. Mais celui-ci prend trop de temps quand lordre de la rcurrence
est lev. Introduire un quotient danneau de polynmes judicieux afin dviter ce
problme.

Extensions algbriques. Un cas particulier important est le quotient de K[x]


par un polynme irrductible pour raliser une extension algbrique de K.
Les corps de nombres, extensions finies de Q, sont reprsents par des objets
NumberField distincts des quotients de QQ['x']. Lorsque cela a un sens, la m-
thode number_field dun quotient danneau de polynmes renvoie le corps de
nombres correspondant. Linterface des corps de nombres, plus riche que celle
des anneaux quotients, dpasse le cadre de ce livre. Les corps finis composs Fpk ,
raliss comme extensions algbriques des corps finis premiers Fp , sont quant
eux dcrits en 6.1.

7.3 Factorisation et racines


Un troisime niveau aprs les oprations lmentaires et larithmtique eu-
clidienne concerne la dcomposition des polynmes en produit de facteurs irr-
ductibles, ou factorisation. Cest peut-tre ici que le calcul formel est le plus
utile !
142 CHAP. 7. POLYNMES

7.3.1 Factorisation
Test dirrductibilit. Sur le plan algbrique, la question la plus simple
concernant la factorisation dun polynme est si celui-ci scrit comme produit
de deux facteurs non triviaux, ou au contraire est irrductible. Naturellement,
la rponse dpend de lanneau de base. La mthode is_irreducible indique si
un polynme est irrductible dans son anneau parent. Par exemple, le polynme
3x2 6 est irrductible sur Q, mais pas sur Z (pourquoi ?) :
sage: R.<x> = QQ[]; p = 3*x^2 - 6
sage: p.is_irreducible(), p.change_ring(ZZ).is_irreducible()
(True, False)

Factorisation. Dcomposer en facteurs premiers un entier de plusieurs centaines


ou milliers de chiffres est un problme trs difficile. Factoriser un polynme de
degr 1000 sur Q ou Fp ne demande en revanche que quelques secondes de temps
processeur 3 :
sage: p = QQ['x'].random_element(degree=1000)
sage: %timeit p.factor()
5 loops, best of 3: 32.2 s per loop
Ici sarrte donc la similitude algorithmique entre polynmes et entiers que nous
avons pu observer dans les sections prcdentes.
Tout comme le test dirrductibilit, la factorisation a lieu sur lanneau de
base du polynme. Par exemple, la factorisation dun polynme sur les entiers est
constitue dune partie constante, elle-mme dcompose en facteurs premiers,
et dun produit de polynmes primitifs, cest--dire dont les coefficients sont
premiers entre eux :
sage: x = polygen(ZZ); p = 54*x^4+36*x^3-102*x^2-72*x-12
sage: p.factor()
2 * 3 * (3*x + 1)^2 * (x^2 - 2)
Sage permet de factoriser sur des anneaux varis rationnels, complexes (appro-
chs), corps finis et corps de nombres notamment :
sage: for A in [QQ, ComplexField(16), GF(5), QQ[sqrt(2)]]:
....: print A, ":"; print A['x'](p).factor()
Rational Field :
(54) * (x + 1/3)^2 * (x^2 - 2)
Complex Field with 16 bits of precision :
(54.00) * (x - 1.414) * (x + 0.3333)^2 * (x + 1.414)
Finite Field of size 5 :
(4) * (x + 2)^2 * (x^2 + 3)
Number Field in sqrt2 with defining polynomial x^2 - 2 :
(54) * (x - sqrt2) * (x + sqrt2) * (x + 1/3)^2
3. Dun point de vue thorique, on sait factoriser dans Q[x] en temps polynomial, et dans
Fp [x] en temps polynomial probabiliste, alors que lon ignore sil est possible de factoriser les
entiers en temps polynomial.
7.3. FACTORISATION ET RACINES 143

Factorisation
test dirrductibilit p.is_irreducible()
factorisation p.factor()
factorisation sans carr p.squarefree_decomposition()
partie sans carr p/ pgcd(p, p0 ) p.radical()

Racines
racines dans A, dans D p.roots(), p.roots(D)
racines relles p.roots(RR), p.real_roots()
racines complexes p.roots(CC), p.complex_roots()
isolation des racines relles p.roots(RIF), p.real_root_intervals()
isolation des racines complexes p.roots(CIF)
rsultant p.resultant(q)
discriminant p.discriminant()
groupe de Galois (p irrductible) p.galois_group()

Tableau 7.5 Factorisation et racines.

Le rsultat dune dcomposition en facteurs irrductibles nest pas un polynme


(puisque les polynmes sont toujours sous forme normale, cest--dire dvelopps !),
mais un objet f de type Factorization. On peut rcuprer le i-me facteur avec
f[i], et on retrouve le polynme par f.expand(). Les objets Factorization
disposent aussi de mthodes comme gcd et lcm qui ont le mme sens que pour
les polynmes mais oprent sur les formes factorises.

Dcomposition sans carr. Malgr sa bonne complexit thorique et pratique,


la factorisation complte dun polynme est une opration complexe. La dcom-
position sans carr constitue une forme plus faible de factorisation, beaucoup
plus facile obtenir quelques calculs de pgcd suffisent et qui apporte dj
beaucoup dinformation.
Qr
Soit p = i=1 pm i
i
K[x] un polynme dcompos en produit de facteurs
irrductibles sur un corps K de caractristique nulle. On dit que p est sans
carr (en anglais squarefree) si tous les facteurs pi sont de multiplicit mi = 1,
cest--dire si les racines de p dans une clture algbrique de K sont simples. Une
dcomposition sans carr est une factorisation en produit de facteurs sans carr
deux deux premiers entre eux :
Y
p = f1 f22 . . . fss o fm = pi .
mi =m

La dcomposition sans carr spare donc les facteurs irrductibles de p par


multiplicit. La partie sans carr f1 . . . fs = p1 . . . pr de p est le polynme
racines simples qui a les mmes racines que p aux multiplicits prs.

7.3.2 Recherche de racines


Le calcul des racines dun polynme admet de nombreuses variantes, suivant
que lon cherche des racines relles, complexes, ou dans un autre domaine, exactes
144 CHAP. 7. POLYNMES

ou approches, avec ou sans multiplicits, de faon garantie ou heuristique... La


mthode roots dun polynme renvoie par dfaut les racines du polynme dans
son anneau de base, sous la forme dune liste de couples (racine, multiplicit) :
sage: R.<x> = ZZ[]; p = (2*x^2-5*x+2)^2 * (x^4-7); p.roots()
[(2, 2)]
Avec un paramtre, roots(D) renvoie les racines dans le domaine D, ici les racines
rationnelles, puis des approximations des racines `-adiques pour ` = 19 :
sage: p.roots(QQ)
[(2, 2), (1/2, 2)]
sage: p.roots(Zp(19, print_max_terms=3))
[(2 + 6*19^10 + 9*19^11 + ... + O(19^20), 1),
(7 + 16*19 + 17*19^2 + ... + O(19^20), 1),
(10 + 9*19 + 9*19^2 + ... + O(19^20), 1),
(10 + 9*19 + 9*19^2 + ... + O(19^20), 1),
(12 + 2*19 + 19^2 + ... + O(19^20), 1),
(2 + 13*19^10 + 9*19^11 + ... + O(19^20), 1)]
Cela fonctionne pour une grande varit de domaines, avec une efficacit variable.
En particulier, choisir pour D le corps des nombres algbriques QQbar ou celui
des algbriques rels AA permet de calculer de faon exacte les racines complexes
ou relles dun polynme coefficients rationnels :
sage: racines = p.roots(AA); racines
[(-1.626576561697786?, 1), (0.500000000000000?, 2),
(1.626576561697786?, 1), (2.000000000000000?, 2)]
Sage jongle de faon transparente pour lutilisateur entre diverses reprsentations
des nombres algbriques. Lune consiste par exemple coder chaque Q
via son polynme minimal coupl un encadrement suffisamment prcis pour
distinguer des autres racines. Ainsi, malgr leur affichage, les racines renvoyes
ne sont pas de simples valeurs approches. Elles peuvent tre rutilises dans des
calculs exacts :
sage: a = racines[0][0]^4; a.simplify(); a
7
Ici, on a lev la premire des racines trouves la puissance quatrime, puis
forc Sage simplifier suffisamment le rsultat pour rendre manifeste quil sagit
de lentier 7.
Une variante de la rsolution exacte consiste simplement isoler les racines,
cest--dire calculer des intervalles contenant chacun exactement une racine,
en passant comme domaine D celui des intervalles rels RIF ou complexes CIF.
Parmi les autres domaines utiles dans le cas dun polynme coefficients ration-
nels, citons RR, CC, RDF, CDF, qui correspondent tous des racines approches,
cherches numriquement, ainsi que les corps de nombres QQ[alpha]. Les m-
thodes spcifiques real_roots, complex_roots et (pour certains anneaux de
base) real_root_intervals offrent des options supplmentaires ou donnent des
rsultats lgrement diffrents des appels correspondant roots. La recherche et
lisolation de racines numriques sont traites plus en dtail en 12.2.
7.3. FACTORISATION ET RACINES 145

7.3.3 Rsultant
Sur tout anneau factoriel, lexistence dun facteur commun non constant
deux polynmes se caractrise par lannulation de leur rsultant Res(p, q), qui est
un polynme en leurs coefficients. Un intrt majeur du rsultant par rapport
au pgcd est quil se spcialise bien par morphismes danneaux. Par exemple, les
polynmes x 12 et x 20 sont premiers entre eux dans Z[x], mais lannulation
de leur rsultant
sage: x = polygen(ZZ); (x-12).resultant(x-20)
-8

modulo n montre quils ont une racine commune dans Z/nZ si et seulement
n divise 8.
Pm Pn
Soient p = i=0 pi xi et q = i=0 qi xi deux polynmes non constants de A[x],
avec pm , qn 6= 0. Le rsultant de p et q est dfini par

p m p0
.. ..

. .




pm p0
Res(p, q) = qn
q0 .

(7.1)
.. ..
. .


.. ..

. .



qn q0

Cest le dterminant, dans des bases convenables, de lapplication linaire

An1 [x] Am1 [x] Am+n1 [x]


u, v 7 up + vq

o Ak [x] A[x] dsigne le sous-module des polynmes de degr au plus k. Si p


et q sont scinds, leur rsultant scrit aussi en fonction des diffrences de leurs
racines :

p = pm (x 1 ) . . . (x m )
Y 
Res(p, q) = pm qn
n m
(i j ),
q = qn (x 1 ) . . . (x n ).
i,j

La proprit de spcialisation mentionne plus haut se dduit de la dfini-


tion (7.1) : si : A A0 est un morphisme danneaux dont lapplication p et
q ne fait pas chuter leurs degrs, autrement dit tel que (pm ) 6= 0 et (qn ) 6= 0,
alors on a
Res((p), (q)) = (Res(p, q)).

Ainsi, (Res(p, q)) sannule lorsque (p) et (q) ont un facteur commun. Nous
avons vu un exemple de ce phnomne un peu plus haut, avec pour la projection
canonique de Z dans Z/nZ.
146 CHAP. 7. POLYNMES

Mais lutilisation la plus commune du rsultant concerne le cas o lanneau de


base est lui-mme un anneau de polynmes : p, q A[x] avec A = K[a1 , . . . , ak ].
En particulier, soient 1 , . . . , k K, et considrons la spcialisation

: B[a1 , . . . , ak ] K
q(a1 , . . . , ak ) 7 q(1 , . . . , k ).

On voit alors que le rsultant Res(p, q) sannule en (1 , . . . , k ) si et seulement


si les spcialisations (p), (q) K[x] ont un facteur commun, sous rserve que
lun des termes dominants de p et q soit diffrent de zro en (1 , . . . , k ).
Par exemple, le discriminant de p est dfini par

disc(p) = (1)d(d1)/2 Res(p, p0 )/pm .

Cette dfinition gnralise les discriminants classiques des polynmes de degr


deux ou trois :
sage: R.<a,b,c,d> = QQ[]; x = polygen(R); p = a*x^2+b*x+c
sage: p.resultant(p.derivative())
-a*b^2 + 4*a^2*c
sage: p.discriminant()
b^2 - 4*a*c
sage: (a*x^3 + b*x^2 + c*x + d).discriminant()
b^2*c^2 - 4*a*c^3 - 4*b^3*d + 18*a*b*c*d - 27*a^2*d^2
Comme le discriminant de p est, une normalisation prs, le rsultant de p et de
sa drive, il sannule si et seulement si p a une racine multiple.

7.3.4 Groupe de Galois


Le groupe de Galois dun polynme irrductible p Q[x] est un objet alg-
brique qui dcrit certaines symtries des racines de p. Il sagit dun objet
central de la thorie des quations algbriques. Notamment, lquation p(x) = 0
est rsoluble par radicaux, cest--dire que ses solutions sexpriment partir des
coefficients de p au moyen des quatre oprations et de lextraction de racine
n-ime, si et seulement si le groupe de Galois de p est rsoluble.
Sage permet de calculer les groupes de Galois des polynmes coefficients
rationnels de degr modr, et deffectuer toutes sortes doprations sur les
groupes obtenus. Tant la thorie de Galois que les fonctionnalits de thorie des
groupes de Sage dpassent le cadre de ce livre. Bornons-nous appliquer sans plus
dexplications le thorme de Galois sur la rsolubilit par radicaux. Le calcul
suivant 4 montre que les racines de x5 x 1 ne sexpriment pas par radicaux :
sage: x = polygen(QQ); G = (x^5 - x - 1).galois_group(); G
Transitive group number 5 of degree 5
4. Ce calcul ncessite une table de groupes finis qui ne fait pas partie de linstallation
de base de Sage, mais que lon peut tlcharger et installer automatiquement par la com-
mande install_package("database_gap") (il peut tre ncessaire de redmarrer Sage aprs
linstallation).
7.4. FRACTIONS RATIONNELLES 147

sage: G.is_solvable()
False
Il sagit dun des exemples les plus simples dans ce cas, puisque les polynmes
de degr infrieur ou gal 4 sont toujours rsolubles par radicaux, de mme
videmment que ceux de la forme x5 a. En examinant les gnrateurs de G vu
comme un groupe de permutations, on reconnat que G ' S5 , ce que lon vrifie
facilement :
sage: G.gens()
[(1,2,3,4,5), (1,2)]
sage: G.is_isomorphic(SymmetricGroup(5))
True

7.4 Fractions rationnelles


7.4.1 Construction et proprits lmentaires
La division de deux polynmes (sur un anneau intgre) produit une fraction
rationnelle. Son parent est le corps des fractions de lanneau de polynmes, qui
peut sobtenir par Frac(R) :
sage: x = polygen(RR); r = (1 + x)/(1 - x^2); r.parent()
Fraction Field of Univariate Polynomial Ring in x over Real
Field with 53 bits of precision
sage: r
(x + 1.00000000000000)/(-x^2 + 1.00000000000000)
On observe que la simplification nest pas automatique. Cest parce que RR
est un anneau inexact, cest--dire dont les lments sinterprtent comme des
approximations dobjets mathmatiques. La mthode reduce met la fraction
sous forme rduite. Elle ne renvoie pas de nouvel objet, mais modifie la fraction
rationnelle existante :
sage: r.reduce(); r
1.00000000000000/(-x + 1.00000000000000)
Sur un anneau exact, en revanche, les fractions rationnelles sont automatiquement
rduites.
Les oprations sur les fractions rationnelles sont analogues celles sur les
polynmes. Celles qui ont un sens dans les deux cas (substitution, drive, facto-
risation...) sutilisent de la mme faon. Le tableau 7.6 numre quelques autres
mthodes utiles. La dcomposition en lments simples et surtout la reconstruction
rationnelle mritent quelques explications.

7.4.2 Dcomposition en lments simples


Sage calcule la dcomposition en lments simples dune fraction rationnelle
a/b de Frac(K['x']) partir de la factorisation de b dans K['x']. Il sagit donc
148 CHAP. 7. POLYNMES

Fractions rationnelles
corps des fractions K(x) Frac(K['x'])
numrateur r.numerator()
dnominateur r.denominator()
simplification (modifie r) r.reduce()
dcomposition en lments simples r.partial_fraction_decomposition()
reconstruction rationnelle de s mod m s.rational_reconstruct(m)

Sries tronques
anneau A[[t]] PowerSeriesRing(A, 'x', default_prec=n)
anneau A((t)) LaurentSeriesRing(A, 'x', default_prec=n)
coefficient [xk ] f (x) f[k]
troncature x + O(x^n)
prcision f.prec()
drive, primitive
p(nulle en 0) f.derivative(), f.integral()
oprations usuelles f , exp f , ... f.sqrt(), f.exp(), ...
rciproque (f g = g f = x) g = f.reversion()
solution de y 0 = ay + b a.solve_linear_de(precision, b)

Tableau 7.6 Objets construits partir des polynmes.

de la dcomposition en lments simples sur K. Le rsultat est form dune partie


polynomiale p et dune liste de fractions rationnelles dont les dnominateurs sont
des puissances de facteurs irrductibles de b :
sage: R.<x> = QQ[]; r = x^10 / ((x^2-1)^2 * (x^2+3))
sage: poly, parts = r.partial_fraction_decomposition()
sage: poly
x^4 - x^2 + 6
sage: for part in parts: part.factor()
(17/32) * (x - 1)^-2 * (x - 15/17)
(-17/32) * (x + 1)^-2 * (x + 15/17)
(-243/16) * (x^2 + 3)^-1
On a ainsi obtenu la dcomposition en lments simples sur les rationnels
17
x10 x 15 17 x 15 243
r= = x4 x2 + 6 + 32 32
+ 32 32
+ 2 16 .
(x2 1) (x + 3)
2 2 (x 1) 2 (x + 1) 2 x +3
Il nest pas difficile de voir que cest aussi la dcomposition de r sur les rels.
Sur les complexes en revanche, le dnominateur du dernier terme nest pas
irrductible, et donc la fraction rationnelle peut encore se dcomposer. On peut
calculer la dcomposition en lments simples sur les rels ou les complexes
numriquement :
sage: C = ComplexField(15)
sage: Frac(C['x'])(r).partial_fraction_decomposition()
(x^4 - x^2 + 6.000, [(0.5312*x - 0.4688)/(x^2 - 2.000*x + 1.000),
4.384*I/(x - 1.732*I), (-4.384*I)/(x + 1.732*I),
(-0.5312*x - 0.4688)/(x^2 + 2.000*x + 1.000)])
7.4. FRACTIONS RATIONNELLES 149

La dcomposition exacte sur C sobtient de la mme faon, en remplaant C


par QQbar. En faisant le calcul sur AA, on aurait la dcomposition sur les rels
mme quand toutes les racines relles du dnominateur ne sont pas rationnelles.

7.4.3 Reconstruction rationnelle


Un analogue de la reconstruction rationnelle prsente en 6.1.3 existe pour les
polynmes coefficients dans A = Z/nZ. tant donns m, s A[x], la commande
sage: s.rational_reconstruct(m, dp, dq)
calcule lorsque cest possible des polynmes p, q A[x] tels que
qs p mod m, deg p 6 dp , deg q 6 dq .
Restreignons-nous pour simplifier au cas o n est premier. Une telle relation
avec q et m premiers entre eux entrane p/q = s dans A[x]/hmi, do le nom de
reconstruction rationnelle.
Le problme de reconstruction rationnelle se traduit par un systme linaire
sur les coefficients de p et q, et un simple argument de dimension montre quil
admet une solution non triviale ds que dp + dq > deg m 1. Il ny a pas toujours
de solution avec q et m premiers entre eux (par exemple, les solutions de p qx
mod x2 avec deg p 6 0, deg q 6 1 sont les multiples constants de (p, q) = (0, x)),
mais rational_reconstruct cherche en priorit les solutions q premires avec m.

Approximants de Pad. Le cas m = xn est appel approximation de Pad.


Un approximant de Pad de type (k, n k) dune srie formelle f K[[x]] est une
fraction rationnelle p/q K(x) telle que deg p 6 k 1, deg q 6 n k, q(0) = 1,
et p/q = f + O(xn ). On a alors p/q f mod xn .
Commenons par un exemple purement formel. P Les commandes suivantes
calculent un approximant de Pad de la srie f = i=0 (i + 1)2 xi coefficients
dans Z/101Z :
sage: A = Integers(101); R.<x> = A[]
sage: f6 = sum( (i+1)^2 * x^i for i in (0..5) ); f6
36*x^5 + 25*x^4 + 16*x^3 + 9*x^2 + 4*x + 1
sage: num, den = f6.rational_reconstruct(x^6, 1, 3); num/den
(100*x + 100)/(x^3 + 98*x^2 + 3*x + 100)
En dveloppant nouveau en srie la fraction rationnelle trouve, on observe
que non seulement les dveloppements concident jusqu lordre 6, mais le terme
suivant aussi est juste !
sage: S = PowerSeriesRing(A, 'x', 7); S(num)/S(den)
1 + 4*x + 9*x^2 + 16*x^3 + 25*x^4 + 36*x^5 + 49*x^6 + O(x^7)
En effet, f est elle-mme une fraction rationnelle : on a f = (1 + x)/(1 x)3 . Le
dveloppement tronqu f6, accompagn de bornes sur les degrs du numrateur
et du dnominateur, suffit la reprsenter sans ambigut. De ce point de vue,
le calcul dapproximants de Pad est linverse du dveloppement en srie des
fractions rationnelles : il permet de repasser de cette reprsentation alternative
la reprsentation habituelle comme quotient de deux polynmes.
150 CHAP. 7. POLYNMES

3
2
1
-6 -4 -2 2 4 6 type (4, 2)
-1
type (8, 4)
-2
type (12, 6)
-3

Figure 7.1 La fonction tangente et quelques approximants de Pad sur [2, 2].

Un exemple analytique. Historiquement, les approximants de Pad ne sont


pas ns de ce genre de considrations formelles, mais de la thorie de lap-
proximation des fonctions analytiques. En effet, les approximants de Pad du
dveloppement en srie dune fonction analytique approchent souvent mieux la
fonction que les troncatures de la srie. Quand le degr du dnominateur est
assez grand, ils peuvent mme fournir de bonnes approximations mme en-dehors
du disque de convergence de la srie. On dit parfois quils avalent les ples .
La figure 7.1, qui montre la convergence des approximants de type (2k, k) de la
fonction tangente au voisinage de 0, illustre ce phnomne.
Bien que rational_reconstruct soit limit aux polynmes sur Z/nZ, il est
possible de sen servir pour calculer des approximants de Pad coefficients
rationnels, et aboutir cette figure. Le plus simple est de commencer par effectuer
la reconstruction rationnelle modulo un nombre premier assez grand :
sage: x = var('x'); s = tan(x).taylor(x, 0, 20)
sage: p = previous_prime(2^30); ZpZx = Integers(p)['x']
sage: Qx = QQ['x']

sage: num, den = ZpZx(s).rational_reconstruct(ZpZx(x)^10,4,5)


sage: num/den
(1073741779*x^3 + 105*x)/(x^4 + 1073741744*x^2 + 105)
puis de relever la solution trouve. La fonction suivante relve un lment a
de Z/pZ en un entier de valeur absolue au plus p/2.
sage: def lift_sym(a):
....: m = a.parent().defining_ideal().gen()
....: n = a.lift()
....: if n <= m // 2: return n
....: else: return n - m
On obtient :
sage: Qx(map(lift_sym, num))/Qx(map(lift_sym, den))
7.5. SRIES FORMELLES 151

(-10*x^3 + 105*x)/(x^4 - 45*x^2 + 105)


Lorsque les coefficients cherchs sont trop grands pour cette technique, on peut
faire le calcul modulo plusieurs premiers, et appliquer le thorme chinois afin
de retrouver une solution coefficients entiers, comme expliqu en 6.1.4. Une
autre possibilit est de calculer une relation de rcurrence coefficients constants
satisfaite par les coefficients de la srie. Ce calcul est presque quivalent celui
dun approximant de Pad (voir exercice 27), mais la fonction berlekamp_massey
de Sage permet de le faire sur un corps quelconque.
Systmatisons un peu le calcul prcdent, en crivant une fonction qui cal-
cule directement lapproximant coefficients rationnels, sous des hypothses
suffisamment favorables :
sage: def mypade(pol, n, k):
....: x = ZpZx.gen();
....: n,d = ZpZx(pol).rational_reconstruct(x^n, k-1, n-k)
....: return Qx(map(lift_sym, n))/Qx(map(lift_sym, d))
Il ny a plus alors qu appeler plot sur les rsultats de cette fonction (convertis
en lments de SR, car plot ne permet pas de tracer directement le graphe dune
fraction rationnelle algbrique ) pour obtenir le graphique de la figure 7.1 :
sage: add(
....: plot(expr, -2*pi, 2*pi, ymin=-3, ymax=3,
....: linestyle=sty, detect_poles=True, aspect_ratio=1)
....: for (expr, sty) in [
....: (tan(x), '-'),
....: (SR(mypade(s, 4, 2)), ':' ),
....: (SR(mypade(s, 8, 4)), '-.'),
....: (SR(mypade(s, 12, 6)), '--') ])
Les exercices suivants prsentent deux autres applications classiques de la
reconstruction rationnelle.
Exercice 27. 1. Montrer que si (un )nN
P satisfait une rcurrence linaire co-
n
efficients constants, la srie formelle nN
u n z est une fraction rationnelle.
Comment sinterprtent le numrateur et le dnominateur ?
2. Deviner les termes suivants de la suite

1, 1, 2, 3, 8, 11, 34, 39, 148, 127, 662, 339, 3056, 371, 14602, 4257, . . . ,

en utilisant rational_reconstruct. Retrouver le rsultat laide de la fonction


berlekamp_massey.
Exercice 28 (Interpolation de Cauchy). Trouver une fraction rationnelle r = p/q
F17 (x) telle que r(0) = 1, r(1) = 0, r(2) = 7, r(3) = 5, avec p de degr minimal.

7.5 Sries formelles


Une srie formelle est une srie entire vue comme une simple suite de coeffi-
cients, sans considration de convergence. Plus prcisment, si A est un anneau
152 CHAP. 7. POLYNMES

commutatif, on appelle sries formelles (en anglais formal


P power series) dind-
termine x coefficients dans A les sommes formelles n=0 an xn o (an ) est
une suite quelconque dlments de A. Munies des oprations daddition et de
multiplication naturelles

X
X
X
an xn + bn x n = (an + bn )xn ,
n=0 n=0 n=0

X
 X   X
X 
an xn bn xn = ai bj xn ,
n=0 n=0 n=0 i+j=n

les sries formelles forment un anneau not A[[x]].


Dans un systme de calcul formel, ces sries sont utiles pour reprsenter
des fonctions analytiques dont on na pas dcriture exacte. Comme toujours,
lordinateur fait les calculs, mais cest lutilisateur de leur donner un sens
mathmatique. lui par exemple de sassurer que les sries quil manipule sont
convergentes.
Les sries formelles interviennent aussi abondamment en combinatoire, en
tant que sries gnratrices. Nous verrons un exemple de ce type en 15.1.2.

7.5.1 Oprations sur les sries tronques


Lanneau de sries formelles Q[[x]] sobtient par
sage: R.<x> = PowerSeriesRing(QQ)
ou en abrg R.<x> = QQ[[]] 5 . Les lments de A[['x']] sont des sries tron-
ques, cest--dire des objets de la forme

f = f0 + f1 x + + fn1 xn1 + O(xn ).

Ils jouent le rle dapproximations des sries mathmatiques infinies, tout


comme les lments de RR reprsentent des approximations de rels. Lanneau
A[['x']] est donc un anneau inexact.
Chaque srie possde son propre ordre de troncature 6 , et la prcision 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 sries de prcision infinie, qui correspondent exactement aux poly-
nmes :

5. Ou partir de Q[x], par QQ['x'].completion('x').


6. Dun certain point de vue, cest la principale diffrence entre un polynme modulo xn et
une srie tronque lordre n : les oprations sur ces deux sortes dobjets sont analogues, mais
les lments de A[[x]]/hxn i ont, eux, tous la mme prcision .
7.5. SRIES FORMELLES 153

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

Une prcision par dfaut est utilise quand il est ncessaire de tronquer un
rsultat exact. Elle se rgle la cration de lanneau, ou ensuite par la mthode
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 entrane quil nest pas possible de tester lgalit mathmatique
de deux sries. Cest une diffrence conceptuelle importante entre celles-ci et les
autres classes dobjets vues dans ce chapitre. Sage considre donc deux lments
de A[['x']] comme gaux ds quils concident jusqu la plus faible de leurs
prcisions :

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 test O(x^2) == 0 renvoie vrai,
puisque la srie nulle a une prcision infinie.
Les oprations arithmtiques de base sur les sries fonctionnent comme sur les
polynmes. On dispose aussi de quelques fonctions usuelles, par exemple f.exp()
lorsque f (0) = 0, ainsi que des oprations de drivation et dintgration. Ainsi,
un dveloppement asymptotique quand x 0 de

1 Z x r 1 
exp dt
x2 0 1+t

est donn par

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, mme si seuls quatre termes apparaissent dans le rsultat, chaque opration
est effectue la prcision par dfaut 20, qui suffit largement pour obtenir un
reste final en O(x4 ). Pour obtenir plus de vingt termes, il faudrait augmenter la
prcision des calculs intermdiaires.
Cet exemple montre aussi que si f, g K[[x]] et g(0) = 0, le quotient f /g
renvoie un objet srie de Laurent formelle.
P Contrairement aux sries de Laurent
de lanalyse complexe, deP la forme n= an xn , les sries de Laurent formelles

sont des sommes du type n=N an xn , avec un nombre fini de termes dexposant
ngatif. Cette restriction est ncessaire pour donner un sens au produit de deux
sries formelles : sans celle-ci, chaque coefficient du produit sexprime comme une
somme de srie infinie.
154 CHAP. 7. POLYNMES

7.5.2 Dveloppement de solutions dquations


Face une quation diffrentielle dont les solutions exactes sont trop compli-
ques calculer ou exploiter une fois calcules, ou tout simplement qui nadmet
pas de solution en forme close, un recours frquent consiste chercher des solutions
sous forme de sries. On commence habituellement par dterminer les solutions
de lquation dans lespace des sries formelles, et si ncessaire, on conclut ensuite
par un argument de convergence que les solutions formelles construites ont un
sens analytique. Sage peut tre dune aide prcieuse pour la premire tape.
Considrons par exemple lquation diffrentielle
p
y 0 (x) = 1 + x2 y(x) + exp(x), y(0) = 1.

Cette quation admet une unique solution en srie 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 thorme de Cauchy dexistence de solutions dquations diffrentielles
linaires coefficients analytiques assure que cette srie converge pour |x| < 1 :
sa somme fournit donc une solution analytique sur le disque unit complexe.
Cette approche nest pas limite aux quations diffrentielles. Lquation
fonctionnelle exf (x) = f (x) est plus complique, ne serait-ce que parce quelle
nest pas linaire. Mais cest une quation de point fixe, nous pouvons essayer de
raffiner une solution (formelle) par itration :
sage: S.<x> = PowerSeriesRing(QQ, default_prec=5)
sage: f = S(1)
sage: for i in range(5):
....: f = (x*f).exp()
....: print f
1 + x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + O(x^5)
1 + x + 3/2*x^2 + 5/3*x^3 + 41/24*x^4 + O(x^5)
1 + x + 3/2*x^2 + 8/3*x^3 + 101/24*x^4 + O(x^5)
1 + x + 3/2*x^2 + 8/3*x^3 + 125/24*x^4 + O(x^5)
1 + x + 3/2*x^2 + 8/3*x^3 + 125/24*x^4 + O(x^5)

Que se passe-t-il ici ? Les solutions de exf (x) = f (x) dans Q[[x]] sont les points
fixes de la transformation : f 7 exf . Si une suite ditrs de la forme n (a)
converge,
Psa limite est ncessairement solution de lquation. Inversement, posons

f (x) = n=0 fn xn , et dveloppons en srie les deux membres : il vient
k
1
X X  X
fn xn = x fj xj
n=0
k! j=0
k=0
(7.2)
1
X  X X 
= fj1 fj2 . . . fjk xn .
k!
n=0 k=0 j1 ,...,jk N
j1 ++jk =nk
7.5. SRIES FORMELLES 155

Peu importent les dtails de la formule ; lessentiel est que fn se calcule en


fonction des coefficients prcdents f0 , . . . , fn1 , comme on le voit en identifiant
les coefficients des deux membres. Chaque itration de fournit donc un nouveau
terme correct.
Exercice 29. Calculer le dveloppement limit lordre 15 de tan x au voisinage
de zro partir de lquation diffrentielle tan0 = 1 + tan2 .

7.5.3 Sries paresseuses


Le phnomne de point fixe motive lintroduction dune autre sorte de s-
ries formelles appeles sries paresseuses (en anglais lazy). Ce ne sont pas des
sries tronques, mais bien des sries infinies ; ladjectif paresseux signifie que
les coefficients ne sont calculs que quand ils sont explicitement demands. En
contrepartie, on ne peut reprsenter que des sries dont on sait calculer les coeffi-
cients : essentiellement, des combinaisons de sries de base et certaines solutions
dquations pour lesquelles existent des relations comme (7.2). Par exemple, la
srie paresseuse lazy_exp dfinie par
sage: L.<x> = LazyPowerSeriesRing(QQ)
sage: lazy_exp = x.exponential(); lazy_exp
O(1)

est un objet qui contient dans sa reprsentation interne toutes les informations
ncessaires pour calculer le dveloppement en srie de exp x nimporte quel
ordre. Elle saffiche initialement comme O(1) car aucun coefficient na encore t
calcul. Tenter daccder au coefficient de x5 dclenche le calcul, et les coefficients
calculs sont alors mmoriss :
sage: lazy_exp[5]
1/120
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 lexemple de lquation exf (x) = f (x) pour voir comment il se traite
avec des sries paresseuses. Nous pouvons dabord essayer de reproduire le calcul
fait plus haut dans lanneau QQ[['x']] :
sage: f = L(1) # la srie 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)
156 CHAP. 7. POLYNMES

Les dveloppements obtenus sont bien sr les mmes que prcdemment 7 . Mais la
valeur de f chaque itration est maintenant une srie infinie, dont on peut calculer
des coefficients la demande. Toutes ces sries intermdiaires sont conserves
en mmoire. Le calcul de chacune dentre elles est automatiquement pouss la
prcision requise de manire fournir, par exemple, le coefficient de x7 dans le
dernier itr lorsque lon tente dy accder :
sage: f[7]
28673/630
Avec le code de la 7.5.2, laccs f[7] aurait provoqu une erreur, lindice 7
tant suprieur lordre de troncature de la srie f.
Cependant, la valeur renvoye par f[7] nest que le coefficient de x7 dans
litr 5 (1), et non dans la solution. La force des sries paresseuses est la
possibilit de passer directement la limite, en codant f elle-mme comme une
srie 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 itratif est la relation (7.2). En coulisses, Sage
dduit de la dfinition rcursive f.define((x*f).exponential()) une formule
du mme genre, qui permet de calculer les coefficients par rcurrence.

7.6 Reprsentation informatique des polynmes


Un mme objet mathmatique le polynme p, coefficients dans A peut
se coder sur ordinateur de faons trs diffrentes. Si le rsultat mathmatique dune
opration sur p est bien sr indpendant de la reprsentation, il en va autrement du
comportement des objets Sage correspondants. Le choix de la reprsentation influe
sur les oprations possibles, la forme exacte de leurs rsultats, et particulirement
lefficacit des calculs.

Reprsentation dense et reprsentation creuse. Il existe deux faons prin-


cipales
Pnde reprsenter les polynmes. En reprsentation dense, les coefficients de
p = i=0 pi xi sont stocks dans un tableau [p0 , . . . , pn ] index par les exposants.
Une reprsentation creuse ne stocke que les coefficients non nuls : le polynme
est cod par un ensemble de paires exposant-coefficient (i, pi ), regroupes dans
une liste, ou mieux, dans un dictionnaire index par les exposants (voir 3.3.9).
Pour des polynmes qui sont effectivement denses, cest--dire dont la plupart
des coefficients sont non nuls, la reprsentation dense occupe moins de mmoire et
7. On constate cependant que Sage emploie parfois des conventions incohrentes : la m-
thode qui sappelait exp pour les sries tronques sappelle ici exponential, et compute_
coefficients(5) calcule les coefficients jusqu lordre 5 inclus tandis que default_prec=5
donnait des sries tronques aprs le coefficient de x4 .
7.6. REPRSENTATION INFORMATIQUE DES POLYNMES 157

permet des calculs plus rapides. Elle conomise le stockage des exposants et des
structures de donnes internes du dictionnaire : ne reste que le strict ncessaire, les
coefficients. De plus, laccs un lment ou litration sur les lments sont plus
rapides dans un tableau que dans un dictionnaire. Inversement, la reprsentation
creuse permet de calculer efficacement sur des polynmes qui ne tiendraient mme
pas en mmoire en reprsentation dense :
sage: R = PolynomialRing(ZZ, 'x', sparse=True)
sage: p = R.cyclotomic_polynomial(2^50); p, p.derivative()
(x^562949953421312 + 1, 562949953421312*x^562949953421311)
Comme lillustre lexemple prcdent, la reprsentation est une caractristique
de lanneau de polynmes, que lon choisit sa construction. Le polynme dense
x Q[x] et le polynme creux x Q[x] nont donc pas le mme 8 parent. La
reprsentation par dfaut des polynmes une indtermine est dense. Loption
sparse=True de PolynomialRing sert construire un anneau de polynmes
creux.
Certains dtails de reprsentation varient de plus suivant la nature des co-
efficients des polynmes. Il en va de mme du code utilis pour effectuer les
oprations fondamentales. Sage offre en effet, outre une implmentation gnrique
des polynmes qui fonctionne sur tout anneau commutatif, plusieurs variantes
optimises pour un type particulier de coefficients. Celles-ci apportent quelques
fonctionnalits supplmentaires, et surtout sont considrablement plus efficaces
que la version gnrique. Elles sappuient pour cela sur des bibliothques externes
spcialises, par exemple flint ou ntl dans le cas de Z[x].
Pour mener bien de trs gros calculs, il est crucial de travailler autant que
possible dans des anneaux de polynmes disposant dimplmentations efficaces.
La page daide affiche par p? pour un polynme p indique quelle implmentation
il utilise. Le choix de limplmentation dcoule le plus souvent de ceux de lanneau
de base et de la reprsentation. Loption implementation de PolynomialRing
permet de prciser une implmentation quand plusieurs choix sont possibles.

Expressions symboliques. Les expressions symboliques dcrites dans les


chapitres 1 et 2 (cest--dire les lments de SR) fournissent une troisime repr-
sentation des polynmes. Elles constituent un choix naturel quand un calcul mle
polynmes et expressions plus complexes, comme cest souvent le cas en analyse.
Mais la souplesse de reprsentation quelles offrent est parfois utile mme dans un
10
contexte plus algbrique. Par exemple, le polynme (x + 1)10 , une fois dvelopp,
est dense, mais il nest pas ncessaire (ni souhaitable !) de le dvelopper pour le
driver ou lvaluer numriquement.
Attention cependant : contrairement aux polynmes algbriques, les polynmes
symboliques (de SR) ne sont pas rattachs un anneau de coefficients particulier
et ne sont pas manipuls sous forme canonique. Un mme polynme a un grand
nombre dcritures diffrentes, entre lesquelles cest lutilisateur dexpliciter
8. Pourtant, QQ['x'] == PolynomialRing(QQ, 'x', sparse=True) renvoie vrai : les deux
parents sont gaux, car ils reprsentent le mme objet mathmatique. Naturellement, le test
correspondant avec is renvoie faux.
158 CHAP. 7. POLYNMES

Un peu de thorie

Pour tirer le meilleur parti des oprations rapides sur les polynmes, il
est bon davoir une ide de leur complexit algorithmique. En voici un bref
aperu lintention du lecteur connaissant un peu dalgorithmique. Nous
nous limitons au cas des polynmes denses.
Additions, soustractions et autres manipulations directes des coefficients
se font facilement en temps linaire en les degrs des polynmes en jeu. Leur
rapidit en pratique dpend donc essentiellement de la possibilit daccder
rapidement aux coefficients, et donc de la structure de donnes.
Lopration cruciale est la multiplication. En effet, non seulement cest
une opration arithmtique de base, mais aussi dautres oprations utilisent
des algorithmes dont la complexit dpend essentiellement de celle de la
multiplication. Par exemple, on peut calculer la division euclidienne de deux
polynmes de degr au plus n pour le cot de O(1) multiplications, ou encore
leur pgcd pour celui de O(log n) multiplications.
Bonne nouvelle : on sait multiplier les polynmes en temps presque linaire.
Prcisment, la meilleure complexit connue sur un anneau quelconque est
de O(n log n log log n) oprations dans lanneau de base. Elle repose sur des
gnralisations du clbre algorithme de Schnhage-Strassen, qui atteint
la mme complexit pour la multiplication dentiers. En comparaison, la
mthode que lon utilise la main pour multiplier les polynmes demande
un nombre doprations de lordre de n2 .
Les algorithmes de multiplication rapide sont comptitifs en pratique
pour les polynmes de degr suffisamment grand, de mme que les mthodes
qui en drivent pour la division. Les bibliothques sur lesquelles sappuie
Sage pour certains types de coefficients font appel ce genre dalgorithmes
avancs : cest ainsi que Sage est capable de travailler efficacement avec des
polynmes de degr astronomique sur certains anneaux de coefficients.

les conversions ncessaires. Dans le mme ordre dides, le domaine SR regroupe


toutes les expressions symboliques, sans distinction entre les polynmes et les
autres, mais on peut tester explicitement si une expression symbolique f est
polynomiale en une variable x par f.is_polynomial(x).
Mathematics is the art of reducing any problem to linear
algebra.
William Stein

8
Algbre linaire

Ce chapitre traite de lalgbre linaire exacte et symbolique, cest--dire sur


des anneaux propres au calcul formel, tels que Z, des corps finis, des anneaux de
polynmes... Lalgbre linaire numrique est traite quant elle au chapitre 13.
Nous prsentons les constructions sur les matrices et leurs espaces ainsi que les
oprations de base (8.1), puis les diffrents calculs possibles sur ces matrices, re-
groups en deux thmes : ceux lis llimination de Gauss et aux transformations
par quivalence gauche (8.2.1 et 8.2.2), et ceux lis aux valeurs et espaces
propres et aux transformations de similitude (8.2.3). On peut trouver dans les
ouvrages de Gantmacher [Gan90], de von zur Gathen et Gerhard [vzGG03], de
Lombardi et Journadi [LA04] un traitement approfondi des notions abordes
dans ce chapitre.

8.1 Constructions et manipulations


lmentaires
8.1.1 Espaces de vecteurs, de matrices
De la mme faon que pour les polynmes, les vecteurs et les matrices sont
manipuls comme des objets algbriques appartenant un espace. Si les coefficients
appartiennent un corps K, cest un espace vectoriel sur K ; sils appartiennent
un anneau, cest un K-module libre.
On construit ainsi lespace M2,3 (Z) et lespace vectoriel (F32 )3 par
sage: MS = MatrixSpace(ZZ,2,3); MS
Full MatrixSpace of 2 by 3 dense matrices over Integer Ring
sage: VS = VectorSpace(GF(3^2,'x'),3); VS
160 CHAP. 8. ALGBRE LINAIRE

Espaces de matrices
construction MS = MatrixSpace(K, nrows, ncols)
construction (mat. creuses) MS = MatrixSpace(K, nrows, ncols, sparse = True)
anneau de base K MS.base_ring()
extension de lanneau MS.base_extend(B)
changement de lanneau MS.change_ring(B)
groupe engendr MatrixGroup([A,B])
base de lespace MS.basis() ou MS.gens()

Construction de matrices
matrice nulle MS() ou MS.zero() ou matrix(K,nrows,ncols)
matrice avec coefficients MS([1,2,3,4] ou matrix(K,2,2,[1,2,3,4]) ou
matrix(K,[[1,2],[3,4]])
matrice identit MS.one() ou MS.identity_matrix() ou
identity_matrix(K,n)
matrice alatoire MS.random_element() ou
random_matrix(K,nrows,ncols)
bloc de Jordan jordan_block(x,n)
matrice par blocs block_matrix([A,1,B,0]) ou block_diagonal_matrix

Manipulations de base
accs un coefficient A[2,3]
accs une ligne, colonne A[-1,:], A[:,2]
accs aux colonnes paires A[:,0:8:2]
sous-matrices A[3:4,2:5], A[:,2:5], A[:4,2:5]
A.matrix_from_rows([1,3]),
A.matrix_from_columns([2,5]),
A.matrix_from_rows_and_columns([1,3],[2,5])
A.submatrix(i,j,nrows,ncols)
concatnation par lignes A.stack(B)
concatnation par colonnes A.augment(B)

Tableau 8.1 Constructeurs de matrices et de leurs espaces.

Vector space of dimension 3 over Finite Field in x of size 3^2


Un systme gnrateur pour ces espaces est donn par la base canonique ; elle
peut tre obtenue indiffremment par les mthodes MS.gens() ou MS.basis().
sage: MatrixSpace(ZZ,2,3).basis()
1 0 0 , 0 1 0 , 0 0 1 , 0 0 0 , 0 0 0 , 0 0 0
h      i
0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1

Groupes de matrices. On pourra par ailleurs dfinir des sous-groupes de


lespace total des matrices. Ainsi le constructeur MatrixGroup([A,B,...]) ren-
voie le groupe engendr par les matrices passes en argument, qui doivent tre
inversibles.
sage: A = matrix(GF(11), 2, 2, [1,0,0,2])
sage: B = matrix(GF(11), 2, 2, [0,1,1,0])
sage: MG = MatrixGroup([A,B])
8.1. CONSTRUCTIONS ET MANIPULATIONS LMENTAIRES 161

sage: MG.cardinality()
200
sage: identity_matrix(GF(11),2) in MG
True
Le groupe gnral linaire de degr n sur un corps K, not GLn (K), est
le groupe form par les matrices n n inversibles de Mn,n (K). Il se construit
naturellement en Sage avec la commande GL(n,K). Le groupe spcial linaire
SLn (K) des lments de GLn (K) de dterminant 1 se construit avec la commande
SL(n,K).

8.1.2 Construction des matrices et des vecteurs


Les matrices et les vecteurs peuvent naturellement tre gnrs comme des
lments dun espace en fournissant la liste des coefficients en arguments. Pour
les matrices, ceux-ci seront lus par ligne :
sage: MS = MatrixSpace(ZZ,2,3); A = MS([1,2,3,4,5,6]); A
1 2 3
 
4 5 6
Le constructeur vide MS() renvoie une matrice nulle, tout comme la mthode
MS.zero(). Plusieurs constructeurs spcialiss permettent de produire les ma-
trices usuelles, comme random_matrix, identity_matrix, jordan_block (voir
tableau 8.1). En particulier on pourra construire des matrices et des vecteurs
avec les constructeurs matrix et vector, sans devoir construire lespace associ
pralablement. Par dfaut une matrice est construite sur lanneau des entiers Z
et a pour dimensions 0 0.
sage: a = matrix(); a.parent()
Full MatrixSpace of 0 by 0 dense matrices over Integer Ring
On peut naturellement spcifier un domaine pour les coefficients ainsi que
les dimensions, pour crer ainsi une matrice nulle, ou remplie dune liste de
coefficients passe en argument.
sage: a = matrix(GF(8,'x'),3,4); a.parent()
Full MatrixSpace of 3 by 4 dense matrices over Finite Field
in x of size 2^3
Le constructeur matrix accepte aussi comme argument des objets admettant
une transformation naturelle en matrice. Ainsi, il peut tre utilis pour obtenir la
matrice dadjacence dun graphe, sous la forme dune matrice coefficients dans
Z.
sage: g = graphs.PetersenGraph()
sage: m = matrix(g); m; m.parent()
[0 1 0 0 1 1 0 0 0 0]
[1 0 1 0 0 0 1 0 0 0]
[0 1 0 1 0 0 0 1 0 0]
[0 0 1 0 1 0 0 0 1 0]
162 CHAP. 8. ALGBRE LINAIRE

[1 0 0 1 0 0 0 0 0 1]
[1 0 0 0 0 0 0 1 1 0]
[0 1 0 0 0 0 0 0 1 1]
[0 0 1 0 0 1 0 0 0 1]
[0 0 0 1 0 1 1 0 0 0]
[0 0 0 0 1 0 1 1 0 0]
Full MatrixSpace of 10 by 10 dense matrices over Integer Ring

Matrices par blocs. Pour construire une matrice par blocs partir de sous-
matrices, on peut utiliser la fonction block_matrix.
sage: A = matrix([[1,2],[3,4]])
sage: block_matrix([[A,-A],[2*A, A^2]])
1 2 1 2

3 4 3 4
2 4 7 10

6 8 15 22
La structure est carre par blocs par dfaut mais le nombre de blocs ligne ou
colonne peut tre spcifi par les arguments optionnels ncols et nrows. Lorsque
cela est possible, un coefficient comme 0 ou 1 est interprt comme un bloc
diagonal (ici zro ou identit) de dimension approprie.
sage: A = matrix([[1,2,3],[4,5,6]])
sage: block_matrix([1,A,0,0,-A,2],
ncols=3)
1 0 1 2 3 0 0

0 1 4 5 6 0 0
0 0 1 2 3 2 0

0 0 4 5 6 0 2
Pour le cas particulier des matrices diagonales par blocs, on passe simplement
la liste des blocs diagonaux au constructeur block_diagonal_matrix.
sage: A = matrix([[1,2,3],[0,1,0]])
sage: block_diagonal_matrix(A, A.transpose())
1 2 3 0 0

0 1 0 0 0
0 0 0 1 0

0 0 0 2 1

0 0 0 3 0
La structure par blocs nest quune commodit daffichage, et Sage traite la
matrice comme toute autre matrice. On peut par ailleurs dsactiver cet affichage
en ajoutant largument subdivide=False au constructeur block_matrix.

8.1.3 Manipulations de base et arithmtique sur les


matrices
Indices et accs aux coefficients. Laccs aux coefficients ainsi qu des
sous-matrices extraites se fait de faon unifie par loprateur crochet A[i,j],
8.1. CONSTRUCTIONS ET MANIPULATIONS LMENTAIRES 163

selon les conventions usuelles de Python. Les indices de ligne i et de colonne j


peuvent tre des entiers (pour laccs des coefficients) ou des intervalles sous la
forme 1:3 (on rappelle que par convention, en Python les indices commencent
0, et les intervalles sont toujours inclusifs pour la borne infrieure et exclusifs
pour la borne suprieure). Lintervalle : sans bornes correspond la totalit
des indices possibles dans la dimension considre. La notation a:b:k permet
daccder aux indices compris entre a et b 1 par pas de k. Enfin, les indices
ngatifs sont aussi valides, et permettent de parcourir les indices partir de la
fin. Ainsi A[-2,:] correspond lavant dernire ligne. Laccs ces sous-matrices
se fait aussi bien en lecture quen criture. On peut par exemple modifier une
colonne donne de la faon suivante :
sage: A = matrix(3,3,range(9))
sage: A[:,1] = vector([1,1,1]); A
0 1 2

3 1 5
6 1 8

Lindice de pas k peut aussi tre ngatif, indiquant un parcours par valeurs
dcroissantes.
sage: A[::-1], A[:,::-1], A[::2,-1]
6 1 8 2 1 0

2
 
3 1 5 , 5 1 3 ,
8

0 1 2 8 1 6

Extraction de sous-matrices. Pour extraire une matrice partir dune


liste dindices de ligne ou de colonne non ncessairement contigus, on utilise les
mthodes A.matrix_from_rows, A.matrix_from_columns, ou dans le cas gnral
la mthode A.matrix_from_rows_and_columns.
sage: A = matrix(ZZ,4,4,range(16)); A
0 1 2 3

4 5 6 7
8 9 10 11

12 13 14 15

sage: A.matrix_from_rows_and_columns([0,2,3],[1,2])
1 2

9 10
13 14

Pour extraire une sous-matrice de lignes et de colonnes contigus, on pourra


aussi utiliser la mthode submatrix(i,j,m,n) formant la sous-matrice de dimen-
sion m n dont le coefficient suprieur gauche se trouve en position (i, j).
164 CHAP. 8. ALGBRE LINAIRE

Plongements et extensions. Lorsque lon veut plonger un espace de matrices


dans lespace des matrices de mme dimension mais coefficients dans une
extension de lanneau de base, on pourra utiliser la mthode base_extend de
lespace de matrice. Cette opration nest toutefois valide que pour les oprations
dextension de corps ou danneau. Pour effectuer le changement de lanneau
de base suivant un morphisme (lorsquil existe), on utilise plutt la mthode
change_ring.
sage: MS = MatrixSpace(GF(3),2,3)
sage: MS.base_extend(GF(9,'x'))
Full MatrixSpace of 2 by 3 dense matrices over Finite Field
in x of size 3^2
sage: MS = MatrixSpace(ZZ,2,3)
sage: MS.change_ring(GF(3))
Full MatrixSpace of 2 by 3 dense matrices over Finite Field of size 3

Mutabilit et mise en cache. Les objets reprsentant les matrices sont par
dfaut mutables, cest--dire que lon peut librement en modifier leurs membres
(ici leurs coefficients) aprs leur construction. Si on souhaite protger la matrice
contre les modifications, on utilise la fonction A.set_immutable(). Il est alors
toujours possible den tirer des copies mutables par la fonction copy(A). noter
que le mcanisme de mise en cache des rsultats calculs (tels que le rang, le
dterminant...) reste toujours fonctionnel, quel que soit ltat de mutabilit.

8.1.4 Oprations de base sur les matrices


Les oprations arithmtiques sur les matrices se font avec les oprateurs usuels
+,-,*,^. Linverse dune matrice A peut scrire aussi bien A^-1 que ~A. Lorsque
a est un scalaire et A une matrice, lopration a*A correspond la multiplication
externe de lespace de matrices. Pour les autres oprations o un scalaire a
est fourni en lieu et place dune matrice (par exemple lopration a+A), il est
considr comme la matrice scalaire correspondante aIn si a 6= 0 et les dimensions
le permettent. Le produit lment par lment de deux matrices seffectue avec
lopration elementwise_product.

8.2 Calculs sur les matrices


En algbre linaire, les matrices peuvent tre utilises pour reprsenter aussi
bien des familles de vecteurs, des systmes dquations linaires, des applications
linaires ou des sous-espaces. Ainsi, le calcul dune proprit comme le rang dune
famille, la solution dun systme, les espaces propres dune application linaire, ou
la dimension dun sous-espace se ramnent des transformations sur ces matrices
rvlant cette proprit.
Ces transformations correspondent des changements de base, vus au niveau
matriciel comme des transformations dquivalence : B = P AQ1 , o P et Q sont
des matrices inversibles. Deux matrices sont dites quivalentes sil existe une telle
8.2. CALCULS SUR LES MATRICES 165

Oprations de base
transpose, conjugue A.tranpose(), A.conjugate()
produit externe a*A
somme, produit, puissance k-ime, inverse A + B, A * B, A^k, A^-1 ou ~A

Tableau 8.2 Oprations de base et arithmtique sur les matrices.

transformation pour passer de lune lautre. On peut ainsi former des classes
dquivalence pour cette relation, et lon dfinit des formes normales, permettant
de caractriser de manire unique chaque classe dquivalence. Dans ce qui suit,
nous prsentons lessentiel des calculs sur les matrices disponibles avec Sage, sous
langle de deux cas particuliers de ces transformations :
Les transformations dquivalence gauche, de la forme B = U A, qui
rvlent les proprits caractristiques pour les familles de vecteurs, telles
que le rang (nombre de vecteurs linairement indpendants), le dterminant
(volume du paralllpipde dcrit par la famille de vecteurs), le profil de rang
(premier sous-ensemble de vecteurs formant une base), . . . Llimination de
Gauss est loutil central pour ces transformations, et la forme chelonne
rduite (forme de Gauss-Jordan dans un corps ou forme de Hermite dans Z)
est la forme normale. En outre, ces transformations servent la rsolution
des systmes linaires.
Les transformations de similitude, de la forme B = U AU 1 , qui rvlent les
proprits caractristiques des matrices reprsentant des endomorphismes,
comme les valeurs propres, les espaces propres, les polynmes minimal et
caractristique, . . . La forme de Jordan ou la forme de Frobenius, selon les
domaines de calcul, seront les formes normales pour ces transformations.
La forme de Gram-Schmidt est une autre dcomposition base sur les transfor-
mations dquivalence gauche, transformant une matrice en un ensemble de
vecteurs orthogonaux.

8.2.1 limination de Gauss, forme chelonne


limination de Gauss et quivalence gauche. Llimination de Gauss est
lune des oprations fondamentales en algbre linaire car elle permet daccder
une reprsentation de la matrice la fois plus adapte au calcul, comme la
rsolution de systmes, et rvlant certaines de ses proprits fondamentales,
comme le rang, le dterminant, le profil de rang, etc. Les oprations de base pour
llimination sont les oprations lmentaires sur les lignes :
permutation de deux lignes : Li Lj ,
ajout dun multiple dune ligne une autre : Li Li + sLj .
Au niveau matriciel, ces transformations correspondent la multiplication
gauche respectivement par les matrices de transposition Ti,j et par les matrices
166 CHAP. 8. ALGBRE LINAIRE

limination de Gauss et applications


transvection sur les lignes add_multiple_of_row(i,j,s)
transvection sur les colonnes add_multiple_of_column(i,j,s)
transposition de lignes, colonnes swap_rows(i1,i2), swap_columns(j1,j2)
forme de Gauss-Jordan, immuable echelon_form
forme de Gauss-Jordan en place echelonize
facteurs invariants elementary_divisors
forme normale de Smith smith_form
dterminant, rang det, rank
mineurs dordre k minors(k)
profil de rang en colonne, en ligne pivots, pivot_rows
rsolution de systme gauche (t x A = b) b/A ou A.solve_left(b)
rsolution de systme droite (Ax = b) A\b ou A.solve_right(b)
espace image image
noyau gauche kernel ou left_kernel
noyau droite right_kernel
noyau dans lanneau de base integer_kernel

Dcomposition spectrale
polynme minimal minimal_polynomial ou minpoly
polynme caractristique characteristic_polynomial ou charpoly
itrs de Krylov gauche maxspin(v)
valeurs propres eigenvalues
vecteurs propres gauche, droite eigenvectors_left, eigenvectors_right
espaces propres gauche, droite eigenspaces_left, eigenspaces_right
diagonalisation eigenmatrix_left, eigenmatrix_right
bloc de Jordan Ja,k jordan_block(a,k)

Tableau 8.3 Calculs sur les matrices.

de transvection Ci,j,s , donnes par :

i j
1

1

.. ..

.



.


0 1
1 s i
Ti,j = , Ci,j,s = .

.. ..
.
.
1

1 0
j
..
.. .
.
1

Ces matrices ont toutes pour dterminant 1 ou 1. Ainsi toute multiplica-


tion gauche par un produit de ces matrices peut tre vue comme un chan-
gement de base prservant les volumes et donc en particulier le dterminant
(au signe prs). En Sage, lopration de transvection est effectue par la m-
thode add_multiple_of_row(i,j,s), et celle de transposition par la mthode
swap_rows(i,j).
8.2. CALCULS SUR LES MATRICES 167



x1
tant donn un vecteur colonne x = ... dont la k-ime composante xk

xm
est inversible, on dfinit la transformation de Gauss comme la composition des
transvections Ci,k,`i pour i = k + 1 . . . m, avec `i = xxki (peu importe lordre
tant donn quelles commutent). La matrice correspondante est la suivante :
1
..
.
1

k
.

Gx,k = Ck+1,k,`k+1 Cm,k,`m = `k+1 . .

.
..

.

`k+2
.. ..

. .

`m 1

Une transformation de Gauss Gx,k a pour effet dliminer les coefficients du


vecteur situs sous le coefficient pivot xk :

x1 x1
.. ..
. .

xk xk
Gx,k = .
xk+1 0


. .
.. ..
xm 0

Pour une matrice A = [ai,j ] de dimension m n, lalgorithme du pivot de Gauss


procde alors itrativement, de la colonne gauche la colonne droite. En supposant
que les k 1 premires colonnes ont dj t traites, fournissant p 6 k 1 pivots,
la k-ime est alors traite de la faon suivante :
trouver la premire composante inversible ai,k de la colonne Ck sur une
ligne i > p. On lappelle le pivot.
Si aucun pivot nest trouv, passer la colonne suivante.
Appliquer la transposition Ti,p+1 sur les lignes pour placer le pivot en
position (p + 1, k).
Appliquer la transformation de Gauss Gx,p+1 , x tant la nouvelle colonne
Ck .
Cet algorithme transforme la matrice A en une matrice triangulaire suprieure.
Plus prcisment elle aura une forme chelonne, cest--dire telle que le premier
coefficient non nul de chaque ligne se trouve plus droite que celui de la ligne
prcdente ; de plus, toutes les lignes nulles se trouvent regroupes en bas de la
matrice. Voici un exemple de droulement de cet algorithme.
sage: a = matrix(GF(7),4,3,[6,2,2,5,4,4,6,4,5,5,1,3]); a
168 CHAP. 8. ALGBRE LINAIRE

6 2 2

5 4 4
6 4 5

5 1 3

sage: u = copy(identity_matrix(GF(7),4)); u[1:,0] = -a[1:,0]/a[0,0]


sage: u, u*a
1 0 0 0 6 2 2

5 1 0 0 0 0 0
6 0 1 0 , 0 2 3

5 0 0 1 0 4 6

sage: v = copy(identity_matrix(GF(7),4)); v.swap_rows(1,2)


sage: b = v*u*a; v, b
1 0 0 0 6 2 2

0 0 1 0 , 0 2 3

0 1 0 0 0 0 0

0 0 0 1 0 4 6

sage: w = copy(identity_matrix(GF(7),4))
sage: w[2:,1] = -b[2:,1]/b[1,1]; w, w*b
1 0 0 0 6 2 2

0 1 0 0 0 2 3
0 0 1 0 , 0 0 0

0 5 0 1 0 0 0

limination de Gauss-Jordan. La transformation de Gauss-Jordan est si-


milaire celle de Gauss, en ajoutant Gx,k les transvections correspondant aux
lignes dindice i < k ; cela revient liminer les coefficients dune colonne au-dessus
et au-dessous du pivot. Si de plus on divise chaque ligne par son pivot, on obtient
alors une forme chelonne dite rduite encore appele forme de Gauss-Jordan.
Pour toute classe dquivalence de matrices, il existe une unique matrice sous
cette forme ; il sagit donc dune forme normale.
Dfinition. Une matrice est dite sous forme chelonne rduite si :
toutes les lignes nulles sont en bas de la matrice,
le coefficient non nul le plus gauche de chaque ligne non nulle, appel le
pivot, est un 1, et est situ droite du pivot de la ligne prcdente,
les pivots sont les seuls coefficients non nuls au sein de leur colonne.
Thorme. Pour toute matrice A de dimension m n coefficients dans un
corps, il existe une unique matrice R de dimension m n sous forme chelonne
rduite et une matrice inversible U de dimension m m telles que U A = R. Il
sagit de la dcomposition de Gauss-Jordan.
8.2. CALCULS SUR LES MATRICES 169

En Sage, la forme chelonne rduite est donne par les mthodes echelonize
et echelon_form. La premire remplace la matrice initiale par sa forme chelonne
rduite alors que la deuxime renvoie une matrice immuable sans modifier la
matrice initiale.
sage: A = matrix(GF(7),4,5,[4,4,0,2,4,5,1,6,5,4,1,1,0,1,0,5,1,6,6,2])
sage: A, A.echelon_form()
4 4 0 2 4 1 0 5 0 3

5 1 6 5 4 0 1 2 0 6
1 1 0 1 0 , 0 0 0 1 5

5 1 6 6 2 0 0 0 0 0
Plusieurs variantes de llimination de Gauss sinterprtent sous la forme de
diffrentes dcompositions matricielles, parfois utiles pour le calcul : les dcom-
positions A = LU pour les matrices gnriques, A = LU P pour les matrices
rgulires, A = LSP , A = LQU P ou A = P LU Q pour les matrices de rang quel-
conque. Les matrices L sont triangulaires infrieures (valeurs nulles au-dessus de
la diagonale principale, en anglais Lower triangular), U triangulaires suprieures
(Upper triangular), et les matrices P, Q sont des permutations. Si ces variantes
sont algorithmiquement moins coteuses que la forme chelonne rduite, elles
noffrent pas lavantage de fournir une forme normale.

Forme chelonne dans les anneaux euclidiens. Dans un anneau euclidien,


les coefficients non nuls ne sont pas ncessairement inversibles, et llimination
de Gauss consisterait donc choisir le premier lment inversible de la colonne
courante pour pivot. Ainsi certaines colonnes non nulles peuvent ne pas contenir
de pivot et llimination nest alors plus possible.
Il est cependant toujours possible de dfinir une transformation unimodu-
laire liminant le coefficient de tte dune ligne avec celui dune autre, grce
lalgorithme dEuclide
  tendu.
a
Soit A = et soit g = pgcd(a, b). Soient u et v les coefficients de Bzout
b
fournis par lalgorithme dEuclide tendu appliqu a et b (tels que g = ua + vb),
et s = b/g, t = a/g tels que
    
u v a g
= .
s t b 0
 
u v
Cette transformation est unimodulaire car det = 1.
s t
Par ailleurs, comme pour Gauss-Jordan, on peut toujours ajouter des multiples
de la ligne pivot aux lignes suprieures afin de rduire leurs coefficients dans la
mme colonne modulo le pivot g. Cette opration effectue itrativement sur
toutes les colonnes de la matrice produit la forme normale de Hermite.
Dfinition. Une matrice est dite sous forme de Hermite si
ses lignes nulles sont en bas,
170 CHAP. 8. ALGBRE LINAIRE

le coefficient non nul le plus gauche de chaque ligne, appel le pivot, se


trouve droite de celui de la ligne suprieure,
tous les coefficients au-dessus du pivot sont rduits modulo le pivot.
Thorme. Pour toute matrice A de dimension m n coefficients dans
un anneau euclidien, il existe une unique matrice H de dimension m n sous
forme de Hermite et une matrice U unimodulaire, de dimension m m, telles que
U A = H.
Dans le cas dun corps, la forme de Hermite correspond la forme chelonne
rduite, ou forme de Gauss-Jordan. En effet, dans ce cas, tous les pivots sont
inversibles, chaque ligne peut tre divise par son pivot, et les coefficients au-dessus
de celui-ci peuvent tre nouveau limins par des transformations de Gauss,
produisant ainsi une forme chelonne rduite. En Sage, il ny a donc quune
seule mthode : echelon_form, qui renvoie soit la forme de Hermite, soit la forme
chelonne rduite, selon que la matrice est coefficients dans un anneau ou dans
un corps.
Par exemple, pour une matrice coefficients dans Z, on obtient les deux
formes chelonnes diffrentes, selon que le domaine de base soit Z ou Q :
sage: a = matrix(ZZ, 4, 6, [2,1,2,2,2,-1,1,2,-1,2,1,-1,2,1,-1,\
....: -1,2,2,2,1,1,-1,-1,-1]); a.echelon_form()
1 2 0 5 4 1

0 3 0 2 6 7
0 0 1 3 3 0

0 0 0 6 9 3

sage: a.base_extend(QQ).echelon_form()
1 0 0 0 5 11

2 6
0 1 0 0 3 38
0 0 1 0 32 32

0 0 0 1 3
2
1
2
Pour les matrices sur Z, la forme normale de Hermite est aussi accessible
par la fonction hermite_form. Pour obtenir la matrice de passage U telle que
U A = H, on peut utiliser loption transformation=True.
sage: A = matrix(ZZ,4,5,[4,4,0,2,4,5,1,6,5,4,1,1,0,1,0,5,1,6,6,2])
sage: H, U = A.echelon_form(transformation=True); H, U
1 1 0 0 2 0 1 1 1

0 4 6 0 4 0 1 5 0
,
0 0 0 1 2 0 1 0 1


0 0 0 0 0 1 2 4 2

Facteurs invariants et forme normale de Smith. Si lon sautorise liminer


plus avant la forme de Hermite par des transformations unimodulaires droite (i.e.,
sur les colonnes), on peut alors obtenir une forme diagonale canonique, appele
forme normale de Smith. Ses coefficients diagonaux sont appels les facteurs
invariants (en anglais elementary divisors) de la matrice. Ils sont totalement
ordonns pour la divisibilit (i.e., si | si+1 ).
8.2. CALCULS SUR LES MATRICES 171

Thorme. Pour toute matrice A de dimension m n et coefficients dans


un anneau principal, il existe des matrices unimodulaires U et V de dimension
m m et n n et une unique matrice m n diagonale S telles que S = U AV .
Les coefficients si = Si,i pour i {1, . . . , min(m, n)} vrifient si | si+1 et sont
appels les facteurs invariants de A.
En Sage, la mthode elementary_divisors renvoie la liste des facteurs in-
variants. On peut par ailleurs calculer la forme normale de Smith ainsi que les
matrices de passages U et V par la commande smith_form.
sage: A = matrix(ZZ, 4, 5,\
....: [-1,-1,-1,-2,-2,-2,1,1,-1,2,2,2,2,2,-1,2,2,2,2,2])
sage: S,U,V = A.smith_form(); S,U,V
0 2 1 5 0

1 0 0 0 0 1 0 0 0

1 0 1 1 1
0 1 0 0 0 0 0 1 0

0 0 3 0 0 , 2 1 , 0 0 0 0 1

0 0
1 2 0 5 0
0 0 0 6 0 0 0 2 1

0 1 0 2 0

sage: A.elementary_divisors()
[1, 1, 3, 6]
sage: S == U*A*V
True

Rang, profil de rang et pivots. Llimination de Gauss rvle de nombreux


invariants de la matrice, tels que son rang et son dterminant (qui peut tre lu
comme le produit des pivots). Ils sont accessibles par les fonctions det et rank.
Ces valeurs seront mises en cache, et ne seront donc pas recalcules lors dun
deuxime appel.
Plus gnralement, la notion de profil de rang est trs utile, lorsque lon
considre la matrice comme une squence de vecteurs.
Dfinition. Le profil de rang par colonne dune matrice m n A de rang r
est la squence de r indices lexicographiquement minimale, telle que les colonnes
correspondantes dans A sont linairement indpendantes.
Le profil de rang se lit directement sur la forme chelonne rduite, comme la
squence des indices des pivots. Il est calcul par la fonction pivots. Lorsque la
forme chelonne rduite a dj t calcule, le profil de rang est aussi mmoris
dans le cache, et peut tre obtenu sans calcul supplmentaire.
Le profil de rang par ligne se dfinit de manire similaire, en considrant la
matrice comme une squence de m vecteurs ligne. Il sobtient par la commande
pivot_rows ou comme sous-produit de la forme chelonne rduite de la matrice
transpose.
sage: B = matrix(GF(7),5,4,[4,5,1,5,4,1,1,1,0,6,0,6,2,5,1,6,4,4,0,2])
sage: B.transpose().echelon_form()
1 0 5 0 3

0 1 2 0 6
0 0 0 1 5

0 0 0 0 0
172 CHAP. 8. ALGBRE LINAIRE

sage: B.pivot_rows()
(0, 1, 3)
sage: B.transpose().pivots() == B.pivot_rows()
True

8.2.2 Rsolution de systmes ; image et base du noyau


Rsolution de systmes. Un systme linaire peut tre reprsent par une
matrice A et un vecteur b soit droite : Ax = b, soit gauche : t x A = b. Les
fonctions solve_right et solve_left effectuent leur rsolution. On peut aussi
utiliser de faon quivalente les oprateurs A\b et b/A. Lorsque le systme est donn
par une matrice coefficients dans un anneau, la rsolution est systmatiquement
effectue dans le corps des fractions de cet anneau (e.g., Q pour Z ou K(X) pour
K[X]). On verra plus loin comment la rsolution peut tre faite dans lanneau
lui-mme. Le membre de droite dans lgalit du systme peut tre aussi bien un
vecteur quune matrice (ce qui correspond rsoudre plusieurs systmes linaires
simultanment, avec la mme matrice).
Les matrices des systmes peuvent tre rectangulaires et les systmes peuvent
admettre une unique, aucune ou une infinit de solutions. Dans ce dernier cas, les
fonctions solve renvoient lune de ces solutions, en mettant zro les composantes
correspondant aux colonnes linairement dpendantes du systme.
sage: R.<x> = PolynomialRing(GF(5),'x')
sage: A = random_matrix(R,2,3); A
3x2 + x x2 + 2x 2x2 + 2
 

x2 + x + 2 2x2 + 4x + 3 x2 + 4x + 3

sage: b = random_matrix(R,2,1); b
4x2 + 1
 

3x2 + 2x

sage: A.solve_right(b)
3

4x +2x+4
3x3 +2x2 +2x
3x2 +4x+3


x3 +4x2 +4x
0

sage: A.solve_right(b) == A\b


True

Image et noyau. Interprte comme une application linaire , une matrice A


de dimension m n dfinit deux sous-espaces vectoriels de K m et K n , respecti-
vement limage et le noyau de .
Limage est lensemble des vecteurs de K m obtenus par combinaisons linaires
des colonnes de A. Il sobtient par la fonction image qui renvoie un espace vectoriel
dont la base est sous forme chelonne rduite.
8.2. CALCULS SUR LES MATRICES 173

Le noyau est le sous-espace vectoriel de K n des vecteurs x tels que Ax = 0.


Obtenir une base de ce sous-espace sert en particulier dcrire lensemble des
solutions dun systme linaire, lorsque celui-ci en possde une infinit : si x
est une solution de Ax = b et V le noyau de A, alors lensemble des solutions
scrit simplement x + V . Il sobtient par la fonction right_kernel qui renvoie
lespace vectoriel ainsi quune base mise sous forme chelonne rduite. On peut
naturellement aussi dfinir le noyau gauche (lensemble des x dans K m tels que
t
x A = 0), qui correspond au noyau droite de la transpose de A (i.e., ladjoint
de ). Il sobtient avec la fonction left_kernel. Par convention, la fonction
kernel renvoie le noyau gauche. De plus les bases sont donnes comme des
matrices de vecteurs lignes dans les deux cas.
sage: a = matrix(QQ,3,5,[2,2,-1,-2,-1,2,-1,1,2,-1/2,2,-2,-1,2,-1/2])
sage: a.image()
Vector space of degree 5 and dimension 3 over Rational Field
Basis matrix:
[ 1 0 0 1/4 -11/32]
[ 0 1 0 -1 -1/8]
[ 0 0 1 1/2 1/16]
sage: a.right_kernel()
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:
[ 1 0 0 -1/3 8/3]
[ 0 1 -1/2 11/12 2/3]
La notion de noyau se gnralise naturellement au cas o les coefficients ne
sont plus dans un corps ; il sagit alors dun module libre. En particulier, pour une
matrice dfinie dans un corps de fractions, on obtiendra le noyau dans lanneau
de base par la commande integer_kernel. Par exemple, pour une matrice
coefficients dans Z, plonge dans lespace vectoriel des matrices coefficients dans
Q, on pourra calculer aussi bien son noyau comme un sous-espace vectoriel de
Qm ou comme un module libre de Zm .
sage: a = matrix(ZZ,5,3,[1,1,122,-1,-2,1,-188,2,1,1,-10,1,-1,-1,-1])
sage: a.kernel()
Free module of degree 5 and rank 2 over Integer Ring
Echelon basis matrix:
[ 1 979 -11 -279 811]
[ 0 2079 -22 -569 1488]
sage: b = a.base_extend(QQ)
sage: b.kernel()
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:
[ 1 0 -121/189 -2090/189 6949/63]
[ 0 1 -2/189 -569/2079 496/693]
sage: b.integer_kernel()
Free module of degree 5 and rank 2 over Integer Ring
Echelon basis matrix:
174 CHAP. 8. ALGBRE LINAIRE

[ 1 979 -11 -279 811]


[ 0 2079 -22 -569 1488]

8.2.3 Valeurs propres, forme de Jordan et transformations


de similitude
Lorsque lon interprte une matrice carre comme un oprateur linaire (un
endomorphisme), elle nen est que la reprsentation dans une base donne. Tout
changement de base correspond une transformation de similitude B = U 1 AU
de la matrice. Les deux matrices A et B sont alors dites semblables. Ainsi les
proprits de loprateur linaire, qui sont indpendantes de la base, sont rvles
par ltude des invariants de similitude de la matrice.
Parmi ces invariants, les plus simples sont le rang et le dterminant. En effet
les matrices U et U 1 tant inversibles, le rang de U 1 AU gale le rang de A. De
plus det(U 1 AU ) = det(U 1 ) det(A) det(U ) = det(U 1 U ) det(A) = det(A). De
la mme faon, le polynme caractristique de la matrice A, dfini par A (x) =
det(xId A) est aussi invariant par transformation de similitude :

det(xId U 1 AU ) = det(U 1 (xId A)U ) = det(xId A).

Par consquent, les valeurs caractristiques dune matrice, dfinies comme les
racines du polynme caractristique dans son corps de dcomposition, sont donc
aussi des invariants de similitude. Par dfinition, un scalaire est une valeur
propre dune matrice A sil existe un vecteur non nul u tel que Au = u. Lespace
propre associ une valeur propre est lensemble des vecteurs u tels que Au = u.
Cest un sous-espace vectoriel dfini par E = Ker(Id A).
Les valeurs propres concident avec les valeurs caractristiques :

det(Id A) = 0 dim(Ker(Id A)) > 1 u 6= 0, u Au = 0.

Ces deux points de vue correspondent respectivement lapproche algbrique et


gomtrique des valeurs propres. Dans le point de vue gomtrique, on sintresse
laction de loprateur linaire A sur les vecteurs de lespace avec plus de prcision
que dans le point de vue algbrique. En particulier on distingue les notions de
multiplicit algbrique, correspondant lordre de la racine dans le polynme
caractristique, de la multiplicit gomtrique, correspondant la dimension du
sous-espace propre associ la valeur propre. Pour les matrices diagonalisables, ces
deux notions sont quivalentes. Dans le cas contraire, la multiplicit gomtrique
est toujours infrieure la multiplicit algbrique.
Le point de vue gomtrique permet de dcrire plus en dtail la structure de
la matrice. Par ailleurs, il donne des algorithmes beaucoup plus rapides pour le
calcul des valeurs et espaces propres, et des polynmes caractristique et minimal.

Espaces invariants cycliques, et forme normale de Frobenius. Soit A


une matrice n n sur un corps K et u un vecteur de K n . La famille de vecteurs
u, Au, A2 u, . . . , An u, appele suite de Krylov, est lie (comme famille de n + 1
8.2. CALCULS SUR LES MATRICES 175

vecteurs en dimension n). Soit d tel que Ad u soit le premier vecteur de la squence
linairement dpendant avec ses prdcesseurs u, Au, . . . , Ad1 u. On crira
d1
X
Ad u = i Ai u
i=0
Pd1
cette relation de dpendance linaire. Le polynme A,u (x) = xd i=0 i xi ,
qui vrifie A,u (A)u = 0 est donc un polynme unitaire annulateur de la suite de
Krylov et de degr minimal. On lappelle le polynme minimal du vecteur u (sous
entendu, relativement la matrice A). Lensemble des polynmes annulateurs de
u forme un idal de K[X], engendr par A,u .
Le polynme minimal de la matrice A est dfini comme le polynme unitaire
A (x) de plus petit degr annulant la matrice A : A (A) = 0. En particulier, en
appliquant A (A) au vecteur u, on constate que A est un polynme annulateur
de la suite de Krylov. Il est donc ncessairement un multiple du polynme minimal
de u. On peut en outre montrer (cf. exercice 30) quil existe un vecteur u tel que
A,u = A . (8.1)
Lorsque le vecteur u est choisi alatoirement, la probabilit quil satisfasse lqua-
tion (8.1) est dautant plus grande que la taille du corps est grande (on peut
montrer quelle est au moins de 1 |K|n
).
Exercice 30. Montrons quil existe toujours un vecteur u dont le polynme minimal
concide avec le polynme minimal de la matrice.
1. Soit (e1 , . . . , en ) une base de lespace vectoriel. Montrer que A concide avec le
ppcm des A,ei .
2. Dans le cas particulier o A est une puissance dun polynme irrductible,
montrer quil existe un indice i0 tel que A = A,ei0 .
3. Montrer que si les polynmes minimaux i = A,ei et j = A,ej des vecteurs ei
et ej sont premiers entre eux, alors A,ei +ej = i j .
4. Montrer que si A = P1 P2 o P1 et P2 sont premiers entre eux, alors il existe des
vecteurs x1 6= 0 et x2 6= 0 tels que Pi soit le polynme minimal de xi .
mk
5. Conclure en utilisant la factorisation en polynmes irrductibles A = m 1
1 . . . k .

0 0 3 0 0
1 0 6 0 0
6. Illustration : soit A = 0 1 5 0 0 une matrice dans GF(7). Calculer les

0 0 0 0 5
0 0 0 1 5
degrs du polynme minimal de A, et des polynmes minimaux des vecteurs de
la base canonique u = e1 et v = e4 , ainsi que de u + v. On peut se servir de
la fonction maxspin(u) applique la transpose de A, qui renvoie la squence
maximale des itrs de Krylov dun vecteur u.
Pk1
Soit P = xk + i=0 i xi un polynme unitaire de degr k. La matrice
compagnon associe au polynme P est la matrice k k dfinie par
0

0
1 1
CP = .. .. .

. .
1 k1
176 CHAP. 8. ALGBRE LINAIRE

Cette matrice a la proprit davoir P pour polynme minimal et caractris-


tique. Elle joue ainsi un grand rle dans le calcul des polynmes minimal et
caractristique.
Proposition. Soit Ku la matrice forme par les d premiers itrs de Krylov
dun vecteur u. Alors
AKu = Ku CA,u
Ainsi, lorsque d = n, la matrice Ku est carre dordre n et inversible. Elle
dfinit une transformation de similitude Ku1 AKu = CA,u rduisant la matrice
A une matrice compagnon. Or cette transformation prserve le dterminant, et
donc le polynme caractristique ; on pourra ainsi lire directement les coefficients
du polynme minimal et caractristique (ici identiques) sur la matrice compagnon.

sage: A = matrix(GF(97), 4, 4,\


....: [86,1,6,68,34,24,8,35,15,36,68,42,27,1,78,26])
sage: e1 = identity_matrix(GF(97),4)[0]
sage: U = matrix(A.transpose().maxspin(e1)).transpose()
sage: F = U^-1*A*U; F
0 0 0 83

1 0 0 77
0 1 0 20

0 0 1 10

sage: K.<x> = GF(97)[]


sage: P = x^4-sum(F[i,3]*x^i for i in range(4)); P
x4 + 87x3 + 77x2 + 20x + 14

sage: P == A.charpoly()
True

Dans le cas gnral (d 6 n) les vecteurs itrs u, . . . , Ad1 u forment une base
dun sous-espace I invariant sous laction de la matrice A (i.e., tel que AI I).
Comme chacun de ces vecteurs est obtenu cycliquement en appliquant la matrice
A au vecteur prcdent, on lappelle aussi sous-espace cyclique. La dimension
maximale dun tel sous-espace est le degr du polynme minimal de la matrice.
Il est engendr par les itrs de Krylov du vecteur construit dans lexercice 30,
quon notera u1 . On lappelle le premier sous-espace invariant. Ce premier espace
invariant admet un espace supplmentaire V . En calculant modulo le premier
espace invariant, cest--dire en considrant que deux vecteurs sont gaux si leur
diffrence appartient au premier sous-espace invariant, on peut dfinir un second
sous-espace invariant pour les vecteurs dans cet espace supplmentaire ainsi quun
polynme minimal qui est appel le second invariant de similitude. On obtiendra
alors une relation de la forme :
 
 C1
A Ku1 Ku2 = Ku1 Ku2
  
,
C2
8.2. CALCULS SUR LES MATRICES 177

o 1 , 2 sont les deux premiers invariants de similitude, et Ku1 , Ku2 sont les
matrices de Krylov correspondant aux deux espaces cycliques engendrs par les
vecteurs u1 et u2 .
Itrativement, on construit une matrice K = Ku1 . . . Kuk carre, inver-
 

sible, telle que


C1
K 1 AK = .. (8.2)
. .

Ck

Comme chaque ui est annul par les j pour j 6 i on en dduit que i | i1


pour tout 2 6 i 6 k, autrement dit, la suite des i est totalement ordonne
pour la division. On peut montrer que pour toute matrice, il existe une unique
squence de polynmes invariants 1 , . . . , k . Ainsi la matrice diagonale par blocs
Diag(C1 , . . . , Ck ), semblable la matrice A et rvlant ces polynmes, est
une forme normale, appele forme rationnelle canonique, ou forme normale de
Frobenius.
Thorme (Forme normale de Frobenius).Toute matrice carre
A dans un
C1
corps est semblable une unique matrice F = .. , avec i+1 | i
.

Ck
pour tout i < k.
Daprs lquation (8.2), il apparat quon peut lire les bases des sous-espaces
invariants sur la matrice de passage K.
Remarque. Le thorme de Cayley-Hamilton nonce que le polynme ca-
ractristique annule sa matrice : A (A) = 0. Il se montre simplement, aprs
lintroduction de cette forme normale de Frobenius. En effet,

A (x) = det(xId A) = det(K) det(xId F ) det(K 1 )


k
Y k
Y
= det(xId Ci ) = i (x).
i=1 i=1

Ainsi, le polynme minimal 1 est un diviseur du polynme caractristique, qui


est donc annulateur de la matrice A.
En Sage, on pourra calculer la forme normale de Frobenius dans Q de matrices
coefficients dans Z avec la mthode frobenius 1 :
sage: A = matrix(ZZ,8,[[6,0,-2,4,0,0,0,-2],[14,-1,0,6,0,-1,-1,1],\
....: [2,2,0,1,0,0,1,0],[-12,0,5,-8,0,0,0,4],\
....: [0,4,0,0,0,0,4,0],[0,0,0,0,1,0,0,0],\
....: [-14,2,0,-6,0,2,2,-1],[-4,0,2,-4,0,0,0,4]])
sage: A.frobenius()

1. Cest une lgre aberration de linterface actuelle du logiciel : alors que la forme de
Frobenius est dfinie pour toute matrice dans un corps, Sage ne permet de la calculer que pour
les matrices coefficients dans Z, en effectuant implicitement le plongement dans Q.
178 CHAP. 8. ALGBRE LINAIRE

0 0 0 4 0 0 0 0

1 0 0 4 0 0 0 0
0 1 0 1 0 0 0 0


0 0 1 0 0 0 0 0


0 0 0 0 0 0 4 0


0 0 0 0 1 0 0 0


0 0 0 0 0 1 1 0


0 0 0 0 0 0 0 2
On peut obtenir par ailleurs la liste de polynmes invariants en passant 1
en argument. Pour obtenir linformation sur les espaces invariants associs, on
passe largument 2 qui produira la matrice de passage K. Elle fournit une base
de lespace total, dcompose en la somme directe des espaces invariants.
sage: A.frobenius(1)
x x2 4x 4, x3 x2 4, x 2
 4 

sage: F,K = A.frobenius(2)


sage: K
1 12

1 15 3 7
16 64 128 64 23
64
43
128
0 0 64 128 256
5 13 15 17 7
128 53

128 256
0 0 9 11 7 1 5 5

128 128 128 32 128 32


0 0 128
5
0 7 7
128 1
64 9
256 256
0 1 1 5 17
64 1
32 31
21

16 32 32 64


0 0 1 5 31
17 1
64 21
128
32 64 128 64
0 0 1 5 1
128 15 1
64 21
128

32 64 64
0 0 1 5
2 14 12 12 21
4

sage: K^-1*F*K == A
True
Ces rsultats sous-entendent que la matrice A coefficients dans Z a t
plonge dans son corps de fractions Q. Pour tudier laction de la matrice A sur
le module libre Zn , et la dcomposition du module quelle engendre, on utilise la
fonction decomposition ; cependant son tude dpasse le cadre de cet ouvrage.

Facteurs invariants et invariants de similitude. Une proprit importante


relie les invariants de similitude et les facteurs invariants vus dans la section 8.2.1.
Thorme. Les invariants de similitude dune matrice A coefficients dans
un corps correspondent aux facteurs invariants de sa matrice caractristique
xId A.
La preuve de ce rsultat dpasse le cadre de cet ouvrage et nous nous contentons
de lillustrer sur lexemple prcdent.
sage: S.<x> = QQ[]
sage: B = x*identity_matrix(8) - A
8.2. CALCULS SUR LES MATRICES 179

sage: B.elementary_divisors()
1, 1, 1, 1, 1, x 2, x3 x2 4, x4 x2 4x 4
 

sage: A.frobenius(1)
x x2 4x 4, x3 x2 4, x 2
 4 

Valeurs propres, vecteurs propres. Si lon dcompose le polynme minimal


en facteurs irrductibles, 1 = 1m1 . . . sms , alors tous les facteurs invariants
m m
scrivent sous la forme i = 1 i,1 . . . s i,s , avec des multiplicits mi,j 6 mj .
On montre que lon peut alors trouver une transformation de similitude qui
change chaque bloc compagnon Ci de la forme de Frobenius en un bloc diagonal
Diag(Cmi,1 , . . . , Cmi,s ). Cette variante de la forme de Frobenius, que lon appelle
1 s
forme intermdiaire, est toujours forme de blocs compagnons, mais cette fois
correspondant chacun une puissance dun polynme irrductible.

Cm1,1
1
..

.

Csm1,s



C m2,1
1

F = .. (8.3)

.



..

.

Cmk,1


1
..

.

Lorsquun facteur irrductible i est de degr 1 et de multiplicit 1, son bloc


compagnon est une matrice 1 1 sur la diagonale et correspond ainsi une valeur
propre. Lorsque le polynme minimal est scind et sans carr, la matrice est donc
diagonalisable.
On obtiendra les valeurs propres par la mthode eigenvalues. La liste des
vecteurs propres droite (respectivement gauche) associs leur valeur propre et
sa multiplicit est donne par la mthode eigenvectors_right (respectivement
eigenvectors_left). Enfin les espaces propres, ainsi que leur base de vecteurs
propres, sont fournis par les mthodes eigenspaces_right et eigenspaces_left.
sage: A = matrix(GF(7),4,[5,5,4,3,0,3,3,4,0,1,5,4,6,0,6,3])
sage: A.eigenvalues()
[4, 1, 2, 2]
sage: A.eigenvectors_right()
[(4, [
(1, 5, 5, 1)
], 1), (1, [
(0, 1, 1, 4)
], 1), (2, [
(1, 3, 0, 1),
180 CHAP. 8. ALGBRE LINAIRE

(0, 0, 1, 1)
], 2)]
sage: A.eigenspaces_right()
[
(4, Vector space of degree 4 and dimension 1 over Finite Field
of size 7
User basis matrix:
[1 5 5 1]),
(1, Vector space of degree 4 and dimension 1 over Finite Field
of size 7
User basis matrix:
[0 1 1 4]),
(2, Vector space of degree 4 and dimension 2 over Finite Field
of size 7
User basis matrix:
[1 3 0 1]
[0 0 1 1])
]
De faon plus concise, la mthode eigenmatrix_right renvoie le couple form
par la matrice diagonalise et la matrice de ses vecteurs propres droite. (La
mthode eigenmatrix_left fait de mme avec les vecteurs propres gauche.)
sage: A.eigenmatrix_right()
4 0 0 0 1 0 1 0

0 1 0 0 5 1 3 0
0 0 2 0 , 5 1 0 1


0 0 0 2 1 4 1 1

Forme de Jordan. Lorsque le polynme minimal est scind mais ayant des
facteurs avec des multiplicits suprieures 1, la forme intermdiaire (8.3) nest
pas diagonale. On montre alors quil nexiste pas de transformation de similitude
la rendant diagonale, la matrice initiale nest donc pas diagonalisable. On peut
en revanche la trigonaliser, cest--dire la rendre triangulaire suprieure, telle que
les valeurs propres apparaissent sur la diagonale. Parmi les diffrentes matrices
triangulaires possibles, la plus rduite de toutes est la forme normale de Jordan.
Un bloc de Jordan J,k , associ la valeur propre et lordre k, est la matrice
J,k de dimensions k k donne par

1

.. .
. ..

J,k = .

1

Cette matrice joue un rle similaire celui des blocs compagnons, en rvlant
plus prcisment la multiplicit dune valeur propre. En effet, son polynme
caractristique vaut J,k = (X )k . De plus son polynme minimal vaut aussi
8.2. CALCULS SUR LES MATRICES 181

J,k = (X )k , en effet, il est ncessairement un multiple de P = X . Or la


matrice
0 1

.. ..
. .

P (J,k ) =

0 1


0
est nilpotente dordre k, do J,k = J,k = (X )k . La forme normale de
Jordan correspond la forme intermdiaire (8.3), o les blocs compagnons des
m
j i,j ont t remplacs par les blocs de Jordan Jj ,mi,j (on rappelle que, le
polynme minimal tant scind, les j scrivent sous la forme X j ).
Ainsi lorsque son polynme minimal est scind, toute matrice est semblable
une matrice de Jordan de la forme

J1 ,m1,1
..
.




Js ,m1,s


J1 ,m2,1

J =
.. .

(8.4)
.
..

.



J1 ,mk,1
..

.

En particulier, dans tout corps algbriquement clos, comme C, la forme de


Jordan dune matrice est toujours dfinie.
En Sage, le constructeur jordan_block(a,k) produit le bloc de Jordan Ja,k .
On obtiendra la forme normale de Jordan par la mthode jordan_form. Loption
transformation=True permet dobtenir la matrice de transformation U telle que
U 1 AU est sous forme de Jordan.
sage: A = matrix(ZZ,4,[3,-1,0,-1,0,2,0,-1,1,-1,2,0,1,-1,-1,3])
sage: A.jordan_form()
3 0 0 0

0 3 0 0
0 0 2 1

0 0 0 2

sage: J,U = A.jordan_form(transformation=True)


sage: U^-1*A*U == J
True
La forme de Jordan est unique une permutation des blocs de Jordan prs.
Selon les ouvrages, on peut imposer ou non que leur ordre dapparition sur
la diagonale respecte lordre des polynmes invariants, comme dans lquation
(8.4). On remarque dans lexemple ci-dessus que Sage ne respecte pas cet ordre,
puisque le premier polynme invariant (le polynme minimal) est le polynme
(X 3)(X 2)2 .
182 CHAP. 8. ALGBRE LINAIRE

Forme normale primaire. Pour tre complet, il faut mentionner une dernire
forme normale qui gnralise la forme de Jordan dans le cas quelconque o le
polynme minimal nest pas scind. Pour un polynme irrductible P de degr k,
on dfinit le bloc de Jordan de multiplicit m comme la matrice JP,m de dimension
km km vrifiant
CP B
.. ..
. .

JP,m =


CP B
CP
o B est la matrice k k dont le seul coefficient non nul est Bk,1 = 1, et CP est la
matrice compagnon associe au polynme P (8.2.3). On note que si P = X ,
on retrouve la notion de bloc de Jordan associ la valeur propre . On montre
de faon similaire que les polynmes minimal et caractristique de cette matrice
valent
JP,m = JP,m = P m .
Ainsi on montre quil existe une transformation de similitude remplaant chaque
bloc compagnon Cmi,j de la forme intermdiaire (8.3) en un bloc de Jordan
j
Jj ,mi,j . La matrice ainsi forme est appele la forme primaire ou encore la
deuxime forme de Frobenius. Il sagit l encore dune forme normale, cest--dire
unique une permutation des blocs diagonaux prs.
Lunicit de ces formes normales permet en particulier de tester si deux
matrices sont semblables, et par la mme occasion de produire une matrice de
passage entre lune et lautre.
Exercice 31. crire un programme qui dtermine si deux matrices A et B sont
semblables et renvoie la matrice U de passage telle que A = U 1 BU (on pourra renvoyer
None dans le cas o les matrices ne sont pas semblables).
Systmes polynomiaux
9
Ce chapitre prolonge les deux prcdents. Les objets sont des systmes dqua-
tions plusieurs variables, comme ceux du chapitre 8. Ces quations, dans la
ligne du chapitre 7, sont polynomiales. Par rapport aux polynmes une seule
indtermine, ceux plusieurs indtermines prsentent une grande richesse
mathmatique mais aussi des difficults nouvelles, lies notamment au fait que
lanneau K[x1 , . . . , xn ] nest pas principal. La thorie des bases de Grbner fournit
des outils pour contourner cette limitation. Au final, on dispose de mthodes puis-
santes pour tudier les systmes polynomiaux, avec dinnombrables applications
qui couvrent des domaines varis.
Une bonne partie du chapitre ne prsuppose que des connaissances de base
sur les polynmes plusieurs indtermines. Certains passages sont cependant du
niveau dun cours dalgbre commutative de L3 ou M1. Pour une introduction
moins allusive et en franais la thorie mathmatique des systmes polynomiaux,
accessible au niveau licence, le lecteur pourra se reporter au chapitre [FSED09]
de Faugre et Safey El Din. On trouvera un traitement plus avanc dans le livre
de Elkadi et Mourrain [EM07]. Enfin, en anglais cette fois, le livre de Cox, Little
et OShea [CLO07] est la fois accessible et fort complet.

9.1 Polynmes plusieurs indtermines


9.1.1 Les anneaux A[x1 , . . . , xn ]
Nous nous intressons ici aux polynmes plusieurs indtermines, dits aussi
anglicisme commun dans le domaine du calcul formel multivaris.
Comme pour les autres structures algbriques disponibles dans Sage, avant de
pouvoir construire des polynmes, il nous faut dfinir une famille dindtermines
184 CHAP. 9. SYSTMES POLYNOMIAUX

vivant toutes dans un mme anneau. La syntaxe est pratiquement la mme quen
une variable (cf. 7.1.1) :
sage: R = PolynomialRing(QQ, 'x,y,z')
sage: x,y,z = R.gens() # donne le n-uplet des indtermines
ou en abrg :
sage: R.<x,y,z> = QQ[]
(ou encore R = QQ['x,y,z']). Le constructeur PolynomialRing permet aussi de
crer une famille dindtermines de mme nom, avec des indices entiers :
sage: R = PolynomialRing(QQ, 'x', 10)
Placer le n-uplet renvoy par gens lui-mme dans la variable x permet alors
daccder naturellement lindtermine xi par x[i] :
sage: x = R.gens()
sage: sum(x[i] for i in xrange(5))
x0 + x1 + x2 + x3 + x4
Lordre des variables est significatif. La comparaison par == de QQ['x,y'] et
QQ['y,x'] renvoie faux, et un mme polynme vu comme lment de lun ou de
lautre saffiche diffremment :
sage: def test_poly(ring, deg=3):
....: monomials = Subsets(
....: flatten([(x,)*deg for x in (1,) + ring.gens()]),
....: deg, submultiset=True)
....: return add(mul(m) for m in monomials)

sage: test_poly(QQ['x,y'])
x^3 + x^2*y + x*y^2 + y^3 + x^2 + x*y + y^2 + x + y + 1
sage: test_poly(QQ['y,x'])
y^3 + y^2*x + y*x^2 + x^3 + y^2 + y*x + x^2 + y + x + 1
sage: test_poly(QQ['x,y']) == test_poly(QQ['y,x'])
True

Exercice 32. Expliquer le fonctionnement de la fonction test_poly dfinie ci-


dessus.
Plus largement, crire les polynmes sous forme canonique demande de choisir
une faon dordonner les termes de la somme. Les trier par degr simpose
naturellement quand il ny a quune indtermine, mais dans le cas des polynmes
multivaris, aucun ordre sur les monmes ne couvre tous les besoins. Sage permet
donc de choisir entre plusieurs ordres, grce loption order de PolynomialRing.
Par exemple, lordre not deglex range les monmes par degr total, puis par
ordre lexicographique des degrs des indtermines en cas dgalit :
sage: test_poly(PolynomialRing(QQ, 'x,y', order='deglex'))
x^3 + x^2*y + x*y^2 + y^3 + x^2 + x*y + y^2 + x + y + 1
9.1. POLYNMES PLUSIEURS INDTERMINES 185

Construction danneaux de polynmes


anneau A[x, y] PolynomialRing(A, 'x,y') ou A['x,y']
anneau A[x0 , . . . , xn1 ] PolynomialRing(A, 'x', n)
anneau A[x0 , x1 , . . . , y0 , y1 , . . . ] InfinitePolynomialRing(A, ['x','y'])
n-uplet des gnrateurs R.gens()
1er, 2e... gnrateur R.0, R.1, ...
indtermines de R = A[x, y][z][. . . ] R.variable_names_recursive()
conversion A[x1 , x2 , y] A[x1 , x2 ][y] p.polynomial(y)

Accs aux coefficients


support, coefficients non nuls p.exponents(), p.coefficients()
coefficient dun monme p[x^2*y] ou p[2,1]
degr(s) total, en x, partiels p.degree(), p.degree(x), p.degrees()
monme/coefficient/terme de tte p.lm(), p.lc(), p.lt()

Oprations de base
transformation des coefficients p.map_coefficients(f)
drive partielle d/dx p.derivative(x)
valuation p(x, y)|x=a,y=b p.subs(x=a, y=b) ou p(x=a, y=b)
homognisation p.homogenize()
dnominateur commun (p Q[x, y, . . . ]) p.denominator()

Tableau 9.1 Polynmes plusieurs indtermines.

Les principaux ordres disponibles sont dcrits plus en dtail en 9.3.1. Nous
verrons que le choix de lordre nest pas quune question daffichage, mais exerce
une influence sur certains calculs.
Exercice 33. Dfinir lanneau Q[x2 , x3 , . . . , x37 ] dont les indtermines sont indexes
par les nombres premiers infrieurs 40, ainsi que des variables x2, x3, . . ., x37 pour
accder aux indtermines.
Il peut enfin savrer utile, dans quelques cas, de manipuler des polynmes
plusieurs indtermines en reprsentation rcursive, cest--dire comme lments
dun anneau de polynmes coefficients eux-mmes polynomiaux (voir encadr
page 134).

9.1.2 Polynmes
Tout comme les polynmes en une variable sont de classe Polynomial, ceux
en plusieurs variables (dans les anneaux avec un nombre fini dindtermines)
sont de classe MPolynomial 1 . Pour les anneaux de base usuels (comme Z, Q ou
Fq ), ils sappuient sur le logiciel Singular, un systme de calcul formel spcialis
dans les calculs rapides sur les polynmes. Dans les autres cas, Sage se rabat sur
une implmentation gnrique beaucoup plus lente.
1. Contrairement Polynomial, cette classe nest pas accessible directement depuis la ligne
de commande : il faut utiliser son nom complet. Par exemple, on peut tester si un objet est
de type polynme multivari par isinstance(p, sage.rings.polynomial.multi_polynomial.
MPolynomial).
186 CHAP. 9. SYSTMES POLYNOMIAUX

Les anneaux A[(xn , yn , . . . )nN ]

Il arrive que lon ne sache pas, au dbut dun calcul, combien de variables
seront ncessaires. Cela rend lutilisation de PolynomialRing assez pnible :
il faut commencer calculer dans un premier domaine, puis ltendre et
convertir tous les lments chaque fois que lon souhaite introduire une
nouvelle variable.
Les anneaux de polynmes en une infinit dindtermines offrent une
structure de donnes plus souple. Leurs lments peuvent contenir des va-
riables prises dans une ou plusieurs familles infinies dindtermines. Chaque
gnrateur de lanneau correspond non pas une seule variable, mais une
famille de variables indexes par les entiers naturels :
sage: R.<x,y> = InfinitePolynomialRing(ZZ, order='lex')
sage: p = mul(x[k] - y[k] for k in range(2)); p
x_1*x_0 - x_1*y_0 - x_0*y_1 + y_1*y_0
sage: p + x[100]
x_100 + x_1*x_0 - x_1*y_0 - x_0*y_1 + y_1*y_0
On revient un anneau de polynmes PolynomialRing usuel grce la
mthode polynomial, qui renvoie limage dun lment dun Infinite
PolynomialRing dans un anneau suffisamment grand pour contenir tous les
lments de lanneau une infinit de variables manipuls jusque-l. Lanneau
obtenu nest gnralement pas le plus petit avec cette proprit.
En contrepartie de cette souplesse, ces anneaux sont moins efficaces que
les anneaux PolynomialRing. Par ailleurs, leurs idaux ne se substituent pas
ceux des anneaux de polynmes usuels pour les calculs sur les systmes
polynomiaux, sujet central du prsent chapitre.

Les polynmes plusieurs indtermines sont toujours cods en reprsentation


creuse 2 . Pourquoi ce choix ? Un polynme dense n variables de degr total d
compte n+d monmes : pour n = d = 10, cela fait 184 756 coefficients stocker !

d
Il est donc trs difficile de manipuler de gros polynmes denses comme on le fait
en une variable. Par ailleurs, mme quand les polynmes sont denses, les supports
(les positions des monmes non nuls) rencontrs en pratique ont des formes varies.
Or, si par exemple un polynme n variables dense jusquau degr total d 1
est reprsent par un tableau rectangulaire d d, pour d grand, seul un
coefficient sur n! environ est non nul. Au contraire, la reprsentation creuse par
dictionnaire sadapte la forme du support ainsi dailleurs qu lordre sur les
monmes.

2. La reprsentation rcursive (voir encadr page 134) fournit cependant une forme de
polynmes multivaris partiellement denses. Dans la reprsentation en mmoire dun polynme
de A[x][y], chaque coefficient de y k occupe (en rgle gnrale) un espace proportionnel son
degr en x, quoi il faut ajouter une place proportionnelle au degr en y pour le polynme
lui-mme.
9.1. POLYNMES PLUSIEURS INDTERMINES 187

9.1.3 Oprations de base


Fixons un peu de terminologie. Soit R = A[x1 , . . . , xn ] un anneau de polynmes.
On appelle monme une expression de la forme x 1 x2 xn , cest--dire un
1 2 n

produit dindtermines, et on le note en abrg x . Le n-uplet dentiers =


(1 , 2 , . . . , n ) est lexposant du monme x . Un terme est un monme multipli


par un lment de A, son coefficient.
Puisque la faon dordonner leurs termes nest pas unique, les lments de R
nont pas, en tant quobjets mathmatiques, de coefficient dominant. Mais une
fois un ordre choisi la construction de lanneau, il est possible et utile de
dfinir un monme de tte, le plus gauche dans lordre dcriture. Les mthodes
lm (pour leading monomial), lc (leading coefficient) et lt (leading term) dun
polynme plusieurs indtermines renvoient respectivement son monme de
tte, le coefficient de celui-ci, et le terme quils constituent :
sage: R.<x,y,z> = QQ[]
sage: p = 7*y^2*x^2 + 3*y*x^2 + 2*y*z + x^3 + 6
sage: p.lt()
7*x^2*y^2
Les oprations arithmtiques +, - et *, de mme que les mthodes dict,
coefficients, et bien dautres, sutilisent comme leurs analogues en une seule
variable. Parmi les petites diffrences, loprateur crochets [] dextraction dun
coefficient accepte comme paramtre soit un monme, soit son exposant :
sage: p[x^2*y] == p[(2,1,0)] == p[2,1,0] == 3
True
De mme, lvaluation ncessite de donner des valeurs toutes les variables ou de
prciser celles substituer :
sage: p(0, 3, -1)
0
sage: p.subs(x = 1, z = x^2+1)
2*x^2*y + 7*y^2 + 5*y + 7
La mthode subs peut aussi substituer un nombre quelconque de variables en
une fois, voir sa documentation pour des exemples dusages avancs. Le degr se
dcline quant lui en degr total et degrs partiels :
sage: print "total={d} (en x)={dx} partiels={ds}"\
....: .format(d=p.degree(), dx=p.degree(x), ds=p.degrees())
total=4 (en x)=3 partiels=(3, 2, 1)
Dautres constructions subissent des adaptations videntes, par exemple, la m-
thode derivative prend en paramtre la variable par rapport laquelle driver.

9.1.4 Arithmtique
Au-del des oprations syntaxiques et arithmtiques lmentaires, les fonctions
disponibles dans Sage sont en gnral limites aux polynmes sur un corps, et
188 CHAP. 9. SYSTMES POLYNOMIAUX

parfois sur Z ou Z/nZ. Pour la suite de ce chapitre, et sauf mention contraire


explicite, nous nous placerons sur un corps.
La division euclidienne des polynmes na de sens quen une variable. En Sage,
la mthode quo_rem et les oprateurs associs // et % restent pourtant dfinis
pour les polynmes multivaris. La division avec reste quils calculent vrifie
(p//q)*q + (p%q) == p
et concide avec la division euclidienne lorsque p et q ne dpendent que dune
variable, mais ce nest pas elle-mme une division euclidienne et elle na rien
de canonique. Elle savre tout de mme utile lorsque la division est exacte ou
lorsque le diviseur est un monme. Dans les autres cas, on prfrera quo_rem et
ses variantes la mthode mod, dcrite en 9.2.3, qui rduit un polynme modulo
un idal en tenant compte du choix dordre monomial de lanneau :
sage: R.<x,y> = QQ[]; p = x^2 + y^2; q = x + y
sage: print("({quo})*({q}) + ({rem}) == {p}".format( \
....: quo=p//q, q=q, rem=p%q, p=p//q*q+p%q))
(-x + y)*(x + y) + (2*x^2) == x^2 + y^2
sage: p.mod(q) # n'est PAS quivalent p%q
2*y^2
Les mthodes divides, gcd, lcm ou encore factor ont le mme sens quen une
seule variable. Faute de division euclidienne, les premires ne sont pas disponibles
pour des coefficients de nimporte quel type ; mais elles fonctionnent sur divers
corps usuels, par exemple les corps de nombres :
sage: R.<x,y> = QQ[exp(2*I*pi/5)][]
sage: (x^10 + y^5).gcd(x^4 - y^2)
x^2 + y
sage: (x^10 + y^5).factor()
(x^2 + (a^2)*y) * (x^2 + (a)*y) * (x^2 + (a^3)*y) *
(x^2 + (-a^3 - a^2 - a - 1)*y) * (x^2 + y)

9.2 Systmes polynomiaux et idaux


Nous abordons prsent le sujet central de ce chapitre. Les sections 9.2.1 et
9.2.2 offrent un panorama des manires de trouver et de comprendre les solutions
dun systme dquations polynomiales avec laide de Sage. La section 9.2.3 est
consacre aux idaux associs ces systmes. Les sections suivantes reviennent
de faon plus dtaille sur les outils dlimination algbrique et de rsolution de
systmes.

9.2.1 Un premier exemple


Considrons une variante du systme polynomial de la section 2.2,
x yz = 18
2

xy 3 z = 24 (9.1)
xyz 4 = 6.

9.2. SYSTMES POLYNOMIAUX ET IDAUX 189

Oprations sur les polynmes plusieurs indtermines


divisibilit p | q p.divides(q)
factorisation p.factor()
pgcd, ppcm p.gcd(q), p.lcm(q)
test p sans facteur carr p.is_squarefree()
rsultant Resx (p, q) p.resultant(q, x)

Tableau 9.2 Arithmtique.

La fonction solve() de Sage ne nous avait permis de trouver les solutions que
numriquement. Voyons maintenant comment Sage parvient rsoudre le systme
de faon exacte, et, avec un peu daide de lutilisateur, trouver des formes closes
simples pour toutes les solutions 3 .

numrer les solutions. Commenons par traduire le problme en termes


plus algbriques, en construisant lidal de Q[x, y, z] engendr par les quations :
sage: R.<x,y,z> = QQ[]
sage: J = R.ideal(x^2 * y * z - 18,
....: x * y^3 * z - 24,
....: x * y * z^4 - 6)
Comme nous le verrons dans la section 9.2.3, la commande suivante nous permet
de vrifier que lidal J est de dimension zro, cest--dire que le systme (9.1)
possde un nombre fini de solutions dans C3 :
sage: J.dimension()
0
Ceci tabli, le premier rflexe est dutiliser la mthode variety, qui calcule toutes
les solutions du systme. Sans paramtre, elle donne les solutions dans le corps
de base de lanneau de polynmes :
sage: J.variety()
[{y: 2, z: 1, x: 3}]
La solution (3, 2, 1) dj trouve est donc lunique solution rationnelle.
Ltape suivante est dnumrer les solutions complexes. Afin de le faire
de faon exacte, nous travaillons dans le corps des nombres algbriques. Nous
retrouvons les 17 solutions :
sage: V = J.variety(QQbar)
sage: len(V)
17
Explicitement, les trois dernires ont lallure suivante :
sage: V[-3:]
3. Le propos tant dillustrer les outils de rsolution de systmes polynomiaux, nous ngligeons
la possibilit de ramener (9.1) des quations linaires en passant au logarithme !
190 CHAP. 9. SYSTMES POLYNOMIAUX

[{z: 0.9324722294043558? - 0.3612416661871530?*I,


y: -1.700434271459229? + 1.052864325754712?*I,
x: 1.337215067329615? - 2.685489874065187?*I},
{z: 0.9324722294043558? + 0.3612416661871530?*I,
y: -1.700434271459229? - 1.052864325754712?*I,
x: 1.337215067329615? + 2.685489874065187?*I},
{z: 1, y: 2, x: 3}]

Chaque point solution est donn par un dictionnaire dont les cls sont les gnra-
teurs de QQbar['x,y,z'] (et non de QQ['x,y,z'], do un petit dtour pour y
accder ci-dessous), et les valeurs associes, les coordonnes du point. Hors celle
de la solution rationnelle identifie prcdemment, les premires coordonnes sont
toutes des nombres algbriques de degr 16 :
sage: (xx, yy, zz) = QQbar['x,y,z'].gens()
sage: [ pt[xx].degree() for pt in V ]
[16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1]

Calculer avec les solutions et identifier leur structure. Nous avons obtenu
une reprsentation exacte des solutions complexes du systme (9.1), mais cette
reprsentation nest pas franchement explicite. Ce nest pas grave : disposer des
coordonnes comme lments de QQbar suffit poursuivre les calculs exacts dessus.
Par exemple, il nest pas difficile de voir que si (x, y, z) est solution du
systme (9.1), alors (|x|, |y|, |z|) aussi. Construisons lensemble des (|x|, |y|, |z|)
pour (x, y, z) solution :
sage: Set(tuple(abs(pt[i]) for i in (xx,yy,zz)) for pt in V)
{(3, 2, 1)}

Toutes les valeurs de x (resp. y, z) sont donc de mme module. Mieux, on peut
vrifier que la substitution

(x, y, z) 7 (x, 9 y, 6 z) o = e2i/17 (9.2)

laisse le systme invariant. En particulier, les dernires coordonnes des solutions


sont exactement les racines dix-septimes de lunit, ce dont on sassure nouveau
grce la possibilit de calculer exactement sur les nombres algbriques :
sage: w = QQbar.zeta(17); w # racine primitive de 1
0.9324722294043558? + 0.3612416661871530?*I
sage: Set(pt[zz] for pt in V) == Set(w^i for i in range(17))
True

Les solutions du systme sont donc les triplets (3, 2 9 , 6 ) pour 17 = 1. Voil
qui est plus parlant !
Exercice 34. Chercher les solutions relles (et non seulement rationnelles) de (9.1),
pour vrifier directement quil ny a que (3, 2, 1). Retrouver la substitution (9.2), y
compris la valeur 17 pour lordre de comme racine de lunit, par un calcul avec Sage.
9.2. SYSTMES POLYNOMIAUX ET IDAUX 191

Nous aurions pu arriver au mme rsultat en examinant les polynmes mi-


nimaux des coordonnes des points de V . On observe en effet quune mme
coordonne a le mme polynme minimal pour tous les points solutions autres
que (3, 2, 1). Le polynme minimal commun de leur troisime coordonne nest
autre que le polynme cyclotomique 17 :

sage: set(pt[zz].minpoly() for pt in V[:-1])


set([x^16 + x^15 + x^14 + x^13 + x^12 + x^11 + x^10 + x^9 +
x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1])

Ceux des premire et deuxime coordonnes sont respectivement 316 17 (x/3) et


216 17 (x/2).

Des formules closes. Une expression explicite des solutions est donc possible
en ayant recours la notation exponentielle des complexes :

sage: def polar_form(z):


....: rho = z.abs(); rho.simplify()
....: theta = 2 * pi * z.rational_argument()
....: return (SR(rho) * exp(I*theta))
sage: [tuple(polar_form(pt[i]) for i in [xx,yy,zz]) for pt in V[-3:]]
[(3*e^(-6/17*I*pi), 2*e^(14/17*I*pi), e^(-2/17*I*pi)),
(3*e^(6/17*I*pi), 2*e^(-14/17*I*pi), e^(2/17*I*pi)), (3, 2, 1)]

Naturellement, si nous avions eu lide dcrire les lments de V en notation


exponentielle, cela aurait suffi conclure.

Simplifier le systme. Une approche diffrente est possible. Plutt que de


chercher les solutions, essayons de calculer une forme plus simple du systme lui-
mme. Les outils fondamentaux quoffre Sage pour ce faire sont la dcomposition
triangulaire et les bases de Grbner. Nous verrons plus loin ce quils calculent
exactement ; essayons dj de les utiliser sur cet exemple :

sage: J.triangular_decomposition()
[Ideal (z^17 - 1, y - 2*z^10, x - 3*z^3) of Multivariate
Polynomial Ring in x, y, z over Rational Field]
sage: J.transformed_basis()
[z^17 - 1, -2*z^10 + y, -3*z^3 + x]

On obtient dans un cas comme dans lautre le systme quivalent

z 17 = 1 y = 2z 10 x = 3z 3 ,

soit V = {(3 3 , 2 10 , ) | 17 = 1}. Cest un reparamtrage immdiat de la


description compacte des solutions trouve manuellement plus haut.
192 CHAP. 9. SYSTMES POLYNOMIAUX

9.2.2 Quest-ce que rsoudre ?


Un systme polynomial qui possde des solutions en a souvent une infinit.
Lquation toute simple x2 y = 0 admet une infinit de solutions dans Q2 , sans
parler de R2 ou C2 . Il nest donc pas question de les numrer. Le mieux quon
puisse faire est dcrire lensemble des solutions aussi explicitement que possible ,
cest--dire en calculer une reprsentation dont on puisse facilement extraire des
informations intressantes. La situation est analogue celle des systmes linaires,
pour lesquels (dans le cas homogne) une base du noyau du systme est une bonne
description de lespace des solutions.
Dans le cas particulier o les solutions sont en nombre fini il devient possible
de les calculer . Mais mme dans ce cas, cherche-t-on numrer les solutions
dans Q, ou encore dans un corps fini Fq ? trouver des approximations numriques
des solutions relles ou complexes ? Ou encore, comme dans lexemple de la section
prcdente, reprsenter ces dernires laide de nombres algbriques, cest--dire
par exemple calculer les polynmes minimaux de leurs coordonnes ?
Ce mme exemple illustre que dautres reprsentations de lensemble des
solutions peuvent tre bien plus parlantes quune simple liste de points, surtout
quand les solutions sont nombreuses. Ainsi, les numrer nest pas forcment la
chose la plus pertinente faire mme quand cest possible. In fine, on ne cherche
pas tant calculer les solutions qu calculer avec les solutions, pour en dduire
ensuite, suivant le problme, les informations auxquelles on sintresse vraiment.
La suite de ce chapitre explore diffrents outils utiles pour ce faire.

9.2.3 Idaux et systmes


Si s polynmes p1 , . . . , ps K[x] sannulent en un point x coordonnes
dans K ou dans une extension de K, tout lment de lidal quils engendrent
sannule aussi en x. Il est donc naturel dassocier au systme polynomial

p1 (x) = p2 (x) = = ps (x) = 0

lidal J = hp1 , . . . , ps i K[x]. Deux systmes polynomiaux qui engendrent le


mme idal sont quivalents au sens o ils ont les mmes solutions. Si L est
un corps contenant K, on appelle sous-varit algbrique de Ln associe J
lensemble

VL (J) = {x Ln | p J, p(x) = 0} = {x Ln | p1 (x) = = ps (x) = 0}

des solutions coordonnes dans L du systme. Des idaux diffrents peuvent


avoir la mme varit associe. Par exemple, les quations x = 0 et x2 = 0
admettent la mme unique solution dans C, alors que lon a hx2 i ( hxi. Ce que
lidal engendr par un systme polynomial capture est plutt la notion intuitive
de solutions avec multiplicits .
Ainsi, les deux systmes suivants expriment chacun lintersection du cercle
unit et dune courbe dquation x2 y 2 = 1, runion de deux hyperboles quila-
9.2. SYSTMES POLYNOMIAUX ET IDAUX 193

1 1
0.5 0.5

-1 -0.5 0.5 1 -1 -0.5 0.5 1


-0.5 -0.5
-1 -1

(a) (S1 ) (b) (S2 )

sage: opts = {'axes':True, 'gridlines':True, 'frame':False,


....: 'aspect_ratio':1, 'axes_pad':0, 'fontsize':8,
....: 'xmin':-1.3, 'xmax':1.3, 'ymin':-1.3, 'ymax':1.3}
sage: (ideal(J.0).plot() + ideal(J.1).plot()).show(**opts)

Figure 9.1 Intersection de deux courbes planes, voir systmes (9.3).

tres (voir figure 9.1) :

x2 + y 2 = 1 x2 + y 2 = 1
( (
(S1 ) (S2 ) (9.3)
16 x2 y 2 = 1 4 x2 y 2 = 1.

Le systme (S1 ) possde huit solutions dans C, toutes coordonnes relles.


Quand on le dforme en (S2 ) en faisant varier le paramtre , les deux solutions
sur chaque branche de lhyperbole se rapprochent jusqu tre confondues. Le
systme (S2 ) na plus que quatre solutions, chacune en un certain sens de
multiplicit deux . En diminuant encore , il ny aurait plus de solution relle,
mais huit solutions complexes.

Calcul modulo un idal. Comme dans le cas des polynmes une seule
indtermine, Sage permet de dfinir des idaux 4 J K[x], des anneaux quotients
K[x]/J, et de calculer naturellement avec les lments de ces anneaux quotients.
Lidal J1 associ (S1 ) se construit par :
sage: R.<x,y> = QQ[]
sage: J = R.ideal(x^2 + y^2 - 1, 16*x^2*y^2 - 1)
On peut ensuite effectuer le quotient de K[x] par J1 , y projeter des polynmes,
calculer avec les classes dquivalence modulo J1 , et les remonter en des
reprsentants :

4. Attention : les objets InfinitePolynomialRing ont aussi une mthode ideal, mais celle-ci
na pas le mme sens que pour les anneaux de polynmes usuels. (Un idal quelconque de
K[(xn )nN ] na aucune raison dtre finiment engendr !) La suite du chapitre ne sapplique pas
ces objets.
194 CHAP. 9. SYSTMES POLYNOMIAUX

sage: ybar2 = R.quo(J)(y^2)


sage: [ybar2^i for i in range(3)]
[1, ybar^2, ybar^2 - 1/16]
sage: ((ybar2 + 1)^2).lift()
3*y^2 + 15/16
Il y a ici une difficult thorique. Les lments de K[x]/J sont reprsents
sous forme normale, ce qui est ncessaire pour pouvoir tester lgalit de deux
lments. Or cette forme normale nest pas vidente dfinir, pour la raison dj
mentionne en 9.1.4 : la division dun reprsentant dune classe dquivalence
p + J par un gnrateur principal de J, utilise pour calculer dans K[x]/J, na pas
danalogue direct en plusieurs variables. Bornons-nous pour linstant admettre
quil existe nanmoins une forme normale, qui dpend de lordre sur les lments
choisi la construction de lanneau et repose sur un systme de gnrateurs de
J particulier appel base de Grbner. La section 9.3 la fin de ce chapitre est
consacre dfinir les bases de Grbner et montrer comment on peut les utiliser
dans les calculs. Sage calcule automatiquement des bases de Grbner lorsque
cest ncessaire ; mais ces calculs sont parfois trs coteux, en particulier quand
le nombre de variables est grand, de sorte que calculer dans un anneau quotient
peut tre difficile.
Revenons lutilisation de Sage. Lorsque p J, la commande p.lift(J) crit
p comme combinaison linaire coefficients polynomiaux des gnrateurs de J :
sage: u = (16*y^4 - 16*y^2 + 1).lift(J); u
[16*y^2, -1]
sage: u[0]*J.0 + u[1]*J.1
16*y^4 - 16*y^2 + 1
Pour un polynme quelconque, lexpression p.mod(J) donne la forme normale
de p modulo J, vue comme lment de K[x] :
sage: (y^4).mod(J)
y^2 - 1/16
Attention : si J.reduce(p) est quivalent p.mod(J), en revanche, la variante
p.reduce([p1, p2, ...]) renvoie un reprsentant de p + J qui nest pas forc-
ment la forme normale (voir 9.3.2) :
sage: (y^4).reduce([x^2 + y^2 - 1, 16*x^2*y^2 - 1])
y^4
En combinant p.mod(J) et p.lift(J), on peut dcomposer un polynme p en
une combinaison linaire coefficients polynomiaux de gnrateurs de J, plus un
reste qui est nul si et seulement si p J.

Radical dun idal et solutions. Le point essentiel de la correspondance


entre idaux et varits est le thorme des zros de Hilbert, ou Nullstellensatz.
une clture algbrique de K.
Soit K
Thorme (Nullstellensatz). Soient p1 , . . . , ps K[x], et soit Z K n len-
semble des zros communs des pi . Un polynme p K[x] sannule identiquement
sur Z si et seulement sil existe un entier k tel que pk hp1 , . . . , ps i.
9.2. SYSTMES POLYNOMIAUX ET IDAUX 195

Idaux
idal hp1 , p2 i R R.ideal(p1, p2) ou (p1, p2)*R
somme, produit, puissance I + J, I * J, I^k
intersection I J I.intersection(J)
quotient I : J = {p | pJ I} I.quotient(J)
radical J J.radical()
rduction modulo J J.reduce(p) ou p.mod(J)
section de R  R/J p.lift(J)
anneau quotient R/J R.quo(J)
idal homognis J.homogenize()

Quelques idaux prdfinis


irrelevant ideal hx1 , . . . , xn i R.irrelevant_ideal()
idal jacobien hp/xi ii p.jacobian_ideal()
racines cycliques (9.11) sage.rings.ideal.Cyclic(R)
quations de corps xqi = xi sage.rings.ideal.FieldIdeal(GF(q)['x1,x2'])

Tableau 9.3 Idaux.

Ce rsultat donne un critre algbrique pour tester si un systme polynomial


admet des solutions. Le polynme constant 1 sannule identiquement sur Z si et
seulement si Z est vide, donc le systme p1 (x) = = ps (x) = 0 a des solutions
dans K si et seulement si lidal hp1 , . . . , ps i ne contient pas 1. Par exemple, les
cercles de rayon 1 centrs en (0, 0) et en (4, 0) ont une intersection complexe :
sage: 1 in ideal(x^2+y^2-1, (x-4)^2+y^2-1)
False
En revanche, en ajoutant la condition x = y, le systme na plus de solution. On
peut donner une preuve triviale vrifier quil est alors contradictoire en exhibant
comme certificat une combinaison des quations qui se rduit 1 = 0 si elles sont
satisfaites. Le calcul
sage: R(1).lift(ideal(x^2+y^2-1, (x-4)^2+y^2-1, x-y))
[-1/28*y + 1/14, 1/28*y + 1/14, -1/7*x + 1/7*y + 4/7]
fournit dans notre cas la relation
1
(y + 2)(x2 + y 2 1) + (y + 2) (x 4)2 + y 2 1

28 
+ (4x + 4y + 16)(x y) = 1.

En termes didaux, le Nullstellensatz affirme que lensemble des polynmes


qui sannulent identiquement sur la varit VK (J) associe un idal J est le
radical de cet idal, dfini par

J = {p K[x] | k N, pk J}.

On a
V ( J) = V (J)
196 CHAP. 9. SYSTMES POLYNOMIAUX

mais intuitivement, le passage au radical oublie les multiplicits . Ainsi, lidal


J1 est son propreradical (on dit quil est radical), tandis que lidal J2 associ
(S2 ) vrifie J2 ( J2 :
sage: J1 = (x^2 + y^2 - 1, 16*x^2*y^2 - 1)*R
sage: J2 = (x^2 + y^2 - 1, 4*x^2*y^2 - 1)*R
sage: J1.radical() == J1
True
sage: J2.radical()
Ideal (2*y^2 - 1, 2*x^2 - 1) of Multivariate Polynomial
Ring in x, y over Rational Field
sage: 2*y^2 - 1 in J2
False

Systmes, idaux et cryptographie

Des modules spcifiques, sage.rings.polynomial.multi_polynomial_


sequence et sage.crypto.mq, offrent des outils pour manipuler les systmes
polynomiaux en tenant compte de la forme particulire des quations, et
non seulement de lidal quelles engendrent. Cela est utile pour travailler
avec de gros systmes structurs, comme ceux issus de la cryptographie. Le
module sage.crypto dfinit aussi plusieurs systmes polynomiaux associs
des constructions cryptographiques classiques.

Oprations sur les idaux. Il est aussi possible de calculer sur les idaux
eux-mmes. Rappelons que la somme de deux idaux est dfinie par

I + J = {p + q | p I et q J} = hI Ji.

Elle correspond gomtriquement lintersection des varits :

V (I + J) = V (I) V (J).

Ainsi, lidal J1 associ (S1 ) scrit comme la somme de C = hx2 + y 2 1i et


H = h16 x2 y 2 1i, qui dfinissent respectivement le cercle et la double hyperbole.
En Sage :
sage: C = ideal(x^2 + y^2 - 1); H = ideal(16*x^2*y^2 - 1)
sage: C + H == J1
True
Ce test dgalit sappuie lui aussi sur un calcul de base de Grbner.
De mme, lintersection, le produit et le quotient didaux satisfont

I J = {p | p I et p J} V (I J) = V (I) V (J)
I J = hpq | p I, q Ji V (I J) = V (I) V (J)
I : J = {p | pJ I} V (I : J) = V (I) \ V (J)
9.2. SYSTMES POLYNOMIAUX ET IDAUX 197

et se calculent comme indiqu dans le tableau 9.3. La notation X dsigne ici


la fermeture de Zariski de X, cest--dire la plus petite sous-varit algbrique
contenant X. Par exemple, la courbe de la figure 9.1a est lensemble des zros des
polynmes de C H, et le quotient (C H) : h4xy 1i correspond la runion
du cercle avec une des deux hyperboles :
sage: CH = C.intersection(H).quotient(ideal(4*x*y-1)); CH
Ideal (4*x^3*y + 4*x*y^3 + x^2 - 4*x*y + y^2 - 1) of
Multivariate Polynomial Ring in x, y over Rational Field
sage: CH.gen(0).factor()
(4*x*y + 1) * (x^2 + y^2 - 1)
En revanche, la courbe obtenue en retirant V (H) un nombre fini de points nest
pas une sous-varit algbrique, de sorte que :
sage: H.quotient(C) == H
True

Dimension. tout idal de J K[x] est aussi associe une dimension qui
correspond intuitivement la dimension maximale des composantes de la
varit V (J) sur un corps algbriquement clos 5 . On a par exemple :
sage: [J.dimension() for J in [J1, J2, C, H, H*J2, J1+J2]]
[0, 0, 1, 1, 1, -1]
En effet, V (J1 ) et V (J2 ) sont formes dun nombre fini de points, V (C) et V (H)
sont des courbes, V (H J2 ) est runion de courbes et de points isols, et V (J1 +J2 )
est vide. Les systmes de dimension zro, cest--dire ceux qui engendrent un
idal de dimension zro, ou encore (pour les systmes coefficients rationnels) qui
ne possdent quun nombre fini de solutions, auront une importance particulire
dans la suite du chapitre puisque ce sont ceux que lon peut rsoudre le plus
explicitement.

9.2.4 limination
liminer une variable dans un systme dquations, cest trouver des cons-
quences , ou mieux toutes les consquences du systme indpendantes de
cette variable. Autrement dit, il sagit de trouver des quations vrifies par toute
solution, mais qui ne font pas intervenir la variable limine, ce qui les rend
souvent plus faciles analyser.
Par exemple, on peut liminer x du systme linaire
(
2x + y 2z = 0
(9.4)
2x + 2y + z = 1

en retranchant la premire quation la deuxime. Il vient y + 3z = 1, ce qui


montre que tout triplet (x, y, z) solution de (9.4) est de la forme (x, 1 3z, z).
5. Nous donnons en 9.3.3 une dfinition plus rigoureuse, mais pas forcment plus clairante.
Voir les rfrences mentionnes en dbut de chapitre pour un traitement plus satisfaisant.
198 CHAP. 9. SYSTMES POLYNOMIAUX

Systmes polynomiaux gnraux : limination, gomtrie


idal dlimination J A[z, t] K[x, y, z, t] J.elimination_ideal(x, y)
rsultant Resx (p, q) p.resultant(q, x)
dimension J.dimension()
genre J.genus()

Dimension zro (ensemble fini de solutions)


solutions dans L K J.variety(L)
dimension sur K du quotient J.vector_space_dimension()
base du quotient J.normal_basis()
dcomposition triangulaire J.triangular_decomposition()

Tableau 9.4 Rsolution de systmes polynomiaux.

On peut ensuite vrifier que toute solution partielle (1 3z, z) stend en une
(unique) solution ( 5z1
2 , 1 3z, z) de (9.4). Cela illustre que lalgorithme du pivot
de Gauss rsout les systmes linaires par limination, contrairement par exemple
aux formules de Cramer.

Idaux dlimination. Dans le contexte des systmes polynomiaux, les cons-


quences des quations p1 (x) = = ps (x) = 0 sont les lments de lidal
hp1 , . . . , ps i. Si J est un idal de K[x1 , . . . , xn ], on appelle k-ime idal dlimina-
tion de J lensemble
Jk = J K[xk+1 , . . . , xn ] (9.5)
des lments de J qui ne font intervenir que les n k dernires variables. Cest
un idal de K[xk+1 , . . . , xn ].
En Sage, la mthode elimination_ideal prend la liste des variables li-
miner. Attention : elle ne renvoie pas Jk K[xk+1 , . . . , xn ], mais lidal hJk i
de K[x1 , . . . , xn ] engendr par celui-ci. Dans le cas du systme linaire (9.4), on
trouve
sage: R.<x,y,z> = QQ[]
sage: J = ideal(2*x+y-2*z, 2*x+2*y+z-1)
sage: J.elimination_ideal(x)
Ideal (y + 3*z - 1) of Multivariate Polynomial Ring in x, y, z
over Rational Field
sage: J.elimination_ideal([x,y])
Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field
Mathmatiquement, ces rsultats sinterprtent ainsi : on a J Q[y, z] = hy +
3z 1i Q[y, z] et J Q[z] = Q[z], cest--dire Q[z] J. (En effet, lidal h0i
correspond au systme rduit la seule quation triviale 0 = 0, dont tout
polynme est solution.) Ce nest certes pas une faon recommandable de rsoudre
les systmes linaires : les outils spcifiques discuts au chapitre 8 sont bien plus
efficaces !
Pour un exemple un peu moins trivial, reprenons le systme (S1 ) de la sec-
tion 9.2.3 (voir figure 9.1a) :
9.2. SYSTMES POLYNOMIAUX ET IDAUX 199

sage: J1.gens()
[x^2 + y^2 - 1, 16*x^2*y^2 - 1]

Llimination de y fournit un idal de Q[x] donc principal engendr par un


polynme g dont les racines sont les abscisses
p
2 3
2

des huit solutions de (S1 ) :


sage: g = J1.elimination_ideal(y).gens(); g
[16*x^4 - 16*x^2 + 1]
sage: SR(g[0]).solve(SR(x)) # rsout par radicaux
[x == -1/2*sqrt(sqrt(3) + 2), x == 1/2*sqrt(sqrt(3) + 2),
x == -1/2*sqrt(-sqrt(3) + 2), x == 1/2*sqrt(-sqrt(3) + 2)]

En rinjectant chacune des valeurs de x trouves dans (S1 ), on obtient un systme


(redondant) dquations en y seulement qui permet de calculer les deux valeurs
de y correspondantes.

liminer = projeter. Lexemple prcdent illustre que llimination de y dun


systme correspond gomtriquement la projection de la varit solution sur
un hyperplan dquation y = constante. Mais considrons maintenant sparment
les idaux C = hx2 + y 2 1i et H = h16 x2 y 2 1i dont J1 est la somme, et
nouveau, liminons y :
sage: C.elimination_ideal(y).gens()
[0]
sage: H.elimination_ideal(y).gens()
[0]

Concernant C, rien de bien surprenant. Le cercle {(x, y) R2 | x2 + y 2 = 1} se


projette certes sur [1; 1], mais il est clair que nimporte quelle valeur de x peut tre
rinjecte dans lunique quation x2 +y 2 1 = 0 et que lquation en y obtenue a
des solutions complexes. Ce que traduit llimination de y dans C est la projection
sur la premire coordonne du cercle complexe {(x, y) C2 | x2 + y 2 = 1}, qui
est C tout entier.
La situation de H est un petit peu plus complique. Lquation 16 x2 y 2 = 1
na pas de solution, mme complexe, pour x = 0. On a cette fois

VC (H Q[x]) = C ( (VC (H)) = C \ {0}.

En effet, le projet de lhyperbole, C \ {0}, nest pas une sous-varit algbrique.


Moralit : llimination correspond bien la projection (sur un corps algbrique-
ment clos), mais elle ne calcule pas le projet exact dune varit affine, seulement
la fermeture de Zariski de celui-ci.
200 CHAP. 9. SYSTMES POLYNOMIAUX

Figure 9.2 Une portion de la courbe en (x, y, t) dfinie par (9.6) et sa projection sur le
plan t = 0.

Applications : un peu de gomtrie plane. Si X Ck est donn par une


paramtrisation rationnelle

X = { f1 (t), f2 (t), . . . , fk (t) }, f1 , . . . , fk Q(t1 , . . . , tn ),




trouver une quation implicite pour X revient projeter la partie de Ck+n


dfinie par les quations xi = fi (t) sur le sous-espace (x1 , . . . , xk ) ' Ck . Cest un
problme dlimination. Considrons la paramtrisation classique du cercle

1 t2 2t
x= y= (9.6)
1 + t2 1 + t2
associe lexpression de (sin , cos ) en fonction de tan(/2). Elle se traduit par
des relations polynomiales qui dfinissent un idal de Q[x, y, t] :
sage: R.<x,y,t> = QQ[]
sage: Param = R.ideal((1-t^2)-(1+t^2)*x, 2*t-(1+t^2)*y)
liminons t :
sage: Param.elimination_ideal(t).gens()
[x^2 + y^2 - 1]
On obtient une quation du cercle. On peut remarquer que cette quation sannule
en (x, y) = (1, 0), bien que la paramtrisation (9.6) natteigne pas ce point, car
le cercle priv dun point nest pas une sous-varit algbrique.
Un autre exemple : traons quelques-uns des cercles (Ct ) dquation

t2 + 1
Ct : x2 + (y t)2 = (9.7)
2
au moyen des commandes Sage (voir figure 9.3) :
sage: R.<x,y,t> = QQ[]
sage: eq = x^2 + (y-t)^2 - 1/2*(t^2+1)
9.2. SYSTMES POLYNOMIAUX ET IDAUX 201

2.4 2.4
1.6 1.6
0.8 0.8
0 0
-0.8 -0.8
-1.6 -1.6
-2.4 -2.4

-1.8-1.2-0.6 0 0.6 1.2 1.8 -1.8-1.2-0.6 0 0.6 1.2 1.8


Figure 9.3 Une famille de cercles et son enveloppe.

sage: fig = add((eq(t=k/5)*QQ[x,y]).plot() for k in (-15..15))


sage: fig.show(aspect_ratio=1, xmin=-2, xmax=2, ymin=-3, ymax=3)
On voit apparatre lenveloppe de la famille de cercles (Ct ), une courbe limite
tangente tous les Ct , que lon peut dcrire informellement comme lensemble
des points dintersection de cercles infiniment proches de la famille.
Plus prcisment, si f est une fonction diffrentiable et si la courbe Ct a pour
quation f (x, y, t) = 0 pour tout t, lenveloppe de (Ct ) est lensemble des (x, y)
tels que
f
t, f (x, y, t) = 0 et (x, y, t) = 0. (9.8)
t
Dans le cas des cercles (9.7), la fonction f (x, y, t) est un polynme. Leur enveloppe
est le projet sur le plan (x, y) des solutions de (9.8), donc on peut en dterminer
une quation par le calcul didal dlimination suivant :
sage: env = ideal(eq, eq.derivative(t)).elimination_ideal(t)
sage: env.gens()
[2*x^2 - 2*y^2 - 1]
Il ny a plus qu tracer la courbe trouve :
sage: env.change_ring(QQ[x,y]).plot()

Rsultant et limination. Les oprations dlimination des exemples prc-


dents sappuient implicitement sur des bases de Grbner calcules automatique-
ment par Sage. Mais nous avons rencontr auparavant dans ce livre un autre outil
dlimination : le rsultant.
Considrons deux polynmes non constants p, q K[x1 , . . . , xn , y]. On note
Resy (p, q) le rsultant de p et q vus comme des polynmes en une indtermine y
202 CHAP. 9. SYSTMES POLYNOMIAUX

Ingalits

Considrons un triangle de sommets A = (0, 0), B = (1, 0) et C = (x, y).


Supposons les angles BAC
\ et CBA \ gaux, et tentons de prouver par le calcul
que le triangle est alors isocle. En introduisant le paramtre t = tan A =
la situation est code par les quations y = tx = t(1 x), et il sagit
tan B,
de montrer quelles entranent

x2 + y 2 = (1 x)2 + y 2 .

Avec Sage, on obtient :


sage: R.<x,y,t> = QQ[]
sage: J = (y-t*x, y-t*(1-x))*R
sage: (x^2+y^2) - ((1-x)^2+y^2) in J
False
Et pour cause : lorsque x = y = t = 0, les hypothses sont satisfaites, mais la
conclusion est fausse ! Gomtriquement, on doit exclure le cas des triangles
plats, qui peuvent avoir deux angles gaux sans tre isocles.
Comment coder, disons, la contrainte t 6= 0 ? Lastuce est dintroduire
une variable auxiliaire u, et dimposer tu = 1. Le calcul devient :
sage: R.<x,y,t,u> = QQ[]
sage: J = (y-t*x, y-t*(1-x), t*u-1)*R
sage: (x^2+y^2) - ((1-x)^2+y^2) in J
True
et lon a cette fois le rsultat attendu. Observons en passant que lon peut
forcer plusieurs expressions la fois ne pas sannuler avec une seule variable
auxiliaire, via une quation du type t1 t2 tn u = 1.

coefficients dans K[x1 , . . . , xn ]. Nous avons vu en 7.3.3 que cest un polynme


de K[x1 , . . . , xn ] qui sannule en u K n si et seulement si p(u1 , . . . , un , y) et
q(u1 , . . . , un , y) (qui sont deux polynmes de K[y]) ont un zro commun, sauf peut-
tre lorsque les coefficients dominants (en y) de p et q sannulent eux-mmes en u.
On peut dire un petit peu plus : en fait, Resy (p, q) engendre lidal dlimination 6
hp, qi K[x1 , . . . , xn ].
Ainsi, tous les calculs dlimination que nous avons faits entre deux polynmes
peuvent tre remplacs par des rsultants. Par exemple, lquation de lenveloppe
des cercles (9.7) est

sage: eq.derivative(t).resultant(eq, t)
x^2 - y^2 - 1/2

6. Les points dannulation des coefficients dominants o la proprit de spcialisation du


rsultant ne tient pas sont ceux ajouts par le passage la fermeture de Zariski lors de la
projection.
9.2. SYSTMES POLYNOMIAUX ET IDAUX 203

Nous nous en tiendrons ici au cas de deux polynmes. Il est possible dutiliser le
rsultant ou des gnralisations du rsultant pour des problmes dlimination
plus gnraux, mais la thorie est plus complique, et les outils correspondants
ne sont pas encore disponibles dans Sage.

9.2.5 Systmes de dimension zro


On peut traiter bien des problmes partir du seul calcul didaux dlimina-
tion, et Sage noffre gure dautre outil bote noire pour rsoudre des systmes
polynomiaux gnraux. La situation est diffrente en ce qui concerne les systmes
de dimension zro.
Un idal J K[x] est dit de dimension zro lorsque le quotient K[x]/J est
un espace vectoriel de dimension finie. Sur un corps algbriquement clos, cela
quivaut dire que la varit V (J) est forme dun nombre fini de points. Ainsi,
les systmes (9.1) et (9.3) engendrent des idaux de dimension zro on dit aussi
quils sont eux-mmes de dimension zro. En revanche, lidal h(x2 +y 2 )(x2 +y 2 +1)i
de Q[x, y] est de dimension 1 bien que sa seule solution relle soit (0, 0) :
sage: R.<x,y> = QQ[]
sage: ((x^2 + y^2)*(x^2 + y^2 + 1)*R).dimension()
1
Les systmes de dimension zro se rsolvent de faon plus explicite que ce
quautorisent les outils gnraux de la section prcdente. Nous avons dj vu
plusieurs de ces possibilits luvre sur lexemple de la section 9.2.1.

numrer les solutions. Tout dabord, le fait de navoir quun nombre fini de
solutions permet de les numrer, exactement ou approximativement.
Lexpression Sage J.variety(L) sert calculer la varit VL (J). Elle dclenche
une erreur si J nest pas de dimension zro. Par dfaut, elle cherche les solutions
du systme coordonnes dans le corps de base de lanneau de polynmes ambiant.
Par exemple, la sous-varit de Qn dfinie par J1 est vide :
sage: J1 = (x^2 + y^2 - 1, 16*x^2*y^2 - 1)*R
sage: J1.variety()
[]
Mais tout comme la mthode roots des polynmes une seule indtermine,
variety fonctionne pour toutes sortes de domaines L. Le plus important pour
nous ici est le corps des nombres algbriques. On peut en effet montrer que les
solutions dun systme de dimension zro coefficients dans K sont coordonnes
dans la clture algbrique de K. Ainsi, il est possible de calculer exactement la
varit complexe VC (J) = VQ (J) associe un idal J Q[x] :
sage: J1.variety(QQbar)[0:2]
[{y: -0.9659258262890683?, x: -0.2588190451025208?},
{y: -0.9659258262890683?, x: 0.2588190451025208?}]
p
Exercice 35. Montrer que les solutions de (S1 ) sont coordonnes dans Q[ 2 3]
et les exprimer par radicaux.
204 CHAP. 9. SYSTMES POLYNOMIAUX

Dcomposition triangulaire. En interne, J.variety(L) passe par le calcul


dune dcomposition triangulaire de lidal J. Cette dcomposition est intressante
en elle-mme car elle donne parfois une description de la varit V (J) plus
commode pour la suite des calculs, voire plus facile interprter que la sortie de
variety (voir 9.2.1), particulirement quand les solutions sont nombreuses.
Un systme polynomial est dit triangulaire sil est de la forme

p1 (x1 ) := xd11 + a1,d1 1 xd11 1 + + a1,0 = 0




p2 (x1 , x2 ) := xd22 + a2,d2 1 (x1 ) xd22 1 + + a2,0 (x1 ) = 0



..


.
pn (x1 , . . . , xn ) := xdnn + an,dn 1 (x1 , . . . , xn1 ) xdnn 1 + = 0

autrement dit si chaque polynme pi ne fait intervenir que les variables x1 , . . . , xi


et est unitaire en la variable xi . Quand un systme de dimension zro est de
cette forme, sa rsolution se ramne un nombre fini de rsolutions dquations
polynomiales une seule variable : il suffit de trouver les racines x1 de p1 , les
reporter dans p2 , chercher alors les racines x2 de ce dernier, et ainsi de suite. Cette
stratgie fonctionne que lon cherche les solutions exactement ou numriquement.
Tout systme nest pas quivalent un systme triangulaire. Soit par exemple J
lidal dfini par :
sage: R.<x,y> = PolynomialRing(QQ, order='lex')
sage: C = ideal(x^2+y^2-1)
sage: D = ideal((x+y-1)*(x+y+1))
sage: J = C + D
En image (voir figure 9.4) :
sage: opts = {'axes':True, 'gridlines':True, 'frame':False,
....: 'aspect_ratio':1, 'axes_pad':0, 'xmin':-1.3, 'xmax':1.3,
....: 'ymin':-1.3, 'ymax':1.3, 'fontsize': 8}
sage: show(C.plot() + D.plot(), figsize=[2,2], **opts)
La varit V (J) contient deux points dabscisse 0 mais un seul point dabscisse 1,
et de mme, un point dordonne 1 contre deux dordonne nulle. Lidal J ne
peut donc tre dcrit par un systme triangulaire.
On peut montrer en revanche que tout idal de dimension zro scrit comme
intersection finie didaux engendrs par des systmes triangulaires. La mthode
triangular_decomposition calcule une telle dcomposition :
sage: J.triangular_decomposition()
[Ideal (y, x^2 - 1) of Multivariate Polynomial Ring in x, y
over Rational Field,
Ideal (y^2 - 1, x) of Multivariate Polynomial Ring in x, y
over Rational Field]
Gomtriquement, on obtient une reprsentation de la varit V (J) comme runion
de varits associes des systmes plus simples, et souvent assez simples pour
constituer une bonne description des solutions.
9.2. SYSTMES POLYNOMIAUX ET IDAUX 205

1 1
0.5 0.5

-1 -0.5 0.5 1 -1 -0.5 0.5 1


-0.5 -0.5
-1 -1

hx2 + y 2 1, (x + y 1)(x + y + 1)i hx2 + y 2 1, (x + 2y 1)(x + 2y + 1)i


Figure 9.4 Dans chacun des deux cas, la varit associe lidal J du texte est
lintersection dun cercle et de la runion de deux droites.

Quelques difficults. On peut lgitimement se demander quel est lintrt de


la dcomposition triangulaire pour numrer les solutions. Aprs tout, face un
systme de dimension zro, il est toujours possible de trouver un polynme une
seule variable dont les racines soient exactement les premires coordonnes des
solutions, par un calcul didal dlimination. En reportant ses racines dans le
systme dquations, on diminue le nombre de variables, ce qui permet ditrer le
procd jusqu avoir compltement rsolu le systme.
Mais la remonte dans le systme en propageant les rsultats partiels peut
tre dlicate. Modifions un peu le systme prcdent :
sage: D = ideal((x+2*y-1)*(x+2*y+1)); J = C + D
sage: J.variety()
[{y: -4/5, x: 3/5}, {y: 0, x: -1}, {y: 0, x: 1}, {y: 4/5, x: -3/5}]
sage: [T.gens() for T in J.triangular_decomposition()]
[[y, x^2 - 1], [25*y^2 - 16, 4*x + 3*y]]
La forme de la dcomposition triangulaire ne change pas : pour chacune des
composantes, on dispose dune quation en y seulement, et dune seconde quation
qui permet dexprimer x en fonction de y.
liminons donc x, pour avoir de mme une quation en y seul, en loccurrence
le produit des deux prcdentes :
sage: Jy = J.elimination_ideal(x); Jy.gens()
[25*y^3 - 16*y]
Il ny a plus qu reporter les racines de cette quation dans les quations qui
dfinissent lidal J pour trouver x. Avec la premire quation, x2 + y 2 1 = 0, il
vient :
sage: ys = QQ['y'](Jy.0).roots(); ys
[(4/5, 1), (0, 1), (-4/5, 1)]
sage: QQ['x'](J.1(y=ys[0][0])).roots()
[(-3/5, 1), (-13/5, 1)]
206 CHAP. 9. SYSTMES POLYNOMIAUX

Lune des deux valeurs obtenues est correcte on a (3/5, 4/5) V (J) mais
lautre ne correspond aucune solution : il faut tester les valeurs trouves au
moyen de la seconde quation de dpart, (x + 2y 1)(x + 2y + 1), pour lliminer.
Le problme se corse si lon rsout les quations univaries numriquement,
ce qui est parfois ncessaire en raison du cot des oprations sur les nombres
algbriques :
sage: ys = CDF['y'](Jy.0).roots(); ys
[(-0.8, 1), (0.0, 1), (0.8, 1)]
sage: [CDF['x'](p(y=ys[0][0])).roots() for p in J.gens()]
[[(-0.6 - 1.30624677741e-16*I, 1), (0.6 + 1.30624677741e-16*I, 1)],
[(0.6 - 3.13499226579e-16*I, 1), (2.6 + 3.13499226579e-16*I, 1)]]
Ici, en reportant y ' 0,8 dans les deux gnrateurs de J, on trouve deux valeurs
de x proches de 0,6. Comment sassurer que ce sont des approximations de la
coordonne x dune mme solution exacte (x, y) ' (0,6, 0, 8), et non des racines
parasites comme dans lexemple prcdent ? Ces phnomnes samplifient quand
le nombre de variables et dquations augmente. Quand le systme est triangulaire
en revanche, il ny a chaque tape de remonte quune quation considrer, et
comme elle est toujours unitaire, les approximations numriques naffectent pas
le nombre de solutions.
Continuons dans la mme veine. Pour le systme suivant, J.variety() calcule
(exactement) une dcomposition triangulaire de J, puis cherche numriquement
les solutions relles du ou des systmes obtenus. Cela donne une unique solution
relle :
sage: R.<x,y> = QQ[]; J = ideal([ x^7-(100*x-1)^2, y-x^7+1 ])
sage: J.variety(RDF)
[{y: 396340.890167, x: 26.612261084}]
En menant le calcul exactement jusquau bout, on voit pourtant quil existe trois
solutions relles, et que la valeur de x dans la solution trouve numriquement
est compltement fausse :

sage: J.variety(AA)
[{x: 0.00999999900000035?, y: -0.999999999999990?},
{x: 0.01000000100000035?, y: -0.999999999999990?},
{x: 6.305568998641385?, y: 396340.8901665450?}]
Moralit : la dcomposition triangulaire nest pas une panace, et ne dispense pas
dtre prudent dans linterprtation des rsultats de calculs approchs.
Il existe un grand nombre dautres mthodes pour paramtrer et approcher
les solutions de systmes de dimension zro, plus ou moins adaptes suivant les
problmes, qui ne sont pas implmentes dans Sage. Lexercice 36 donne un aperu
de certaines ides utilises.

Algbre quotient. Les quotients par des idaux de dimension zro sont beau-
coup plus maniables que les quotients danneaux de polynmes en gnral, car les
9.3. BASES DE GRBNER 207

Mathmatiques avances

Sage dispose aussi dun grand nombre de fonctions dalgbre commutative


et de gomtrie algbrique qui dpassent largement le niveau de ce livre.
Le lecteur intress est invit explorer la documentation des idaux de
polynmes ainsi que celle du module sage.schemes. Dautres fonctionnalits
encore sont accessibles travers les interfaces aux logiciels spcialiss Singular,
CoCoA et Macaulay2.

calculs dans lalgbre quotient se ramnent de lalgbre linaire en dimension


finie.
Si J K[x] est un idal de dimension zro, la dimension dimK K[x]/J de
lalgbre quotient en tant que K-espace vectoriel est une borne sur le nombre de
points de V (J). (En effet, pour tout u V (J), il existe un polynme coefficients
dans K qui vaut 1 en u et 0 en tout autre point de V (J). Deux tels polynmes ne
peuvent pas tre quivalents modulo J.) On peut penser cette dimension comme
le nombre de solutions avec multiplicits du systme dans la clture algbrique
de K. Par exemple, nous avons relev que les quatre solutions du systme (S2 )
introduit en 9.2.3 sont chacune la double intersection de deux courbes. Cela
explique que lon ait :
sage: len(J2.variety(QQbar)), J2.vector_space_dimension()
(4, 8)
La mthode normal_basis calcule une liste de monmes dont les projections
dans K[x]/J forment une base :
sage: J2.normal_basis()
[x*y^3, y^3, x*y^2, y^2, x*y, y, x, 1]
La base renvoye dpend de lordre sur les termes choisi la construction de
lanneau de polynmes ; nous la dcrivons plus prcisment en 9.3.3.
Exercice 36. Soit J un idal de dimension zro de Q[x, y]. Soit x le polynme
caractristique de lapplication linaire

mx : Q[x, y]/J Q[x, y]/J


p+J 7 xp + J.

Calculer x dans le cas J = J2 = hx2 + y 2 1, 4x2 y 2 1i. Montrer que toute racine
de x est labscisse dun point de la varit VC (J).

9.3 Bases de Grbner


Nous avons jusquici utilis les fonctionnalits dlimination algbrique et
de rsolution de systmes polynomiaux quoffre Sage comme des botes noires.
Cette section introduit quelques-uns des outils mathmatiques et algorithmiques
sous-jacents. Le but est la fois dy recourir directement et de faire un usage
avis des fonctions de plus haut niveau prsentes auparavant.
208 CHAP. 9. SYSTMES POLYNOMIAUX

Principaux ordres monomiaux, avec lexemple de Q[x, y, z]


lex x < x 1 < 1 ou (1 = 1 et 2 < 2 ) ou . . .
ou (1 = 1 , . . . , n1 = n1 et n < n )
x3 > x2 y > x2 z > x2 > xy 2 > xyz > xy > xz 2 > xz > x > y 3
> y 2 z > y 2 > yz 2 > yz > y > z 3 > z 2 > z > 1

invlex x < x n < n ou (n = n et n1 < n1 ) ou . . .


ou (n = n , . . . , 2 = 2 et 1 < 1 )
z 3 > yz 2 > xz 2 > z 2 > y 2 z > xyz > yz > x2 z > xz > z > y 3
> xy 2 > y 2 > x2 y > xy > y > x3 > x2 > x > 1

deglex x < x || < || ou (|| = || et x <lex x )


x3 > x2 y > x2 z > xy 2 > xyz > xz 2 > y 3 > y 2 z > yz 2 > z 3 > x2
> xy > xz > y 2 > yz > z 2 > x > y > z > 1

degrevlex x < x || < || ou (|| = || et x >invlex x )


x3 > x2 y > xy 2 > y 3 > x2 z > xyz > y 2 z > xz 2 > yz 2 > z 3 > x2
> xy > y 2 > xz > yz > z 2 > x > y > z > 1

Construction dordres monomiaux


objet reprsentant un ordre prdfini sur n variables TermOrder('nom', n)
ordre matriciel : x <M x M <lex M TermOrder(M)
blocs : x y < x y <1 ou ( = et <2 ) T1 + T2

Tableau 9.5 Ordres monomiaux.

Les techniques employes par Sage pour les calculs sur les idaux et llimi-
nation reposent sur la notion de base de Grbner. On peut voir celle-ci, entre
autres, comme une extension plusieurs indtermines de la reprsentation par
gnrateur principal des idaux de K[x]. Le problme central de cette section est
de dfinir et calculer une forme normale pour les lments des algbres quotients
de K[x]. Notre point de vue reste celui de lutilisateur : nous dfinissons les bases
de Grbner, montrons comment en obtenir avec Sage et quoi cela peut servir,
mais nous nabordons pas les algorithmes utiliss pour faire le calcul.

9.3.1 Ordres monomiaux


Un ordre monomial ou ordre admissible (global) est un ordre total sur les
monmes x dun anneau de polynmes K[x] qui satisfait

x < x = x+ < x+ et 6= 0 = 1 < x (9.9)

pour tous exposants , , . De faon quivalente, on peut considrer < comme


un ordre sur les exposants Nn ou encore sur les termes c x . Les monme de
tte, coefficient de tte et terme de tte dun polynme p (voir 9.1.3) pour lordre
monomial ambiant sont ceux de plus grand exposant ; on les note respectivement
lm p, lc p et lt p.
La premire des conditions (9.9) exprime une contrainte de compatibilit avec
la multiplication : le produit par un monme fix ne change pas lordre. La seconde
9.3. BASES DE GRBNER 209

impose que < soit un bon ordre, cest--dire quil nexiste pas de suite infinie
strictement dcroissante de monmes. Remarquons que le seul ordre admissible
sur K[x] est lordre usuel xn > xn1 > > 1.
Nous avons vu en 9.1.1 que Sage permet de slectionner un ordre lors de la
dfinition dun anneau de polynmes via des constructions comme
sage: R.<x,y,z,t> = PolynomialRing(QQ, order='lex')

Le tableau 9.5 recense les principaux ordres admissibles prdfinis 7 : lex est lordre
lexicographique des exposants, invlex lordre lexicographique des exposants lus
de droite gauche, et deglex range les monmes par degr total puis par ordre
lexicographique. La dfinition de degrevlex est un peu plus complique : les
monmes sont rangs par degr total, puis dans lordre lexicographique dcroissant
des exposants lus partir de la droite. Cet ordre surprenant est pourtant celui
adopt par dfaut quand on omet loption order, car il est plus efficace que les
autres pour certains calculs.
On choisit gnralement (mais pas toujours !) conjointement lordre des va-
riables de lanneau et celui des monmes de sorte que x1 > x2 > > xn , et lon
parle alors souvent, par exemple, de lordre lex tel que x > y > z plutt que
de lordre lex sur K[x, y, z] . Les ordres prdfinis lex, deglex et degrevlex
obissent cette convention ; quant lordre invlex sur K[x, y, z], cest aussi
lordre lex tel que z > y > x, cest--dire celui sur K[z, y, x].

9.3.2 Division par une famille de polynmes


Un ordre monomial < tant fix, soit G = {g1 , g2 , . . . , gs } un ensemble fini
de polynmes de K[x]. On note hGi = hg1 , g2 , . . . , gs i lidal de K[x] engendr
par G.
La division dun polynme p K[x] par G est un analogue multivari de la
division euclidienne dans K[x]. Comme cette dernire, elle associe p un reste,
donn en Sage par lexpression p.reduce(G), qui est un polynme plus petit
appartenant la mme classe dquivalence modulo hGi :
sage: ((x+y+z)^2).reduce([x-t, y-t^2, z^2-t])
2*z*t^2 + 2*z*t + t^4 + 2*t^3 + t^2 + t

Le reste est obtenu en retranchant p, tant que cest possible, des multiples
dlments de G dont le terme de tte sannule avec un terme de p lors de la
soustraction. la diffrence du cas univari, il arrive que lon puisse annuler ainsi
un terme de p, mais pas celui de tte : on demande donc seulement dannuler un
terme le plus grand possible au sens de lordre monomial.

7. Sage admet aussi des ordres (dits locaux) dans lesquels 1 est le plus grand des monmes au
lieu dtre le plus petit. Par exemple, dans lordre neglex sur Q[x, y, z], on a 1 > z > z 2 > z 3 >
y > yz > yz 2 > y 2 > y 2 z > y 3 > x > xz > xz 2 > xy > xyz > xy 2 > x2 > x2 z > x2 y > x3 .
Les ordres locaux ne sont pas des ordres admissibles au sens de la dfinition (9.9), et nous ne les
utilisons pas dans ce livre, mais le lecteur intress pourra complter le tableau 9.5 en utilisant
la fonction test_poly dfinie en 9.1.1.
210 CHAP. 9. SYSTMES POLYNOMIAUX

Formellement, pour p K[x], notons ltG p le terme de p dexposant maximal


divisible par un terme de tte dlment de G. Appelons rduction lmentaire
toute transformation de la forme
p 7 p = p c x g, o g G et ltG p = c x lt g. (9.10)
Une rduction lmentaire prserve la classe dquivalence de p modulo hGi, et
fait disparatre le plus grand monme de p quelle affecte : on a
p p hGi et ltG p < ltG p.
Comme < est un bon ordre, il nest pas possible dappliquer un polynme
une infinit de rductions lmentaires successives. Toute suite de rductions
lmentaires se termine donc sur un polynme qui ne peut plus tre rduit, qui
est le reste de la division.
Observons que ce procd gnralise des mthodes familires dlimination
la fois pour les polynmes une indtermine et pour les systmes linaires.
Sil ny a quune seule variable, la division dun polynme p par un singleton
G = {g} se rduit exactement la division euclidienne de p par g. Dans lautre
cas extrme de polynmes en plusieurs indtermines mais dont tous les monmes
sont de degr 1, elle devient identique lopration lmentaire de rduction de
la mthode de Gauss-Jordan.
Mais contrairement ce quil se passe dans ces cas particuliers, en gnral,
le reste dpend du choix des rductions lmentaires. (On dit que le systme
de rgles de rcriture (9.10) nest pas confluent.) Ainsi, changer lordre dans
lequel on donne les lments de G conduit dans lexemple suivant des choix de
rductions diffrents :
sage: R.<x,y> = PolynomialRing(QQ, order='lex')
sage: (g, h) = (x-y, x-y^2); p = x*y - x
sage: p.reduce([g, h]) # deux rductions par h
y^3 - y^2
sage: p.reduce([h, g]) # deux rductions par g
y^2 - y
Quand bien mme les lments de G seraient considrs dans un ordre dterministe
(de faon rendre le rsultat unique pour p et G donns), comment sassurer, par
exemple, que la suite de rductions lmentaires de p par {g, h} choisie dcouvrira
la relation suivante qui montre que p hg, hi ?
sage: p - y*g + h
0

9.3.3 Bases de Grbner


Les limitations de la division multivarie expliquent la difficult mentionne
en 9.2.3 obtenir une forme normale pour les lments des algbres K[x]/J :
diviser par les gnrateurs de lidal ne suffit pas... Du moins en gnral ! Car
il existe des systmes de gnrateurs particuliers pour lesquels la division est
confluente, et calcule une forme normale. Ces systmes sappellent des bases de
Grbner, ou bases standard.
9.3. BASES DE GRBNER 211

y
y

x z
4 3 3 4 5
hxy , x y , x y, x i hx3 , xy 2 z, xz 2 i
Figure 9.5 Escaliers didaux engendrs par des monmes.

y y y

x x x
hx + y 1, 16 x y 1i
2 2 2 2
h16 x y 1i
2 2
hx + y 1, (x + y)2
2 2

1i
Figure 9.6 Escaliers didaux de Q[x, y] rencontrs dans ce chapitre. Dans ces trois
cas, lescalier et la position des gnrateurs sont les mmes pour les ordres lex, deglex et
degrevlex.

y y y

x x x
lex(x, y) invlex(x, y) = lex(y, x) degrevlex(x, y)
Figure 9.7 Escaliers de lidal hxy + x + y 2 + 1, x2 y + xy 2 + 1i Q[x, y] relativement
diffrents ordres monomiaux.

Sur chaque schma, la zone grise correspond aux termes de tte des lments de lidal. Les
carrs noirs donnent la position des gnrateurs utiliss pour le dcrire.
212 CHAP. 9. SYSTMES POLYNOMIAUX

Escaliers. Une faon plaisante dapprhender les bases de Grbner passe par la
notion descalier dun idal. Attachons chaque polynme non nul de K[x1 , . . . , xn ]
au point de Nn donn par son exposant de tte, et dessinons la partie E Nn
ainsi occupe par un idal J (voir figures 9.5 9.7). Le dessin obtenu (qui dpend
de lordre monomial) est en forme descalier : en effet, on a + Nn E pour tout
E. Les lments de J \{0} sont dans la zone grise, au-dessus de lescalier ou
sa frontire. Les points strictement sous lescalier correspondent exclusivement
des polynmes de K[x] \ J, mais tous les polynmes de K[x] \ J ne sont pas
sous lescalier.
Par exemple, dans un polynme de hx3 , xy 2 z, xz 2 i, tout monme, de tte
ou non, est multiple dun des polynmes x3 , xy 2 z et xz 2 . Les monmes de tte
sont donc exactement les x y z vrifiant lune des ingalits (, , ) > (3, 0, 0),
(, , ) > (1, 2, 1) ou (, , ) > (1, 0, 2) composante par composante (figure 9.5).
Un polynme dont lexposant de tte ne satisfait pas ces conditions, par exemple
x2 + xz 2 si lordre ambiant est lordre lexicographique avec x > y > z, ne peut
appartenir lidal. Certains polynmes comme x3 + x ne sont pas non plus dans
lidal malgr un monme de tte au-dessus de lescalier. La situation est analogue
pour tout idal engendr par des monmes.
Pour un idal quelconque, la structure de lescalier ne se lit pas facilement sur
les gnrateurs.
Ss Ainsi, en notant 1 , . . . , s les exposants de tte des gnrateurs,
on a i=1 ( i + Nn ) ( E dans tous les exemples des figures 9.6 et 9.7 sauf le
deuxime. On peut cependant montrer que E scrit toujours comme runion
dun nombre fini densembles de la forme + Nn , cest--dire intuitivement que
lescalier na quun nombre fini de coins. Ce rsultat est parfois appel lemme de
Dickson.

Bases de Grbner. Une base de Grbner est simplement une famille de


gnrateurs qui capture la forme de lescalier, et plus prcisment qui compte un
polynme chaque coin de celui-ci.
Dfinition. Une base de Grbner dun idal J K[x] relativement un
ordre monomial < est une partie finie G de J telle que pour tout p J non nul,
il existe g G dont le monme de tte (pour lordre <) lm g divise lm p.
Tester si les gnrateurs par lesquels est dfini un idal forment une base de
Grbner se fait en Sage avec la mthode basis_is_groebner. Nous avons dj
observ que tout ensemble de monmes est une base de Grbner :
sage: R.<x,y> = PolynomialRing(QQ, order='lex')
sage: R.ideal(x*y^4, x^2*y^3, x^4*y, x^5).basis_is_groebner()
True
En revanche, le systme {x2 + y 2 1, 16 x2 y 2 1} qui code lintersection du cercle
et des hyperboles de la figure 9.1a nest pas une base de Grbner :
sage: R.ideal(x^2+y^2-1, 16*x^2*y^2-1).basis_is_groebner()
False
Daprs la forme de lescalier (figure 9.6), il lui manque pour cela un polynme
de J1 de monme de tte y 4 .
9.3. BASES DE GRBNER 213

Largument fond sur le lemme de Dickson esquiss ci-dessus montre que tout
idal admet des bases de Grbner 8 . Calculons des bases de Grbner de J1 et des
autres idaux dont les escaliers sont reprsents figure 9.6. Dans le cas de J1 , il
vient :
sage: R.ideal(x^2+y^2-1, 16*x^2*y^2-1).groebner_basis()
[x^2 + y^2 - 1, y^4 - y^2 + 1/16]

On voit apparatre comme prvu les monmes de tte x2 et y 4 . Leur prsence


explique la faon dont lescalier se referme sur les axes, dont nous verrons quelle est
caractristique des systmes de dimension zro. Concernant la double hyperbole
seule, on trouve :
sage: R.ideal(16*x^2*y^2-1).groebner_basis()
[x^2*y^2 - 1/16]

cest--dire un multiple du gnrateur. De faon gnrale, tout singleton est une


base de Grbner. Le troisime exemple montre quune base de Grbner peut
ncessiter plus de polynmes quun systme de gnrateurs quelconque :
sage: R.ideal(x^2+y^2-1, (x+y)^2-1).groebner_basis()
[x^2 + y^2 - 1, x*y, y^3 - y]

Du fait de la simplicit des exemples prcdents, ces trois bases de Grbner ne


dpendent pas ou peu de lordre monomial. Il en va bien diffremment en gnral.
La figure 9.7 reprsente les escaliers associs un mme idal de Q[x, y] pour
trois ordres monomiaux classiques. Des bases de Grbner correspondantes sont :
sage: R_lex.<x,y> = PolynomialRing(QQ, order='lex')
sage: J_lex = (x*y+x+y^2+1, x^2*y+x*y^2+1)*R_lex; J_lex.gens()
[x*y + x + y^2 + 1, x^2*y + x*y^2 + 1]
sage: J_lex.groebner_basis()
[x - 1/2*y^3 + y^2 + 3/2, y^4 - y^3 - 3*y - 1]

sage: R_invlex = PolynomialRing(QQ, 'x,y', order='invlex')


sage: J_invlex = J_lex.change_ring(R_invlex); J_invlex.gens()
[y^2 + x*y + x + 1, x*y^2 + x^2*y + 1]
sage: J_invlex.groebner_basis()
[y^2 + x*y + x + 1, x^2 + x - 1]

sage: R_drl = PolynomialRing(QQ, 'x,y', order='degrevlex')


sage: J_drl = J_lex.change_ring(R_drl); J_drl.gens()
[x*y + y^2 + x + 1, x^2*y + x*y^2 + 1]
sage: J_drl.groebner_basis()
[y^3 - 2*y^2 - 2*x - 3, x^2 + x - 1, x*y + y^2 + x + 1]

8. On peut voir ce rsultat comme une version effective du thorme de nthrianit de


Hilbert, qui affirme que les idaux de K[x] sont engendrs par un nombre fini dlments. Une
preuve classique de ce thorme rappelle fortement la construction dune base de Grbner pour
lordre lexicographique.
214 CHAP. 9. SYSTMES POLYNOMIAUX

Rduction
division multivarie de p par G p.reduce(G)
gnrateurs inter-rduits J.interreduced_basis()

Bases de Grbner
test de base de Grbner J.basis_is_groebner()
base de Grbner (rduite) J.groebner_basis()
changement dordre pour lex J.transformed_basis()
changement dordre R1 R2 J.transformed_basis('fglm', other_ring=R2)

Tableau 9.6 Bases de Grbner.

La base de Grbner pour lordre lex met en vidence la rgle de rcriture x =


2 y y 2 , grce laquelle on peut exprimer les lments de lalgbre quotient
1 3 2 3

en fonction de la seule variable y. La forme allonge de lescalier correspondant


reflte cette possibilit. De mme, la base de Grbner pour lordre invlex indique
quon peut liminer les puissances de y via lgalit y 2 = xy x 1. Nous y
reviendrons la fin de la section suivante.

9.3.4 Proprits des bases de Grbner


Les bases de Grbner servent implmenter les oprations tudies dans la
section 9.2. On les utilise notamment afin de calculer des formes normales pour
les idaux danneaux de polynmes et les lments des quotients par ces idaux,
dliminer des variables dans les systmes polynomiaux, ou encore de dterminer
des caractristiques des solutions telles que leur dimension.

Division par une base de Grbner. La division par une base de Grbner G
dun polynme de hGi ne peut sarrter sur un lment non nul de hGi. Cest une
consquence immdiate de la dfinition : en effet, un tel lment serait au-dessus
de lescalier associ hGi, donc encore divisible par G. Tout lment de hGi se
rduit donc zro dans la division par G. En particulier, une base de Grbner
dun idal J engendre J.
De mme, la division dun polynme p / J par une base de Grbner de J ne
peut sarrter que sur un polynme sous lescalier , or deux polynmes distincts
sous lescalier appartiennent des classes dquivalence distinctes modulo J
(puisque leur diffrence est encore sous lescalier ). La division par une base de
Grbner fournit donc une forme normale pour les lments du quotient K[x]/J, et
ce, indpendamment de lordre dans lequel on effectue les rductions lmentaires.
La forme normale dune classe dquivalence p + J est son unique reprsentant
situ sous lescalier ou nul. Cest cette forme normale que calculent les oprations
dans lalgbre quotient prsentes en 9.2.3. Pour poursuivre lexemple de la
figure 9.7, la rduction
sage: p = (x + y)^5
sage: J_lex.reduce(p)
9.3. BASES DE GRBNER 215

17/2*y^3 - 12*y^2 + 4*y - 49/2

se dcompose en un calcul de base de Grbner suivi dune division :


sage: p.reduce(J_lex.groebner_basis())
17/2*y^3 - 12*y^2 + 4*y - 49/2

Le rsultat dune projection dans le quotient est essentiellement le mme :


sage: R_lex.quo(J_lex)(p)
17/2*ybar^3 - 12*ybar^2 + 4*ybar - 49/2

Naturellement, changer dordre monomial donne lieu un choix de forme normale


diffrent :
sage: R_drl.quo(J_drl)(p)
5*ybar^2 + 17*xbar + 4*ybar + 1

Les monmes qui apparaissent dans la forme normale correspondent aux points
sous lescalier.
Ainsi, lidal J est de dimension zro si et seulement si le nombre de points sous
son escalier est fini, et ce nombre de points est la dimension du quotient K[x]/J.
Dans ce cas, la base que renvoie la mthode normal_basis dcrite en 9.2.5
est simplement lensemble des monmes sous lescalier pour lordre monomial
ambiant :
sage: J_lex.normal_basis()
[y^3, y^2, y, 1]
sage: J_invlex.normal_basis()
[x*y, y, x, 1]
sage: J_drl.normal_basis()
[y^2, y, x, 1]

Remarquons en passant que le nombre de monmes sous lescalier est indpendant


de lordre monomial.

Dimension. Nous sommes maintenant arms pour donner une dfinition de la


dimension dun idal dans le cas gnral : J est de dimension d lorsque le nombre
de points sous lescalier correspondant des monmes de degr total au plus t
est de lordre de td quand t . Par exemple, lidal h16 x2 y 2 1i (figure 9.6)
est de dimension 1 :
sage: ideal(16*x^2*y^2-1).dimension()
1

En effet, le nombre de monmes m sous lescalier tels que degx m + degy m 6 t


est gal 4t 2 pour t > 3. De mme, les deux idaux de la figure 9.5 sont
respectivement de dimension 1 et de dimension 2. On peut montrer que la
valeur de la dimension ne dpend pas de lordre monomial, et correspond hors
dgnrescences la dimension gomtrique de la varit associe lidal.
216 CHAP. 9. SYSTMES POLYNOMIAUX

Bases rduites. Un ensemble fini de polynmes qui contient une base de


Grbner est lui-mme une base de Grbner, donc un idal non nul a une infinit
de bases de Grbner. Une base de Grbner G = {g1 , . . . , gs } est dite rduite
lorsque
les coefficients de tte des gi valent tous 1 (et 0
/ G) ;
et aucun des gi nest rductible par le reste de la base G \ {gi } au sens des
rgles (9.10).
ordre monomial fix, chaque idal admet une unique base de Grbner rduite.
Par exemple, la base de Grbner rduite de lidal h1i est le singleton {1}, quel
que soit lordre. Les bases de Grbner rduites fournissent donc une forme normale
pour les idaux de K[x].
Une base de Grbner rduite est minimale au sens o, si on lui enlve un
quelconque lment, ce qui reste nest plus un systme de gnrateurs de lidal.
Concrtement, elle comporte exactement un polynme par coin de lescalier.
Elle peut se calculer partir dune base de Grbner quelconque G en remplaant
chaque lment g G par son reste dans la division par G \ {g}, et ainsi de suite
tant que cest possible. Cest ce que fait la mthode interreduced_basis. Les
polynmes qui se rduisent zro sont effacs.

limination. Les ordres lexicographiques jouissent de la proprit fondamentale


suivante : si G est une base de Grbner pour lordre lexicographique de J
K[x1 , . . . , xn ], alors les G K[xk+1 , . . . , xn ] sont des bases de Grbner des idaux
dlimination 9 J K[xk+1 , . . . , xn ]. Une base de Grbner lexicographique se
dcompose en blocs dont le dernier ne dpend que de xn , lavant-dernier de xn
et xn1 , et ainsi de suite 10 :
sage: R.<t,x,y,z> = PolynomialRing(QQ, order='lex')
sage: J = R.ideal(t+x+y+z-1, t^2-x^2-y^2-z^2-1, t-x*y)
sage: [u.polynomial(u.variable(0)) for u in J.groebner_basis()]
[t + x + y + z - 1,
(y + 1)*x + y + z - 1,
(z - 2)*x + y*z - 2*y - 2*z + 1,
(z - 2)*y^2 + (-2*z + 1)*y - z^2 + z - 1]
Dans cet exemple, le dernier polynme de la base ne dpend que de y et z.
Viennent auparavant un bloc de deux polynmes en x, y et z, et en premier
un polynme qui fait intervenir toutes les variables. Les idaux dlimination
successifs sy lisent immdiatement.
Nous avons vu cependant (9.2.5) que ces derniers ne fournissent pas une
description parfaite de lidal. Ici, le bloc des polynmes en z seul est vide,
donc toute valeur de z sauf peut-tre un nombre fini apparat comme dernire
coordonne dune solution. On est tent dexprimer les valeurs de y possibles
9. Pour un k donn, cest vrai plus gnralement de tout ordre tel que i 6 k < j = xi > xj .
Un ordre qui satisfait une proprit de ce type est dit par blocs (voir aussi tableau 9.5).
10. Cest donc une forme triangulaire du systme form par les gnrateurs de lidal,
quoiquen un sens plus faible que celui dfini en 9.2.5 : on ne peut pas dire grand-chose a priori
sur le nombre de polynmes de chaque bloc ou leurs termes de tte.
9.3. BASES DE GRBNER 217

pour chaque z grce la dernire quation. Elles sont au nombre de deux, sauf
pour z = 2, pour lequel seul y = 1 convient. Ce nest quen passant lquation
prcdente que lon voit que le choix z = 2 est contradictoire. Inversement,
nouveau daprs la dernire quation, y = 1 implique z = 2, donc est exclu. Il
savre donc finalement quaucun des coefficients de tte des polynmes (crits
en leur variable principale respective, comme dans la sortie Sage ci-dessus) ne
sannule pour z 6= 2.
Exercice 37 (Relations trigonomtriques). crire (sin )6 comme un polynme en
u() = sin + cos et v() = sin(2) + cos(2).

9.3.5 Calcul
Nous renvoyons le lecteur intress par les algorithmes de calcul de bases de
Grbner aux rfrences [CLO07, FSED09, EM07] mentionnes en introduction.
En complment, le module sage.rings.polynomial.toy_buchberger de Sage
offre une implmentation pdagogique de lalgorithme de Buchberger et de
diffrents algorithmes lis, qui suit de prs leur description thorique.

Changement dordre

Les bases de Grbner les plus intressantes ne sont pas les plus faciles
calculer : souvent, lordre degrevlex est le moins coteux, mais on lit plus
dinformations utiles sur une base de Grbner lexicographique. Par ailleurs,
on a occasionnellement besoin de bases de Grbner dun mme idal pour
plusieurs ordres diffrents.
Cela motive lintroduction, en plus des algorithmes de calcul de base
de Grbner gnraux, dalgorithmes dits de changement dordre. Ceux-ci
calculent une base de Grbner pour un ordre monomial partir dune base de
Grbner du mme idal pour un ordre diffrent. Ils sont souvent plus efficaces
que ceux qui partent dun systme de gnrateurs quelconques. Ainsi, une stra-
tgie souvent fructueuse pour obtenir une base de Grbner lexicographique
consiste commencer par en calculer une pour lordre degrevlex, puis ap-
pliquer une mthode de changement dordre. Sage fait cela automatiquement
dans certains cas.
La mthode transformed_basis permet de calculer la main des
bases de Grbner par changement dordre, quand lidal est de dimension
zro ou si lordre cible est lex. Au besoin, elle commence par calculer une
base de Grbner pour lordre attach lanneau de polynmes.

Retenons toutefois que le calcul dune base de Grbner est une opration
coteuse en temps de calcul comme en mmoire, voire trs coteuse dans les
cas dfavorables. La mthode groebner_basis admet dailleurs de nombreuses
options 11 qui permettent lutilisateur expert de choisir manuellement un algo-
rithme de calcul de base de Grbner en fonction des caractristiques du problme.
11. Pour plus de dtails, voir sa page daide ainsi que celles des mthodes internes de lidal
concern, dont le nom commence par _groebner_basis.
218 CHAP. 9. SYSTMES POLYNOMIAUX

Considrons les idaux Cn (K) K[x0 , . . . , xn1 ] dfinis par :

C2 (K) = hx0 + x1 , x0 x1 1i
C3 (K) = hx0 + x1 + x2 , x0 x1 + x0 x2 + x1 x2 , x0 x1 x2 1i
..
. (9.11)
D X Y k En2
Cn (K) = xi+j + hx0 xn1 1i,
k=0
iZ/nZ j=0

et accessibles en Sage par des commandes telles que :


sage: from sage.rings.ideal import Cyclic
sage: Cyclic(QQ['x,y,z'])
Ideal (x + y + z, x*y + x*z + y*z, x*y*z - 1) of
Multivariate Polynomial Ring in x, y, z over Rational Field
Ce sont des problmes de test classiques pour valuer les performances doutils de
rsolution des systmes polynomiaux. Sur une machine o Sage met moins dune
seconde calculer la base de Grbner rduite de C6 (Q) :
sage: def C(R, n): return Cyclic(PolynomialRing(R, 'x', n))

sage: %time len(C(QQ, 6).groebner_basis())


CPU times: user 0.25 s, sys: 0.01 s, total: 0.26 s
Wall time: 0.97 s
45
le calcul de celle de C7 (Q) ne se termine pas en une douzaine dheures, et utilise
plus de 3 Go de mmoire.
dfaut de pouvoir calculer la base de Grbner sur les rationnels, essayons de
remplacer Q par un corps fini Fp . Lide, habituelle en calcul formel, est de limiter
le cot des oprations sur les coefficients : celles sur les lments de Fp prennent
un temps constant, tandis que le nombre de chiffres des rationnels a tendance
crotre violemment au fil des calculs. On choisit p suffisamment petit pour que
les calculs dans Fp puissent tre faits directement sur des entiers machine. Il ne
doit cependant pas tre trop petit, de sorte que la base de Grbner sur Fp ait des
chances de partager une bonne partie de la structure de celle sur Q.
Par exemple, avec un p convenable, la base de Grbner de C6 (Fp ) a le mme
nombre dlments que celle de C6 (Q) :
sage: p = previous_prime(2^30)
sage: len(C(GF(p), 6).groebner_basis())
45
En augmentant la taille du systme traiter, on voit que linfluence du corps des
coefficients sur le temps de calcul est loin dtre ngligeable : les cas n = 7 et
n = 8 deviennent faisables sans problme.
sage: %time len(C(GF(p), 7).groebner_basis())
9.3. BASES DE GRBNER 219

CPU times: user 3.71 s, sys: 0.00 s, total: 3.71 s


Wall time: 3.74 s
209
sage: %time len(C(GF(p), 8).groebner_basis())
CPU times: user 104.30 s, sys: 0.07 s, total: 104.37 s
Wall time: 104.49 s
372
Ces exemples illustrent aussi un autre phnomne important : la sortie dun calcul
de base de Grbner peut tre beaucoup plus grosse que lentre. Ainsi, le dernier
calcul ci-dessus montre que toute base de Grbner, rduite ou non, de C8 (Fp )
(avec cette valeur de p) pour lordre degrevlex compte au moins 372 lments,
alors que C8 est engendr par seulement 8 polynmes.
220 CHAP. 9. SYSTMES POLYNOMIAUX
Pour rsoudre cette quation diffrentielle, regardez-la
jusqu ce que la solution vienne delle-mme.
George Plya (1887 - 1985)

quations diffrentielles et suites dfinies


10
par une relation de rcurrence

10.1 quations diffrentielles


10.1.1 Introduction
Si la mthode de George Plya semble peu efficace, on peut faire appel
Sage mme si le domaine de la rsolution formelle des quations diffrentielles
demeure une faiblesse de nombreux logiciels de calcul. Sage est en pleine volution
cependant et progresse chaque version un peu plus en largissant son spectre de
rsolution.
On peut, si on le souhaite, invoquer Sage afin dobtenir une tude qualitative :
en effet, ses outils numriques et graphiques guideront lintuition. Cest lobjet
de la section 14.2 du chapitre consacr au calcul numrique. Des outils dtude
graphique des solutions sont donns la section 4.1.6. Des mthodes de rsolution
laide de sries se trouvent la section 7.5.2.
On peut prfrer rsoudre les quations diffrentielles exactement. Sage peut
alors parfois y aider en donnant directement une rponse formelle comme nous le
verrons dans ce chapitre.
Dans la plupart des cas, il faudra passer par une manipulation savante de
ces quations pour aider Sage. Il faudra veiller garder en tte que la solution
attendue dune quation diffrentielle est une fonction drivable sur un certain
intervalle mais que Sage, lui, manipule des expressions sans domaine de dfinition.
La machine aura donc besoin dune intervention humaine pour aller vers une
solution rigoureuse.
222 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

Nous tudierons dabord les gnralits sur les quations diffrentielles ordi-
naires dordre 1 et quelques cas particuliers comme les quations linaires, les
quations variables sparables, les quations homognes, une quation dpendant
dun paramtre (10.1.2) ; puis de manire plus sommaire les quations dordre 2
ainsi quun exemple dquation aux drives partielles (10.1.3). Nous terminerons
par lutilisation de la transforme de Laplace (10.1.4) et enfin la rsolution de
certains systmes diffrentiels (10.1.5).
On rappelle quune quation diffrentielle ordinaire (parfois note EDO, ou
ODE en anglais) est une quation faisant intervenir une fonction (inconnue)
dune seule variable, ainsi quune ou plusieurs drives, successives ou non, de la
fonction.
Dans lquation y 0 (x) + x y(x) = sin(x) la fonction inconnue y est appele la
variable dpendante et la variable x (par rapport laquelle y varie) est appele la
variable indpendante.
Une quation aux drives partielles (note parfois EDP, ou PDE en anglais)
fait intervenir plusieurs variables indpendantes ainsi que les drives partielles
de la variable dpendante par rapport ces variables indpendantes.
Sauf mention contraire, on considrera dans ce chapitre des fonctions dune
variable relle.

10.1.2 quations diffrentielles ordinaires dordre 1


Commandes de base. On voudrait rsoudre une EDO dordre 1 :

F (x, y(x), y 0 (x)) = 0.

On commence par dfinir une variable x et une fonction y dpendant de cette


variable :
sage: x = var('x')
sage: y = function('y', x)
On utilise ensuite :
sage: desolve(equation, variable,ics = ..., ivar = ...,
....: show_method = ..., contrib_ode = ...)
o :
equation est lquation diffrentielle. Lgalit est symbolise par ==. Par
exemple lquation y 0 = 2y + x scrit diff(y,x) == 2*y+x ;
variable est le nom de la variable dpendante, cest--dire la fonction y
dans y 0 = 2y + x ;
ics est un argument optionnel qui permet dindiquer des conditions initiales.
Pour une quation du premier ordre, on donne une liste [x0 ,y0 ], pour les
quations du second ordre cest [x0 ,y0 ,x1 ,y1 ] ou [x0 ,y0 ,y00 ] ;
ivar est un argument optionnel qui permet de prciser la variable indpen-
dante, cest--dire x dans y 0 = 2y + x. Cet argument doit absolument tre
prcis en cas dquations dpendant de paramtres comme par exemple
y 0 = ay + bx + c ;
10.1. QUATIONS DIFFRENTIELLES 223

show_method est un argument optionnel fix False par dfaut. Dans


le cas contraire, il demande Sage de prciser la mthode de rsolution
utilise. Les termes anglais renvoys peuvent tre linear, separable, exact,
homogeneous, bernoulli, generalized homogeneous. Sage renvoie alors
une liste dont le premier argument est la solution et le deuxime la mthode ;
contrib_ode est un argument optionnel par dfaut fix False. Dans le
cas contraire, desolve pourra soccuper des quations de Riccati, Lagrange,
Clairaut et dautres cas pathologiques.

quations du premier ordre pouvant tre rsolues directement par


Sage. Nous allons tudier dans cette section comment rsoudre avec Sage les
quations linaires, les quations variables sparables, les quations de Bernoulli,
les quations homognes, les quations exactes, ainsi que les quations de Riccati,
Lagrange et Clairaut.
quations linaires. Il sagit dquations du type :

y 0 + P (x)y = Q(x),

o P et Q sont des fonctions continues sur des intervalles donns.


Exemple : y 0 + 3y = ex .
sage: x = var('x'); y = function('y', x)

sage: desolve(diff(y,x) + 3*y == exp(x), y, show_method=True)


[1/4*(4*c + e^(4*x))*e^(-3*x), 'linear']

quations variables sparables. Il sagit dquations du type :

P (x) = y 0 Q(y),

o P et Q sont des fonctions continues sur des intervalles donns.


Exemple : yy 0 = x.
sage: desolve(y*diff(y,x) == x, y, show_method=True)
[1/2*y(x)^2 == 1/2*x^2 + c, 'separable']
Attention ! Sage parfois ne reconnat pas les quations variables sparables et
les traite comme des quations exactes. Exemple : y 0 = ex+y .
sage: desolve(diff(y,x) == exp(x+y), y, show_method=True)
[-(e^(x + y(x)) + 1)*e^(-y(x)) == c, 'exact']

quations de Bernoulli. Il sagit dquations du type :

y 0 + P (x)y = Q(x)y ,

o P et Q sont des fonctions continues sur des intervalles donns et 6 0, 1 .




Exemple : y 0 y = xy 4 .
sage: desolve(diff(y,x)-y == x*y^4, y, show_method=True)
224 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

[e^x/(-1/3*(3*x - 1)*e^(3*x) + c)^(1/3), 'bernoulli']

quations homognes. Il sagit dquations du type :

P (x, y)
y0 = ,
Q(x, y)

o P et Q sont des fonctions homognes de mme degr sur des intervalles donns.
Exemple : x2 y 0 = y 2 + xy + x2 .
sage: desolve(x^2*diff(y,x) == y^2+x*y+x^2, y, show_method=True)
[c*x == e^(arctan(y(x)/x)), 'homogeneous']

Les solutions ne sont pas donnes de manire explicite. Nous verrons plus loin
comment se dbrouiller dans certains cas.
quations exactes. Il sagit dquations du type :

f f
dx + dy,
x y

avec f une fonction de deux variables diffrentiable.


cos(y)2x
Exemple : y 0 = y+x sin(y) avec f = x x cos y + y /2.
2 2

sage: desolve(diff(y,x) == (cos(y)-2*x)/(y+x*sin(y)), y,


....: show_method=True)
[x^2 - x*cos(y(x)) + 1/2*y(x)^2 == c, 'exact']

Ici encore, les solutions ne sont pas donnes de manire explicite.


quations de Riccati. Il sagit dquations du type :

y 0 = P (x)y 2 + Q(x)y + R(x),

o P , Q et R sont des fonctions continues sur des intervalles donns.


Exemple : y 0 = xy 2 + x1 y x12 .
Il faut dans ce cas fixer loption contrib_ode True pour que Sage cherche des
solutions avec des mthodes plus complexes.
sage: desolve(diff(y,x) == x*y^2+y/x-1/x^2, y,
....: contrib_ode=True, show_method=True)[1]
'riccati'

quations de Lagrange et de Clairaut. Lorsque lquation est de la


forme y = xP (y 0 ) + Q(y 0 ) o P et Q sont de classe C 1 sur un certain intervalle,
on parle dquation de Lagrange. Lorsque P est lidentit, on parle dquation de
Clairaut. Exemple : y = xy 0 y 02 .
sage: desolve(y == x*diff(y,x)-diff(y,x)^2, y,
....: contrib_ode=True, show_method=True)
[[y(x) == -c^2 + c*x, y(x) == 1/4*x^2], 'clairault']
10.1. QUATIONS DIFFRENTIELLES 225

quation linaire. Rsolvons par exemple y 0 + 2y = x2 2x + 3 :


sage: x = var('x'); y = function('y', x)

sage: DE = diff(y,x)+2*y == x**2-2*x+3


sage: desolve(DE, y)
-1/4*(2*(2*x - 1)*e^(2*x) - (2*x^2 - 2*x + 1)*e^(2*x) - 4*c
- 6*e^(2*x))*e^(-2*x)
Ordonnons un peu tout a avec la commande expand :
sage: desolve(DE, y).expand()
c*e^(-2*x) + 1/2*x^2 - 3/2*x + 9/4
On prendra donc lhabitude dutiliser desolve(...).expand(). Quelle est la
mthode utilise ?
sage: desolve(DE, y, show_method=True)[1]
'linear'
Ajoutons des conditions initiales, par exemple x(0) = 1 :
sage: desolve(DE, y, ics=[0,1]).expand()
1/2*x^2 - 3/2*x - 5/4*e^(-2*x) + 9/4

quations variables sparables. tudions lquation y 0 log(y) = y sin(x) :


sage: x = var('x'); y = function('y', x)
sage: desolve(diff(y,x)*log(y) == y*sin(x), y, show_method=True)
[1/2*log(y(x))^2 == c - cos(x), 'separable']
Sage est daccord avec nous : cest bien une quation variables sparables.
Prenons lhabitude de nommer nos solutions pour pouvoir les rutiliser par la
suite :
sage: ed = desolve(diff(y,x)*log(y) == y*sin(x), y); ed
1/2*log(y(x))^2 == c - cos(x)
Ici, y(x) nest pas donn de faon explicite : 21 log2 y(x) = c cos(x).


On peut demander une expression de y(x) en utilisant solve. On fera attention


la nature de ed et de y :
sage: solve(ed, y)
[y(x) == e^(-sqrt(2*c - 2*cos(x))), y(x) == e^(sqrt(2*c - 2*cos(x)))]
Il faudra tout de mme faire attention ce sqrt(2c - 2cos(x)) mme si Sage
ne nous met pas tout de suite en garde : on veillera donc choisir par la suite
c > 1.
Pour avoir lallure des courbes des solutions, il nous faut rcuprer le membre
de droite de chaque solution avec la commande rhs(). Par exemple, pour obtenir
le membre de droite de la premire solution en remplaant c par 5 :
sage: solve(ed, y)[0].subs_expr(c==5).rhs()
226 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

Traceback (most recent call last):


...
NameError: name 'c' is not defined
En effet, nous navons pas dfini c : cest Sage qui la introduit. Pour accder
c, nous pouvons utiliser variables() qui donne la liste des variables dune
expression :
sage: ed.variables()
(c, x)
Seules c et x sont considres comme des variables car y a t dfini comme une
fonction de la variable x. On accde donc c avec ed.variables()[0] :
sage: c = ed.variables()[0]
sage: solve(ed, y)[0].subs_expr(c == 5).rhs()
e^(-sqrt(-2*cos(x) + 10))
Autre exemple, pour avoir le trac de la premire solution avec c = 2 :
sage: plot(solve(ed, y)[0].subs_expr(c == 2).rhs(), x, -3, 3)
et on obtient :
0.24
0.22
0.2
0.18
0.16
0.14
0.12
0.1

-3 -2 -1 0 1 2 3
Pour avoir plusieurs courbes (voir figure 10.1), on utilise une boucle :
sage: P = Graphics()
sage: for k in range(1,20,2):
....: P += plot(solve(ed, y)[0].subs_expr(c==1+k/4).rhs(), x, -3, 3)
On aurait pu avoir laspect correspondant aux deux solutions en effectuant
une double boucle :
sage: P = Graphics()
sage: for j in [0,1]:
....: for k in range(1,10,2):
....: f = solve(ed,y)[j].subs_expr(c==2+0.25*k).rhs()
....: P += plot(f, x, -3, 3)
10.1. QUATIONS DIFFRENTIELLES 227

0.25

0.2

0.15

0.1

0.05

-3 -2 -1 0 1 2 3

Figure 10.1 Quelques solutions de y 0 log(y) = y sin(x).

sage: P
mais la diffrence dchelle entre les solutions ne permet plus de distinguer les
courbes correspondant la premire solution :

25

20

15

10

-3 -2 -1 1 2 3
Exercice 38 (quations diffrentielles variables sparables). Rsolvez dans R les
quations variables sparables suivantes :
0 sin(x)
1. (E1 ) : yy = sin(x) ; 2. (E2 ) : y 0 = cos(y)
.
1+y 2

quations homognes. On veut rsoudre lquation homogne xy 0 = y +


y + x . Cest bien une quation homogne car on peut lcrire
p
2 2

dy y+ y 2 + x2 N (y, x)
p
= = ,
dx x M (y, x)
228 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

or N (ky, kx) = kN (y, x) et M (ky, kx) = kM (y, x).


Il suffit donc deffectuer le changement de variable vrifiant y(x) = x u(x)
pour tout rel x pour obtenir une quation variables sparables.
sage: u = function('u',x)
sage: y = x*u
sage: DE = x*diff(y,x) == y + sqrt(x**2 + y**2)
On applique le changement de variables dans lquation diffrentielle de dpart.
Lquation ntant pas dfinie en 0, on va la rsoudre sur ]0, +[ et sur
] , 0[. Travaillons dabord sur ]0, +[ :

sage: assume(x>0)
sage: desolve(DE, u)
x == c*e^(arcsinh(x^2*u(x)/sqrt(x^4)))
On nobtient pas u de manire explicite. Pour y remdier, on va utiliser une
commande Maxima : ev comme valuer, avec loption logarc=True qui indique
que les fonctions trigonomtriques hyperboliques inverses seront converties laide
de logarithmes. Ensuite on va pouvoir exprimer u laide de la commande solve
de Sage :
sage: S = desolve(DE,u)._maxima_().ev(logarc=True).sage().solve(u); S
[u(x) == -(sqrt(u(x)^2 + 1)*c - x)/c]
Ici, S est une liste constitue dune quation ; S[0] sera donc lquation elle-mme.
Lquation nest cependant toujours pas rsolue explicitement. Nous allons
aider un peu Sage en lui demandant de rsoudre lquation quivalente

c2 (u2 + 1) = (x uc)2 ,

via les commandes :


sage: solu = (x-S[0]*c)^2; solu
(c*u(x) - x)^2 == (u(x)^2 + 1)*c^2
sage: sol = solu.solve(u); sol
[u(x) == -1/2*(c^2 - x^2)/(c*x)]
Il ne reste plus qu revenir y :
sage: y(x) = x*sol[0].rhs(); y(x)
-1/2*(c^2 - x^2)/c
Nous obtenons bien les solutions sous forme explicite :

x2 c2
y(x) = .
2c
Il ne reste plus qu tracer les solutions sur ]0, +[ en faisant attention prendre
des constantes c non nulles :
sage: P = Graphics()
10.1. QUATIONS DIFFRENTIELLES 229

sage: for k in range(-19,19,2):


....: P += plot(y(x).subs_expr(c == 1/k), x, 0, 3)
sage: P

80
60
40
20
0.5 1 1.5 2 2.5 3
-20
-40
-60
-80

Exercice 39 (quations diffrentielles homognes). Rsolvez dans R lquation


homogne suivante : (E5 ) : xyy 0 = x2 + y 2 .

Une quation paramtres : le modle de Verhulst. Le taux relatif


de croissance dune population est une fonction linairement dcroissante de la
population. Pour ltudier, on peut tre amen rsoudre une quation de la
forme :
y 0 = ay by 2 ,
avec a et b des paramtres rels positifs.
sage: x = var('x'); y = function('y', x); a, b = var('a, b')
sage: DE = diff(y,x) - a*y == -b*y**2
sage: sol = desolve(DE,[y,x]); sol
-(log(b*y(x) - a) - log(y(x)))/a == c + x

Nous nobtenons pas y explicitement. Essayons de lisoler avec solve :


sage: Sol = solve(sol, y)[0]; Sol
log(y(x)) == (c + x)*a + log(b*y(x) - a)

Nous navons toujours pas de solution explicite. Nous allons regrouper les termes
gauche et simplifier cette expression laide de simplify_log() :
sage: Sol(x) = Sol.lhs()-Sol.rhs(); Sol(x)
-(c + x)*a - log(b*y(x) - a) + log(y(x))
sage: Sol = Sol.simplify_log(); Sol(x)
-(c + x)*a + log(y(x)/(b*y(x) - a))
sage: solve(Sol, y)[0].simplify()
y(x) == a*e^(a*c + a*x)/(b*e^(a*c + a*x) - 1)
230 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

10.1.3 quations dordre 2


quations linaires coefficients constants. Rsolvons maintenant une
quation du second ordre linaire coefficients constants, par exemple :

y 00 + 3y = x2 7x + 31.

On utilise la mme syntaxe que pour les quations dordre 1, la drive seconde
de y par rapport x sobtenant avec diff(y,x,2).
sage: x = var('x'); y = function('y', x)
sage: DE = diff(y,x,2)+3*y == x^2-7*x+31
sage: desolve(DE, y).expand()
k1*sin(sqrt(3)*x) + k2*cos(sqrt(3)*x) + 1/3*x^2 - 7/3*x + 91/9
Ajoutons des conditions initiales, par exemple y(0) = 1 et y 0 (0) = 2 :
sage: desolve(DE, y, ics=[0,1,2]).expand()
1/3*x^2 + 13/9*sqrt(3)*sin(sqrt(3)*x) - 7/3*x
- 82/9*cos(sqrt(3)*x) + 91/9
ou bien y(0) = 1 et y(1) = 0 :
sage: desolve(DE, y, ics=[0,1,-1,0]).expand()
1/3*x^2 - 7/3*x - 82/9*sin(sqrt(3)*x)*cos(sqrt(3))/sin(sqrt(3))
+ 115/9*sin(sqrt(3)*x)/sin(sqrt(3)) - 82/9*cos(sqrt(3)*x) + 91/9
cest--dire

1 2 7 82 sin( 3x) cos( 3) 115 sin( 3x) 82 91
x x + cos( 3x) + .
3 3 9 sin( 3) 9 sin( 3) 9 9

Rsolution dune EDP : lquation de la chaleur. tudions la clbre


quation de la chaleur. La temprature z se rpartit dans une tige rectiligne
homogne de longueur ` selon lquation (o x est labscisse le long de la tige, et
t le temps) :
2z z
(x, t) = C (x, t).
x2 t
On tudiera cette quation pour :

t R+ , z(0, t) = 0 z(`, t) = 0 x ]0; `[, z(x, 0) = 1.

On va chercher des solutions ne sannulant pas sous la forme :

z(x, t) = f (x)g(t).

Cest la mthode de sparation des variables.


sage: x, t = var('x, t'); f = function('f',x); g = function('g',t)
sage: z = f*g
sage: eq(x,t) = diff(z,x,2) == diff(z,t); eq(x,t)
g(t)*D[0, 0](f)(x) == f(x)*D[0](g)(t)
10.1. QUATIONS DIFFRENTIELLES 231

Lquation devient donc :

d2 f (x) dg(t)
g(t) = f (x) .
dx 2 dt
Divisons par f (x)g(t), suppos non nul :
sage: eqn = eq/z; eqn(x,t)
D[0, 0](f)(x)/f(x) == D[0](g)(t)/g(t)
On obtient alors une quation o chaque membre ne dpend que dune variable :

1 d2 f (x) 1 dg(t)
= .
f (x) dx 2 g(t) dt

Chaque membre ne peut donc qutre constant. Sparons les quations et


introduisons une constante k :
sage: k = var('k')
sage: eq1(x,t) = eqn(x,t).lhs() == k; eq2(x,t) = eqn(x,t).rhs() == k
Rsolvons sparment les quations en commenant par la deuxime :
sage: g(t) = desolve(eq2(x,t),[g,t]); g(t)
c*e^(k*t)
donc g(t) = cekt avec c une constante.
Pour la premire, nous ny arrivons pas directement :
sage: desolve(eq1,[f,x])
Traceback (most recent call last):
...
TypeError: ECL says: Maxima asks:
Is k positive, negative, or zero?
Utilisons assume :
sage: assume(k>0); desolve(eq1,[f,x])
k1*e^(sqrt(k)*x) + k2*e^(-sqrt(k)*x)

cest--dire f (x) = k1 ex k
+ k2 ex k
.

10.1.4 Transforme de Laplace


La transforme de Laplace permet de convertir une quation diffrentielle avec
des conditions initiales en quation algbrique et la transforme inverse permet
ensuite de revenir la solution ventuelle de lquation diffrentielle.
Pour mmoire, si f est une fonction dfinie sur R en tant identiquement nulle
sur ]; 0[, on appelle transforme de Laplace de f la fonction F dfinie, sous
certaines conditions, par :
Z +
L f (x) = F (s) = esx f (x) dx.

0
232 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

On obtient facilement les transformes de Laplace des fonctions polynomiales,


trigonomtriques, exponentielles, etc. Ces transformes ont des proprits fort
intressantes, notamment concernant la transforme dune drive : si f 0 est
continue par morceaux sur R+ alors
L f 0 (x) = sL f (x) f (0),
 

et si f 0 satisfait les conditions imposes sur f :


L f 00 (x) = s2 L f (x) sf (0) f 0 (0).
 

Exemple. On veut rsoudre lquation diffrentielle y 00 3y 0 4y = sin(x)


en utilisant la transforme de Laplace avec les conditions initiales y(0) = 1 et
y 0 (0) = 1. Alors :
L (y 00 3y 0 4y) = L (sin(x)) ,
cest--dire :
(s2 3s 4)L(y) sy(0) y 0 (0) + 3y(0) = L(sin(x)).
Si on a oubli les tables des transformes de Laplace des fonctions usuelles,
on peut utiliser Sage pour retrouver la transforme du sinus :
sage: x, s = var('x, s'); f = function('f',x)
sage: f(x) = sin(x); f.laplace(x,s)
x |--> 1/(s^2 + 1)
Ainsi on obtient une expression de la transforme de Laplace de y :
1 s4
L(y) = + .
(s2 3s 4)(s2 + 1) s2 3s 4
Utilisons alors Sage pour obtenir la transforme inverse :
sage: X(s) = 1/(s^2-3*s-4)/(s^2+1) + (s-4)/(s^2-3*s-4)
sage: X(s).inverse_laplace(s, x)
9/10*e^(-x) + 1/85*e^(4*x) - 5/34*sin(x) + 3/34*cos(x)
Si lon veut moiti tricher , on peut dcomposer X(s) en lments simples
dabord :
sage: X(s).partial_fraction()
1/34*(3*s - 5)/(s^2 + 1) + 1/85/(s - 4) + 9/10/(s + 1)
et il ne reste plus qu lire une table dinverses. On peut cependant utiliser
directement la bote noire desolve_laplace qui donnera directement la solution :

sage: x = var('x'); y = function('y',x)


sage: eq = diff(y,x,x) - 3*diff(y,x) - 4*y - sin(x) == 0
sage: desolve_laplace(eq, y)
1/10*(8*y(0) - 2*D[0](y)(0) - 1)*e^(-x) + 1/85*(17*y(0) +
17*D[0](y)(0) + 1)*e^(4*x) - 5/34*sin(x) + 3/34*cos(x)
sage: desolve_laplace(eq, y, ics=[0,1,-1])
9/10*e^(-x) + 1/85*e^(4*x) - 5/34*sin(x) + 3/34*cos(x)
10.1. QUATIONS DIFFRENTIELLES 233

10.1.5 Systmes diffrentiels linaires


Un exemple simple de systme diffrentiel linaire du premier ordre.
On veut rsoudre le systme diffrentiel suivant :
(
y 0 (x) = A y(x)
y(0) = c

avec

2 0 y1 (x) 2

2
A = 2 0 2 , y(x) = y2 (x) , c = 1 .
0 2 2 y3 (x) 2

On crit :

sage: x = var('x'); y1 = function('y1', x)


sage: y2 = function('y2', x); y3 = function('y3', x)
sage: y = vector([y1, y2, y3])
sage: A = matrix([[2,-2,0],[-2,0,2],[0,2,2]])
sage: system = [diff(y[i], x) - (A * y)[i] for i in range(3)]
sage: desolve_system(system, [y1, y2, y3], ics=[0,2,1,-2])
[y1(x) == e^(-2*x) + e^(4*x),
y2(x) == 2*e^(-2*x) - e^(4*x),
y3(x) == -e^(-2*x) - e^(4*x)]

Pour les conditions initiales, la syntaxe est : ics = [x0,y1(x0),y2(x0),y3(x0)].

Avec une matrice de valeurs propres complexes. Prenons cette fois

3 2
   
4
A= , c= .
1 3 0

Avec Sage :

sage: x = var('x'); y1 = function('y1', x); y2 = function('y2', x)


sage: y = vector([y1,y2])
sage: A = matrix([[3,-4],[1,3]])
sage: system = [diff(y[i], x) - (A * y)[i] for i in range(2)]
sage: desolve_system(system, [y1, y2], ics=[0,2,0])
[y1(x) == 2*e^(3*x)*cos(2*x), y2(x) == e^(3*x)*sin(2*x)]

soit : (
y1 (x) = 2 cos(2x)e3x
y2 (x) = sin(2x)e3x .
234 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

Un systme du second ordre. On veut rsoudre le systme :


(
y100 (x) 2y1 (x) + 6y2 (x) y10 (x) 3y20 (x) = 0
y200 (x) + 2y1 (x) 6y2 (x) y10 (x) + y20 (x) = 0.

On se ramne un systme du premier ordre en posant

u = (u1 , u2 , u3 , u4 ) = (y1 , y2 , y10 , y20 ).

On a alors :
= u3
0

u1
u0 = u4

2


u0
3 = 2u1 6u2 + u3 + 3u4
= 2u1 + 6u2 + u3 u4 ,
0
u4
cest--dire u0 (x) = A u(x) avec

0 0 1 0

0 0 0 1
A=
2
.
6 1 3
2 6 1 1

Avec Sage :
sage: x = var('x'); u1 = function('u1', x); u2 = function('u2', x)
sage: u3 = function('u3', x); u4 = function('u4', x)
sage: u = vector([u1,u2,u3,u4])
sage: A = matrix([[0,0,1,0],[0,0,0,1],[2,-6,1,3],[-2,6,1,-1]])
sage: system = [diff(u[i], x) - (A*u)[i] for i in range(4)]
sage: sol = desolve_system(system, [u1, u2, u3, u4])
On ne retiendra que les deux premires composantes car ce sont y1 et y2 qui
nous intressent, cest--dire u1 et u2 :
sage: sol[0]
u1(x) == 1/24*(2*u1(0) - 6*u2(0) - u3(0) + 3*u4(0))*e^(-4*x)
+ 1/12*(2*u1(0) - 6*u2(0) + 5*u3(0) + 3*u4(0))*e^(2*x)
+ 3/4*u1(0) + 3/4*u2(0) - 3/8*u3(0) - 3/8*u4(0)
sage: sol[1]
u2(x) == -1/12*(2*u1(0) - 6*u2(0) - u3(0) - 3*u4(0))*e^(2*x)
- 1/24*(2*u1(0) - 6*u2(0) - u3(0) + 3*u4(0))*e^(-4*x)
+ 1/4*u1(0) + 1/4*u2(0) - 1/8*u3(0) - 1/8*u4(0)
ce qui peut se rsumer, avec un bon sens de lobservation, :
(
y1 (x) = k1 e2x + k2 e4x + 3k3
y2 (x) = k4 e2x k2 e4x + k3

avec k1 , k2 , k3 et k4 des paramtres dpendant des conditions initiales.


10.2. SUITES DFINIES PAR UNE RELATION DE RCURRENCE 235

quations diffrentielles
Dclaration de variable x=var('x')
Dclaration de fonction y=function('y',x)
Rsolution dune quation desolve(equation, y, <options>)
Rsolution dun systme desolve_system([eq1, ...], [y1, ...],
<options>)
Conditions initiales 1er ordre [x0 , y(x0 )]
Conditions initiales 2e ordre [x0 , y(x0 ), x1 , y(x1 )]
[x0 , y(x0 ), y 0 (x0 )]
Conditions initiales pour les systmes [x0 , y1 (x0 ), y2 (x0 ), ...]
Variable indpendante ivar=x
Mthode de rsolution show_method=True
Appel des mthodes particulires contrib_ode=True

Transformes de Laplace
Transforme dune fonction f : x 7 f (x) f.laplace(x,s)
Transforme inverse de X(s) X(s).inverse_laplace(s,x)
Rsolution via la transformation de Laplace desolve_laplace(equation,fonction)

Commandes diverses
Expression de la drive premire diff(y,x)
Forme dveloppe dune expression expr.expand()
Variables intervenant dans une expression expr.variables()
Substitution dune variable expr.subs_expr(var==val)
Membre de droite dune quation equation.rhs()
Membre de gauche dune quation equation.lhs()

Tableau 10.1 Commandes utiles pour la rsolution dquations diffrentielles.

10.2 Suites dfinies par une relation de


rcurrence
10.2.1 Suites dfinies par un+1 = f (un )
Dfinition de la suite. Considrons une suite dfinie par une relation un+1 =
f (un ) avec u0 = a. On peut dfinir la suite naturellement laide dun algorithme
rcursif. Prenons par exemple une suite logistique (suite dfinie par une rcurrence
de la forme xn+1 = rxn (1 xn )) :
 x 
f : x 7 3.83 x 1 et u0 = 20 000.
100 000
Celle-ci peut se dfinir en Sage par :
sage: x = var('x'); f = function('f',x)
sage: f(x) = 3.83*x*(1 - x/100000)
sage: def u(n):
....: if n==0: return(20000)
....: else: return f(u(n-1))
On peut prfrer une dfinition itrative :
236 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

sage: def v(n):


....: V = 20000;
....: for k in [1..n]:
....: V = f(V)
....: return V

Reprsentation graphique. On peut demander de tracer les points de coor-


donnes (k, uk ) :
sage: def nuage(u,n):
....: L = [[0,u(0)]];
....: for k in [1..n]:
....: L += [[k,u(k)]]
....: points(L).show()
partir du dessin suivant, on conjecture lexistence de trois valeurs dadhrence :

sage: nuage(u,50)

90000
80000
70000
60000
50000
40000
30000
20000

0 10 20 30 40 50
On aurait pu prfrer la reprsentation faisant intervenir la premire bissectrice
et la courbe reprsentative de f . Celle-ci nexistant pas nativement dans Sage,
nous allons construire une petite procdure qui effectuera le travail :
sage: def escargot(f,x,u0,n,xmin,xmax):
....: u = u0
....: P = plot(x, x, xmin, xmax, color='gray')
....: for i in range(n):
....: P += line([[u,u],[u,f(u)],[f(u),f(u)]], color = 'red')
....: u = f(u)
....: P += f.plot(x, xmin, xmax, color='blue') # Courbe de f
....: P.show()
Par exemple, avec la mme suite :
sage: f(x) = 3.83*x*(1 - x/100000)
10.2. SUITES DFINIES PAR UNE RELATION DE RCURRENCE 237

sage: escargot(f,x,20000,100,0,100000)
on observe galement les trois valeurs dadhrence :
1e5

8e4

6e4

4e4

2e4

2e4 4e4 6e4 8e4 1e5

10.2.2 Suites rcurrentes linaires


Sage traite les suites du type :

ak un+k + ak1 un+k1 + + a1 un+1 + a0 un = 0

avec (ai )06i6k une famille de scalaires.


Par exemple, considrons la suite :
3 1
u0 = 1, u1 = 1, un+2 = un+1 un .
2 2
Dans la version 5.9 de Sage, la fonction bien connue rsolve nest pas acces-
sible directement. Il faut aller la chercher dans SymPy, ce qui entrane certains
dsagrments comme les changements de syntaxe pour dclarer les variables. Voici
par exemple le prambule ncessaire la dfinition de la suite :
sage: from sympy import Function, Symbol
sage: u = Function('u'); n = Symbol('n', integer=True)
Il faut ensuite dfinir la relation linaire sous la forme ak un+k + + a0 un = 0 :
sage: f = u(n+2)-(3/2)*u(n+1)+(1/2)*u(n)
On invoque enfin rsolve en observant bien comment sont dclares les condi-
tions initiales :
sage: from sympy import rsolve
sage: rsolve(f, u(n), {u(0):-1,u(1):1})
3 - 4*2**(-n)
cest--dire un = 3 2n2 .
1
238 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES

Remarque. Attention certaines limitations de rsolve. Par exemple, pour


les suites rcurrentes linaires dordre 2, un rsultat correct nest obtenu que
si lquation caractristique admet deux racines relles distinctes comme dans
lexemple prcdent. Sinon, Sage exprime la solution laide du symbole de
Pochhammer (RisingFactorial(x,n)) ce qui est peu exploitable.

10.2.3 Suites rcurrentes avec second membre


Sage traite aussi des suites du type :

ak (n)un+k + ak1 (n)un+k1 + + a1 (n)un+1 + a0 (n)un = f (n)

avec (ai )06i6k une famille de fonctions polynomiales en n et f qui peut tre une
fonction polynomiale, rationnelle ou hypergomtrique de n.
Selon la nature de f (n), la commande sera diffrente :
rsolve_poly si f est polynomiale ;
rsolve_ratio si f est rationnelle ;
rsolve_hyper si f est hypergomtrique.
On dfinit les ai (n) sous forme dune liste [a0 (n), . . . , ak1 (n), ak (n)]. Par exemple,
pour tudier la complexit du tri fusion, on est amen tudier la suite :

un+1 = 2un + 2n+2 , u0 = 0.

Le calcul donne
sage: from sympy import rsolve_hyper
sage: n = Symbol('n', integer=True)
sage: rsolve_hyper([-2,1],2**(n+2),n)
2**n*C0 + 2**(n + 2)*(C0 + n/2)
or u0 = 0 donne C0=0 donc un = n 2n+1 .
Troisime partie

Calcul numrique
11
Nombres virgule flottante

Dans les chapitres suivants, les nombres virgule flottante sont au cur des
calculs ; il convient de les tudier car leur comportement suit des rgles prcises.
Comment reprsenter des nombres rels en machine ? Comme ces nombres ne
peuvent pas en gnral tre cods avec une quantit finie dinformation, ils ne
sont pas toujours reprsentables sur un ordinateur : il faut donc les approcher
avec une quantit de mmoire finie.
Un standard sest dgag autour dune approximation des nombres rels avec
une quantit fixe dinformation : la reprsentation virgule flottante.
Dans ce chapitre, on trouve : une description sommaire des nombres virgule
flottante et des diffrents types de ces nombres disponibles dans Sage, et la d-
monstration de quelquesunes de leurs proprits. Quelques exemples montreront
certaines des difficults quon rencontre en calculant avec les nombres virgule
flottante, quelques astuces pour arriver parfois les contourner, en esprant dve-
lopper chez le lecteur une prudence bien ncessaire ; en conclusion, nous essayons
de donner quelques proprits que doivent possder les mthodes numriques pour
pouvoir tre utilises avec ces nombres.
Pour aller plus loin, le lecteur pourra consulter les documents [BZ10] et [Gol91]
(disponibles sur le web) ou le livre [MBdD+ 10].

11.1 Introduction
11.1.1 Dfinition
Un ensemble F (, r, m, M ) de nombres virgule flottante est dfini par quatre
paramtres : une base > 2, un nombre de chiffres r et deux entiers relatifs m et
242 CHAP. 11. NOMBRES VIRGULE FLOTTANTE

M . Les lments de F (, r, m, M ) sont les nombres de la forme

x = (1)s 0.d1 d2 . . . dr j ,

o les chiffres di sont des nombres entiers qui vrifient 0 6 di < pour i > 1 et
0 < d1 < . Le nombre de chiffres r est la prcision ; lindicateur de signe s vaut
0 ou 1 ; lexposant j est compris entre les deux entiers m et M , et 0.d1 d2 . . . dr
est la mantisse.

11.1.2 Proprits, exemples


La normalisation 0 < d1 < garantit que tous les nombres ont la mme quan-
tit de chiffres significatifs. On remarque que la valeur zro nest pas reprsentable
avec la convention d1 > 0 : zro admet une reprsentation spciale.
titre dexemple, le nombre not 0.028 en base 10 (reprsentation virgule
fixe), sera reprsent par 0.28 101 (sous rserve bien sr que r > 2 et
m 6 1 6 M ). La base 2 tant bien adapte la reprsentation binaire des
ordinateurs, sera gal 2 dans les diffrents ensembles de nombres flottants
proposs par Sage, et nous nous placerons donc toujours dans ce cadre dans la
suite de ce chapitre. Pour donner un exemple, 0.101 21 reprsente la valeur 5/4
dans lensemble F (2, 3, 1, 2).
Comme la seule valeur possible de d1 pour = 2 est d1 = 1, il peut tre omis
dans une implantation machine et, toujours dans lensemble F (2, 3, 1, 2), 5/4
pourra par exemple tre cod en machine avec les 5 bits : 00110, o le premier
chiffre gauche reprsentera le signe +, les 2 chiffres suivants (01) la mantisse
(101), et les deux derniers chiffres droite lexposant (00 codant la valeur 1 de
lexposant, 01 la valeur 0, etc.).
Il doit tre bien vident pour le lecteur que les ensembles F (, r, m, M ) d-
crivent seulement un sous-ensemble fini des nombres rels. Pour reprsenter un
nombre rel x qui se situe entre deux nombres conscutifs de F (, r, m, M ), il faut
une application appele arrondi qui dfinisse quel nombre approchera x : on peut
prendre le nombre le plus proche de x, mais dautres choix sont possibles ; la norme
impose que larrondi laisse F (, r, m, M ) invariant. Lensemble des nombres repr-
sentables est born, et les ensembles de nombres flottants contiennent les valeurs
exceptionnelles +, qui reprsentent non seulement les infinis (comme 1/0)
mais aussi toutes les valeurs suprieures au plus grand nombre positif reprsen-
table (ou infrieures au plus petit nombre ngatif reprsentable), ainsi que des
valeurs reprsentant des oprations indfinies comme 0/0.

11.1.3 Normalisation
Aprs quelques ttonnements, la ncessit dune norme sest fait sentir, afin
que des programmes identiques fournissent les mmes rsultats sur des machines
diffrentes. Depuis 1985, la norme IEEE 754 dfinit plusieurs ensembles de nombres,
dont, entre autres, des nombres stocks sur 64 bits ( double prcision ) : le signe
11.2. LES NOMBRES FLOTTANTS 243

s est cod sur 1 bit, la mantisse sur 53 bits (dont 52 seulement sont stocks), et
lexposant sur 11 bits. Les nombres sont de la forme :

(1)s 0.d1 d2 . . . d53 2j1023 .

Ils correspondent au type double du langage C.

11.2 Les nombres flottants


Sage fournit deux sortes de nombres flottants :
1. Les nombres flottants double prcision dcrits en 11.1.3 : ce sont les
nombres fournis par le processeur de lordinateur ; dans Sage ces nombres
appartiennent la classe RDF :
sage: xrdf = RDF(3.0)
2. Des nombres virgule flottante de prcision arbitraire : chaque instance de
la classe RealField dfinit un ensemble de nombres virgule flottante de
prcision donne (et ventuellement avec un mode darrondi donn : voir
11.3.2). Pour dclarer un nombre x100 avec une prcision de 100 bits, on
crira par exemple :
sage: R100 = RealField(100) # prcision : 100 bits.
sage: x100 = R100(3/8); x100
0.37500000000000000000000000000
Les nombres de lensemble RealField(p) sont de la forme

(1)s 0.d1 d2 . . . dp 2e ,

avec s {0, 1} ; la mantisse comporte p chiffres binaires, et e peut avoir 30 bits


(ou plus sur certaines machines). On peut laisser implicite la prcision :
sage: Rdefaut = RealField() # prcision par dfaut de 53 bits
sage: xdefaut = Rdefaut(2/3)
et on peut tester la prcision de tous les nombres virgule flottante avec la
mthode prec() :
sage: xrdf.prec()
53
sage: x100.prec()
100
sage: xdefaut.prec()
53
Ainsi, les nombres de lensemble RealField() et ceux de lensemble RDF ont
la mme prcision, mais RealField() accepte des exposants bien plus grands.
Lensemble RealField() avec la prcision de 53 bits est le type par dfaut des
nombres rels de Sage :
244 CHAP. 11. NOMBRES VIRGULE FLOTTANTE

sage: x = 1.0; print type(x)


<type 'sage.rings.real_mpfr.RealLiteral'>
sage: x.prec()
53
Ici, real_mpfr.RealLiteral indique que lensemble de nombres auquel appartient
x est implant avec la bibliothque GNU MPFR.
Rappelons que le type dun nombre est dfini automatiquement par le second
membre lors dune affectation :
sage: x = 1.0 # x appartient RealField()
sage: x = 0.1e+1 # idem : x appartient RealField()
sage: x = 1 # x est entier
sage: x = RDF(1) # x est un flottant double prcision machine
sage: x = RDF(1.) # idem : x est un flottant double prcision
sage: x = RDF(0.1e+1) # idem
sage: x = 4/3 # x est un nombre rationnel
sage: R = RealField(20)
sage: x = R(1) # x est un flottant de prcision 20 bits
et des conversions naturelles des nombres rationnels sont effectues :
sage: RDF(8/3)
2.66666666667
sage: R100 = RealField(100); R100(8/3)
2.6666666666666666666666666667
ainsi que des conversions entre nombres appartenant des ensembles de nombres
virgule flottante diffrents :
sage: x = R100(8/3)
sage: R = RealField(); R(x)
2.66666666666667
sage: RDF(x)
2.66666666667
Les diffrents ensembles de nombres virgule flottante contiennent aussi les
valeurs particulires +0, -0, +infinity, -infinity, et NaN :
sage: 1.0/0.0
+infinity
sage: RDF(1)/RDF(0)
+infinity
sage: RDF(-1.0)/RDF(0.)
-infinity
La valeur NaN est attribue aux rsultats indfinis :
sage: 0.0/0.0
NaN
sage: RDF(0.0)/RDF(0.0)
NaN
11.3. PROPRITS DES NOMBRES VIRGULE FLOTTANTE 245

x R2(x).ulp() RDF(x).ulp() R100(x).ulp()


30
10 3.9e-31 8.75811540203e-47 1.2446030555722283414288128108e-60
1010 2.9e-11 6.46234853557e-27 9.1835496157991211560057541970e-41
103 0.00049 1.08420217249e-19 1.5407439555097886824447823541e-33
1 0.50 1.11022302463e-16 1.5777218104420236108234571306e-30
103 510. 5.68434188608e-14 8.0779356694631608874161005085e-28
1010 4.3e9 9.53674316406e-07 1.3552527156068805425093160011e-20
1030 3.2e29 7.03687441777e+13 1.0000000000000000000000000000

Tableau 11.1 Distances entre flottants.

11.2.1 Quel type de nombres choisir ?


Les flottants de prcision arbitraire permettent de calculer avec une prcision
trs grande, alors que la prcision est fixe pour les nombres RDF. En contrepartie
les calculs avec les nombres RealField(n) font appel la bibliothque logicielle
GNU MPFR, alors que pour les nombres RDF, les calculs sont effectus par
larithmtique flottante du processeur, qui est beaucoup plus rapide. On donne en
13.2.10 une comparaison o lefficacit des nombres flottants machine se conjugue
avec lutilisation de bibliothques optimises pour ces nombres. Notons que, parmi
les mthodes de calcul numrique quon rencontrera dans les chapitres suivants,
nombreuses sont celles qui utilisent uniquement les nombres flottants RDF et,
quoiquon fasse, convertiront toujours les nombres virgule flottante dans ce
format.

R2, un ensemble de flottants jouets. Les flottants de prcision arbitraire,


outre quils sont irremplaables pour des calculs en grande prcision, permettent
de dfinir une classe de flottants qui, parce quils sont trs peu prcis, montrent
de manire caricaturale les proprits des nombres virgule flottante : lensemble
R2 des nombres de prcision 2 bits :
sage: R2 = RealField(2)

11.3 Quelques proprits des nombres virgule


flottante
11.3.1 Des ensembles pleins de trous
Dans chaque ensemble de nombres virgule flottante, la mthode ulp() (unit
in the last place) donne la taille de lintervalle sparant chaque nombre du nombre
reprsentable le plus proche (dans la direction oppose de celle de zro) :
sage: x2 = R2(1.); x2.ulp()
0.50
sage: xr = 1.; xr.ulp()
2.22044604925031e-16
246 CHAP. 11. NOMBRES VIRGULE FLOTTANTE

Le lecteur pourra vrifier facilement la valeur donne pour x2.ulp().


Le tableau 11.1 donne la taille de lintervalle sparant un nombre x ou plus
exactement R(x) o R est lensemble considr de son voisin le plus proche
(dans la direction oppose de celle de zro) pour diffrents ensembles de nombres
(R100 est lensemble RealField(100)), et diffrentes valeurs de x.
Comme on peut facilement le prvoir, la taille des trous sparant deux nombres
conscutifs crot avec la taille des nombres.
Exercice 40 (une valeur un peu surprenante). Montrer que R100(1030 ).ulp() vaut
bien 1.0000000000000000000000000000.

11.3.2 Larrondi
Comment approcher un nombre qui nest pas reprsentable dans un ensemble
de nombres virgule flottante ? On peut dfinir larrondi de diffrentes manires :
vers le nombre reprsentable le plus proche : cest ainsi que lon procde
dans lensemble RDF, et cest le comportement par dfaut des ensembles de
nombres crs par RealField. Pour un nombre situ gale distance de
deux nombres reprsentables, on arrondit la mantisse paire la plus proche ;
en direction de ; RealField(p,rnd=RNDD) fournira ce comportement,
avec une prcision de p bits ;
en direction de zro ; exemple : RealField(p,rnd=RNDZ) ;
en direction de + ; exemple : RealField(p,rnd=RNDU).

11.3.3 Quelques proprits


Larrondi ncessaire aux ensembles de nombres virgule flottante cause de
nombreux effets pernicieux. Explorons-en quelques-uns.

Un phnomne dangereux. Connu en anglais sous le nom de catastrophic


cancellation, il sagit de la perte de prcision qui rsulte de la soustraction de
deux nombres voisins ; plus exactement, il sagit dune amplification des erreurs :
sage: a = 10000.0; b = 9999.5; c = 0.1; c
0.100000000000000
sage: a1 = a+c # on perturbe a
sage: a1-b
0.600000000000364
Ici lerreur c introduite sur a rend le calcul de la diffrence imprcis (les 3 dernires
dcimales sont fausses).

Application : calcul des racines dun trinme du second degr. Mme


la rsolution dune quation du second degr ax2 + bx + c = 0 peut poser des
problmes. Considrons le cas a = 1, b = 104 , c = 1 :
sage: a = 1.0; b = 10.0^4; c = 1.0
sage: delta = b^2-4*a*c
11.3. PROPRITS DES NOMBRES VIRGULE FLOTTANTE 247

sage: x = (-b-sqrt(delta))/(2*a); y = (-b+sqrt(delta))/(2*a)


sage: x, y
(-9999.99990000000, -0.000100000001111766)

La somme des racines calcules est juste, mais pas le produit :


sage: x+y+b/a
0.000000000000000
sage: x*y-c/a
1.11766307320238e-9

Lerreur est due au phnomne de catastrophic cancellation qui se manifeste


quand on ajoute -b et sqrt(delta) lors du calcul de y. Ici, on peut rcuprer
une meilleure approximation de y :
sage: y = (c/a)/x; y
-0.000100000001000000
sage: x+y+b/a
0.000000000000000

On remarque que, du fait de larrondi, la somme des racines reste correcte. Le


lecteur pourra envisager tous les cas possibles pour le choix de a, b et c pour se
convaincre que lcriture dun programme numriquement robuste pour le calcul
des racines dun trinme du second degr est loin dtre simple.

Les ensembles de nombres flottants ne sont pas des groupes pour


laddition. En effet, laddition ny est pas associative. Utilisons lensemble R2
(avec 2 bits de prcision) :
sage: x1 = R2(1/2); x2 = R2(4); x3 = R2(-4)
sage: x1, x2, x3
(0.50, 4.0, -4.0)
sage: x1+(x2+x3)
0.50
sage: (x1+x2)+x3
0.00

Nous pouvons en dduire que les diffrents arrangements possibles des calculs
dans un programme ne sont pas sans importance sur le rsultat !

Rcurrences, suites de nombres virgule flottante. Considrons 1 la


rcurrence un+1 = 4un 1. Si u0 = 1/3, la suite est stationnaire : ui = 1/3 pour
tout i.
sage: x = RDF(1/3)
sage: for i in range(1,100): x = 4*x-1; print x

1. Merci Marc Delglise (Institut Camille Jordan, Lyon) pour cet exemple.
248 CHAP. 11. NOMBRES VIRGULE FLOTTANTE

0.333333333333
0.333333333333
0.333333333333
...
-1.0
-5.0
-21.0
-85.0
-341.0
-1365.0
-5461.0
-21845.0
...
La suite calcule diverge ! On peut remarquer que ce comportement est assez
naturel car il sagit dun phnomne classique dinstabilit : toute erreur sur u0 ,
est multiplie par 4 chaque itration, et nous savons que larithmtique flottante
introduit des erreurs qui vont donc tre amplifies chaque itration.
Calculons maintenant la rcurrence un+1 = 3un 1, avec u0 = 1/2. On
sattend au mme rsultat : la suite, si elle est exactement calcule, est constante,
mais toute erreur sera multiplie par 3 chaque pas.
sage: x = RDF(1/2)
sage: for i in range(1,100): x = 3*x-1; print x
0.5
0.5
0.5
...
0.5
Cette fois-ci, la suite calcule reste constante ! Comment expliquer ces deux
comportements diffrents ? Regardons la reprsentation binaire de u0 dans chaque
cas.
Dans le premier cas (un+1 = 4un 1, u0 = 1/3), on a :

1 1X 1 1X 1
= = ,
3 4 i=0 4 i 4 i=0 22i

et donc 1/3 nest pas reprsentable exactement dans les ensembles de nombres
virgule flottante dont nous disposons (avec = 2), quelle que soit leur prcision.
Le lecteur est invit refaire le calcul prcdent dans un ensemble de grande
prcision, par exemple RealField(1000) pour vrifier que la suite calcule diverge
toujours. Notons que si on remplace dans le premier programme la ligne
sage: x = RDF(1/3)
par
sage: x = 1/3
11.3. PROPRITS DES NOMBRES VIRGULE FLOTTANTE 249

alors les calculs seffectuent dans lensemble des nombres rationnels et les itrs
successifs vaudront toujours 1/3.
Dans le deuxime cas (un+1 = 3un 1, u0 = 1/2), u0 et 3/2 scrivent
respectivement 0.1 et 1.1 en base 2 ; ils sont donc reprsentables exactement, sans
arrondi, dans les divers ensembles de nombres flottants. Le calcul est donc exact,
et la suite reste constante.
Lexercice suivant montre quune suite programme dans un ensemble de
nombres virgule flottante peut converger vers une limite fausse.
Exercice 41 (exemple d Jean-Michel Muller). On considre la rcurrence suivante
(cf. [MBdD+ 10, p. 9]) :
1130 3000
un = 111 + .
un1 un1 un2
On peut montrer que la solution gnrale est de la forme :
100n+1 + 6n+1 + 5n+1
un = .
100n + 6n + 5n
1. On choisit u0 = 2 et u1 = 4 : quelles sont les valeurs de , et ? Vers quelle
limite converge la suite ?
2. Programmer le calcul de la suite (toujours avec u0 = 2 et u1 = 4) dans lensemble
RealField() (ou dans RDF). Que peut-on constater ?
3. Expliquer ce comportement.
4. Effectuer le mme calcul dans un ensemble de grande prcision, par exemple
RealField(5000). Commenter le rsultat.
5. La suite est dfinie dans Q. La programmer dans lensemble des nombres rationnels
et commenter le rsultat.

Les nombres flottants et la sommation des sries numriques. On


considre une sriePnumrique relle de terme gnral un positif. Le calcul des
m
sommes partielles i=0 ui dans un ensemble de nombres virgule flottante va
tre perturb par les erreurs darrondi. Le lecteur pourra samuser montrer que,
si un tend vers 0 quand n tend vers linfini, et si les sommes partielles restent
dans lintervalle
Pm des nombres reprsentables, alors, partir dun certain rang m,
la suite i=0 ui calcule avec arrondi est stationnaire (cf. [Sch91]). Bref, dans le
monde des nombres flottants, la vie est simple : les sries dont le terme gnral
positif tend vers 0 convergent, condition que les sommes partielles ne croissent
pas trop !
Regardons cela avec la srie harmonique (divergente) de terme un = 1/n :
sage: def sumharmo(P):
....: RFP = RealField(P)
....: y = RFP(1.); x = RFP(0.); n = 1
....: while x <> y:
....: y = x; x += 1/n; n += 1
....: return P, n, x
Testons cette procdure avec diffrentes valeurs de la prcision P :
250 CHAP. 11. NOMBRES VIRGULE FLOTTANTE

sage: sumharmo(2)
(2, 5, 2.0)
sage: sumharmo(20)
(20, 131073, 12.631)
Le lecteur pourra vrifier avec une feuille de papier et un crayon que, dans notre
ensemble R2 de flottants jouets, la procdure converge bien en 5 itrations vers la
valeur 2.0. videmment le rsultat dpend de la prcision p, et le lecteur pourra
aussi vrifier (toujours avec son crayon...) que pour n > p , la somme calcule est
stationnaire. Attention toutefois : avec la prcision par dfaut de 53 bits, et en
effectuant 109 oprations par seconde, il faudra 253 /109 /3600 heures, soit environ
104 jours, pour atteindre la valeur stationnaire !

Amliorer le calcul de certaines rcurrences. Moyennant quelques prcau-


tions, il est possible damliorer certains rsultats : voici un exemple utile.
Il est frquent de rencontrer des rcurrences de la forme :

yn+1 = yn + n ,

o les nombres n sont petits en valeur absolue par rapport aux nombres yn :
penser par exemple lintgration des quations diffrentielles de la mcanique
cleste pour la simulation du systme solaire, o de grandes valeurs (des distances,
des vitesses) subissent de trs petites perturbations, en temps long [HLW02].
Mme si on peut calculer avec prcision les termes n , les erreurs darrondi lors
des additions yn+1 = yn + n vont introduire des erreurs considrables.
Prenons par exemple la suite dfinie par y0 = 1013 , 0 = 1 et n+1 = an avec
a = 1 108 . Voici la programmation habituelle, nave, du calcul de yn :
sage: def iter(y,delta,a,n):
....: for i in range(0,n):
....: y += delta
....: delta *= a
....: return y
Avec les valeurs rationnelles que nous avons choisies pour y0 , 0 et a, nous pouvons
calculer la valeur exacte des itrs avec Sage :
sage: def exact(y,delta,a,n):
....: return y+delta*(1-a^n)/(1-a)
Calculons prsent 100 000 itrs avec les nombres virgule flottante RDF (par
exemple), et comparons le rsultat la valeur exacte :
sage: y0 = RDF(10^13); delta0 = RDF(1); a = RDF(1-10^(-8)); n = 100000
sage: ii = iter(y0,delta0,a,n)
sage: s = exact(10^13,1,1-10^(-8),n)
sage: print "exact - sommation classique:", s-ii
exact - sommation classique: -45.5
Voici maintenant lalgorithme de la sommation compense :
11.3. PROPRITS DES NOMBRES VIRGULE FLOTTANTE 251

sage: def sumcomp(y,delta,e,n,a):


....: for i in range(0,n):
....: b = y
....: e += delta
....: y = b+e
....: e += (b-y)
....: delta = a*delta # nouvelle valeur de delta
....: return y
Pour comprendre son comportement, regardons le schma ci-dessous (on suit ici
les prsentations de Higham [Hig93] et[HLW02]), o les botes reprsentent les
mantisses des nombres. La position des botes reprsente lexposant (plus la bote
est gauche, plus lexposant est grand) :
b = yn b1 b2
e e1 0
n 1 2
e = e + n 1 e1 + 2
yn+1 = b + e b1 b2 + 1
e = e + (b yn+1 ) e1 + 2 0
Lerreur darrondi est accumule dans e, et on constate quaucun des chiffres de
n nest perdu, tandis quavec la manire nave de procder, les bits nots 2
disparaissent du calcul.
Effectuons nouveau le calcul de 100 000 itrs, avec la mthode de la som-
mation compense :
sage: c = sumcomp(y0,delta0,RDF(0.0),n,a)
sage: print "exact-sommation compensee:", s-c
exact-sommation compensee: -0.001953125
Lerreur absolue est de 45.5 avec lalgorithme naf, et de 0.0019 avec la
sommation compense ! Au passage, observons que pour les erreurs relatives on
obtient 4.549 1012 avec la sommation nave, et 1.95 1016 avec la sommation
compense.

11.3.4 Nombres flottants complexes


Sage propose deux familles de nombres complexes reprsents en machine par
des couples de nombres virgule flottante appartenant aux ensembles prcdem-
ment rencontrs :
1. Les nombres complexes double prcision ComplexDoubleField (ou de ma-
nire abrge CDF). Ce sont les nombres de la forme x + i y o x et y sont
chacun des nombres flottants double prcision . On cre les nombres
ainsi :
sage: x = CDF(2,1.); x
2.0 + 1.0*I
sage: y = CDF(20,0); y
252 CHAP. 11. NOMBRES VIRGULE FLOTTANTE

20.0
ou bien :
sage: z = ComplexDoubleElement(2.,1.); z
2.0 + 1.0*I
2. Les nombres flottants complexes de prcision arbitraire ComplexField. Ce
sont les nombres de la forme x + i y, o x et y ont la mme prcision de p
bits. Une instance de la classe ComplexField cre un ensemble de prcision
donne (53 par dfaut) :
sage: C = ComplexField(); C(2,3)
2.00000000000000 + 3.00000000000000*I
sage: C100 = ComplexField(100); C100(2,3)
2.0000000000000000000000000000 + 3.0000000000000000000000000000*I
Bien entendu, les calculs avec ces diffrents ensembles posent les mmes
problmes darrondi que ceux avec les nombres rels virgule flottante.

11.3.5 Mthodes
Nous avons dj vu les mthodes prec et ulp. Les diffrents ensembles de
nombres rencontrs ici fournissent un grand nombre de mthodes. Donnons
quelques exemples :
des mthodes qui renvoient des constantes. Exemples :
sage: R200 = RealField(200); R200.pi()
3.1415926535897932384626433832795028841971693993751058209749
sage: R200.euler_constant()
0.57721566490153286060651209008240243104215933593992359880577
des fonctions trigonomtriques sin, cos, arcsin, arccos, etc. Exemple :
sage: x = RDF.pi()/2; x.cos() # approximation flottante de zero!
6.12323399574e-17
sage: x.cos().arccos() - x
0.0
les logarithmes (log, log10, log2, etc.), les fonctions trigonomtriques
hyperboliques et leurs inverses (sinh, arcsinh, cosh, arccosh, etc.).
des fonctions spciales (gamma, j0, j1, jn(k), etc.).
Le lecteur consultera la documentation de Sage pour avoir une liste complte
des trs nombreuses mthodes disponibles. Rappelons que cette liste peut tre
obtenue en ligne de la manire suivante :
sage: x = 1.0; x.<tab>
Pour chaque mthode on obtient sa dfinition, ses paramtres ventuels et un
exemple dutilisation en tapant (ici pour la fonction dEuler (x)) :
sage: x.gamma?
11.4. EN GUISE DE CONCLUSION 253

Ensembles de nombres flottants


Nombres rels de prcision p bits RealField(p)
Nombres flottants machine RDF
Nombres complexes de prcision p bits ComplexField(p)
Nombres complexes machine CDF

Tableau 11.2 Rcapitulatif des ensembles de nombres flottants.

11.4 En guise de conclusion


Les mthodes numriques implantes dans Sage, quon trouvera dcrites
dans les chapitres suivants, ont toutes t tudies thoriquement ; leur analyse
numrique consiste, entre autres, tudier la convergence des mthodes itratives,
lerreur introduite en simplifiant un problme pour le rendre calculable, mais aussi
le comportement des calculs en prsence de perturbations, par exemple celles
introduites par larithmtique inexacte des nombres virgule flottante.
Considrons un algorithme F, qui, partir de donnes d, calcule x = F(d). Cet
algorithme ne sera utilisable que sil namplifie pas exagrment les erreurs sur d :
une perturbation de d correspond une solution perturbe x = F(d + ). Il faut
que lerreur introduite x x dpende raisonnablement de (de manire continue,
ne croissant pas trop vite,...) : les algorithmes doivent avoir des proprits de
stabilit pour pouvoir tre utilisables. Au chapitre 13, on explorera des problmes
de stabilit pour les algorithmes utiliss en algbre linaire.
Notons aussi que certains calculs sont dfinitivement irralisables en prcision
finie, comme par exemple le calcul de la suite donne dans lexercice 41 : toute
perturbation, aussi faible soit-elle, entranera la convergence de la suite vers une
valeur fausse ; cest un phnomne typique dinstabilit de la solution du problme
que lon cherche rsoudre : ltude exprimentale dune suite laide de nombres
virgule flottante doit tre mene avec une grande prudence.
Le lecteur pourra peut-tre trouver dsesprante la pratique du calcul avec
des nombres virgule flottante, mais ce jugement doit tre modr : la trs
large majorit des ressources de calcul disponibles est utilise effectuer des
oprations dans ces ensembles de nombres : rsolution approche dquations
aux drives partielles, optimisation ou traitement du signal, etc. Les nombres
virgule flottante doivent tre regards avec mfiance, mais ils nont pas empch
le dveloppement du calcul et de ses applications : ce ne sont pas les erreurs
darrondi qui limitent la validit de la prvision mtorologique, pour ne citer que
cet exemple.
254 CHAP. 11. NOMBRES VIRGULE FLOTTANTE
12
quations non linaires

Ce chapitre explique comment rsoudre une quation non linaire avec Sage.
Dans un premier temps on tudie les quations polynomiales et on montre les
limitations de la recherche de solutions exactes. Ensuite on dcrit le fonctionnement
de quelques mthodes classiques de rsolution numrique. Au passage on indique
quels sont les algorithmes de rsolution numrique implments dans Sage.

12.1 quations algbriques


Par quation algbrique on entend une quation de la forme p(x) = 0 o p
dsigne un polynme une indtermine dont les coefficients appartiennent un
anneau intgre A. On dit quun lment A est une racine du polynme p si
p() = 0.
Soit un lment de A. La division euclidienne de p par x assure lexistence
dun polynme constant r tel que :

p = (x )q + r.

En valuant cette quation en , on obtient r = p(). Donc le polynme x divise


p si, et seulement si, est une racine de p. Cette remarque permet dintroduire
la notion de multiplicit dune racine du polynme p : il sagit du plus grand
entier m tel que (x )m divise p. On observe que la somme des multiplicits
des racines de p est infrieure ou gale au degr de p.

12.1.1 Mthode Polynomial.roots()


Rsoudre lquation algbrique p(x) = 0 consiste identifier les racines du
polynme p avec leur multiplicit. La mthode Polynomial.roots() donne les
256 CHAP. 12. QUATIONS NON LINAIRES

racines dun polynme. Elle prend jusqu trois paramtres, tous optionnels. Le
paramtre ring permet de prciser lanneau o chercher les racines. Si on ne
prcise pas de valeur pour ce paramtre, il sagira de lanneau des coefficients
du polynme. Le boolen multiplicities indique la nature des informations
renvoyes par Polynomial.roots() : chaque racine peut tre accompagne de sa
multiplicit. Le paramtre algorithm sert prciser quel algorithme utiliser ; les
diffrentes valeurs possibles sont explicites plus loin (cf. 12.2.2).
sage: R.<x> = PolynomialRing(RealField(prec=10))
sage: p = 2*x^7 - 21*x^6 + 64*x^5 - 67*x^4 + 90*x^3 \
....: + 265*x^2 - 900*x + 375
sage: p.roots()
[(-1.7, 1), (0.50, 1), (1.7, 1), (5.0, 2)]
sage: p.roots(ring=ComplexField(10), multiplicities=False)
[-1.7, 0.50, 1.7, 5.0, -2.2*I, 2.2*I]
sage: p.roots(ring=RationalField())
[(1/2, 1), (5, 2)]

12.1.2 Reprsentation des nombres


Rappelons comment dsigner les anneaux usuels avec Sage (cf. 5.2). Les
entiers relatifs sont reprsents par des objets de la classe Integer et, pour
effectuer des conversions, on utilise le parent ZZ ou la fonction IntegerRing()
qui renvoie lobjet ZZ. De la mme faon, les nombres rationnels sont reprsents
par des objets de la classe Rational ; le parent commun ces objets est lobjet
QQ que renvoie la fonction RationalField(). Dans les deux cas Sage utilise la
bibliothque de calcul en prcision arbitraire GMP. Sans rentrer dans le dtail de
la ralisation de cette bibliothque, les entiers manipuls avec Sage sont de taille
arbitraire, la seule limitation provenant de la quantit de mmoire disponible sur
la machine sur laquelle est excut le logiciel.
Plusieurs reprsentations approches des nombres rels sont disponibles (cf. cha-
pitre 11). Il y a RealField() pour la reprsentation utilisant les nombres virgule
flottante avec une prcision donne et, en particulier, RR pour une prcision de 53
bits. Mais il y a aussi RDF et la fonction RealDoubleField() pour les nombres
machine double prcision ; et encore les classes RIF et RealIntervalField()
pour lesquelles un nombre rel est reprsent par un intervalle le contenant, les
extrmits de cet intervalle tant des nombres virgule flottante.
Les reprsentations analogues pour les nombres complexes se nomment : CC, CDF
et CIF. L aussi, chaque objet est associ une fonction ; ce sont ComplexField(),
ComplexDoubleField() et ComplexIntervalField().
Les calculs effectus par Polynomial.roots() sont exacts ou approchs selon
le type de reprsentation des coefficients du polynme et une ventuelle valeur
du paramtre ring : par exemple avec ZZ ou QQ, les calculs sont exacts ; avec
RR les calculs sont approchs. Dans la seconde partie de ce chapitre on prcise
lalgorithme utilis pour le calcul des racines et le rle des paramtres ring et
algorithm (cf. 12.2).
12.1. QUATIONS ALGBRIQUES 257

La rsolution des quations algbriques est intimement lie la notion de


nombre. Le corps de dcomposition du polynme p (suppos non constant) est la
plus petite extension du corps des coefficients de p dans laquelle p est un produit
de polynmes de degr 1 ; on montre quune telle extension existe toujours. Avec
Sage, on peut construire le corps de dcomposition dun polynme irrductible
avec la mthode Polynomial.root_field(). On peut alors calculer avec les
racines implicites contenues dans le corps de dcomposition.
sage: R.<x> = PolynomialRing(QQ, 'x')
sage: p = x^4 + x^3 + x^2 + x + 1
sage: K.<alpha> = p.root_field()
sage: p.roots(ring=K, multiplicities=None)
[alpha, alpha^2, alpha^3, -alpha^3 - alpha^2 - alpha - 1]
sage: alpha^5
1

12.1.3 Thorme de dAlembert


Le corps de dcomposition du polynme coefficients rels x2 + 1 nest autre
que le corps des nombres complexes. Il est remarquable que tout polynme non
constant coefficients complexes possde au moins une racine complexe : cest ce
quaffirme le thorme de dAlembert. En consquence tout polynme complexe
non constant est un produit de polynmes de degr 1. On a observ un peu plus
haut que la somme des multiplicits des racines dun polynme p est infrieure ou
gale au degr de p. Dans le corps des complexes, on sait maintenant que cette
somme est gale au degr de p. Autrement dit toute quation polynomiale de
degr n coefficients complexes possde n racines complexes, comptes avec leur
multiplicit.
Voyons comment la mthode Polynomial.roots() permet dillustrer ce rsul-
tat. Dans lexemple qui suit, on construit lanneau des polynmes coefficients
rels (on se contente dune reprsentation utilisant les nombres virgule flottante
avec une prcision de 53 bits). Puis un polynme de degr infrieur 15 est choisi
alatoirement dans cet anneau. Enfin on additionne les multiplicits des racines
complexes calcules avec la mthode Polynomial.roots() et on compare cette
somme au degr du polynme.
sage: R.<x> = PolynomialRing(RR, 'x')
sage: d = ZZ.random_element(1, 15)
sage: p = R.random_element(d)
sage: p.degree() == sum(r[1] for r in p.roots(CC))
True

12.1.4 Distribution des racines


On poursuit avec une curieuse illustration de la puissance de la mthode
Polynomial.roots() : on trace tous les points du plan complexe dont laffixe
est une racine dun polynme de degr 12 et coefficients gaux 1 ou -1. Le
choix du degr est un compromis plus ou moins arbitraire ; il permet dobtenir un
258 CHAP. 12. QUATIONS NON LINAIRES

Figure 12.1 Distribution des racines de tous les polynmes de degr 12 coefficients 1
ou 1.

trac prcis en peu de temps. Lutilisation de valeurs approches pour les nombres
complexes sest galement impose pour des raisons de performance (cf. 13).
sage: def build_complex_roots(degree):
....: R.<x> = PolynomialRing(CDF, 'x')
....: v = []
....: for c in CartesianProduct(*[[-1, 1]] * (degree + 1)):
....: v.extend(R(c).roots(multiplicities=False))
....: return v
sage: data = build_complex_roots(12)
sage: g = plot(points(data, pointsize=1), aspect_ratio=1)

12.1.5 Rsolution par radicaux


Il est possible dans certains cas de calculer les valeurs exactes des racines
dun polynme. Cest par exemple le cas ds que lon sait exprimer les racines en
fonction des coefficients du polynme et au moyen de radicaux (racines carrs,
racines cubiques, etc.). Dans ce cas on parle de rsolution par radicaux.
Pour effectuer ce type de rsolution avec Sage, il faut travailler avec les objets
de la classe Expression qui reprsentent les expressions symboliques. On a vu
que les entiers reprsents par des objets de la classe Integer ont un mme parent,
lobjet ZZ. De la mme faon, les objets de la classe Expression ont un mme
parent : il sagit de lobjet SR (acronyme de Symbolic Ring) ; il offre notamment
des possibilits de conversion vers la classe Expression.

quations quadratiques.
sage: a, b, c, x = var('a, b, c, x')
sage: p = a * x^2 + b * x + c
sage: type(p)
<type 'sage.symbolic.expression.Expression'>
12.1. QUATIONS ALGBRIQUES 259

sage: p.parent()
Symbolic Ring
sage: p.roots(x)
[(-1/2*(b + sqrt(-4*a*c + b^2))/a, 1),
(-1/2*(b - sqrt(-4*a*c + b^2))/a, 1)]

Degr strictement suprieur 2. Il est possible de rsoudre par radicaux


les quations algbriques complexes de degr 3 et 4. En revanche il est impossible
de rsoudre par radicaux toutes les quations polynomiales de degr suprieur
ou gal 5 (cf. 7.3.4). Cette impossibilit conduit envisager des mthodes de
rsolution numrique (cf. 12.2).
sage: a, b, c, d, e, f, x = var('a, b, c, d, e, f, x')
sage: p = a*x^5+b*x^4+c*x^3+d*x^2+e*x+f
sage: p.roots(x)
Traceback (most recent call last):
...
RuntimeError: no explicit roots found
Illustrons avec Sage une mthode de rsolution des quations de degr 3 sur le
corps des nombres complexes. Pour commencer on montre que lquation gnrale
du troisime degr se ramne la forme x3 + px + q = 0.
sage: x, a, b, c, d = var('x, a, b, c, d')
sage: P = a * x^3 + b * x^2 + c * x + d
sage: alpha = var('alpha')
sage: P.subs(x = x + alpha).expand().coeff(x, 2)
3*a*alpha + b
sage: P.subs(x = x - b / (3 * a)).expand().collect(x)
a*x^3 - 1/3*(b^2/a - 3*c)*x - 1/3*b*c/a + 2/27*b^3/a^2 + d
Pour obtenir les racines dune quation de la forme x3 + px + q = 0 on pose
x = u + v.
sage: p, q, u, v = var('p, q, u, v')
sage: P = x^3 + p * x + q
sage: P.subs(x = u + v).expand()
u^3 + 3*u^2*v + 3*u*v^2 + v^3 + p*u + p*v + q
Supposons la dernire expression nulle. On remarque alors que u3 + v 3 + q = 0
quivaut 3uv+p = 0 ; de plus, si ces galits sont vrifies, u3 et v 3 sont les racines
dune quation du second degr : (X u3 )(X v 3 ) = X 2 (u3 + v 3 )X + (uv)3 =
X 2 + qX p3 /27.
sage: P.subs({x: u + v, q: -u^3 - v^3}).factor()
(u + v)*(3*u*v + p)
sage: P.subs({x: u+v, q: -u^3 - v^3, p: -3 * u * v}).expand()
0
sage: X = var('X')
sage: solve([X^2 + q*X - p^3 / 27 == 0], X, solution_dict=True)
260 CHAP. 12. QUATIONS NON LINAIRES

[{X: -1/2*q - 1/18*sqrt(12*p^3 + 81*q^2)},


{X: -1/2*q + 1/18*sqrt(12*p^3 + 81*q^2)}]

Les solutions de lquation x3 + px + q = 0 sont donc les sommes u + v o u


et v sont des racines cubiques de

4p3 + 27q 2 3 q 4p3 + 27q 2 3 q
p p
et
18 2 18 2

vrifiant 3uv + p = 0.

12.1.6 Mthode Expression.roots()


Les exemples prcdents utilisent la mthode Expression.roots(). Cette
mthode renvoie une liste de racines exactes, sans garantie de les trouver toutes.
Parmi les paramtres optionnels de cette mthode, on retrouve les paramtres
ring et multiplicities dj rencontrs avec la mthode Polynomial.roots().
Il est important de se rappeler que la mthode Expression.roots() ne sapplique
pas uniquement des expressions polynomiales.

sage: e = sin(x) * (x^3 + 1) * (x^5 + x^4 + 1)


sage: roots = e.roots(); len(roots)
9
sage: roots
[(0, 1),
(-1/2*(I*sqrt(3) + 1)*(1/18*sqrt(3)*sqrt(23) - 1/2)^(1/3)
- 1/6*(-I*sqrt(3) + 1)/(1/18*sqrt(3)*sqrt(23) - 1/2)^(1/3), 1),
(-1/2*(-I*sqrt(3) + 1)*(1/18*sqrt(3)*sqrt(23) - 1/2)^(1/3)
- 1/6*(I*sqrt(3) + 1)/(1/18*sqrt(3)*sqrt(23) - 1/2)^(1/3), 1),
((1/18*sqrt(3)*sqrt(23) - 1/2)^(1/3) + 1/3/(1/18*sqrt(3)*sqrt(23)
- 1/2)^(1/3), 1),
(-1/2*I*sqrt(3) - 1/2, 1), (1/2*I*sqrt(3) - 1/2, 1),
(1/2*I*(-1)^(1/3)*sqrt(3) - 1/2*(-1)^(1/3), 1),
(-1/2*I*(-1)^(1/3)*sqrt(3) - 1/2*(-1)^(1/3), 1), ((-1)^(1/3), 1)]

Lorsque le paramtre ring nest pas dfini, la mthode roots() de la classe


Expression dlgue le calcul des racines au programme Maxima qui tente de
factoriser lexpression puis effectue une rsolution par radicaux sur chaque facteur
de degr strictement infrieur 5. Lorsque le paramtre ring est dfini, lexpression
est convertie en objet de la classe Polynomial dont les coefficients ont pour
parent lobjet identifi par le paramtre ring ; ensuite le rsultat de la mthode
Polynomial.roots() est renvoy. On dcrit plus loin lalgorithme utilis dans ce
cas (cf. 12.2.2).
On expose galement des exemples de calculs avec des racines implicites,
auxquelles on accde par les objets QQbar et AA qui reprsentent les corps de
nombres algbriques (cf. 7.3.2).
12.2. RSOLUTION NUMRIQUE 261

limination des racines multiples. tant donn un polynme p ayant des


racines multiples, il est possible de construire un polynme racines simples (cest-
-dire de multiplicit 1), identiques celles de p. Donc, lorsquon calcule les racines
dun polynme, on peut toujours supposer que ces racines sont simples. Justifions
lexistence du polynme racines simples et voyons comment le construire. Ceci
permet de donner une nouvelle illustration de la mthode Expression.roots().
Soit une racine du polynme p dont la multiplicit est un entier m strictement
suprieur 1. Cest une racine du polynme driv p0 avec multiplicit m 1. En
effet, si p = (x )m q alors on a p0 = (x )m1 (mq + (x )q 0 ).
sage: alpha, m, x = var('alpha, m, x'); q = function('q', x)
sage: p = (x - alpha)^m * q
sage: p.derivative(x)
m*(-alpha + x)^(m - 1)*q(x) + (-alpha + x)^m*D[0](q)(x)
sage: simplify(p.derivative(x)(x=alpha))
0
En consquence le pgcd de p et p0 est le produit (x )m 1 avec
Q
lensemble des racines de p de multiplicit strictement suprieure 1, et m la
multiplicit de la racine . Si d dsigne ce pgcd, alors le quotient de p par d a
bien les proprits attendues.
Notons que le degr du quotient de p par d est strictement infrieur au degr de
p. En particulier, si ce degr est strictement infrieur 5, il est possible dexprimer
les racines au moyen de radicaux. Lexemple qui suit en donne une illustration
pour un polynme coefficients rationnels de degr 13.
sage: R.<x> = PolynomialRing(QQ, 'x')
sage: p = 128 * x^13 - 1344 * x^12 + 6048 * x^11 - 15632 * x^10 \
....: + 28056 * x^9 - 44604 * x^8 + 71198 * x^7 - 98283 * x^6 \
....: + 105840 * x^5 - 101304 * x^4 + 99468 * x^3 - 81648 * x^2 \
....: + 40824 * x - 8748
sage: d = gcd(p, p.derivative())
sage: (p // d).degree()
4
sage: roots = SR(p // d).roots(multiplicities=False)
sage: roots
[1/2*I*2^(1/3)*sqrt(3) - 1/2*2^(1/3),
-1/2*I*2^(1/3)*sqrt(3) - 1/2*2^(1/3), 2^(1/3), 3/2]
sage: [QQbar(p(alpha)).is_zero() for alpha in roots]
[True, True, True, True]

12.2 Rsolution numrique


En mathmatiques, on oppose traditionnellement le discret et le continu.
Lanalyse numrique relativise en quelque sorte cette opposition : un des aspects
majeurs de lanalyse numrique consiste en effet aborder des questions portant
sur les nombres rels, par essence du domaine du continu, en adoptant un point
262 CHAP. 12. QUATIONS NON LINAIRES

de vue exprimental sappuyant notamment sur lordinateur qui, lui, relve du


discret.
Sagissant de la rsolution dquations non linaires, de nombreuses questions
se posent naturellement en dehors du calcul des valeurs approches des solutions :
combien de racines relles possde une quation donne ? Combien de racines
imaginaires, positives, ngatives ?
Dans cette partie on commence par donner des lments de rponse pour le
cas particulier des quations algbriques. Ensuite on dcrit quelques-unes des
mthodes dapproximation qui permettent de calculer des valeurs approches des
solutions dune quation non linaire.

12.2.1 Localisation des solutions des quations algbriques


Rgle de Descartes. La rgle de Descartes snonce de la manire suivante :
le nombre de racines positives dun polynme coefficients rels est infrieur ou
gal au nombre de changements de signe de la suite des coefficients du polynme.
sage: R.<x> = PolynomialRing(RR, 'x')
sage: p = x^7 - 131/3*x^6 + 1070/3*x^5 - 2927/3*x^4 \
....: + 2435/3*x^3 - 806/3*x^2 + 3188/3*x - 680
sage: sign_changes = \
....: [p[i] * p[i + 1] < 0 for i in range(p.degree())].count(True)
sage: real_positive_roots = \
....: sum([alpha[1] if alpha[0] > 0 else 0 for alpha in p.roots()])
sage: sign_changes, real_positive_roots
(7, 5)
En effet, soient p un polynme coefficients rels de degr d et p0 le polynme
driv. On note u et u0 les suites des signes des coefficients des polynmes p et
p0 : on a ui = 1 selon que le coefficient de degr i de p est positif ou ngatif. La
suite u0 se dduit de u par simple troncature : on a u0i = ui+1 pour 0 6 i < d. Il
en rsulte que le nombre de changements de signe de la suite u est au plus gal
au nombre de changements de signe de la suite u0 plus 1.
Par ailleurs, le nombre de racines positives de p est au plus gal au nombre de
racines positives de p0 plus un : un intervalle dont les extrmits sont des racines
de p contient toujours une racine de p0 .
Comme la rgle de Descartes est vraie pour un polynme de degr 1, les deux
observations prcdentes montrent quelle est encore vraie pour un polynme de
degr 2, etc.
Il est possible de prciser la relation entre le nombre de racines positives et le
nombre de changements de signes de la suite des coefficients : la diffrence entre
ces nombres est toujours paire.

Isolation de racines relles de polynmes. On vient de voir quil est possible


dtablir, pour les polynmes coefficients rels, une majoration du nombre de
racines contenues dans lintervalle [0, +[. Plus gnralement, il existe des moyens
de prciser le nombre de racines dans un intervalle donn.
12.2. RSOLUTION NUMRIQUE 263

nonons par exemple le thorme de Sturm. Soient p un polynme coeffi-


cients rels, d son degr et [a, b] un intervalle. On construit une suite de polynmes
par rcurrence. Pour commencer p0 = p et p1 = p0 ; ensuite, pi+2 est loppos
du reste de la division euclidienne de pi par pi+1 . En valuant cette suite de
polynmes aux points a et b on obtient deux suites relles finies (p0 (a), . . . , pd (a))
et (p0 (b), . . . , pd (b)). Le thorme de Sturm snonce ainsi : le nombre de racines
de p appartenant lintervalle [a, b] est gal au nombre de changements de signe
de la suite (p0 (a), . . . , pd (a)) diminu du nombre de changements de signe de la
suite (p0 (b), . . . , pd (b)) en supposant que les racines de p sont simples, p(a) 6= 0
et p(b) 6= 0.
Montrons comment implmenter ce thorme avec Sage.

sage: def count_sign_changes(l):


....: changes = [l[i]*l[i + 1] < 0 for i in range(len(l) - 1)]
....: return changes.count(True)

sage: def sturm(p, a, b):


....: assert p.degree() > 2
....: assert not (p(a) == 0)
....: assert not (p(b) == 0)
....: assert a <= b
....: remains = [p, p.derivative()]
....: for i in range(p.degree() - 1):
....: remains.append(-(remains[i] % remains[i + 1]))
....: evals = [[], []]
....: for q in remains:
....: evals[0].append(q(a))
....: evals[1].append(q(b))
....: return count_sign_changes(evals[0]) \
....: - count_sign_changes(evals[1])

Voici maintenant une illustration de cette fonction sturm().

sage: R.<x> = PolynomialRing(QQ, 'x')


sage: p = (x - 34) * (x - 5) * (x - 3) * (x - 2) * (x - 2/3)
sage: sturm(p, 1, 4)
2
sage: sturm(p, 1, 10)
3
sage: sturm(p, 1, 200)
4
sage: p.roots(multiplicities=False)
[34, 5, 3, 2, 2/3]
sage: sturm(p, 1/2, 35)
5
264 CHAP. 12. QUATIONS NON LINAIRES

12.2.2 Mthodes dapproximations successives


Approximation : Gn. au sing. Opration par laquelle on tend se
rapprocher de plus en plus de la valeur relle dune quantit ou dune
grandeur sans y parvenir rigoureusement.
Trsor de la Langue Franaise
Dans cette section, on illustre diffrentes mthodes dapproximation des solu-
tions dune quation non linaire f (x) = 0. Il y a essentiellement deux dmarches
pour calculer ces approximations. Lalgorithme le plus performant mle les deux
dmarches.
La premire dmarche consiste construire une suite dintervalles embots qui
contiennent une solution de lquation. On contrle la prcision, la convergence
est assure mais la vitesse de convergence nest pas toujours bonne.
La seconde dmarche suppose connue une valeur approche dune solution de
lquation. Si le comportement local de la fonction f est suffisamment rgulier,
on pourra calculer une nouvelle valeur approche plus proche de la solution. Par
rcurrence, on obtient donc une suite de valeurs approches. Cette dmarche
suppose donc connue une premire approximation du nombre cherch. Par ailleurs,
son efficacit repose sur le bon comportement local de la fonction f : a priori,
on ne matrise pas la prcision des valeurs approches ; pire, la convergence de la
suite de valeurs approches nest pas ncessairement garantie.
Dans toute cette partie, on considre une quation non linaire f (x) = 0 o
f dsigne une fonction numrique dfinie sur un intervalle [a, b] et continue sur
cet intervalle. On suppose que les valeurs de f aux extrmits de lintervalle
[a, b] sont non nulles et de signes opposs : autrement dit, le produit f (a)f (b) est
strictement ngatif. La continuit de f assure donc lexistence dans lintervalle
[a, b] dau moins une solution lquation f (x) = 0.
Pour chaque mthode, on exprimente avec la fonction suivante.
sage: f(x) = 4 * sin(x) - exp(x) / 2 + 1
sage: a, b = RR(-pi), RR(pi)
sage: bool(f(a) * f(b) < 0)
True
Il convient de noter quavec cet exemple la commande solve nest daucune
utilit.
sage: solve(f(x) == 0, x)
[sin(x) == 1/8*e^x - 1/4]
sage: f.roots()
Traceback (most recent call last):
...
RuntimeError: no explicit roots found
Les algorithmes de recherche de solutions dquations non linaires peuvent
tre coteux : il convient de prendre quelques prcautions avant den dmarrer
lexcution. On sassure notamment de lexistence de solutions en tudiant la conti-
nuit et la drivabilit de la fonction annuler ainsi que dventuels changements
de signe ; cet effet le trac de graphe peut tre utile (cf. chapitre 4).
12.2. RSOLUTION NUMRIQUE 265

-3 -2 -1 1 2 3

-2

-4

-6

-8

-10

Figure 12.2 Courbe reprsentative de la fonction f .

Mthode de dichotomie. Cette mthode repose sur la premire dmarche :


construire une suite dintervalles embots qui contiennent tous une solution de
lquation f (x) = 0.
On divise lintervalle [a, b] en son milieu, not c. Supposons f (c) 6= 0. Soit
f (a)f (c) est strictement infrieur zro et lintervalle [a, c] contient ncessaire-
ment une solution de lquation ; soit f (c)f (b) est strictement infrieur zro et
lintervalle [c, b] contient une solution de lquation. Ainsi on sait construire un
intervalle contenant une solution et dont la longueur est deux fois plus petite que
celle de lintervalle [a, b]. En rptant cette construction on obtient bien une suite
dintervalles aux proprits attendues. Pour mettre en uvre cette dmarche, on
dfinit la fonction Python intervalgen comme suit.
sage: def phi(s, t): return (s + t) / 2
sage: def intervalgen(f, phi, s, t):
....: msg = 'Wrong arguments: f({0})*f({1})>=0)'.format(s, t)
....: assert (f(s) * f(t) < 0), msg
....: yield s
....: yield t
....: while True:
....: u = phi(s, t)
....: yield u
....: if f(u) * f(s) < 0:
266 CHAP. 12. QUATIONS NON LINAIRES

....: t = u
....: else:
....: s = u
La dfinition de cette fonction mrite quelques explications. La prsence du
mot cl yield dans la dfinition de intervalgen en fait un gnrateur (voir
15.2.4). Lors dun appel la mthode next() dun gnrateur, si linterprteur
rencontre le mot cl yield, toutes les donnes locales sont sauvegardes, lexcution
est interrompue et lexpression immdiatement droite du mot cl rencontr
est renvoye. Lappel suivant la mthode next() dmarre linstruction qui
suit le mot cl yield avec les donnes locales sauvegardes avant linterruption.
Utilis dans une boucle infinie (while True:) le mot cl yield permet donc
de programmer une suite rcurrente avec une syntaxe proche de sa description
mathmatique. Il est possible de stopper dfinitivement lexcution en utilisant
lhabituel mot cl return.
Le paramtre phi reprsente une fonction ; elle caractrise la mthode dap-
proximation. Pour la mthode de la dichotomie, cette fonction calcule le milieu
dun intervalle. Pour tester une autre mthode dapproximations successives repo-
sant galement sur la construction dintervalles embots, on donne une nouvelle
dfinition de la fonction phi et on utilise nouveau la fonction intervalgen pour
construire le gnrateur correspondant.
Les paramtres s et t de la fonction reprsentent les extrmits du premier
intervalle. Un appel assert permet de vrifier que la fonction f change de signe
entre les extrmits de cet intervalle ; on a vu que cela garantit lexistence dune
solution.
Les deux premires valeurs du gnrateur correspondent aux paramtres s et
t. La troisime valeur est le milieu de lintervalle correspondant. Les paramtres
s et t reprsentent ensuite les extrmits du dernier intervalle calcul. Aprs
valuation de f au milieu de cet intervalle, on change une des extrmits de
lintervalle en sorte que le nouvel intervalle contienne encore une solution. On
convient de prendre pour valeur approche de la solution cherche le milieu du
dernier intervalle calcul.
Exprimentons avec lexemple choisi : suivent les trois approximations obtenues
par la mthode de dichotomie applique sur lintervalle [, ].
sage: a, b
(-3.14159265358979, 3.14159265358979)
sage: bisection = intervalgen(f, phi, a, b)
sage: bisection.next()
-3.14159265358979
sage: bisection.next()
3.14159265358979
sage: bisection.next()
0.000000000000000
Pour comparer les diffrentes mthodes dapproximation, il est commode de
disposer dun mcanisme automatisant le calcul de la valeur approche dune
solution de lquation f (x) = 0 partir des gnrateurs dfinis avec Sage pour
12.2. RSOLUTION NUMRIQUE 267

chacune de ces mthodes. Ce mcanisme doit permettre de contrler la prcision


du calcul et le nombre maximum ditrations. Cest le rle de la fonction iterate
dont la dfinition suit.
sage: from types import GeneratorType, FunctionType
sage: def checklength(u, v, w, prec):
....: return abs(v - u) < 2 * prec
sage: def iterate(series, check=checklength, prec=10^-5, maxit=100):
....: assert isinstance(series, GeneratorType)
....: assert isinstance(check, FunctionType)
....: niter = 2
....: v, w = series.next(), series.next()
....: while niter <= maxit:
....: niter += 1
....: u, v, w = v, w, series.next()
....: if check(u, v, w, prec):
....: print 'After {0} iterations: {1}'.format(niter, w)
....: return
....: print 'Failed after {0} iterations'.format(maxit)
Le paramtre series doit tre un gnrateur. On conserve les trois dernires
valeurs de ce gnrateur pour pouvoir effectuer un test de convergence. Cest le
rle du paramtre check : une fonction qui stoppe ou non les itrations. Par dfaut
la fonction iterate utilise la fonction checklength qui stoppe les itrations si
le dernier intervalle calcul est de longueur strictement infrieure au double du
paramtre prec ; cela garantit que la valeur calcule par la mthode de dichotomie
est une valeur approche avec une erreur strictement infrieure prec.
Une exception est dclenche ds que le nombre ditrations dpasse le para-
mtre maxit.
sage: bisection = intervalgen(f, phi, a, b)
sage: iterate(bisection)
After 22 iterations: 2.15847275559132
Exercice 42. Modifier la fonction intervalgen pour que le gnrateur stoppe si
une des extrmits de lintervalle est une solution.
Exercice 43. Utiliser les fonctions intervalgen et iterate pour programmer le
calcul dune valeur approche dune solution de lquation f (x) = 0 partir dune
suite dintervalles embots, chaque intervalle tant obtenu en divisant alatoirement le
prcdent.

Mthode de la fausse position. Cette mthode repose encore sur la premire


dmarche : construire une suite dintervalles embots qui contiennent tous une
solution de lquation f (x) = 0. Mais cette fois-ci on utilise une interpolation
linaire de la fonction f pour diviser chaque intervalle.
Prcisment, pour diviser lintervalle [a, b], on considre le segment joignant
les deux points de la courbe reprsentative de f dabscisses a et b. Comme f (a)
et f (b) sont de signes opposs, ce segment coupe laxe des abscisses : il divise
donc lintervalle [a, b] en deux intervalles. Comme pour la mthode de dichotomie,
268 CHAP. 12. QUATIONS NON LINAIRES

-3 -2 -1 1 2 3

-2

-4

-6

-8

-10

Figure 12.3 Mthode de la fausse position sur [, ].

on identifie un intervalle contenant une solution en calculant la valeur que prend


la fonction f au point commun ces deux intervalles.
La droite passant par les points de coordonnes (a, f (a)) et (b, f (b)) a pour
quation :
f (b) f (a)
y= (x a) + f (a). (12.1)
ba
Puisque f (b) 6= f (a), cette droite coupe laxe des abscisses au point dabscisse :

ba
a f (a) .
f (b) f (a)

On peut donc tester cette mthode de la manire suivante.


sage: phi(s, t) = s - f(s) * (t - s) / (f(t) - f(s))
sage: falsepos = intervalgen(f, phi, a, b)
sage: iterate(falsepos)
After 8 iterations: -2.89603757331027

Il est important de remarquer que les suites construites avec les mthodes
de dichotomie et de la fausse position ne convergent pas ncessairement vers les
mmes solutions. En rduisant lintervalle dtude on retrouve la solution positive
obtenue avec la mthode de dichotomie.
12.2. RSOLUTION NUMRIQUE 269

0 1.6 1.8 2 2.2 2.4 2.6 2.8 3

-2

-4

-6

-8

-10

Figure 12.4 Mthode de la fausse position sur [/2, ].

sage: a, b = RR(pi/2), RR(pi)


sage: phi(s, t) = t - f(t) * (s - t) / (f(s) - f(t))
sage: falsepos = intervalgen(f, phi, a, b)
sage: phi(s, t) = (s + t) / 2
sage: bisection = intervalgen(f, phi, a, b)
sage: iterate(falsepos)
After 15 iterations: 2.15846441170219
sage: iterate(bisection)
After 20 iterations: 2.15847275559132

Mthode de Newton. Comme la mthode de la fausse position, la mthode


de Newton utilise une approximation linaire de la fonction f . Du point de vue
graphique, il sagit de considrer une tangente la courbe reprsentative de f
comme approximation de cette courbe.
On suppose donc maintenant f drivable et la fonction drive f 0 de signe
constant dans lintervalle [a, b] ; ainsi f est monotone. On suppose aussi que f
change de signe dans lintervalle [a, b]. Lquation f (x) = 0 a donc une unique
solution dans cet intervalle ; on note ce nombre.
Soit u0 [a, b]. La tangente la courbe reprsentative de f au point dabscisse
u0 a pour quation :
y = f 0 (u0 )(x u0 ) + f (u0 ). (12.2)
270 CHAP. 12. QUATIONS NON LINAIRES

Les coordonnes du point dintersection de cette droite avec laxe des abscisses
sont :
(u0 f (u0 )/f 0 (u0 ), 0).
On note la fonction x 7 x f (x)/f 0 (x). Elle est dfinie condition que f 0 ne
sannule pas dans lintervalle [a, b]. On sintresse la suite rcurrente u dfinie
par un+1 = (un ).
Si la suite u est convergente 1 , alors sa limite ` vrifie ` = ` f (`)/f 0 (`) dont
rsulte f (`) = 0 : la limite est gale , la solution de lquation f (x) = 0.
Pour que lexemple respecte les hypothses de monotonie, on est amen
rduire lintervalle dtude.
sage: f.derivative()
x |--> -1/2*e^x + 4*cos(x)
sage: a, b = RR(pi/2), RR(pi)
On dfinit un gnrateur Python newtongen reprsentant la suite rcurrente
que lon vient de dfinir. Ensuite on dfinit un nouveau test de convergence
checkconv qui stoppe les itrations si les deux derniers termes calculs sont
suffisamment proches ; bien entendu ce test ne garantit pas la convergence de la
suite des valeurs approches.
sage: def newtongen(f, u):
....: while True:
....: yield u
....: u -= f(u) / f.derivative()(u)
sage: def checkconv(u, v, w, prec):
....: return abs(w - v) / abs(w) <= prec
On peut maintenant tester la mthode de Newton sur notre exemple.
sage: iterate(newtongen(f, a), check=checkconv)
After 6 iterations: 2.15846852566756

Mthode de la scante. Dans la mthode de Newton le calcul de drive peut


tre coteux. Il est possible de substituer ce calcul de drive une interpolation
linaire : si on dispose de deux approximations de la solution, donc de deux
points de la courbe reprsentative de f , et si la droite passant par ces deux points
rencontre laxe des abscisses, on considre labscisse du point dintersection comme
une nouvelle approximation. Pour dmarrer la construction et lorsque les deux
droites sont parallles on convient de calculer une nouvelle approximation de la
mme faon que dans la mthode de Newton.
Cela donne lieu la mme formule ditration que dans la mthode de la fausse
position, mais applique en des points diffrents. Contrairement la mthode de
la fausse position, celle de la scante nidentifie pas dintervalle contenant une
racine.
On dfinit un gnrateur Python mettant en uvre cette mthode.

1. Un thorme de L. Kantorovich donne une condition suffisante pour que la mthode de


Newton converge.
12.2. RSOLUTION NUMRIQUE 271

0 1.6 1.8 2 2.2 2.4 2.6 2.8 3

-2

-4

-6

-8

-10

Figure 12.5 Mthode de Newton.

sage: def secantgen(f, a):


....: yield a
....: estimate = f.derivative()(a)
....: b = a - f(a) / estimate
....: yield b
....: while True:
....: fa, fb = f(a), f(b)
....: if fa == fb:
....: estimate = f.derivative()(a)
....: else:
....: estimate = (fb - fa) / (b - a)
....: a = b
....: b -= fb / estimate
....: yield b
On peut maintenant tester la mthode de la scante sur notre exemple.
sage: iterate(secantgen(f, a), check=checkconv)
After 8 iterations: 2.15846852557553

Mthode de Muller. Il est possible dtendre la mthode de la scante en


substituant f des approximations polynomiales de degr quelconque. Par exemple
272 CHAP. 12. QUATIONS NON LINAIRES

0 1.6 1.8 2 2.2 2.4 2.6 2.8 3

-2

-4

-6

-8

-10

Figure 12.6 Mthode de la scante.

la mthode de Muller 2 utilise des approximations quadratiques.


Supposons construites trois approximations r, s et t de la solution de lquation
f (x) = 0. On considre le polynme dinterpolation de Lagrange dfini par les trois
points de la courbe reprsentative de f dabscisses r, s et t. Cest un polynme
du second degr. On convient de prendre pour nouvelle approximation la racine
de ce polynme qui est la plus proche de t. Par ailleurs, les trois premiers termes
de la suite sont fixs de manire arbitraire : a, b puis (a + b)/2.
Il convient de remarquer que les racines des polynmes et donc les approxi-
mations calcules peuvent tre des nombres complexes.
La programmation de cette mthode en Sage nest pas difficile ; elle peut se
faire sur le mme modle que la mthode de la scante. Notre ralisation utilise
toutefois une structure de donne mieux adapte lnumration des termes dune
suite rcurrente.
sage: from collections import deque
sage: basering = PolynomialRing(CC, 'x')
sage: def quadraticgen(f, r, s):
....: t = (r + s) / 2
....: yield t
....: points = deque([(r,f(r)), (s,f(s)), (t,f(t))], maxlen=3)
2. Il sagit ici de David E. Muller, bien connu aussi pour avoir invent le code de Reed-Muller,
et non de Jean-Michel Muller cit au chapitre 11.
12.2. RSOLUTION NUMRIQUE 273

....: while True:


....: pol = basering.lagrange_polynomial(points)
....: roots = pol.roots(ring=CC, multiplicities=False)
....: u = min(roots, key=lambda x: abs(x - points[2][0]))
....: points.append((u, f(u)))
....: yield points[2][0]
Le module collections de la bibliothque de rfrence Python implmente
plusieurs structures de donnes. Dans quadraticgen, la classe deque est utilise
pour stocker les dernires approximations calcules. Un objet deque stocke des
donnes dans la limite du nombre maxlen fix lors de sa cration ; ici le nombre
maximal de donnes stockes est gal lordre de rcurrence de la suite des
approximations. Lorsquun objet deque a atteint sa capacit maximale de stockage,
la mthode deque.append() ajoute les nouvelles donnes sur le principe premier
entr, premier sorti .
Notons que les itrations de cette mthode ne ncessitent pas le calcul de
valeurs drives. De plus chaque itration ne ncessite quune valuation de la
fonction f .
sage: generator = quadraticgen(f, a, b)
sage: iterate(generator, check=checkconv)
After 5 iterations: 2.15846852554764

Retour aux polynmes. Revenons la situation tudie au dbut de ce


chapitre. Il sagissait de calculer les racines dun polynme coefficients rels ; on
notera P ce polynme. Supposons P unitaire :

P = a0 + a1 x + . . . + ad1 xd1 + xd .

Il est facile de vrifier que P est le polynme caractristique de la matrice


compagnon (cf. 8.2.3) :

0 0 0 ... 0

a0
1 0 0 . . . 0 a1
A= 0 1 0 0

. . . a2 .
. . . . . . . . . . . . . . . . . . . . . . . . .
0 0 0 . . . 1 ad1

En consquence les racines du polynme P sont les valeurs propres de la matrice A.


Les mthodes du chapitre 13 sappliquent donc.
On a vu que la mthode Polynomial.roots() prend jusqu trois paramtres,
tous optionnels : ring, multiplicities et algorithm. Supposons quun ob-
jet Sage de la classe Polynomial est associ au nom p (donc isinstance(p,
Polynomial) renvoie True). Lalgorithme utilis par la commande p.roots()
dpend alors des paramtres ring et algorithm ainsi que de lanneau des coeffi-
cients du polynme, cest--dire p.base_ring().
Lalgorithme teste si les oprations arithmtiques effectues dans ring et
p.base_ring() sont exactes. Si cela nest pas le cas, des valeurs approches des
274 CHAP. 12. QUATIONS NON LINAIRES

racines sont calcules avec la bibliothque NumPy si p.base_ring() est RDF ou


CDF, ou avec la bibliothque PARI autrement (le paramtre algorithm permet
lutilisateur dimposer son choix de bibliothque pour ce calcul). En consultant
le code source de NumPy on voit que la mthode dapproximation des racines
utilise par cette bibliothque consiste calculer les valeurs propres de la matrice
compagnon.
La commande qui suit permet didentifier les objets pour lesquels les oprations
arithmtiques sont exactes (la valeur renvoye par la mthode Ring.is_exact()
est True dans ce cas).
sage: for ring in [ZZ, QQ, QQbar, RDF, RIF, RR, AA, CDF, CIF, CC]:
....: print("{0:50} {1}".format(ring, ring.is_exact()))
Integer Ring True
Rational Field True
Algebraic Field True
Real Double Field False
Real Interval Field with 53 bits of precision False
Real Field with 53 bits of precision False
Algebraic Real Field True
Complex Double Field False
Complex Interval Field with 53 bits of precision False
Complex Field with 53 bits of precision False
Lorsque le paramtre ring vaut AA ou RIF, tandis que p.base_ring() vaut ZZ,
QQ ou AA, lalgorithme appelle la fonction real_roots() du module sage.rings.
polynomial.real_roots. Cette fonction convertit le polynme dans la base
de Bernstein, puis utilise lalgorithme de Casteljau (pour valuer le polynme
exprim dans la base de Bernstein) et la rgle de Descartes (cf. 12.2.1) pour
localiser les racines.
Lorsque le paramtre ring vaut QQbar ou CIF, et p.base_ring() vaut ZZ,
QQ, AA ou reprsente des rationnels Gaussiens, lalgorithme dlgue les calculs
NumPy et PARI dont les rsultats sont convertis dans les anneaux attendus.
On peut prendre connaissance de toutes les situations couvertes par la mthode
Polynomial.roots() en consultant la documentation de cette mthode.

Vitesse de convergence. Considrons une suite numrique convergente u et


notons ` sa limite. On dit que la vitesse de convergence de la suite u est linaire
sil existe K ]0, 1[ tel que :
|un+1 `|
lim = K.
n |un `|
La vitesse de convergence de la suite u est dite quadratique sil existe K > 0 tel
que :
|un+1 `|
lim = K.
n |u `|2
n
Revenons la mthode de Newton. On a construit une suite rcurrente u
dfinie par un+1 = (un ) avec la fonction x 7 x f (x)/f 0 (x). Sous lhypothse
12.2. RSOLUTION NUMRIQUE 275

que f est deux fois drivable, la formule de Taylor pour la fonction et x au


voisinage de la racine scrit :

(x )2 00
(x) = () + (x )0 () + () + O ((x )3 ).
2
Or () = , 0 () = 0 et 00 () = f 00 ()/f 0 (). En substituant dans la formule
prcdente et en revenant la dfinition de la suite u, on obtient :

(un )2 f 00 ()
un+1 = + O ((un )3 ).
2 f 0 ()

Lorsque la mthode de Newton converge, la vitesse de convergence de la suite


construite est donc quadratique.

Acclration de la convergence. partir dune suite convergente dont la


vitesse de convergence est linaire, il est possible de construire une suite dont
la vitesse de convergence est quadratique. La mme technique, applique la
mthode de Newton, est connue sous le nom de mthode de Steffensen.
sage: def steffensen(sequence):
....: assert isinstance(sequence, GeneratorType)
....: values = deque(maxlen=3)
....: for i in range(3):
....: values.append(sequence.next())
....: yield values[i]
....: while True:
....: values.append(sequence.next())
....: u, v, w = values
....: yield u - (v - u)^2 / (w - 2 * v + u)

sage: g(x) = sin(x^2 - 2) * (x^2 - 2)


sage: sequence = newtongen(g, RR(0.7))
sage: accelseq = steffensen(newtongen(g, RR(0.7)))
sage: iterate(sequence, check=checkconv)
After 17 iterations: 1.41422192763287
sage: iterate(accelseq, check=checkconv)
After 10 iterations: 1.41421041980166
On notera que la vitesse de convergence est une notion asymptotique : elle ne
dit rien de lerreur |un `| pour n donn.
sage: sequence = newtongen(f, RR(a))
sage: accelseq = steffensen(newtongen(f, RR(a)))
sage: iterate(sequence, check=checkconv)
After 6 iterations: 2.15846852566756
sage: iterate(accelseq, check=checkconv)
After 7 iterations: 2.15846852554764
276 CHAP. 12. QUATIONS NON LINAIRES

Rsolution des quations non linaires


Racines approches dun polynme Polynomial.roots()
Racines exactes sans garantie de les avoir toutes Expression.roots()
Racines approches dans le corps des rels real_roots()
Racines approches par la mthode de Brent Expression.find_root()

Tableau 12.1 Rcapitulatif des commandes dcrites dans ce chapitre.

Mthode Expression.find_root(). On sintresse maintenant la situation


la plus gnrale : le calcul dune valeur approche dune solution dune quation
f (x) = 0. Avec Sage, ce calcul se fait avec la mthode Expression.find_root().
Les paramtres de la mthode Expression.find_root() permettent de dfinir
un intervalle o chercher une racine, la prcision du calcul ou le nombre ditrations.
Le paramtre full_output permet dobtenir des informations sur le calcul,
notamment le nombre ditrations et le nombre dvaluations de la fonction.
sage: result = (f == 0).find_root(a, b, full_output=True)
sage: result[0], result[1].iterations
(2.1584685255476415, 9)
En fait, la mthode Expression.find_root() nimplmente pas rellement
dalgorithme de recherche de solutions dquations : les calculs sont dlgus au
module SciPy. La fonctionnalit de SciPy utilise par Sage pour rsoudre une
quation implmente la mthode de Brent qui combine trois des mthodes vues
prcdemment : la mthode de dichotomie, la mthode de la scante et linterpo-
lation quadratique. Les deux premires valeurs approches sont les extrmits de
lintervalle o est cherche la solution de lquation. La valeur approche suivante
est obtenue par interpolation linaire comme on la fait dans la mthode de la s-
cante. Avec les itrations suivantes la fonction est approche par une interpolation
quadratique et labscisse du point dintersection de la courbe dinterpolation avec
laxe des abscisses est la nouvelle valeur approche, moins que cette abscisse ne
soit pas comprise entre les deux prcdentes valeurs approches calcules auquel
cas on poursuit avec la mthode de dichotomie.
La bibliothque SciPy ne permet pas de calculer en prcision arbitraire (
moins de se contenter de calculer avec des entiers) ; dailleurs le code source
de la mthode Expression.find_root() commence par convertir les bornes en
nombres machine double prcision. loppos, toutes les illustrations de mthodes
de rsolution dquation construites dans ce chapitre fonctionnent en prcision
arbitraire et mme symbolique.
sage: a, b = pi/2, pi
sage: generator = newtongen(f, a)
sage: generator.next(); generator.next()
1/2*pi
1/2*pi - (e^(1/2*pi) - 10)*e^(-1/2*pi)
Exercice 44. crire un gnrateur pour la mthode de Brent qui fonctionne en
prcision arbitraire.
13
Algbre linaire numrique

On traite ici les aspects numriques de lalgbre linaire, lalgbre linaire


symbolique tant prsente au chapitre 8. Pour des textes en franais sur les
mthodes et lanalyse numrique de lalgbre linaire, on pourra consulter les
livres de M. Schatzman [Sch91], de P. Ciarlet [Cia82] ou ceux plus spcialiss
de Lascaux-Thodor [LT93, LT94]. Le livre de Golub et Van Loan [GVL96], en
anglais, est une rfrence incontournable.
Lalgbre linaire numrique joue un rle prpondrant dans ce quil est
convenu dappeler le calcul scientifique, appellation impropre pour dsigner des
problmes dont ltude mathmatique relve de lanalyse numrique : rsolution
approche de systmes dquations diffrentielles, rsolution approche dquations
aux drives partielles, optimisation, traitement du signal, etc.
La rsolution numrique de la plupart de ces problmes, mme linaires, est
fonde sur des algorithmes forms de boucles imbriques ; au plus profond de ces
boucles, il y a trs souvent la rsolution dun systme linaire. On utilise souvent
la mthode de Newton pour rsoudre des systmes algbriques non linaires : l
encore il faut rsoudre des systmes linaires. La performance et la robustesse
des mthodes dalgbre linaire numrique sont donc cruciales.
Ce chapitre comporte trois sections : dans la premire, on sefforce de sen-
sibiliser le lecteur linfluence de linexactitude des calculs en algbre linaire ;
la deuxime section (13.2) traite, sans tre exhaustive, des problmes les plus
classiques (rsolution de systmes, calcul de valeurs propres, moindres carrs) ;
dans la troisime section (13.3) on montre comment rsoudre certains problmes
si on fait lhypothse que les matrices sont creuses. Cette dernire partie se veut
autant une initiation des mthodes qui font partie dun domaine de recherche
actif quun guide dutilisation.
278 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

13.1 Calculs inexacts en algbre linaire


On sintresse aux problmes classiques de lalgbre linaire (rsolution de
systmes, calcul de valeurs et de vecteurs propres, etc.) rsolus au moyen de
calculs inexacts. La premire source dinexactitude vient de ce quon va utiliser
une approximation flottante des nombres (rels ou complexes), et donc non
seulement travailler sur des objets connus approximativement, mais aussi entacher
tous les calculs derreurs. Les diffrents types de nombres flottants utilisables
dans Sage sont dcrits au chapitre 12.
Soit par exemple rsoudre le systme Ax = b o A est une matrice
coefficients rels. Quelle erreur x commet-on si on perturbe A de A ou b de b ?
On apporte quelques lments de rponse dans ce chapitre.

13.1.1 Normes de matrices et conditionnement


Soit A Rnn (ou Cnn ). On quipe Rn (ou PnC ) dune norme kxk, par
n

exemple la norme kxkPn = max |xi | ou kxk1 = i=1 |xi |, ou encore la norme
euclidienne kxk2 = ( i=1 x2i )1/2 ; alors la quantit
kAk = max kA xk
kxk=1

dfinit une norme sur lensemble des matrices n n. On dit quil sagit dune
norme subordonne la norme dfinie sur Rn (ou Cn ). Le conditionnement de A
est dfini par (A) = kA1 k kAk. Le rsultat fondamental est que, si on fait subir
A une (petite) perturbation A et b une perturbation b, alors la solution x
du systme linaire Ax = b est perturbe de x qui vrifie :
 
kxk (A) kAk kbk
6 + .
kxk 1 (A)kAk/kAk kAk kbk
Pn
Les normes kk et kk1 sont faciles calculer : kAk = max16i6n ( j=1 |Aij |)
Pn
et kAk1 = max16j6n ( q i=1 |Aij |). En revanche la norme kk2 ne sobtient pas

simplement car kAk2 = (t A A), le rayon spectral dune matrice A tant le


maximum des modules de ses valeurs propres.
La norme de Frobenius est dfinie par
Xn X n 1/2
kAkF = |aij |2
.
i=1 j=1

la diffrence des normes prcdentes, ce nest pas une norme subordonne. On


vrifie aisment que kAk2F = trace(t A A).

Le calcul des normes de matrice dans Sage. Les matrices possdent une
mthode norm(p). Selon la valeur de largument p on obtiendra :
p=1: kAk1 , p=2: kAk2 ,
p = Infinity : kAk , p = 'frob' : kAkF .
13.1. CALCULS INEXACTS EN ALGBRE LINAIRE 279

Cette mthode nest applicable que si les coefficients de la matrice peuvent


tre convertis en nombres complexes CDF. Noter quon crit A.norm(Infinity)
mais A.norm('frob'). Avec A.norm() on obtiendra la norme kAk2 (valeur par
dfaut).

Erreurs et conditionnement : une illustration, avec des calculs exacts,


puis approchs. Utilisons la possibilit de Sage de faire des calculs exacts
quand les coefficients sont rationnels. On considre la matrice de Hilbert

Aij = 1/(i + j 1), i, j = 1, . . . , n.

Le programme suivant calcule exactement le conditionnement des matrices de


Hilbert, en norme kk :
sage: def cond_hilbert(n):
....: A = matrix(QQ, [[1/(i+j-1) for j in [1..n]] for i in [1..n]])
....: return A.norm(Infinity) * (A^-1).norm(Infinity)
Voici les rsultats, en fonction de n :
n conditionnement
2 27
4 28375
8 33872791095
16 5.06277478751e+22
32 1.35710782493e+47
On remarque laccroissement extrmement rapide du conditionnement en
fonction de n. On peut montrer que (A) ' e7n/2 , ce qui videmment, est une
quantit qui crot trs vite. Toujours en calculant exactement dans lensemble des
rationnels, on peut perturber la matrice A, et comparer la solution dun systme
linaire original celle du mme systme perturb :
sage: n = 8
sage: x = vector(QQ,[1 for i in range(0,n)])
sage: A = matrix(QQ, [[1/(i+j-1) for j in [1..n]] for i in [1..n]])
sage: y = A*x
sage: A[n-1,n-1] = (1/(2*n-1))*(1+1/(10^5)) # perturbe la matrice
sage: sol = A\y
sage: diff = max(float(sol[i]-x[i]) for i in range(0,n))
On obtient :
n erreur (diff)
2 1.9999200e-05
4 0.00597609561
8 3.47053530779
16 63.2816091951
32 20034.3477421
280 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

et donc les calculs sont rapidement entachs dune erreur inacceptable.


Calculons maintenant avec des matrices et des vecteurs coefficients flottants.
Cette fois, on ne perturbe pas explicitement la matrice A, mais larithmtique
flottante va introduire de petites perturbations. On refait le calcul prcdent : le
second membre tant calcul par y = Ax, on cherche retrouver x en rsolvant
le systme linaire As = y :
sage: n = 8
sage: A = matrix(RR, [[1/(i+j-1) for j in [1..n]] for i in [1..n]])
sage: x = vector(RR, [1 for i in range(0,n)])
sage: y = A*x
sage: s = A.solve_right(y)
sage: diff = [float(s[i]-x[i]) for i in range(0,n)]
En fonction de n on obtient :
n erreur (diff)
2 2.22044604925e-16
4 3.05977465587e-13
8 6.82028985288e-07
16 8.34139063331
32 257.663242705
On voit que pour n = 16 par exemple, lerreur sur la solution (en norme
infinie) est telle quon ne calcule plus rien du tout de pertinent (avec le choix
particulier de x que nous avons fait (xi = 1), les erreurs absolues et relatives en
norme infinie concident).

Remarques. Pourquoi alors calculer avec des nombres flottants ? La question


des performances nest pas forcment pertinente depuis quil existe des biblio-
thques implantant efficacement des algorithmes dalgbre linaire en arithmtique
rationnelle (Linbox, utilise par Sage), algorithmes qui, sans tre aussi performants
que leur quivalent flottant, pourraient avantageusement tre utiliss, pour cer-
tains problmes comme la rsolution de systmes linaires de taille modre. Mais
cest ici quintervient une deuxime source dincertitude : dans les applications
relles, les coefficients ne peuvent tre connus quapproximativement. Par exemple
la rsolution dun systme dquations non linaires par la mthode de Newton
fait naturellement apparatre des termes calculs de manire inexacte.
Les systmes linaires mal conditionns (sans tre aussi caricaturaux que
la matrice de Hilbert) sont plutt la rgle que lexception : il est frquent (en
physique, en chimie, en biologie, etc.) de rencontrer des systmes dquations
diffrentielles ordinaires de la forme du/dt = F (u) o la matrice jacobienne
DF (u), matrice des drives partielles Fi (u)/uj , dfinit un systme linaire
mal conditionn : les valeurs propres sont rparties dans un ensemble trs vaste,
ce qui entrane le mauvais conditionnement de DF (u) ; cette proprit traduit
le fait que le systme modlise des phnomnes mlangeant plusieurs chelles de
temps. Malheureusement, en pratique, il faut rsoudre des systmes linaires dont
la matrice est DF (u).
13.2. MATRICES PLEINES 281

Tous les calculs (dcomposition de matrices, calcul dlments propres, conver-


gence de mthodes itratives) sont affects par le conditionnement. Il convient
donc davoir cette notion prsente lesprit ds que lon calcule en utilisant une
reprsentation flottante des nombres rels.

13.2 Matrices pleines

13.2.1 Rsolution de systmes linaires


Mthodes viter. Ce quil ne faut (presque) jamais faire, cest utiliser les
formules de Cramer. Un raisonnement par rcurrence montre que le cot du calcul
du dterminant dune matrice n n en utilisant les formules de Cramer est de
lordre n! multiplications (et autant dadditions). Pour rsoudre un systme de
taille n, ce sont n + 1 dterminants quil faut calculer. Prenons n = 20 :

sage: n = 20; cout = (n+1)*factorial(n); cout


51090942171709440000

nous obtenons la valeur respectable de 51 090 942 171 709 440 000 multiplications.
Supposons que notre calculateur effectue 3 109 multiplications par seconde (ce
qui est raliste), et calculons la dure approximative du calcul :

sage: v = 3*10^9
sage: print "%3.3f"%float(cout/v/3600/24/365)
540.028

Il faudra donc 540 ans (environ) pour effectuer le calcul ! Bien sr vous pouvez
utiliser les formules de Cramer pour rsoudre un systme 2 2, mais pas bien au
del ! Toutes les mthodes utilises en pratique ont en commun un cot polynomial,
cest--dire de lordre de np , avec p petit (p = 3, en gnral).

Mthodes pratiques. La rsolution de systmes linaires Ax = b est le plus


souvent base sur une factorisation de la matrice A en un produit de deux matrices
A = M1 M2 , M1 et M2 dfinissant des systmes linaires faciles rsoudre. Pour
rsoudre Ax = b, on rsout alors successivement M1 y = b, puis M2 x = y.
Par exemple M1 et M2 peuvent tre deux matrices triangulaires ; dans ce cas,
une fois la factorisation effectue, il faut rsoudre deux systmes linaires matrice
triangulaire. Le cot de la factorisation est bien plus lev que celui de la rsolution
des deux systmes triangulaires (par exemple O(n3 ) pour la factorisation LU
contre O(n2 ) pour la rsolution des systmes triangulaires). Il convient donc, dans
le cas de la rsolution de plusieurs systmes avec la mme matrice, de ne calculer
quune seule fois la dcomposition. Bien entendu, on ninverse jamais une matrice
pour rsoudre un systme linaire, linversion demandant la factorisation de la
matrice, puis la rsolution de n systmes au lieu dun seul.
282 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

13.2.2 Rsolution directe


Voici la manire la plus simple de procder :
sage: A = matrix(RDF, [[-1,2],[3,4]])
sage: b = vector(RDF, [2,3])
sage: x = A\b; x
(-0.2, 0.9)
Dans Sage, les matrices possdent une mthode solve_right pour la rsolution
de systmes linaires (base sur la dcomposition LU ) ; cest cette commande qui
est appele ci-dessus. On aurait aussi pu crire :
sage: x = A.solve_right(b)
La syntaxe x = A\b est pratiquement identique ce quon utilise dans les systmes
de calcul Matlab, Octave ou Scilab.

13.2.3 La dcomposition LU

sage: A = matrix(RDF, [[-1,2],[3,4]])


sage: P, L, U = A.LU()
Cette mthode fournit les facteurs L et U ainsi que la matrice de permutation P ,
tels que A = P LU (ou de manire quivalente P A = LU , comme le lecteur
averti aura remarqu). Ce sont les choix de pivots qui imposent la cration de la
matrice P . La matrice L est triangulaire infrieure, diagonale unit, et U est une
matrice triangulaire suprieure. Cette dcomposition est directement drive de
la mthode de Gauss (dcrite en 8.2.1). En effet, en ngligeant pour la simplicit
de lexpos les problmes de choix de pivots, la mthode de Gauss consiste
transformer la matrice A (dordre n) pour faire apparatre des coefficients nuls
sous la diagonale de la premire colonne, puis de la deuxime colonne et ainsi de
suite. Cette limination peut scrire

Ln1 . . . L2 L1 A = U.

En posant L = (Ln1 . . . L2 L1 )1 , on obtient bien A = LU et on vrifie sans


difficult que L est triangulaire infrieure diagonale unit.
Notons que Sage garde en mmoire la factorisation de A : la commande
A.LU_valid() va rpondre True si et seulement si la factorisation LU a dj t
calcule. Mieux, la commande A.solve_right(b) ne calculera la factorisation
que si cest ncessaire, cest--dire si elle na pas t calcule auparavant, ou si la
matrice A a chang.
Exemple. Crons une matrice de taille 1000, alatoire et un vecteur de taille
1000 :
sage: A = random_matrix(RDF, 1000)
sage: b = vector(RDF, range(1000))
factorisons A :
13.2. MATRICES PLEINES 283

sage: %time A.LU()


CPU times: user 0.23 s, sys: 0.01 s, total: 0.24 s
Wall time: 0.29 s
et prsent rsolvons le systme Ax = b :
sage: %time x = A.solve_right(b)
CPU times: user 0.10 s, sys: 0.00 s, total: 0.10 s
Wall time: 0.12 s
La rsolution est plus rapide, parce quelle a tenu compte de la factorisation
prcdemment calcule.

13.2.4 La dcomposition de Cholesky des matrices relles


symtriques dfinies positives
Une matrice symtrique A est dite dfinie positive si pour tout vecteur x
non nul, t x Ax > 0. Pour toute matrice symtrique dfinie positive, il existe
une matrice triangulaire infrieure C telle que A = C t C. Cette factorisation est
appele dcomposition de Cholesky. Dans Sage, elle se calcule en appelant la
mthode cholesky(). Dans lexemple suivant on construit une matrice A presque
srement dfinie positive :
sage: m = random_matrix(RDF, 10)
sage: A = transpose(m)*m
sage: C = A.cholesky()
Il faut noter quon ne peut pas tester en un cot raisonnable si une matrice
symtrique est dfinie positive ; si on applique la mthode de Cholesky avec une
matrice qui ne lest pas, la dcomposition ne pourra pas tre calcule et une
exception ValueError sera lance par cholesky() au cours du calcul.
Pour rsoudre un systme Ax = b laide de la dcomposition de Cholesky,
on procde comme avec la dcomposition LU . Une fois la dcomposition calcule,
on excute A.solve_right(b). L aussi, la dcomposition nest pas recalcule.
Pourquoi utiliser la dcomposition de Cholesky plutt que la dcomposition
LU pour rsoudre des systmes matrice symtrique dfinie positive ? Bien sr, la
taille mmoire ncessaire pour stocker les facteurs est deux fois plus petite, mais
cest surtout du point de vue du nombre doprations que la mthode de Cholesky
savre avantageuse : en effet, pour une matrice de taille n, la factorisation de
Cholesky cote n extractions de racines carres, n(n 1)/2 divisions, (n3 n)/6
additions et autant de multiplications. En comparaison la factorisation LU cote
aussi n(n 1)/2 divisions, mais (n3 n)/3 additions et multiplications.

13.2.5 La dcomposition QR
Soit A Rnm , avec n > m. Il sagit ici de trouver deux matrices Q et R
telles que A = QR o Q Rnn est orthogonale (t Q Q = I) et R Rnm est
triangulaire suprieure. Bien sr, une fois la dcomposition calcule, on peut sen
servir pour rsoudre des systmes linaires si la matrice A est carre et inversible,
284 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

mais cest surtout, comme on le verra, une dcomposition intressante pour la


rsolution de systmes aux moindres carrs et pour le calcul de valeurs propres.
Bien noter que A nest pas forcment carre. La dcomposition existe si A est de
rang maximum, soit m. Exemple :
sage: A = random_matrix(RDF,6,5)
sage: Q, R = A.QR()

Exercice 45 (Perturbation dun systme linaire). Soit A une matrice carre


inversible dont on a calcul une dcomposition (LU , QR, Cholesky, etc). Soient deux
vecteurs u et v. On considre la matrice B = A + u t v, et on suppose que 1 + t v A1 u =
6 0.
Comment rsoudre conomiquement le systme Bx = f (cest--dire sans factoriser B) ?
On utilisera la formule de Sherman et Morrison (quon pourra prouver ou admettre) :

A1 u t v A1
(A + u t v)1 = A1 .
1 + t v A1 u

13.2.6 La dcomposition en valeurs singulires


Il sagit dune dcomposition peu enseigne, et pourtant riche en applications !
Soit A une matrice n m coefficients rels. Alors il existe deux matrices
orthogonales U Rnn et V Rmm , telles que
t
U A V = = diag(1 , 2 , . . . , p ),

o 1 > 2 > . . . > p > 0 (avec p = min(m, n)). Les nombres 1 , . . . , p sont les
valeur singulires de A.
Les matrices U et V sont orthogonales (U t U = I et V t V = I) et par
consquent :
A = U tV .

Exemple (les calculs ne sont videmment jamais exacts) :


sage: A = matrix(RDF, [[1,3,2],[1,2,3],[0,5,2],[1,1,1]])
sage: U, Sig, V = A.SVD()
sage: A1 = A - U*Sig*transpose(V); A1
[ 4.4408920985e-16 4.4408920985e-16 -8.881784197e-16]
[ 6.66133814775e-16 -8.881784197e-16 -4.4408920985e-16]
[-1.29063426613e-15 1.7763568394e-15 2.22044604925e-16]
[ 6.66133814775e-16 -6.66133814775e-16 -1.11022302463e-15]

On peut montrer que les valeurs singulires dune matrice A sont les racines
carres des valeurs propres de t A A. Il est facile de vrifier que, pour une matrice
carre de taille n, la norme euclidienne kAk2 est gale 1 et que, si la matrice
est de plus non singulire, le conditionnement de A en norme euclidienne est gal
1 /n . Le rang de A est lentier r dfini par :

1 > 2 > > r > r+1 = = p = 0.


13.2. MATRICES PLEINES 285

13.2.7 Application aux moindres carrs


On voudrait rsoudre le systme surdtermin Ax = b o A est une matrice
coefficients rels, rectangulaire, n lignes et m colonnes avec n > m. videmment
ce systme na pas, en gnral, de solution. On considre alors le problme de
minimisation du carr de la norme euclidienne kk2 du rsidu :

min kAx bk22 .


x

La matrice A peut mme tre de rang infrieur m.

En rsolvant les quations normales. En annulant la diffrentielle par


rapport x du problme de minimisation, on vrifiera sans trop de peine que la
solution vrifie :
t
A Ax = t A b.
Supposant A de rang maximum m, on peut donc penser former la matrice t A A et
rsoudre le systme t A Ax = t A b, par exemple en calculant la dcomposition de
Cholesky de t A A. Cest mme l lorigine du procd du commandant Cholesky 1 .
Quel est le conditionnement de t A A ? Cest ce qui va conditionner la prcision
des calculs. Les valeurs singulires de t A A, qui est de dimension m m, sont les
carrs des valeurs singulires de A ; le conditionnement en norme euclidienne est
donc 12 /m
2
, qui est facilement grand. On prfre donc des mthodes bases soit
sur la dcomposition QR de A, soit sur sa dcomposition en valeurs singulires 2 .
Malgr tout, cette mthode est utilisable pour de petits systmes, pas trop
mal conditionns. Voici le code correspondant :
sage: A = matrix(RDF, [[1,3,2],[1,4,2],[0,5,2],[1,3,2]])
sage: b = vector(RDF, [1,2,3,4])
sage: Z = transpose(A)*A
sage: C = Z.cholesky()
sage: R = transpose(A)*b
sage: Z.solve_right(R)
(-1.5, -0.5, 2.75)

Bien noter ici que la dcomposition de Cholesky est cache et que la rsolution
Z.solve_right(R) utilise cette dcomposition, sans la recalculer.

Avec la dcomposition QR. Supposons A de rang maximum 3 , et soit A = QR.


Alors
kAx bk22 = kQRx bk22 = kRx t Q bk22 .

1. Polytechnicien et officier dartillerie (1875-1918) ; la mthode a t invente pour rsoudre


des problmes de godsie.
2. Mais le commandant Cholesky navait pas dordinateur, et nenvisageait probablement que
la rsolution de petits systmes, pour lesquels le mauvais conditionnement nest pas vraiment
un problme.
3. On peut sen affranchir en utilisant une mthode QR avec pivots.
286 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

 
R1
On a : R = o R1 est un bloc triangulaire suprieur de taille m et
0
 
c
t
Qb = avec c de taille m. Donc kAx bk22 = kR1 x ck22 + kdk22 , et le
d
minimum est obtenu pour x solution du systme triangulaire R1 x = c :
sage: A = matrix(RDF, [[1,3,2],[1,4,2],[0,5,2],[1,3,2]])
sage: b = vector(RDF, [1,2,3,4])
sage: Q, R = A.QR()
sage: R1 = R[0:3,0:3]
sage: b1 = transpose(Q)*b
sage: c = b1[0:3]
sage: R1.solve_right(c)
(-1.5, -0.5, 2.75)

Calculons le conditionnement de t A A en norme infinie :


sage: Z = A.transpose()*A
sage: Z.norm(Infinity)*(Z^-1).norm(Infinity)
1992.375
Le systme tant de petite taille, il nest pas trop mal conditionn : la mthode
QR et la mthode des quations normales (page 285) donnent donc le mme
rsultat.

Avec la dcomposition en valeurs singulires. La dcomposition en valeurs


singulires A = U t V permet aussi de calculer la solution ; mieux, elle est
utilisable mme si A nest pas de rang maximum. Si A nest pas identiquement
nulle, possde r 6 m coefficients strictement positifs i (rangs par ordre
dcroissant). On note ui les colonnes de U . On a alors :

kAx bk22 = kt U AV t V x t U bk22 .

En posant = t V x, on a :
p
X m
X
kAx bk22 = (i i t ui b)2 + (t ui b)2 .
i=1 i=p+1

Le minimum est donc atteint en prenant i = (t ui b)/i pour 1 6 i 6 p. On


choisit alors i = 0 pour i > p, et on obtient finalement la solution x = V .
Voici le programme Sage (on na pas besoin de transposer U.column(i)) :
sage: A = matrix(RDF, [[1,3,2],[1,3,2],[0,5,2],[1,3,2]])
sage: b = vector(RDF, [1,2,3,4])
sage: U, Sig, V = A.SVD()
sage: m = A.ncols()
sage: x = vector(RDF, [0]*m)
sage: lamb = vector(RDF, [0]*m)
13.2. MATRICES PLEINES 287

sage: for i in range(0,m):


....: s = Sig[i,i]
....: if s < 1e-12:
....: break
....: lamb[i] = U.column(i)*b / s
sage: x = V*lamb; x
(0.237037037037, 0.451851851852, 0.37037037037)
Notons que ci-dessus, la matrice A est de rang 2 (ce quon peut vrifier laide
de la commande A.rank()) et quelle nest donc pas de rang maximum (3) ; il y
a donc plusieurs solutions au problme de moindres carrs et la dmonstration
donne ci-dessus montre que x est la solution de norme euclidienne minimale.
Regardons les valeurs singulires :
sage: m = 3
sage: [ Sig[i,i] for i in range(0,m) ]
[8.30931683326, 1.39830388849, 2.40449761305e-16]
La matrice A tant de rang 2, la troisime valeur singulire est forcment 0.
On a donc ici une erreur darrondi, due lapproximation flottante. Pour viter
une division par 0, il convient de ne pas en tenir compte dans le calcul de valeurs
singulires approches trop proches de 0 (cest la raison du test if s < 1e-12
dans le programme).
Exemple. Parmi les merveilleuses applications de la dcomposition en valeurs
singulires (SVD pour Singular Value Decomposition en anglais), voici un problme
quon aura bien du mal rsoudre avec une autre mthode : soient A et B Rnm
les rsultats dune exprience rpte deux fois. On se demande si B peut tre
tourne sur A, cest--dire sil existe une matrice orthogonale Q telle que A = BQ.
videmment, un bruit sest ajout aux mesures et le problme na pas, en gnral,
de solution. Il convient donc de le poser aux moindres carrs ; pour cela, il faut
donc calculer la matrice orthogonale Q qui minimise le carr de la norme de
Frobenius :
kA BQk2F .
On se souvient que kAk2F = trace(t A A). Alors

kA BQk2F = trace(t A A) + trace(t B B) 2 trace(t Q t B A) > 0,

et il faut donc maximiser trace(t Q t B A). On calcule alors la SVD de t B A : on a


t
U (t B A)V = . Soient i les valeurs singulires, et O = t V t Q U. Cette matrice
est orthogonale et donc tous ses coefficients sont infrieurs ou gaux 1. Alors :

m m
Oii i 6
X X
trace(t Q t B A) = trace(t Q U t V ) = trace(O) = i .
i=1 i=1

et le maximum est atteint pour Q = U t V .


sage: A = matrix(RDF, [[1,2],[3,4],[5,6],[7,8]])
288 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

B est obtenue en ajoutant un bruit alatoire A et en lui appliquant une rotation


R dangle thta :

sage: th = 0.7
sage: R = matrix(RDF, [[cos(th),sin(th)],[-sin(th),cos(th)]])
sage: B = (A + 0.1*random_matrix(RDF,4,2)) * transpose(R)

sage: C = transpose(B)*A
sage: U, Sigma, V = C.SVD()
sage: Q = U*transpose(V)

La perturbation alatoire est faible, et Q est proche de R comme attendu :

sage: Q
[ 0.76737943398 0.641193265954]
[-0.641193265954 0.76737943398]
sage: R
[ 0.764842187284 0.644217687238]
[-0.644217687238 0.764842187284]

Exercice 46 (Racine carre dune matrice symtrique semi-dfinie positive). Soit A


une matrice symtrique semi-dfinie positive (cest--dire qui vrifie t x Ax > 0 pour tout
vecteur x). Montrer quon peut calculer une matrice X, elle aussi symtrique semi-dfinie
positive, telle que X 2 = A.

13.2.8 Valeurs propres, vecteurs propres


Jusqu prsent, nous navons utilis que des mthodes directes (dcomposition
LU , QR, de Cholesky), qui fournissent une solution en un nombre fini doprations
(les quatre oprations lmentaires, plus la racine carre pour la dcomposition de
Cholesky). Ce ne peut pas tre le cas pour le calcul des valeurs propres : en effet (cf.
page 292), on peut associer tout polynme une matrice dont les valeurs propres
sont les racines du polynme ; mais on sait quil nexiste pas de formule explicite
pour le calcul des racines dun polynme de degr suprieur ou gal 5, formule
que donnerait prcisment une mthode directe. Dautre part, former le polynme
caractristique pour en calculer les racines serait extrmement coteux (cf. page
281) ; notons toutefois que lalgorithme de Faddeev-Le Verrier permet de calculer
le polynme caractristique dune matrice de taille n en O(n4 ) oprations, ce qui
est malgr tout considr comme bien trop coteux. Les mthodes numriques
utilises pour le calcul de valeurs et de vecteurs propres sont toutes itratives.
On va donc construire des suites convergeant vers les valeurs propres (et
les vecteurs propres) et arrter les itrations quand on sera assez proche de la
solution 4 .

4. Dans les exemples donns ci-aprs, le problme du choix des tests darrt des itrations
est volontairement pass sous silence, pour des raisons de simplicit.
13.2. MATRICES PLEINES 289

La mthode de la puissance itre. Soit A une matrice appartenant Cnn .


On choisit une norme quelconque k.k sur Cn . En partant de x0 , on considre la
suite des xk dfinie par :
Axk
xk+1 = .
kAxk k
Si les valeurs propres vrifient |1 | > |2 | > . . . > |n |, alors la suite des
vecteurs xk converge vers un vecteur propre associ la valeur propre dominante
|1 |. De plus la suite k = t xk+1 xk converge vers |1 |. Cette hypothse de
sparation des valeurs propres peut tre relche.
sage: n =10
sage: A =random_matrix(RDF, n); A = A*transpose(A)
sage: # Avrifie (presque srement) les hypothses
sage: x =vector(RDF, [1 for i in range(0,n)])
sage: fori in range(0,1000):
....: y = A*x
....: z = y/y.norm()
....: lam = z*y
....: s = (x-z).norm()
....: print i, "\ts=", s, "\tlambda=", lam
....: if s < 1e-10: break
....: x = z
0 s= 16.1640760201 lambda= 75.9549361783
1 s= 0.411503846291 lambda= 8.21816164112
2 s= 0.283595513527 lambda= 10.7020239604
3 s= 0.143945984315 lambda= 11.7626944491
4 s= 0.0671326308606 lambda= 12.0292765606
5 s= 0.0313379335883 lambda= 12.0876762358
6 s= 0.0149590182273 lambda= 12.1006031137
7 s= 0.00733280989323 lambda= 12.1036013532
8 s= 0.00368707185825 lambda= 12.1043343433
9 s= 0.00189514202573 lambda= 12.104522518
10 s= 0.000991461650756 lambda= 12.1045728607
...
Maintenant, utilisons :
sage: A.eigenvalues()
[12.1045923186, 6.62564474772, 5.45163183814, 4.81356332812,
2.46643846586, 1.37770690836, 0.966017076179, 0.653324011458,
0.0859636271843, 0.0541281947143]
On a bien calcul la valeur propre dominante.
Lintrt de cette mthode peut sembler limit, mais il apparatra pleinement
lors de ltude des matrices creuses. Elle inspire aussi ce qui suit, qui est trs utile.

La mthode de la puissance inverse avec translation. On suppose connue


une approximation dune valeur propre j ( et j C). Comment calculer un
vecteur propre associ j ?
290 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

On fait lhypothse que k 6= j, 0 < | j | < | k |, et donc, j est une


valeur propre simple. On considre alors (A I)1 , dont la plus grande valeur
propre est (j )1 , et on applique la mthode de la puissance itre cette
matrice.
Prenons par exemple :
sage: A = matrix(RDF, [[1,3,2],[1,2,3],[0,5,2]])
En appelant la mthode A.eigenvalues(), on trouve les valeurs propres
6.39294791649, 0.560519476112, -1.9534673926. On va chercher le vecteur
propre associ la deuxime valeur propre, en partant dune valeur approche :
sage: mu = 0.50519
sage: AT = A - mu*identity_matrix(RDF, 3)
sage: x = vector(RDF, [1 for i in range(0,A.nrows())])
sage: P, L, U = AT.LU()
sage: for i in range(1,10):
....: y = AT.solve_right(x)
....: x = y/y.norm()
....: lamb = x*A*x
....: print x, lamb
(0.960798555257, 0.18570664547, -0.205862036435) 1.08914936279
(0.927972943625, 0.10448610518, -0.357699412529) 0.563839629189
(0.927691613383, 0.103298273577, -0.358772542336) 0.560558807639
(0.927684531828, 0.10329496332, -0.35879180587) 0.560519659839
(0.927684564843, 0.103294755297, -0.358791780397) 0.560519482021
(0.927684562912, 0.103294757323, -0.358791784805) 0.560519476073
(0.927684562945, 0.103294757253, -0.358791784742) 0.560519476114
(0.927684562944, 0.103294757254, -0.358791784744) 0.560519476112
(0.927684562944, 0.103294757254, -0.358791784744) 0.560519476112
On peut faire plusieurs remarques :
on ne calcule pas linverse de la matrice AI, mais on utilise sa factorisation
LU , qui est calcule une fois pour toutes (par solve_right) ;
on profite des itrations pour amliorer lestimation de la valeur propre ;
la convergence est trs rapide ; on peut effectivement montrer que (moyen-
nant les hypothses ci-dessus, plus le choix dun vecteur de dpart non
orthogonal au vecteur propre qj associ j ), on a, pour les itrs x(i) et
(i) :
j i
 
kx qj k = O
(i)
K
et
j 2i
 
k j k = O
(i) ,
K
o K est la seconde valeur propre par ordre de proximit ;
le conditionnement de (A I) (reli au rapport entre la plus grande et la
plus petite valeur propre de (AI)) est mauvais ; mais on peut montrer (cf.
[Sch91], qui cite Parlett) que les erreurs sont malgr tout sans importance !
13.2. MATRICES PLEINES 291

La mthode QR. Soit A une matrice carre non singulire. On considre la


suite A0 = A, A1 , A2 , . . ., Ak , Ak+1 , . . . Dans la forme la plus brute de la mthode
QR, le passage de Ak Ak+1 seffectue ainsi :
1. on calcule la dcomposition QR de Ak : Ak = Qk Rk ,
2. on calcule Ak+1 = Rk Qk .
Programmons cette mthode avec pour A une matrice symtrique relle :
sage: m = matrix(RDF, [[1,2,3,4],[1,0,2,6],[1,8,4,-2],[1,5,-10,-20]])
sage: Aref = transpose(m)*m
sage: A = copy(Aref)
sage: for i in range(0,20):
....: Q, R = A.QR()
....: A = R*Q
....: print A.str(lambda x: RealField(30)(x).str())
[ 347.58031 -222.89331 -108.24117 -0.067928252]
[ -222.89331 243.51949 140.96827 0.081743964]
[ -108.24117 140.96827 90.867499 -0.0017822044]
[ -0.067928252 0.081743964 -0.0017822044 0.032699348]
...
[ 585.03056 -4.2118495e-13 3.2967689e-14 -6.6742634e-14]
[-3.0404094e-13 92.914265 6.1583133e-14 4.0818546e-16]
[-1.5340786e-39 7.0477800e-25 4.0229095 2.0797973e-14]
[ 1.1581440e-82 -4.1761905e-68 6.1677425e-42 0.032266909]
On constate que la convergence est rapide, vers une matrice quasi-diagonale.
Les coefficients diagonaux sont les valeurs propres de A. Vrifions :
sage: Aref.eigenvalues()
[585.03055862, 92.9142649915, 0.0322669089941, 4.02290947948]
On peut prouver la convergence si la matrice est hermitienne dfinie positive.
Si on calcule avec une matrice non symtrique, il convient de travailler dans C, les
valeurs propres tant a priori complexes, et, si la mthode converge, les parties
triangulaires infrieures des Ak tendent vers zro, tandis que la diagonale tend
vers les valeurs propres de A.
La mthode QR ncessite beaucoup damliorations pour tre efficace, ne
serait-ce que parce que les dcompositions QR successives sont coteuses ; parmi
les raffinements utiliss, on commence en gnral par rduire la matrice A
une forme plus simple (forme de Hessenberg : triangulaire suprieure plus une
sous-diagonale), ce qui rend les dcompositions QR bien moins coteuses ; ensuite,
pour acclrer la convergence il faut pratiquer des translations A := A + I,
astucieusement choisies (voir par exemple [GVL96]). Notons que cest la mthode
utilise par Sage quand on travaille avec des matrices pleines CDF ou RDF.

En pratique. Les programmes donns ci-dessus sont l titre dexemples


pdagogiques ; on utilisera donc les mthodes fournies par Sage qui, dans la
mesure du possible, fait appel aux routines optimises de la bibliothque Lapack.
292 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

Les interfaces permettent dobtenir soit uniquement les valeurs propres, soit les
valeurs et les vecteurs propres :
sage: A = matrix(RDF, [[1,3,2],[1,2,3],[0,5,2]])
sage: A.eigenmatrix_right()
(
[ 6.39294791649 0 0]
[ 0 0.560519476112 0]
[ 0 0 -1.9534673926],

[ 0.542484060111 0.927684562944 0.0983425466742]


[ 0.554469286109 0.103294757254 -0.617227053099]
[ 0.631090211687 -0.358791784744 0.780614827195]
)
Cet exemple calcule la matrice diagonale des valeurs propres et la matrice des
vecteurs propres (les colonnes sont les vecteurs propres).
Exemple (Calcul des racines dun polynme). tant donn un polynme (
coefficients rels ou complexes) p(x) = xn + an1 xn1 + . . . + a1 x + a0 , il est
facile de vrifier que les valeurs propres de la matrice compagnon M , dfinie par
Mi+1,i = 1 et Mi,n1 = ai , sont les racines de p (voir 8.2.3), ce qui fournit
donc une mthode pour obtenir les racines de p :
sage: def pol2companion(p):
....: n = len(p)
....: m = matrix(RDF,n)
....: for i in range(1,n):
....: m[i,i-1]=1
....: for i in range(0,n):
....: m[i,n-1]=-p[i]
....: return m
sage: q = [1,-1,2,3,5,-1,10,11]
sage: comp = pol2companion(q); comp
[ 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -1.0]
[ 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0]
[ 0.0 1.0 0.0 0.0 0.0 0.0 0.0 -2.0]
[ 0.0 0.0 1.0 0.0 0.0 0.0 0.0 -3.0]
[ 0.0 0.0 0.0 1.0 0.0 0.0 0.0 -5.0]
[ 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0]
[ 0.0 0.0 0.0 0.0 0.0 1.0 0.0 -10.0]
[ 0.0 0.0 0.0 0.0 0.0 0.0 1.0 -11.0]
sage: racines = comp.eigenvalues(); racines
[0.347521510119 + 0.566550553398*I, 0.347521510119 - 0.566550553398*I,
0.345023776962 + 0.439908702386*I, 0.345023776962 - 0.439908702386*I,
-0.517257614325 + 0.512958206789*I, -0.517257614325 -
0.512958206789*I, -1.36699716455, -9.98357818097]
Dans cet exemple le polynme est reprsent par la liste q de ses coefficients,
de 0 n 1. Le polynme x2 3x + 2 serait ainsi reprsent par q=[2,-3].
13.2. MATRICES PLEINES 293

13.2.9 Ajustement polynomial : le retour du diable


Version continue. On voudrait approcher la fonction f (x) par un polynme
P (x) de degr 6 n, sur lintervalle [, ]. On pose le problme aux moindres
carrs. Z n
X
min J(a0 , . . . , an ) = (f (x) ai xi )2 dx.
a0 ,...,an R i=0

En drivant J(a0 , . . . , an ) par rapport aux coefficients ai , on trouve que


R
a0 , . . . , an sont solutions dun systme linaire M a = F o Mi,j = xi xj dx et
R
Fj = xj f (x) dx. On voit immdiatement en regardant le cas = 0 et = 1
que Mi,j est la matrice de Hilbert ! Mais il y a un remde : il suffit dutiliser une
base de polynmes orthogonaux (par exemple, si = 1 et = 1 la base des
polynmes de Legendre) : alors la matrice M devient lidentit.

Version discrte. On considre m observations y1 ,P . . . , ym dun phnomne


n
aux points xi , . . . , xm . On veut ajuster un polynme i=0 ai xi de degr n au
plus gal m 1 parmi ces points. On minimise donc la fonctionnelle :
m X
X n
J(a0 , . . . , an ) = ( ai xij yj )2 .
j=1 i=0

Ainsi crit, le problme va donner une matrice trs proche de la matrice de Hilbert
et
Pmle systme sera difficile rsoudre. Mais on remarque alors que hP, Qi =
j=1 P (xj )Q(xj ) dfinit un produit scalaire sur les polynmes de degr n 6 m1.
On peut donc dabord fabriquer n polynmes chelonns en degr, orthonorms
pour ce produit scalaire, et donc diagonaliser le systme linaire. En se souvenant 5
que le procd de Gram-Schmidt se simplifie en une rcurrence trois termes
pour le calcul de polynmes orthogonaux, on cherche le polynme Pn+1 (x) sous
la forme Pn+1 (x) = xPn (x) n Pn1 (x) n Pn2 (x) : cest ce que fait la
procdure orthopoly ci-dessous (on reprsente ici les polynmes par la liste de
leurs coefficients : par exemple [1,-2,3] reprsente le polynme 1 2x + 3x2 ).
Lvaluation dun polynme par le schma de Horner se programme ainsi :
sage: def eval(P,x):
....: if len(P) == 0:
....: return 0
....: else:
....: return P[0]+x*eval(P[1:],x)
On peut ensuite programmer le produit scalaire de deux polynmes :
sage: def pscal(P,Q,lx):
....: return float(sum(eval(P,s)*eval(Q,s) for s in lx))
et lopration P P + aQ pour deux polynmes P et Q :

5. Le prouver nest pas trs difficile !


294 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

sage: def padd(P,a,Q):


....: for i in range(0,len(Q)):
....: P[i] += a*Q[i]
Un programme un peu srieux doit lancer une exception quand il est mal utilis ;
dans notre cas, on lance lexception dfinie ci-dessous quand n > m :
sage: class BadParamsforOrthop(Exception):
....: def __init__(self, degreplusun, npoints):
....: self.deg = degreplusun
....: self.np = npoints
....: def __str__(self):
....: return "degre: " + str(self.deg) + \
....: " nb. points: " + repr(self.np)
La procdure suivante calcule les n polynmes orthogonaux :
sage: def orthopoly(n,x):
....: if n > len(x):
....: raise BadParamsforOrthop(n-1, len(x))
....: orth = [[1./sqrt(float(len(x)))]]
....: for p in range(1,n):
....: nextp = copy(orth[p-1])
....: nextp.insert(0,0)
....: s = []
....: for i in range(p-1,max(p-3,-1),-1):
....: s.append(pscal(nextp, orth[i], x))
....: j = 0
....: for i in range(p-1,max(p-3,-1),-1):
....: padd(nextp, -s[j], orth[i])
....: j += 1
....: norm = sqrt(pscal(nextp, nextp, x))
....: nextpn = [nextp[i]/norm for i in range(len(nextp))]
....: orth.append(nextpn)
....: return orth
Une fois les polynmes
Pn orthogonaux P0 (x), . . . , Pn (x) calculs, la solution est
donne par P (x) = i=0 i Pi (x), avec :
m
X
i = Pi (xj )yj ,
j=1

ce quon peut videmment rapatrier sur la base des monmes 1, x, . . . , xn .


Exemple (n = 15) :
sage: L = 40
sage: X = [100*float(i)/L for i in range(40)]
sage: Y = [float(1/(1+25*X[i]^2)+0.25*random()) for i in range(40)]
sage: n = 15; orth = orthopoly(n, X)
13.2. MATRICES PLEINES 295

0.8

0.6

0.4

0.2

20 40 60 80

Figure 13.1 Ajustement polynomial.

Calculons les coefficients de la solution sur la base des polynmes orthogonaux :


sage: coeff = [sum(Y[j]*eval(orth[i],X[j]) for j in
....: range(0,len(X))) for i in range(0,n)]
On peut ensuite transformer ce rsultat dans la base des monmes 1, x, . . . , xn
afin, par exemple, de pouvoir en dessiner le graphe :
sage: polmin = [0 for i in range(0,n)]
sage: for i in range(0,n):
....: padd(polmin, coeff[i], orth[i])
sage: p = lambda x: eval(polmin, x)
sage: plot(p(x), x, 0, X[len(X)-1])
On ne dtaille pas ici le calcul de lajustement naf sur la base des monmes
xi , ni sa reprsentation graphique. On obtient la figure 13.1. Les deux courbes,
lune correspondant lajustement base de polynmes orthogonaux, lautre
la mthode nave, sont trs proches, mais, en calculant leur rsidu (la valeur
de la fonctionnelle J) on trouve 0.1202 pour lajustement par les polynmes
orthogonaux, et 0.1363 pour lajustement naf.

13.2.10 Implantation et performances


Les calculs avec des matrices coefficients dans RDF sont effectus avec larith-
mtique flottante du processeur, ceux avec les matrices RR avec la bibliothque
GNU MPFR. De plus dans le premier cas, Sage se sert de NumPy/SciPy, qui passe
la main la bibliothque Lapack (code en Fortran) et cette dernire bibliothque
296 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

utilise les BLAS 6 dATLAS optimises pour chaque machine. Ainsi, on obtient,
pour le calcul du produit de deux matrices de taille 1000 :
sage: a = random_matrix(RR, 1000)
sage: b = random_matrix(RR, 1000)
sage: %time a*b
CPU times: user 421.44 s, sys: 0.34 s, total: 421.78 s
Wall time: 421.79 s

sage: c = random_matrix(RDF, 1000)


sage: d = random_matrix(RDF, 1000)
sage: %time c*d
CPU times: user 0.18 s, sys: 0.01 s, total: 0.19 s
Wall time: 0.19 s
soit un rapport de plus de 2000 entre les deux temps de calcul !
On peut aussi remarquer la rapidit des calculs avec des matrices coefficients
RDF : on vrifie immdiatement que le produit de deux matrices carres de taille n
cote n3 multiplications (et autant dadditions) ; ici, on effectue donc 109 additions
et multiplications en 0.18 seconde ; ce sont donc environ 1010 oprations quon
effectue par seconde soit encore une vitesse de 10 gigaflops. Lunit centrale de
la machine de test battant 3.1 Ghz, on effectue donc plus dune opration
par tour dhorloge : ceci est rendu possible par lappel presque direct de la
routine correspondante de la bibliothque ATLAS 7 . Notons quil existe aussi un
algorithme de cot infrieur n3 pour effectuer le produit de deux matrices : la
mthode de Strassen. Elle nest pas implante en pratique (pour des calculs en
flottant) pour des raisons de stabilit numrique. Le lecteur pourra vrifier, avec
les programmes ci-dessus, que le temps de calcul avec Sage est bien proportionnel
n3 .

13.3 Matrices creuses


Les matrices creuses sont trs frquentes en calcul scientifique : le caractre
creux (sparsity en anglais) est une proprit recherche qui permet de rsoudre
des problmes de grande taille, inaccessibles avec des matrices pleines.
Une dfinition approximative : on dira quun ensemble de matrices {Mn }n
(de taille n) est une famille de matrices creuses si le nombre de coefficients non
nuls de Mn est de lordre de O(n).
Bien videmment, ces matrices sont reprsentes en machine en utilisant des
structures de donnes o ne sont stocks que les termes non nuls. En tenant
compte du caractre creux des matrices, on veut, bien sr, gagner de la place
mmoire et donc pouvoir manipuler de grandes matrices, mais aussi rduire
fortement le cot des calculs.
6. Basic Linear Algebra Subroutines (produits matrice-vecteur, matrice-matrice, etc.).
7. Cette bibliothque procde par blocs de taille automatiquement adapte (dtermine par
essais successifs) lors de la compilation : elle est en partie responsable du temps considrable
qui est ncessaire la compilation de Sage partir du code source.
13.3. MATRICES CREUSES 297

13.3.1 Origine des systmes creux


Problmes aux limites. Lorigine la plus frquente est la discrtisation dqua-
tions aux drives partielles. Considrons par exemple lquation de Poisson
(quation de la chaleur stationnaire) :
u = f
o u = u(x, y), f = f (x, y),
2u 2u
u := + 2.
x2 y
Lquation est pose dans le carr [0, 1]2 , et munie de conditions aux limites u = 0
sur le bord du carr. Lanalogue en dimension un est le problme
2u
= f, (13.1)
x2
avec u(0) = u(1) = 0.
Une des mthodes les plus simples pour approcher la solution de cette quation
consiste utiliser la mthode des diffrences finies : on dcoupe lintervalle [0, 1] en
un nombre fini N dintervalles de pas h constant. On note ui la valeur approche
de u au point xi = ih. On approche la drive de u par (ui+1 ui )/h et sa drive
seconde par
(ui+1 ui )/h (ui ui1 )/h ui+1 2ui + ui1
= .
h h2
On voit immdiatement que les u0 , . . . , uN , qui approchent u aux points ih,
satisfont un systme linaire nayant que 3 termes non nuls par ligne (et dont on
peut vrifier que la matrice est symtrique dfinie positive).
En dimension 2, on peut plaquer une grille de pas h sur le carr unit et on
obtient un systme pentadiagonal (avec 4/h2 sur la diagonale, deux sur-diagonales
et deux sous-diagonales dont les coefficients sont 1/h2 ). En dimension 3, en
procdant de la mme manire dans un cube, on obtient un systme o chaque
ligne possde 7 coefficients non nuls. On a donc bien des matrices trs creuses.

Marche alatoire sur un grand graphe creux. On considre un graphe dans


lequel chaque sommet est reli un petit nombre de sommets (petit par rapport
au nombre total de sommets). Par exemple, on pourra se figurer un graphe dont
les sommets sont les pages de linternet : chaque page ne cite quun petit nombre
dautres pages (ce qui dfinit les artes du graphe), mais cest assurment un trs
grand graphe. Une marche alatoire sur le graphe est dcrite par une matrice
stochastique, cest--dire une matrice dont chaque coefficient est un rel compris
entre 0 et 1 et dont la somme des coefficients de chaque ligne vaut 1. On montre
quune telle matrice A a une valeur propre dominante gale un. La distribution
stationnaire de la marche alatoire est le vecteur propre x gauche associ
la valeur propre dominante, cest--dire le vecteur qui vrifie xA = x. Une des
applications les plus spectaculaires est lalgorithme Pagerank de Google, dans
lequel le vecteur x sert pondrer les rsultats des recherches.
298 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

13.3.2 Sage et les matrices creuses


Sage permet de travailler avec des matrices creuses, en spcifiant sparse
= True lors de la cration de la matrice. Il sagit dun stockage sous forme de
dictionnaire. Dun autre ct, les calculs avec de grandes matrices creuses,
coefficients flottants (RDF ou CDF) sont effectus par Sage avec la bibliothque
SciPy, qui offre ses propres classes de matrices creuses. Dans ltat actuel des
choses, il nexiste pas dinterface entre les matrices sparse de Sage et les matrices
creuses de SciPy. Il convient donc dutiliser directement les objets de SciPy.
Les classes fournies par SciPy pour reprsenter des matrices creuses sont :
une structure sous forme de liste de listes (mais pas identique celle utilise
par Sage) pratique pour crer et modifier des matrices, les lil_matrix ;
des structures immuables, ne stockant que les coefficients non nuls, et qui
sont un standard de fait en algbre linaire creuse (formats csr et csv).

13.3.3 Rsolution de systmes linaires


Pour des systmes de taille modre tels que ceux dtaills ci-dessus (en
dimension 1 et 2), on peut utiliser une mthode directe, base sur la dcomposition
LU . On peut se convaincre sans grande difficult que, dans la dcomposition LU
dune matrice A creuse, les facteurs L et U contiennent en gnral plus de termes
non nuls eux deux que A. Il faut utiliser des algorithmes de renumrotation des
inconnues pour limiter la taille mmoire ncessaire, comme dans la bibliothque
SuperLU utilise par Sage de manire transparente :
sage: from scipy.sparse.linalg.dsolve import *
sage: from scipy.sparse import lil_matrix
sage: from numpy import array
sage: n = 200
sage: n2 = n*n
sage: A = lil_matrix((n2, n2))
sage: h2 = 1./float((n+1)^2)
sage: for i in range(0,n2):
....: A[i,i]=4*h2+1.
....: if i+1<n2: A[i,int(i+1)]=-h2
....: if i>0: A[i,int(i-1)]=-h2
....: if i+n<n2: A[i,int(i+n)]=-h2
....: if i-n>=0: A[i,int(i-n)]=-h2
sage: Acsc = A.tocsc()
sage: b = array([1 for i in range(0,n2)])
sage: solve = factorized(Acsc) # factorisation LU
sage: S = solve(b) # rsolution
Aprs avoir cr la matrice sous forme de lil_matrix (attention ce format
ncessite des indices de type int de Python) il faut la convertir au format csc.
Ce programme nest pas particulirement performant : la construction de la
lil_matrix est lente, les structures lil_matrix ntant pas trs efficaces. En
13.3. MATRICES CREUSES 299

Commandes les plus utiles


Rsoudre un systme linaire x = A\b
Dcomposition LU P, L, U = A.LU()
Dcomposition de Cholesky C = A.cholesky()
Dcomposition QR Q, R = A.QR()
Dcomposition en valeurs singulires U, Sig, V = A.SVD()
Valeurs et vecteurs propres Val, Vect = A.eigenmatrix_right()

Tableau 13.1 Rcapitulatif.

revanche, la conversion en une matrice csc et la factorisation sont rapides, et la


rsolution qui suit lest plus encore.

Mthodes itratives. Le principe de ces mthodes est de construire une suite


qui converge vers la solution du systme Ax = b. Les mthodes itratives modernes
utilisent lespace de Krylov Kn , espace vectoriel engendr par b, Ab, . . . , An b.
Parmi les mthodes les plus populaires, citons :

la mthode du gradient conjugu : elle ne peut tre utilise que pour des
systmesdont la matrice A est symtrique dfinie positive. Dans ce cas
kxkA = t x Ax est une norme, et litr xn est calcul de sorte minimiser
lerreur kx xn kA entre la solution x et xn pour xn Kn (il existe des
formules explicites, faciles programmer, cf. par exemple [LT94],[GVL96]) ;
la mthode du rsidu minimal gnralis (GMRES ou generalized minimal
residual) : elle a lavantage de pouvoir tre utilise pour des systmes
linaires non symtriques. litration n cest la norme euclidienne du
rsidu kAxn bk2 qui est minimise pour xn Kn . On notera quil sagit
l dun problme aux moindres carrs.

En pratique, ces mthodes ne sont efficaces que prconditionnes : au lieu de


rsoudre Ax = b, on rsout M Ax = M b o M est une matrice telle que M A est
mieux conditionne que A. Ltude et la dcouverte de prconditionneurs efficaces
est une branche actuelle et riche de dveloppements de lanalyse numrique.
titre dexemple, voici la rsolution du systme tudi ci-dessus par la mthode
du gradient conjugu, o le prconditionneur M , diagonal, est linverse de la
diagonale de A. Cest un prconditionneur simple, mais peu efficace :
sage: b = array([1 for i in range(0,n2)])
sage: m = lil_matrix((n2, n2))
sage: for i in range(0,n2):
....: m[i,i] = 1./A[i,i]
sage: msc = m.tocsc()
sage: from scipy.sparse.linalg import cg
sage: x = cg(A, b, M = msc, tol=1.e-8)
300 CHAP. 13. ALGBRE LINAIRE NUMRIQUE

13.3.4 Valeurs propres, vecteurs propres


La mthode de la puissance itre. La mthode de la puissance itre est
particulirement adapte au cas de trs grandes matrices creuses ; en effet il suffit
de savoir effectuer des produits matrice-vecteur (et des produits scalaires) pour
savoir implanter lalgorithme. titre dexemple, revenons aux marches alatoires
sur un graphe creux, et calculons la distribution stationnaire, par la mthode de
la puissance itre :
sage: from scipy import sparse
sage: from numpy.linalg import *
sage: from numpy import array
sage: from numpy.random import rand
sage: def power(A,x): # Puissance itre
....: for i in range(0,1000):
....: y = A*x
....: z = y/norm(y)
....: lam = sum(x*y)
....: s = norm(x-z)
....: print i,"s= "+str(s)+" lambda= "+str(lam)
....: if s < 1e-3:
....: break
....: x = z
....: return x
sage: n = 1000
sage: m = 5
sage: # fabriquer une matrice stochastique de taille n
sage: # avec m coefficients non nuls par ligne
sage: A1 = sparse.lil_matrix((n, n))
sage: for i in range(0,n):
....: for j in range(0,m):
....: l = int(n*rand())
....: A1[l,i] = rand()
sage: for i in range(0,n):
....: s = sum(A1[i,0:n])
....: A1[i,0:n] /= s
sage: At = A1.transpose().tocsc()
sage: x = array([rand() for i in range(0,n)])
sage: # calculer la valeur propre dominante et
sage: # le vecteur propre associ
sage: y = power(At, x)
0 s= 17.637122289 lambda= 255.537958336
1 s= 0.374734872232 lambda= 0.91243996321
2 s= 0.215216267956 lambda= 0.968970901784
3 s= 0.120794893336 lambda= 0.98672095617
4 s= 0.071729229056 lambda= 0.990593746559
...
13.3. MATRICES CREUSES 301

En excutant cet exemple, on pourra samuser chronomtrer ses diffrentes


parties, et on constatera que la quasi totalit du temps de calcul est passe dans
la fabrication de la matrice ; la transposition nest pas trs coteuse ; les itrations
du calcul proprement dit occupent un temps ngligeable sur les 7.5 secondes du
calcul (sur la machine de test). Les stockages sous forme de listes de matrices de
grande taille ne sont pas trs efficaces et ce genre de problme doit plutt tre
trait avec des langages compils et des structures de donnes adaptes.

13.3.5 Thme de rflexion : rsolution de trs grands


systmes non linaires
La mthode la puissance itre et les mthodes bases sur lespace de Krylov
partagent une proprit prcieuse : il suffit de savoir calculer des produits matrice-
vecteur pour pouvoir les implanter. On nest mme pas oblig de connatre la
matrice, il suffit de connatre laction de la matrice sur un vecteur. On peut donc
faire des calculs dans des cas o on ne connat pas exactement la matrice ou des
cas o on est incapable de la calculer. Les mthodes de SciPy acceptent en fait
des oprateurs linaires comme arguments. Voici une application laquelle on
pourra rflchir (et quon pourra implanter).
Soit F : Rn Rn . On veut rsoudre F (x) = 0. La mthode de choix est la
mthode de Newton, o on calcule les itrs xn+1 = xn J(xn )1 F (xn ) en
partant de x0 . La matrice J(xn ) est la jacobienne de F en xn , matrice des drives
partielles de F en xn . En pratique, on rsoudra successivement J(xn )yn = F (xn ),
puis xn+1 = xn yn . Il faut donc rsoudre un systme linaire. Si F est un objet
un peu compliqu calculer, alors ses drives sont en gnral encore beaucoup
plus difficiles calculer et coder et ce calcul peut mme savrer pratiquement
impossible. On a donc recours la drivation numrique : si ej est le vecteur de Rn
partout gal 0 sauf sa j-ime composante gale 1, alors (F (x + hej ) F (x))/h
fournit une (bonne) approximation de la j-ime colonne de la matrice jacobienne.
Il faudra donc faire n + 1 valuations de F pour obtenir J de manire approche,
ce qui est trs coteux si n est grand. Et si on applique une mthode itrative de
type Krylov pour rsoudre le systme J(xn )yn = F (xn ) ? On remarque alors que
J(xn )V ' (F (xn + hV ) F (xn ))/h pour h assez petit, ce qui vite de calculer
toute la matrice. Dans SciPy, il suffira donc de dfinir un oprateur linaire
comme tant lapplication V (F (xn + hV ) F (xn ))/h. Ce genre de mthode
est couramment utilise pour la rsolution de grands systmes non linaires. La
matrice ntant pas symtrique, on utilisera par exemple la mthode GMRES.
302 CHAP. 13. ALGBRE LINAIRE NUMRIQUE
Intgration numrique et quations
diffrentielles
14
Ce chapitre traite le calcul numrique dintgrales (14.1) ainsi que la rsolution
numrique dquations diffrentielles ordinaires (14.2) avec Sage. Nous rappelons
des bases thoriques des mthodes dintgration, puis nous dtaillons les fonctions
disponibles et leur usage (14.1.1).
Le calcul symbolique dintgrales avec Sage a t trait prcdemment (2.3.8),
et ne sera que mentionn rapidement ici comme une possibilit de calculer la
valeur numrique dune intgrale. Cette approche symbolique puis numrique ,
lorsquelle est possible, constitue une des forces de Sage et est privilgier car le
nombre de calculs effectus, et donc derreurs darrondi, est en gnral moindre
que pour les mthodes dintgration numrique.
Nous donnons une rapide introduction aux mthodes classiques de rsolution
dquations diffrentielles, puis le traitement dun exemple (14.2.1) dbutera
linventaire des fonctions disponibles en Sage (14.2.2).

14.1 Intgration numrique


On sintresse au calcul numrique dintgrales de fonctions relles ; pour une
fonction f : I R, o I est un intervalle de R, on veut calculer :
Z
f (x) dx.
I

Par exemple, calculons


Z 3
exp(x2 ) log(x) dx.
1
304 CHAP. 14. INTGRATION NUMRIQUE

0.8
0.04
0.6
0.03
0.4
0.02
0.2
0.01 0 1 2 3 4 5 6 7 8 9 10
0 1 1.5 2 2.5 3 -0.2

sin(x2 )
Figure 14.1 Les fonctions x 7 exp(x2 ) log(x) et x 7 x2
.

sage: x = var('x'); f(x) = exp(-x^2) * log(x)


sage: N(integrate(f, x, 1, 3))
0.035860294991267694
sage: plot(f, 1, 3, fill='axis')

La fonction integrate calcule lintgrale symbolique de lexpression, il faut


demander explicitement une valeur numrique pour lobtenir.
Il est aussi, en principe, possible de calculer des intgrales sur un intervalle
dont les bornes sont infinies :
sage: N(integrate(sin(x^2)/(x^2), x, 1, infinity))
0.285736646322858
sage: plot(sin(x^2)/(x^2), x, 1, 10, fill='axis')
Il existe plusieurs mthodes dans Sage pour calculer numriquement une
intgrale, et si leurs implmentations diffrent techniquement, elles reposent
toutes sur lun des deux principes suivants :
une interpolation polynomiale (mthode de Gauss-Kronrod en particulier) ;
une transformation de fonction (mthode doublement exponentielle).

Mthodes interpolatoires. Dans ces mthodes, on value la fonction f


intgrer en un certain nombre n de points bien choisis x1 , x2 , . . . , xn , et on calcule
une valeur approche de lintgrale de f sur [a, b] par
Z b n
X
f (x) dx wi f (xi ).
a i=1

Les coefficients wi sont appels les poids de la mthode, et ils sont dtermins
par la condition que la mthode doit tre exacte pour tout polynme f de degr
infrieur ou gal n 1. Pour des points (xi ) fixs, les poids (wi ) sont dtermins
de manire unique par cette condition. On dfinit lordre de la mthode comme
le degr maximal des polynmes quelle intgre exactement ; cet ordre est donc
au moins n 1 par construction mais il peut tre plus grand.
14.1. INTGRATION NUMRIQUE 305

Ainsi la famille des mthodes dintgration de Newton-Cotes (dont font partie


les mthodes des rectangles, des trapzes, la rgle de Simpson) choisissent pour
points dintgration des points quirpartis sur lintervalle [a, b] :
sage: fp = plot(f, 1, 3, color='red')
sage: n = 4
sage: interp_points = [(1+2*u/(n-1), N(f(1+2*u/(n-1))))
....: for u in xrange(n)]
sage: A = PolynomialRing(RR, 'x')
sage: pp = plot(A.lagrange_polynomial(interp_points), 1, 3, fill='axis')
sage: show(fp+pp)

0.04

0.03

0.02

0.01

0 1 1.5 2 2.5 3

Pour les mthodes de type interpolatoire, on peut donc considrer que lon
calcule le polynme dinterpolation de Lagrange de la fonction donne et que
lintgrale de ce polynme est choisie comme valeur approche de lintgrale de
la fonction. Ces deux tapes sont en ralit condenses en une formule appele
rgle de quadrature, le polynme dinterpolation de Lagrange nest jamais
calcul explicitement. Le choix des points dinterpolation influe grandement sur la
qualit de lapproximation polynomiale obtenue, et le choix de points quirpartis
nassure pas la convergence quand le nombre de points augmente (phnomne
de Runge). La mthode dintgration correspondante peut ainsi souffrir de ce
problme illustr en figure 14.2.
Lorsquon demande Sage de calculer numriquement une intgrale sur un
intervalle quelconque, la mthode dintgration nest pas applique directement
sur le domaine entier : on subdivise le domaine dintgration en intervalles
suffisamment petits pour que la mthode lmentaire donne un rsultat assez
prcis (on parle de composition de mthodes). Comme stratgie de subdivision,
on peut par exemple sadapter dynamiquement la fonction intgrer : si on
Rb
appelle Iab (f ) la valeur de a f (x) dx calcule par la mthode dintgration, on
compare
I0 = Iab (f )
306 CHAP. 14. INTGRATION NUMRIQUE

-10 -5 5 10

Figure 14.2 Interpolation par un polynme de degr 10 (trait fin) de la fonction


x 7 1/(1 + x2 ) (trait gras) sur 11 points quirpartis sur [10, 10]. Le phnomne de
Runge est apparent aux bornes.

avec
I1 = Ia(a+b)/2 (f ) + I(a+b)/2
b
(f )
et on arrte de subdiviser si |I0 I1 | nest pas significatif par rapport la prcision
de calcul utilise. Cest ici que la notion dordre dune mthode est importante :
pour une mthode dordre n, diviser lintervalle dintgration en 2 divise lerreur
thorique par 2n , sans tenir compte des erreurs darrondi.
Une mthode de type interpolatoire particulire disponible dans Sage est la
mthode de Gauss-Legendre. Dans cette mthode les n points dintgration sont
choisis comme les racines du polynme de Legendre de degr n (avec un intervalle
de dfinition correctement translat lintervalle dintgration considr [a, b]).
Les proprits des polynmes de Legendre, orthogonaux pour le produit scalaire
Z b
hf, gi = f (x)g(x) dx,
a

font que la mthode dintgration obtenue calcule exactement les intgrales des
polynmes de degr 2n 1 inclus, au lieu de simplement jusquau degr n 1
comme on pouvait sy attendre. De plus les poids dintgration correspondants
sont toujours positifs, ce qui rend la mthode moins vulnrable des problmes
numriques du type cancellation 1
Pour terminer sur les mthodes de type interpolatoire, la mthode de Gauss-
Kronrod 2n+1 points est une augmentation de la mthode de Gauss-Legendre
n points :
1. Ce phnomne se produit lorsquune somme est significativement plus petite (en valeur
absolue) que les termes de la somme : chaque erreur darrondi peut alors tre plus grande que
le rsultat final, do une perte totale de prcision. Voir aussi 11.3.3.
14.1. INTGRATION NUMRIQUE 307

parmi les 2n + 1 points, n sont les points de la mthode de Gauss-Legendre ;


la mthode est exacte pour tout polynme de degr infrieur ou gal
3n + 1.
On peut observer navement que les 3n + 2 inconnues (les 2n + 1 poids et les
n + 1 points ajouts) sont a priori dtermins en exigeant que la mthode soit au
moins dordre 3n + 1 (ce qui donne bien 3n + 2 conditions). Attention, les poids
associs dans la mthode de Gauss-Kronrod aux n points de Gauss-Legendre
nont aucune raison de concider avec ceux qui leur sont associs dans la mthode
de Gauss-Legendre.
Lintrt dune telle mthode augmente se manifeste lorsque lon considre
que le cot principal dun algorithme dintgration est le nombre dvaluations
de la fonction f intgrer (en particulier si les points et poids sont tabuls). La
mthode de Gauss-Kronrod tant en principe plus prcise que celle de Gauss-
Legendre, on peut utiliser son rsultat I1 pour valider le rsultat I0 de cette
dernire et obtenir une estimation de lerreur commise par |I1 I0 |, tout en
minimisant le nombre dappels f . On peut comparer cette stratgie, particulire
la mthode de Gauss-Legendre, avec la stratgie plus gnrale de subdivision
vue en page 306.

Mthodes doublement exponentielles. Les mthodes doublement exponen-


tielles (DE) reposent sur le choix dun changement de variable qui transforme un
intervalle dintgration born R, et sur la trs bonne prcision obtenue par la
mthode des trapzes sur R pour les fonctions analytiques. Pour une fonction
f intgrable sur R et un pas dintgration h la mthode des trapzes consiste
calculer
+
X
Ih = h f (hi)
i=
R +
comme valeur approche de f (x) dx. Dcouverte en 1973 par Takahasi et
Mori, la transformation doublement exponentielle est couramment utilise par les
logiciels dintgration numrique. Une introduction la transformation et sa
dcouverte est donne dans [Mor05] ; lessentiel en est restitu ici. On y trouve en
particulier une explication de la surprenante prcision obtenue par la mthode des
trapzes (elle est optimale dans un certain sens) pour les fonctions analytiques
sur R.
Pour calculer Z 1
I= f (x) dx,
1

il est possible dutiliser une transformation x = (t) o est analytique sur R et


vrifie
lim (t) = 1, lim (t) = 1,
t t

et alors Z
I= f ((t))0 (t) dt.

308 CHAP. 14. INTGRATION NUMRIQUE

1.6
1
1.4
1.2
0.5
1
0.8
-3 -2 -1 1 2 3
0.6
0.4
-0.5
0.2

-1 -3 -2 -1 1 2 3

Figure 14.3 La transformation (t) = tanh( 2 sinh t) utilise dans la mthode doublement
exponentielle ( gauche) et la dcroissance de 0 (t) ( droite).

En appliquant la formule des trapzes cette dernire expression on calcule


N
X
IhN = h f ((kh))0 (kh)
k=N

pour un certain pas de discrtisation h et en tronquant la somme aux termes de


N N . Le choix de transformation propos est
 
(t) = tanh sinh t
2
qui donne la formule
N
2 cosh kh
X   
IhN = h f tanh sinh kh .
2 cosh2 ( 2 sinh kh)
k=N

La formule doit son nom la dcroissance doublement exponentielle de

2 cosh t

0 (t) =
cosh2 ( 2 sinh t)

quand |t| (voir figure 14.3). Le principe de la transformation est de concentrer


lessentiel de la contribution de la fonction intgrer autour de 0, do la forte
dcroissance quand |t| crot. Il y a un compromis trouver dans le choix des
paramtres et de la transformation utilise : une dcroissance plus rapide que
doublement exponentielle diminue lerreur de troncature mais augmente lerreur
de discrtisation.
Depuis la dcouverte de la transformation DE, cette mthode est applique
seule ou avec dautres transformations, en fonction de la nature de lintgrande, de
ses singularits et du domaine dintgration. Un tel exemple est la dcomposition
sinus cardinal sinc :
N
X
f (x) f (kh)Sk,h (x)
k=N
14.1. INTGRATION NUMRIQUE 309

0.8

0.6

0.4

0.2

-4 -3 -2 -1 1 2 3 4
-0.2
Figure 14.4 La fonction sinus cardinal.

o
sin((x kh)/h)
Sk,h (x) = ,
(x kh)/h
utilise conjointement la mthode doublement exponentielle dans [TSM05] pour
amliorer les formules prcdentes qui utilisaient une transformation simplement
exponentielle (t) = tanh(t/2). La fonction sinc est dfinie par

1 si x = 0,
sinc = sin(x)
sinon,
x
et son graphe est donn en figure 14.4.
Le choix de la transformation utiliser dtermine en grande partie la qualit
du rsultat en prsence de singularits aux bornes (il ny a cependant pas de bonne
solution en cas de singularits lintrieur de lintervalle). Nous verrons plus
loin que dans la version de Sage considre, seules les fonctions dintgration de
PARI utilisent des transformations doublement exponentielles avec la possibilit
de prciser le comportement aux bornes.

14.1.1 Fonctions dintgration disponibles


Nous allons maintenant voir plus en dtail les diffrentes faons de calculer une
intgrale numrique avec Sage, travers quelques exemples de calculs dintgrales :
42 1
1
Z Z
I1 = exp(x2 ) log(x) dx, I2 = x log(1 + x) dx = ,
17 0 4
310 CHAP. 14. INTGRATION NUMRIQUE

Z 1 p
I3 = 1 x2 dx = ,
0 4

Z 1 Z 4
Z 1
I4 = max(sin(x), cos(x)) dx = cos(x) dx + sin(x) dx

0 0 4

= sin + cos cos 1 = 2 cos 1,
4 4
1
Z 1 Z
I5 = sin(sin(x)) dx, I6 = sin(x) exp(cos(x)) dx = e ,
0 0 e
1
Z 1 Z 1,1
I7 = dx = 105 arctan(105 ), I8 = exp(x100 ) dx,
0 1 + 10 10 x2
0
1 2
Z 10 Z 1

I9 = x sin(x ) dx = (1 cos(1000)), I10 =
2 3
x dx = .
0 3 0 3
Nous ne donnons pas une description exhaustive de lusage des fonctions
dintgration traites cela se trouve dans laide en ligne mais uniquement
leur usage le plus courant.

N(integrate(...)). La premire mthode que lon peut utiliser avec Sage pour
calculer numriquement est N(integrate(...)) :
sage: N(integrate(exp(-x^2)*log(x), x, 17, 42))
2.5657285006962035e-127
Il faut remarquer quil nest pas garanti que lintgrale sera calcule numriquement
par ce biais, en effet la fonction integrate demande une intgration symbolique.
Si celle-ci est possible, alors Sage ne fera quvaluer numriquement lexpression
symbolique obtenue :
sage: integrate(log(1+x)*x, x, 0, 1)
1/4
sage: N(integrate(log(1+x)*x, x, 0, 1))
0.250000000000000

numerical_integral. La fonction numerical_integral, linverse, demande


explicitement une intgration numrique de la fonction donne en paramtre. Elle
utilise pour ceci la bibliothque numrique GSL qui implmente la mthode de
Gauss-Kronrod pour un nombre n fix de points dintgration. Les points et poids
sont prcalculs, et la prcision est limite la prcision des nombres flottants
machine (53 bits de mantisse). Le rsultat est un couple compos du rsultat
calcul et dune estimation de lerreur :
sage: numerical_integral(exp(-x^2)*log(x), 17, 42)
(2.5657285006962035e-127, 3.3540254049238093e-128)
Lestimation de lerreur nest pas une borne garantie de lerreur commise, mais
une simple valeur indicative de la difficult calculer lintgrale donne. On
constate que dans lexemple ci-dessus lestimation donne de lerreur est telle que
lon peut douter de presque tous les chiffres du rsultat (sauf le premier).
Les arguments de numerical_integral permettent notamment :
14.1. INTGRATION NUMRIQUE 311

de choisir le nombre de points utiliss (six choix allant de rule=1 pour 15


points rule=6 pour 61 points, valeur par dfaut) ;
de demander une subdivision adaptative (choix par dfaut), ou dimposer
une application directe sans composition de la mthode sur lintervalle
dintgration (par lajout de algorithm='qng') ;
de borner le nombre dappels lintgrande.
Empcher GSL de procder une intgration adaptative peut entraner une perte
de prcision :
sage: numerical_integral(exp(-x^100), 0, 1.1)
(0.99432585119150..., 4.0775730...e-09)
sage: numerical_integral(exp(-x^100), 0, 1.1, algorithm='qng')
(0.994327538576531..., 0.016840666914688864)
Lorsque la fonction integrate ne trouve pas dexpression analytique correspon-
dant lintgrale demande, elle renvoie une expression symbolique inchange :
sage: integrate(exp(-x^2)*log(x), x, 17, 42)
integrate(e^(-x^2)*log(x), x, 17, 42)
et le calcul numrique effectu via N utilise numerical_integral. Ceci explique
en particulier pourquoi le paramtre de la prcision sera ignor dans ce cas :
sage: N(integrate(exp(-x^2)*log(x), x, 17, 42), 200)
2.5657285006962035e-127
mais on aura :
sage: N(integrate(sin(x)*exp(cos(x)), x, 0, pi), 200)
2.3504023872876029137647637011912016303114359626681917404591
car lintgration symbolique est possible dans ce cas.

sage.calculus.calculus.nintegral. Pour les fonctions dfinies symbolique-


ment, il est possible de demander Maxima de calculer numriquement une
intgrale :
sage: sage.calculus.calculus.nintegral(sin(sin(x)), x, 0, 1)
(0.430606103120690..., 4.780688102287053...e-15, 21, 0)
mais il est aussi possible dappeler la mthode nintegral directement sur un
objet de type Expression :
sage: g(x) = sin(sin(x))
sage: g.nintegral(x, 0, 1)
(0.430606103120690..., 4.780688102287053...e-15, 21, 0)
Maxima utilise la bibliothque dintgration numrique QUADPACK, qui comme
GSL est limite aux nombres flottants machine. La fonction nintegral utilise une
stratgie de subdivision adaptative de lintervalle dintgration, et il est possible
de prciser :
la prcision relative dsire pour la sortie ;
312 CHAP. 14. INTGRATION NUMRIQUE

le nombre maximal de sous-intervalles considrs pour le calcul.


La sortie est un tuple :
1. la valeur approche de lintgrale ;
2. une estimation de lerreur absolue ;
3. le nombre dappels lintgrande ;
4. un code derreur (0 si aucun problme na t rencontr, pour plus de dtails
sur les autres valeurs possibles vous pouvez consulter la documentation avec
sage.calculus.calculus.nintegral?).

gp(intnum(...)). Le calculateur PARI est disponible depuis Sage et impl-


mente aussi une commande pour lintgration numrique de fonctions nomme
intnum :
sage: gp('intnum(x=17, 42, exp(-x^2)*log(x))')
2.5657285005610514829173563961304785900 E-127
La fonction intnum utilise la mthode doublement exponentielle.
Il est possible de choisir la prcision du rsultat en modifiant la prcision
globale de linterprte PARI :
sage: gp('intnum(x=0, 1, sin(sin(x)))')
0.43060610312069060491237735524846578643
sage: old_prec = gp.set_precision(50)
sage: gp('intnum(x=0, 1, sin(sin(x)))')
0.43060610312069060491237735524846578643360804182200
Un inconvnient majeur de cette mthode est que la fonction intgrer est
donner sous la forme dune chane en respectant la syntaxe de PARI, il nest pas
possible dintgrer des fonctions arbitraires par ce biais.
La fonction intnum permet dindiquer le comportement de lintgrande aux
bornes de lintervalle dintgration. Lexemple suivant illustre limpact que cela
peut avoir sur la prcision du rsultat. Intgrons x 7 x1/2 sans indication :
sage: p = gp.set_precision(old_prec) # on remet la prcision par dfaut
sage: gp('intnum(x=0, 1, x^(-1/2))')
1.999999999999999999999999999998...
En indiquant la nature de la singularit, savoir que la fonction se comporte
comme x 7 x1/2 en 0 :
sage: gp('intnum(x=[0, -1/2], 1, x^(-1/2))')
2.00000000000000000000000000000...
Lutilisateur est responsable de lexactitude du comportement annonc ; si par
exemple nous indiquons (de faon errone) que la fonction se comporte comme
x 7 x1/42 en 0, lerreur commise restera importante :
sage: gp('intnum(x=[0, -1/42], 1, x^(-1/2))')
1.9999999999999999999999999999996...
14.1. INTGRATION NUMRIQUE 313

mpmath.quad*. La bibliothque mpmath est une bibliothque de calcul numrique


en prcision arbitraire crite en Python. Elle est capable de calculer avec des
nombres flottants rels et complexes, des matrices, et des intervalles de nombres
flottants rels.
Elle dispose de fonctions dintgration numrique (la principale tant quad) et
est disponible en Sage, il suffit de limporter :
sage: import mpmath
sage: mpmath.mp.prec = 53
sage: mpmath.quad(lambda x: mpmath.sin(mpmath.sin(x)), [0, 1])
mpf('0.43060610312069059')
La valeur de sortie nest pas garantie tre exacte avec toute la prcision demande,
comme on le constate sur lexemple suivant :
sage: mpmath.mp.prec = 113
sage: mpmath.quad(lambda x: mpmath.sin(mpmath.sin(x)), [0, 1])
mpf('0.430606103120690604912377355248465809')
sage: mpmath.mp.prec = 114
sage: mpmath.quad(lambda x: mpmath.sin(mpmath.sin(x)), [0, 1])
mpf('0.430606103120690604912377355248465785')
Il est possible de spcifier la prcision demande en nombre de chiffres dcimaux
(mpmath.mp.dps) ou en nombre de bits (mpmath.mp.prec). Dans un souci de
cohrence avec la fonction N de Sage nous nous restreignons une prcision en
bits.
La fonction mpmath.quad peut faire appel soit la mthode de Gauss-Legendre,
soit la transformation doublement exponentielle (cest cette dernire qui est
utilise par dfaut). Il est possible de spcifier directement la mthode utiliser
avec les fonctions mpmath.quadgl et mpmath.quadts. 2
Une limitation importante pour lutilisation des fonctions dintgration de
mpmath dans Sage est quelles ne savent pas manipuler directement des fonctions
arbitraires dfinies en Sage :
sage: mpmath.quad(sin(sin(x)), [0, 1])
Traceback (most recent call last):
...
TypeError: no canonical coercion from
<type 'sage.libs.mpmath.ext_main.mpf'> to Symbolic Ring
La situation est cependant moins problmatique que pour lutilisation de PARI
qui est elle limite une interaction en mode texte. Il est en effet possible dajouter
les fonctions dvaluation et de conversion ncessaires pour pouvoir intgrer via
mpmath.quad des fonctions quelconques 3 :
sage: g(x) = max_symbolic(sin(x), cos(x))
sage: mpmath.mp.prec = 100
2. Du nom de la transformation utilise : t 7 tanh( 2 sinh(t)) et vue prcdemment.
3. Le lecteur curieux de savoir pourquoi on a utilis max_symbolic essayera avec max, et
regardera ensuite la documentation de max_symbolic.
314 CHAP. 14. INTGRATION NUMRIQUE

0.95

0.9

0.85

0.8

0.75

0.7
0 0.2 0.4 0.6 0.8 1
Figure 14.5 La fonction x 7 max(sin(x), cos(x)). Lirrgularit en /4 rend lintgration
numrique trs problmatique.

sage: mpmath.quadts(lambda x: g(N(x, 100)), [0, 1])


mpf('0.873912416263035435957979086252')
On constate que lintgration de fonctions non rgulires (comme lexemple de I4
ci-dessus) peut entraner des pertes de prcision consquentes, mme en demandant
le rsultat avec une grande prcision :
sage: mpmath.mp.prec = 170
sage: mpmath.quadts(lambda x: g(N(x, 190)), [0, 1])
mpf('0.87391090757400975205393005981962476344054148354188794')
sage: N(sqrt(2) - cos(1), 100)
0.87391125650495533140075211677
Seuls 5 chiffres sont corrects ici. On peut nanmoins aider mpmath en suggrant une
subdivision de lintervalle dintgration (ici, au point irrgulier, cf. figure 14.5) :
sage: mpmath.quadts(lambda x: g(N(x, 170)), [0, mpmath.pi / 4, 1])
mpf('0.87391125650495533140075211676672147483736145475902551')
Les fonctions discontinues reprsentent un pige classique pour les mthodes
dintgration ; nanmoins une stratgie dadaptation automatique par subdivision,
telle quvoque plus haut, peut limiter les dgts.
Exercice 47 (Calcul des coefficients de Newton-Cotes). On cherche calculer les
coefficients de la mthode de Newton-Cotes n points, celle-ci ntant pas disponible
dans Sage. On considre pour simplifier que lintervalle dintgration est I = [0, n 1],
les points dintgration tant alors x1 = 0, x2 = 1, . . . , xn = n 1. Les coefficients (wi )
de la mthode sont tels que lquation
Z n1 n1
X
f (x) dx = wi f (i) (14.1)
0 i=0
14.2. RSOLUTION DQUATIONS DIFFRENTIELLES 315

est exacte pour tout polynme f de degr infrieur ou gal n 1.


Qn1
1. On considre pour i {0, . . . , n 1} le polynme Pi (X) = j=0 (X xj ). En
j6=i
appliquant lquation (14.1) Pi , exprimer wi en fonction de Pi .
2. En dduire une fonction NCRule qui n associe les coefficients de la mthode de
Newton-Cotes n points sur lintervalle [0, n 1].
3. Montrer comment appliquer ces poids sur un segment dintgration [a, b] quel-
conque.
4. crire une fonction QuadNC qui calcule lintgrale dune fonction sur un segment
de R donn en paramtre. Comparer les rsultats avec les fonctions dintgration
disponibles en Sage sur les intgrales I1 I10 .

14.2 Rsolution numrique des quations


diffrentielles ordinaires
On sintresse dans cette section la rsolution numrique dquations diffren-
tielles ordinaires. Les fonctions de rsolution disponibles dans Sage sont capables
de traiter des systmes dquations de la forme :

dt (t) = f1 (t, y1 (t), y2 (t), . . . , yn (t))


dy1

dy2 (t) = f2 (t, y1 (t), y2 (t), . . . , yn (t))


dt
..


.
(t) = fn (t, y1 (t), y2 (t), . . . , yn (t))
dyn
dt

avec des conditions initiales (y1 (0), y2 (0), . . . , yn (0)) connues.


Cette formalisation permet aussi de sintresser des problmes dordre
suprieur 1, en introduisant des variables supplmentaires (voir lexemple
dvelopp en 14.2.1). Elle ne permet cependant pas dexprimer le systme
dquations vrifi par la fonction de Dickman :

u0 (u) + (u 1) = 0 pour u > 1,




(u) = 1 pour 0 6 u 6 1.

Les outils de rsolution dquations diffrentielles ordinaires ne sont en effet pas


adapts une telle quation (dite retard).
Les mthodes de rsolution numrique dites un pas utilisent toutes un
mme principe gnral : pour un pas h et des valeurs de y(t0 ) et y 0 (t0 ) connues,
on calcule une valeur approche de y(t0 + h) partir dune estimation de y 0 (t)
prise sur lintervalle [t0 , t0 + h]. Par exemple la mthode la plus simple consiste
faire lapproximation :

t [t0 , t0 + h], y 0 (t) y 0 (t0 ),


Z t0 +h
y 0 (t) dt hy 0 (t0 ),
t0
y(t0 + h) y(t0 ) + hy 0 (t0 ).
316 CHAP. 14. INTGRATION NUMRIQUE

Le fait dapprocher y 0 par une fonction constante sur [t0 , t0 + h] rappelle la


mthode dintgration numrique des rectangles. La mthode obtenue est dordre
1, cest--dire que lerreur obtenue aprs un pas de calcul est en O(h2 ) sous
lhypothse que f est suffisamment rgulire. De manire gnrale une mthode
est dordre p si lerreur quelle commet sur un pas de longueur h est en O(hp+1 ).
La valeur obtenue en t1 = t0 + h sert alors de point de dpart pour progresser
dun pas de plus, aussi loin que dsir.
Cette mthode dordre 1, appele mthode dEuler, nest pas rpute pour sa
prcision (tout comme la mthode des rectangles pour lintgration) et il existe
des mthodes dordre plus lev, par exemple la mthode Runge-Kutta dordre 2
pour rsoudre lquation y 0 = f (t, y) :

k1 = hf (tn , y(tn ))
1 1
k2 = hf (tn + h, y(tn ) + k1 )
2 2
y(tn+1 ) y(tn ) + k2 + O(h3 ).

Dans cette mthode, on essaie dvaluer y 0 (tn + h/2) pour obtenir une meilleure
estimation de y(tn + h).
On trouve aussi des mthodes multi-pas (cest le cas par exemple des m-
thodes de Gear) qui consistent calculer y(tn ) partir des valeurs dj obtenues
(y(tn1 ), y(tn2 ), . . . , y(tn` )) pour un certain nombre de pas `. Ces mthodes
dmarrent ncessairement par une phase dinitialisation avant quun nombre
suffisant de pas soient calculs.
Tout comme la mthode de Gauss-Kronrod pour lintgration numrique, il
existe des mthodes hybrides pour la rsolution dquations diffrentielles. Ainsi
la mthode de Dormand et Prince calcule avec les mmes points dapproximation
une valeur aux ordres 4 et 5, la deuxime servant pour lestimation derreur de la
premire. On parle dans ce cas de mthode adaptative.
On distingue encore les mthodes dites explicites des mthodes implicites :
dans une mthode explicite, la valeur de y(tn+1 ) est donne par une formule
nutilisant que des valeurs connues ; pour une mthode implicite il faut rsoudre
une quation. Prenons lexemple de la mthode dEuler implicite :

y(tn+1 ) = y(tn ) + hf (tn+1 , y(tn+1 )).

On constate que la valeur recherche y(tn+1 ) apparat des deux cts de lquation ;
si la fonction f est suffisamment complexe il faudra rsoudre un systme algbrique
non linaire, typiquement avec la mthode de Newton (voir 12.2.2).
A priori, on sattend obtenir des rsultats plus prcis mesure que lon
diminue le pas dintgration h ; outre le cot en calculs supplmentaires que cela
reprsente, ce gain espr en prcision est toutefois tempr par un plus grand
nombre derreurs darrondi qui risquent, la longue, de polluer le rsultat.
14.2. RSOLUTION DQUATIONS DIFFRENTIELLES 317

14.2.1 Exemple de rsolution


Considrons loscillateur de Van der Pol de paramtre vrifiant lquation
diffrentielle suivante :
d2 x dx
(t) (1 x2 ) (t) + x(t) = 0.
dt2 dt

Posons y0 (t) = x(t) et y1 (t) = dt ,


dx
on obtient ce systme dordre 1 :
dy0
= y1 ,

dt
dy1
dt = (1 y02 )y1 y0 .

Pour le rsoudre, nous allons utiliser un objet solveur que lon obtient avec la
commande ode_solver :
sage: T = ode_solver()
Un objet solveur sert enregistrer les paramtres et la dfinition du systme que
lon cherche rsoudre ; il donne accs aux fonctions de rsolution numrique
dquations diffrentielles disponibles dans la bibliothque GSL, dj mentionne
au sujet de lintgration numrique.
Les quations du systme sont renseignes sous la forme dune fonction :
sage: def f_1(t,y,params): return [y[1],params[0]*(1-y[0]^2)*y[1]-y[0]]
sage: T.function = f_1
Le paramtre y reprsente le vecteur des fonctions inconnues, et on doit renvoyer
en fonction de t et dun paramtre optionnel (ici params[0] reprsentant ) le
vecteur des membres droits du systme dquations.
Certains des algorithmes de GSL ncessitent de plus de connatre la jacobienne
du systme (la matrice dont le terme (i, j) est yfi
j
, et dont la dernire ligne
fj
contient t ) :
sage: def j_1(t,y,params):
....: return [[0, 1],
....: [-2*params[0]*y[0]*y[1]-1, params[0]*(1-y[0]^2)],
....: [0,0]]
sage: T.jacobian = j_1
Il est maintenant possible de demander une rsolution numrique. On choisit
lalgorithme, lintervalle sur lequel calculer la solution et le nombre de pas voulus
(ce qui dtermine h) :
sage: T.algorithm = "rk8pd"
sage: T.ode_solve(y_0=[1,0], t_span=[0,100], params=[10],
....: num_points=1000)
sage: f = T.interpolate_solution()
Ici on a pris lalgorithme de Runge-Kutta Dormand-Prince pour calculer la
solution sur [0, 100] ; les conditions initiales ainsi que la valeur des paramtres (ici
318 CHAP. 14. INTGRATION NUMRIQUE

un seul) sont prcises : ici y_0=[1,0] signifie y0 (0) = 1, y1 (0) = 0, cest--dire


x(0) = 1, x0 (0) = 0.
Pour afficher la solution (avec plot(f, 0, 2) on verra bien la drive nulle
en t = 0) :
sage: plot(f, 0, 100)

2
1.5
1
0.5

20 40 60 80 100
-0.5
-1
-1.5
-2

14.2.2 Fonctions de rsolution disponibles


Nous avons dj voqu pour les objets solveur de GSL la mthode rk8pd.
Dautres mthodes sont disponibles :
rkf45 : Runga-Kutta-Fehlberg, une mthode adaptative dordres 5 et 4 ;
rk2 : Runge-Kutta adaptative dordres 3 et 2 ;
rk4 : la mthode Runge-Kutta classique dordre 4 ;
rk2imp : une mthode de Runge-Kutta implicite dordre 2 avec valuation au
milieu de lintervalle ;
rk4imp : une mthode de Runge-Kutta implicite dordre 4 avec valuation
aux points Gaussiens 4 ;
bsimp : la mthode implicite de Burlisch-Stoer ;
gear1 : la mthode implicite de Gear un pas ;
gear2 : la mthode implicite de Gear deux pas.
Nous renvoyons le lecteur intress par les dtails de toutes ces mthodes [AP98]
ou [CM84].
Il faut noter que la limitation de GSL aux flottants machine donc de
prcision fixe voque pour lintgration numrique reste valide pour les
mthodes de rsolution dquations diffrentielles.
Maxima dispose aussi de routines de rsolution numrique, avec sa syntaxe
propre :

4. Il sagit des racines du polynme de Legendre de degr 2 dcals sur lintervalle [t, t + h],
nommes en rfrence la mthode dintgration de Gauss-Legendre.
14.2. RSOLUTION DQUATIONS DIFFRENTIELLES 319

sage: t, y = var('t, y')


sage: desolve_rk4(t*y*(2-y), y, ics=[0,1], end_points=[0, 1], step=0.5)
[[0, 1], [0.5, 1.12419127425], [1.0, 1.46159016229]]
La fonction desolve_rk4 utilise la mthode de Runge-Kutta dordre 4 (la mme
que rk4 pour GSL) et prend comme paramtres :
le membre droit de lquation y 0 (t) = f (t, y(t)), ici y 0 = ty(2 y) ;
le nom de la variable fonction inconnue, ici y ;
les conditions initiales ics, ici t = 0 et y = 1 ;
lintervalle de rsolution end_points, ici [0, 1] ;
le pas step, ici 0.5.
Nous ne dveloppons pas la commande similaire desolve_system_rk4, dj
voque au chapitre 4 et qui sapplique un systme dquations diffrentielles.
Maxima se limite aussi la prcision machine.
Si lon recherche des solutions calcules en prcision arbitrairement grande, il
est possible de se tourner vers odefun du module mpmath :
sage: import mpmath
sage: mpmath.mp.prec = 53
sage: sol = mpmath.odefun(lambda t, y: y, 0, 1)
sage: sol(1)
mpf('2.7182818284590451')
sage: mpmath.mp.prec = 100
sage: sol(1)
mpf('2.7182818284590452353602874802307')
sage: N(exp(1), 100)
2.7182818284590452353602874714
Les arguments de la fonction mpmath.odefun sont :
les membres droits du systme dquations, sous la forme dune fonction
(t, y) 7 f (t, y(t)), ici y 0 = y, comme pour la fonction ode_solver. La
dimension du systme est dduite automatiquement de la dimension de la
valeur de retour de la fonction ;
les conditions initiales t0 et y(t0 ), ici y(0) = 1.
Par exemple pour ce systme de dimension 2

y1 = y2
 0
y20 = y1

dont les solutions sont (cos(t), sin(t)), avec comme conditions initiales y1 (0) = 1
et y2 (0) = 0 :
sage: mpmath.mp.prec = 53
sage: f = mpmath.odefun(lambda t, y: [-y[1], y[0]], 0, [1, 0])
sage: f(3)
[mpf('-0.98999249660044542'), mpf('0.14112000805986721')]
sage: (cos(3.), sin(3.))
320 CHAP. 14. INTGRATION NUMRIQUE

(-0.989992496600445, 0.141120008059867)
La fonction mpmath.odefun utilise la mthode de Taylor. Pour un degr p on
utilise :
dy h2 d2 y hp dp y
y(tn+1 ) = y(tn ) + h (tn ) + (tn ) + . . . + (tn ) + O(hp+1 ).
dt 2! dt 2 p! dtp
La principale question est celle du calcul des drives de y. Pour ce faire, odefun
calcule des valeurs approches

[e
y (tn + h), . . . , ye(tn + ph)] [y(tn + h), . . . , y(tn + ph)]

par p pas de la mthode peu prcise dEuler. On calcule ensuite

dy
^ ye(tn + h) ye(tn ) dy ^ ye(tn + 2h) ye(tn + h)
(tn ) , (tn + h)
dt h dt h
puis

dt (tn + h) dt (tn )
dy ^ ^
dy
d^2y
(t n ) ,
dt2 h
et ainsi de suite jusqu obtenir des estimations des drives de y en tn jusqu
lordre p.
Il faut tre vigilant lorsque lon change la prcision de calcul flottant de mpmath.
Pour illustrer ce problme, reprenons la rsolution de lquation diffrentielle
y 0 = y vrifie par la fonction exp donne plus haut :
sage: mpmath.mp.prec = 10
sage: sol = mpmath.odefun(lambda t, y: y, 0, 1)
sage: sol(1)
mpf('2.7148')
sage: mpmath.mp.prec = 100
sage: sol(1)
mpf('2.7135204235459511323824699502438')
Lapproximation de exp(1) est trs mauvaise, et pourtant elle est calcule avec
100 bits de prcision ! La fonction solution sol (un interpolant dans le jargon
mpmath) a t calcule avec seulement 10 bits de prcision et ses coefficients ne
sont pas recalculs en cas de changement de prcision, ce qui explique le rsultat.
Quatrime partie

Combinatoire
Dnombrement et combinatoire
15
Ce chapitre aborde principalement le traitement avec Sage des problmes
combinatoires suivants : le dnombrement (combien y a-t-il dlments dans un
ensemble S ?), lnumration (calculer tous les lments de S, ou itrer parmi
eux), le tirage alatoire (choisir au hasard un lment de S selon une loi, par
exemple uniforme). Ces questions interviennent naturellement dans les calculs de
probabilits (quelle est la probabilit au poker dobtenir une suite, ou un carr
das ?), en physique statistique, mais aussi en calcul formel (nombre dlments
dans un corps fini), ou en analyse dalgorithmes. La combinatoire couvre un
domaine beaucoup plus vaste (ordres partiels, mots, thorie des reprsentations,
etc.) pour lesquels nous nous contentons de donner quelques pointeurs vers les
possibilits offertes par Sage ; la thorie des graphes et la programmation linaire
font lobjet de chapitres spars, respectivement 16 et 17.
Une caractristique de la combinatoire effective est la profusion de types
dobjets et densembles que lon veut manipuler. Il serait impossible de les dcrire
tous, et a fortiori de les implanter. Ce chapitre illustre donc la mthodologie
sous-jacente : fournir des briques de base pour dcrire les ensembles combinatoires
usuels (15.2), des outils pour les combiner et construire de nouveaux ensembles
(15.3), et des algorithmes gnriques pour traiter uniformment de grandes
classes de problmes (15.4). En premire lecture, ce chapitre peut tre parcouru
en diagonale, en sarrtant sur les synthses de 15.1.2 et 15.3.
Cest un domaine o Sage a des fonctionnalits bien plus tendues que la
plupart des systmes de calcul formel et est en pleine expansion ; en revanche il
reste encore trs jeune avec de multiples incohrences et limitations arbitraires.
Ce chapitre a t traduit en anglais et intgr dans le manuel de rfrence de
Sage. On peut y accder avec :
sage: sage.combinat.tutorial?
324 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

15.1 Premiers exemples


15.1.1 Jeu de poker et probabilits
Nous commenons par rsoudre un problme classique : dnombrer certaines
combinaisons de cartes dans un jeu de poker, pour en dduire leur probabilit.
Une carte de poker est caractrise par une couleur (cur, carreau, pique ou
trfle) et une valeur (2, 3, . . ., 9, 10, valet, dame, roi, ou as). Le jeu de poker
est constitu de toutes les cartes possibles ; il sagit donc du produit cartsien de
lensemble des couleurs et de lensemble des valeurs :

Cartes = Symboles Valeurs = {(s, v) | s Symboles et v Valeurs} .

Construisons ces ensembles dans Sage :


sage: Symboles = Set(["Coeur", "Carreau", "Pique", "Trefle"])
sage: Valeurs = Set([2..10] + ["Valet", "Dame", "Roi", "As"])
sage: Cartes = CartesianProduct(Valeurs, Symboles)
Il y a 4 couleurs et 13 valeurs possibles donc 4 13 = 52 cartes dans le jeu de
poker :
sage: Symboles.cardinality()
4
sage: Valeurs.cardinality()
13
sage: Cartes.cardinality()
52
Tirons une carte au hasard :
sage: Cartes.random_element()
[6, 'Trefle']
Une petite digression technique est ici ncessaire. Les lments du produit
cartsien sont renvoys sous forme de listes :
sage: type(Cartes.random_element())
<type 'list'>
Une liste Python ntant pas immuable, on ne peut pas la mettre dans un ensemble
(voir 3.3.7), ce qui nous poserait problme par la suite. Nous redfinissons donc
notre produit cartsien pour que les lments soient reprsents par des tuples :
sage: Cartes = CartesianProduct(Valeurs, Symboles).map(tuple)
sage: Cartes.first()
('Roi', 'Pique')
On peut maintenant construire un ensemble de cartes 1 :
sage: Set([Cartes.random_element(), Cartes.random_element()])
1. Ce problme devrait disparatre terme : il est prvu de changer limplantation des
produits cartsiens pour que leurs lments soient immuables par dfaut.
15.1. PREMIERS EXEMPLES 325

{(2, 'Coeur'), (4, 'Pique')}


Revenons notre propos. On considre ici une version simplifie du jeu de
poker, o chaque joueur pioche directement cinq cartes, qui forment une main.
Toutes les cartes sont distinctes et lordre na pas dimportance ; une main est
donc un sous-ensemble de taille 5 de lensemble des cartes. Pour tirer une main
au hasard, on commence par construire lensemble de toutes les mains possibles
puis on en demande un lment alatoire :
sage: Mains = Subsets(Cartes, 5)
sage: Mains.random_element()
{(2, 'Coeur'), (7, 'Trefle'), (7, 'Coeur'), (2, 'Pique'), (9, 'Coeur')}
Le nombre total de mains est donn par le nombre de sous-ensembles de taille
5 dun ensemble de taille 52, cest--dire le coefficient binomial 52 :

5
sage: binomial(52, 5)
2598960
On peut aussi ne pas se proccuper de la mthode de calcul, et simplement
demander sa taille lensemble des mains :
sage: Mains.cardinality()
2598960
La force dune main de poker dpend de la combinaison de ses cartes. Une de
ces combinaisons est la couleur ; il sagit dune main dont toutes les cartes ont le
mme symbole (en principe il faut exclure les quintes flush ; ce sera lobjet dun
exercice ci-dessous). Une telle main est donc caractrise par le choix dun symbole
parmi les quatre possibles et le choix de cinq valeurs parmi les treize possibles.
Construisons lensemble de toutes les couleurs, pour en calculer le nombre :
sage: Couleurs = CartesianProduct(Subsets(Valeurs, 5), Symboles)
sage: Couleurs.cardinality()
5148
La probabilit dobtenir une couleur en tirant une main au hasard est donc
de :
sage: Couleurs.cardinality() / Mains.cardinality()
33/16660
soit denviron deux sur mille :
sage: 1000.0 * Couleurs.cardinality() / Mains.cardinality()
1.98079231692677
Faisons une petite simulation numrique. La fonction suivante teste si une
main donne est une couleur :
sage: def est_couleur(main):
....: return len(set(symb for (val, symb) in main)) == 1
Nous tirons maintenant 10000 mains au hasard, et comptons le nombre de couleurs
obtenues (cela prend environ 10 secondes) :
326 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

F F F F
F F F F
F F F F F F F F F F F F

Figure 15.1 Les cinq arbres binaires complets quatre feuilles.

sage: n = 10000; ncouleurs = 0


sage: for i in range(n):
....: main = Mains.random_element()
....: if est_couleur(main):
....: ncouleurs += 1
sage: print n, ncouleurs
10000 18
Exercice 48. Une main contenant quatre cartes de la mme valeur est appele un
carr. Construire lensemble des carrs (indication : utiliser Arrangements pour tirer au
hasard un couple de valeurs distinctes puis choisir un symbole pour la premire valeur).
Calculer le nombre de carrs, en donner la liste, puis dterminer la probabilit dobtenir
un carr en tirant une main au hasard.
Exercice 49. Une main dont les cartes ont toutes le mme symbole et dont les
valeurs se suivent est appele une quinte flush et non une couleur. Compter le nombre
de quintes flush, puis en dduire la probabilit correcte dobtenir une couleur en tirant
une main au hasard.
Exercice 50. Calculer la probabilit de chacune des combinaisons de cartes au poker
(voir http://fr.wikipedia.org/wiki/Main_au_poker) et comparer avec le rsultat de
simulations.

15.1.2 Dnombrement darbres par sries gnratrices


Dans cette section, nous traitons lexemple des arbres binaires complets, et
illustrons sur cet exemple plusieurs techniques de dnombrement o le calcul
formel intervient naturellement. Ces techniques sont en fait gnrales, sappliquant
chaque fois que les objets combinatoires considrs admettent une dfinition r-
cursive (grammaire) (voir 15.4.3 pour un traitement automatis). Lobjectif nest
pas de prsenter ces mthodes formellement ; aussi les calculs seront rigoureux
mais la plupart des justifications seront passes sous silence. Les prrequis aug-
mentent progressivement et le lecteur ne doit pas hsiter lire certains passages
en diagonale pour parvenir jusqu la synthse.
Un arbre binaire complet est soit une feuille F, soit un nud sur lequel on a
greff deux arbres binaires complets (voir figure 15.1).
Exercice 51. Chercher la main tous les arbres binaires complets n = 1, 2, 3, 4, 5
feuilles (voir lexercice 59 pour les chercher avec Sage).
Notre objectif est de compter le nombre cn darbres binaires complets n
feuilles (dans cette section, tous les arbres sont binaires complets). Cest une
situation typique o lon ne sintresse pas seulement un ensemble isol, mais
une famille densembles, typiquement paramtre par n N.
15.1. PREMIERS EXEMPLES 327

Daprs lexercice 51, les premiers termes sont donns par

c1 , . . . , c5 = 1, 1, 2, 5, 14.

Le simple fait davoir ces quelques nombres est dj prcieux. En effet, ils per-
mettent une recherche dans une mine dor : lencyclopdie en ligne des suites de
nombres entiers http://oeis.org/ appele communment le Sloane , du nom
de son auteur principal, et qui contient plus de 190000 suites dentiers 2 :
sage: sloane_find([1,1,2,5,14])
Searching Sloane's online database...
[[108, 'Catalan numbers: C(n) = binomial(2n,n)/(n+1) ...
Le rsultat suggre que les arbres sont compts par lune des plus fameuses
suites, les nombres de Catalan. En fouillant dans les rfrences fournies par
lencyclopdie, on trouverait que cest effectivement le cas : les quelques nombres
ci-dessus forment une empreinte digitale de nos objets, qui permet de retrouver
en quelques secondes un rsultat prcis dans une abondante littrature.

Dnombrement par sries gnratrices. Notre objectif est de retrouver ce


rsultat avec laide de Sage. Soit Cn lensemble des arbres n feuilles, de sorte
que cn = |Cn | ; par convention, on dfinira C0 = , soit c0 = 0. Lensemble de
tous les arbres est alors lunion disjointe des Cn :
]
C= Cn .
nN

Du fait davoir nomm lensemble C de tous les arbres, on peut traduire la


dfinition rcursive des arbres en une quation ensembliste :

C {F} ] C C.

En effet, un arbre t (donc dans C) est soit une feuille (donc dans {F}) soit un
nud sur lequel on a greff deux arbres t1 et t2 et que lon peut donc identifier
avec le couple (t1 , t2 ) (donc dans le produit cartsien C C).
Lide fondatrice de la combinatoire algbrique, introduite par Euler dans
une lettre Goldbach en 1751 pour traiter un problme similaire [Vie07], est de
manipuler simultanment tous les nombres cn en les encodant sous la forme dune
srie formelle, dite srie gnratrice des cn :
X
C(z) = cn z n ,
nN

o z est une indtermine formelle (on na donc pas besoin de se proccuper


de questions de convergence). La beaut de cette ide est que les oprations
ensemblistes (A ] B, A B) se traduisent naturellement en oprations algbriques
2. La commande sloane_find est en panne dans Sage 5.9 (voir http://trac.sagemath.org/
sage_trac/ticket/10358) ; mais on peut toujours consulter le site web directement.
328 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

sur les sries (A(z)+B(z), A(z)B(z)), de sorte que lquation ensembliste vrifie
par C se traduit en une quation algbrique sur C(z) :

C(z) = z + C(z) C(z) .

Rsolvons cette quation avec Sage. Pour cela, on introduit deux variables C
et z, et on pose le systme :
sage: C, z = var('C, z'); sys = [ C == z + C*C ]
On a alors deux solutions, qui par chance sont sous forme close :
sage: sol = solve(sys, C, solution_dict=True); sol
[{C: -1/2*sqrt(-4*z + 1) + 1/2}, {C: 1/2*sqrt(-4*z + 1) + 1/2}]
sage: s0 = sol[0][C]; s1 = sol[1][C]
et dont les dveloppements de Taylor commencent par :
sage: s0.series(z, 6)
1*z + 1*z^2 + 2*z^3 + 5*z^4 + 14*z^5 + Order(z^6)
sage: s1.series(z, 6)
1 + (-1)*z + (-1)*z^2 + (-2)*z^3 + (-5)*z^4 + (-14)*z^5 + Order(z^6)
La deuxime solution est clairement aberrante ; par contre, on retrouve les coeffi-
cients prvus sur la premire. Posons donc :
sage: C = s0
On peut maintenant calculer les termes suivants :
sage: C.series(z, 11)
1*z + 1*z^2 + 2*z^3 + 5*z^4 + 14*z^5 + 42*z^6 +
132*z^7 + 429*z^8 + 1430*z^9 + 4862*z^10 + Order(z^11)
ou calculer quasi instantanment le 100-ime coefficient :
sage: C.series(z, 101).coeff(z,100)
227508830794229349661819540395688853956041682601541047340
Il est cependant dommage de devoir tout recalculer si jamais on voulait le
101-ime coefficient. Les sries formelles paresseuses (voir 7.5.3) prennent alors
tout leur sens, dautant que lon peut les dfinir directement partir du systme
dquations, sans le rsoudre, et donc en particulier sans avoir besoin de forme
close pour le rsultat. On commence par dfinir lanneau des sries formelles
paresseuses :
sage: L.<z> = LazyPowerSeriesRing(QQ)
Puis on cre une srie formelle libre , laquelle on donne un nom, et que lon
dfinit ensuite par une quation rcursive :
sage: C = L()
sage: C._name = 'C'
sage: C.define( z + C * C )
15.1. PREMIERS EXEMPLES 329

sage: [C.coefficient(i) for i in range(11)]


[0, 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]
On peut dsormais qurir un coefficient quelconque sans avoir redfinir C :
sage: C.coefficient(100)
227508830794229349661819540395688853956041682601541047340

sage: C.coefficient(200)
1290131580644291140012229076696766751343495305527288824998
10851598901419013348319045534580850847735528275750122188940

Relation de rcurrence et forme close. Nous revenons maintenant la


forme close pour C(z) :
sage: z = var('z'); C = s0; C
-1/2*sqrt(-4*z + 1) + 1/2
Le n-ime coefficient du dveloppement de Taylor de C(z) tant donn par
1
n! C
(n)
(0), regardons les drives successives C (n) (z) :
sage: derivative(C, z, 1)
1/sqrt(-4*z + 1)
sage: derivative(C, z, 2)
2/(-4*z + 1)^(3/2)
sage: derivative(C, z, 3)
12/(-4*z + 1)^(5/2)
Cela suggre lexistence dune formule explicite simple que lon recherche mainte-
nant. La petite fonction suivante renvoie dn = n! cn :
sage: def d(n): return derivative(C, n).subs(z=0)
En prenant les quotients successifs :
sage: [ (d(n+1) / d(n)) for n in range(1,17) ]
[2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62]
on constate que dn satisfait la relation de rcurrence dn+1 = (4n 2)dn , do lon
dduit que cn satisfait la relation de rcurrence cn+1 = 4n2
n+1 cn . En simplifiant,
on obtient alors que cn est le (n 1)-ime nombre de Catalan :

1 2(n 1)
 
cn = Catalan(n 1) = .
n n1

Vrifions cela :
sage: def c(n): return 1/n*binomial(2*(n-1),n-1)
sage: [c(k) for k in range(1, 11)]
[1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]
sage: [catalan_number(k-1) for k in range(1, 11)]
[1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]
330 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

On peut maintenant calculer les coefficients beaucoup plus loin ; ici on calcule
c100000 qui a plus de 60000 chiffres :
sage: %time cc = c(100000)
CPU times: user 2.34 s, sys: 0.00 s, total: 2.34 s
Wall time: 2.34 s
sage: ZZ(cc).ndigits()
60198

Traitement systmatique par quations algbrico-diffrentielles. Les


mthodes que nous avons utilises se gnralisent tous les objets dfinis rcursi-
vement : le systme dquations ensembliste se traduit en un systme dquations
sur la srie gnratrice ; celui-ci permet de calculer rcursivement ses coefficients.
Lorsque les quations ensemblistes sont suffisamment simples (par exemple ne
font intervenir que des produits cartsiens et unions disjointes), on obtient une
quation algbrique en C(z). Celle-ci nadmet gnralement pas une solution en
forme close ; cependant, on peut en dduire par confinement une quation diffren-
tielle linaire sur C(z), qui elle-mme se traduit en une quation de rcurrence de
longueur fixe sur les coefficients cn (la srie est alors dite D-finie). Au final, aprs
le prcalcul de cette quation de rcurrence, le calcul des coefficients devient trs
rapide. Toutes ces tapes sont purement algorithmiques, et il est prvu de porter
vers Sage les implantations existantes dans Maple (paquets gfun et combstruct)
ou MuPAD-Combinat (bibliothque decomposableObjects).
Pour linstant, nous nous contentons dillustrer cette procdure gnrale dans
le cas des arbres binaires complets. La srie gnratrice C(z) est solution dune
quation algbrique P (z, C(z)) = 0, o P (x, y) = y 2 y + x est un polynme
coefficients dans Q. Drivons formellement cette quation algbrique par rapport
z:
sage: x, y, z = var('x, y, z')
sage: P = function('P', x, y); C = function('C', z)
sage: equation = P(x=z, y=C) == 0
sage: diff(equation, z)
D[0](C)(z)*D[1](P)(z, C(z)) + D[0](P)(z, C(z)) == 0
ou, de manire plus lisible,

dC(z) P P
(z, C(z)) + (z, C(z)) = 0
dz y x

Do lon tire :
P
dC(z)
= P
x
(z, C(z)) .
dz y

Dans le cas des arbres binaires complets, cela donne :


sage: P = y^2 - y + x; Px = diff(P, x); Py = diff(P, y)
sage: - Px / Py
-1/(2*y - 1)
15.1. PREMIERS EXEMPLES 331

Or, P (x, y) = 0. On peut donc calculer cette fraction modulo P , et ainsi exprimer
la drive de C(z) comme un polynme en C(z) coefficients dans Q(z). Pour
cela, on construit lanneau quotient R = Q(x)[y]/(P ) :
sage: Qx = QQ['x'].fraction_field(); Qxy = Qx['y']
sage: R = Qxy.quo(P); R
Univariate Quotient Polynomial Ring in ybar
over Fraction Field of Univariate Polynomial Ring in x
over Rational Field with modulus y^2 - y + x
Note : ybar est le nom de la variable y dans le quotient ; pour plus dinformations
sur les anneaux quotients, voir 7.2.2. Reprenons maintenant le calcul de cette
fraction dans R :

sage: fraction = - R(Px) / R(Py); fraction


(1/2/(x - 1/4))*ybar - 1/4/(x - 1/4)
Remontons le rsultat dans Q(x)[y], puis substituons z et C(z) pour obtenir
lexpression de dz
d
C(z) :
sage: fraction = fraction.lift(); fraction
(1/2/(x - 1/4))*y - 1/4/(x - 1/4)
sage: fraction(x=z, y=C)
2*C(z)/(4*z - 1) - 1/(4*z - 1)
o, plus lisiblement,

C(z) 1 2
= C(z) .
z 1 4z 1 4z
Dans ce cas simple, on peut en tirer directement une quation diffrentielle linaire
coefficients dans Q[z] :
sage: equadiff = diff(C,z) == fraction(x=z, y=C); equadiff
D[0](C)(z) == 2*C(z)/(4*z - 1) - 1/(4*z - 1)
sage: equadiff = equadiff.simplify_rational()
sage: equadiff = equadiff * equadiff.rhs().denominator()
sage: equadiff = equadiff - equadiff.rhs()
sage: equadiff
(4*z - 1)*D[0](C)(z) - 2*C(z) + 1 == 0
ou, plus lisiblement,

C(z)
(1 4z) + 2C(z) 1 = 0 .
z
On peut la vrifier trivialement ici sur la forme close :

sage: Cf = sage.symbolic.function_factory.function('C')
sage: bool(equadiff.substitute_function(Cf, s0))
True
332 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

Dans le cas gnral, on doit poursuivre le calcul des drives successives de


C(z). Mais celles-ci sont confines dans lanneau quotient Q(z)[C]/(P ) qui est
de dimension finie degy P sur Q(z). On finit donc ncessairement par trouver
une relation linaire entre les degy P premires drives de C(z). En rduisant au
mme dnominateur, on obtient une quation diffrentielle linaire coefficients
dans Q[z] dordre 6 degy P . En extrayant le coefficient de z n dans lquation
diffrentielle, on obtient lquation de rcurrence dsire sur les coefficients ; on
retrouve ici celle que nous avions obtenue partir de la forme close :
4n 2
cn+1 = cn .
n+1
En insrant les bonnes conditions initiales, on peut alors calculer les coefficients
de C(z) rcursivement :
sage: def C(n): return n if n <= 1 else (4*n-6)/n * C(n-1)
sage: [ C(i) for i in range(10) ]
[0, 1, 1, 2, 5, 14, 42, 132, 429, 1430]
Lorsque n devient trop grand pour calculer cn explicitement, on peut recher-
cher un quivalent asymptotique de la suite des coefficients cn . L encore, les
techniques sont gnriques. Loutil central est lanalyse complexe, avec ltude
du comportement de la srie gnratrice aux alentours de ses singularits. Ici la
n1
singularit est z0 = 1/4 et on obtiendrait cn n43/2 .

Synthse. On retrouve ici un phnomne gnral du calcul formel : la meilleure


structure de donne pour dcrire un objet mathmatique compliqu (un nombre
rel, une suite, une srie formelle, une fonction, un ensemble) est souvent une
quation (ou un systme dquations, typiquement avec des conditions initiales)
qui le dfinit. Chercher rsoudre cette quation par une forme close na pas
forcment dintrt : dune part une telle forme existe rarement (cf. problme de
rsolution par radicaux), et dautre part lquation en elle-mme contient toute
linformation ncessaire pour calculer algorithmiquement les proprits de lobjet
considr (une approximation numrique, les premiers termes ou lments, un
quivalent asymptotique), ou calculer avec lobjet lui-mme (cf. arithmtique sur
les sries). Au lieu de cela, on recherche la meilleure quation dcrivant lobjet
pour rsoudre le problme pos ; voir aussi 2.2.2.
Ainsi que nous lavons vu dans cet exemple, le confinement (par exemple dans
un espace de dimension finie) est un outil fondamental pour rechercher de telles
quations. Ce confinement sappuie gnralement sur des techniques dlimination
(algbre linaire, bases de Grbner et gnralisations algbrico-diffrentielles).
Le mme outil est central dans les algorithmes de sommation symbolique ou de
vrification automatique didentits (algorithmes de Gosper, de Zeilberger et leurs
gnralisations [PWZ96] ; voir aussi les exemples en 2.3.1 et exercice 54).
Toutes ces techniques et leurs multiples gnralisations sont au cur de
thmes trs actifs de recherche : la combinatoire automatique et la combinatoire
analytique, avec des applications majeures pour lanalyse dalgorithmes [FS09]. Il
est probable et souhaitable quelles soient progressivement implantes dans Sage.
15.2. ENSEMBLES NUMRS USUELS 333

15.2 Ensembles numrs usuels


15.2.1 Exemple : les sous-ensembles dun ensemble
Fixons un ensemble E de taille n et considrons les sous-ensembles de E
de taille k. On
 sait que ces sous-ensembles sont compts par les coefficients
binomiaux nk . On peut donc calculer le nombre de sous-ensembles de taille k = 2
de E = {1, 2, 3, 4} avec la fonction binomial :
sage: binomial(4, 2)
6
Alternativement, on peut construire lensemble P2 (E) des sous-ensembles de
taille 2 de E, puis lui demander sa cardinalit :
sage: S = Subsets([1,2,3,4], 2); S.cardinality()
6
Une fois S construit, on peut aussi obtenir la liste de ses lments, tirer un
lment au hasard, ou demander un lment typique :
sage: S.list()
[{1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}]
sage: S.random_element()
{1, 4}
sage: S.an_element()
{2, 3}
Plus prcisment, lobjet S modlise lensemble P2 (E), muni dune numration
fixe (donne ici par lordre lexicographique). On peut donc demander son 5-ime
lment, en prenant garde au fait que, comme pour les listes Python, le premier
lment est de rang 0 ( titre de raccourci, on peut utiliser ici la notation S[.]) :
sage: S.unrank(4)
{2, 4}
sage: S[4]
{2, 4}
mais cela est utiliser avec prudence car certains ensembles sont munis dune
indexation naturelle diffrente.
Rciproquement, on peut calculer le rang dun objet dans cette numration :
sage: s = S([2,4]); S.rank(s)
4
noter que S nest pas la liste de ses lments. On peut par exemple modliser
24
lensemble P(P(P(E))) et calculer sa cardinalit (22 ) :
sage: E = Set([1,2,3,4])
sage: S = Subsets(Subsets(Subsets(E))); S.cardinality()
2003529930406846464979072351560255750447825475569751419265016...736
soit environ 2 1019728 :
334 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

sage: S.cardinality().ndigits()
19729
ou demander son 237 102 124-ime lment :
sage: S.unrank(237102123)
{{{2}, {3}, {1, 2, 3, 4}, {1, 2}, {1, 4}, {}, {2, 3, 4},
{1, 2, 4}, {3, 4}, {4}, {2, 3}, {1, 2, 3}},
{{2}, {3}, {1, 2, 3, 4}, {1, 2}, {1, 4}, {2, 3, 4},
{3, 4}, {1, 3, 4}, {1}, {1, 3}, {1, 2, 3}}}

Il serait physiquement impossible de construire explicitement tous les lments


de S car il y en a bien plus que de particules dans lunivers (estimes 1082 ).
Remarque : il serait naturel avec Python dutiliser len(S) pour demander
la cardinalit de S. Cela nest pas possible car Python impose que le rsultat
de len soit un entier de type int ; cela pourrait causer des dbordements et ne
permettrait pas de renvoyer Infinity pour les ensembles infinis.
sage: len(S)
Traceback (most recent call last):
...
AttributeError: __len__ has been removed; use .cardinality() instead

15.2.2 Partitions dentiers


Nous considrons maintenant un autre problme classique : tant donn un
entier positif n, de combien de faons peut-on lcrire sous la forme dune somme
n = i1 + i2 + + i` , o i1 , . . . , i` sont des entiers strictement positifs ? Il y a
deux cas distinguer :
lordre des lments dans la somme na pas dimportance, auquel cas
(i1 , . . . , i` ) est une partition de n ;
lordre des lments dans la somme revt une importance, auquel cas
(i1 , . . . , i` ) est une composition de n.
Regardons pour commencer les partitions de n = 5 ; comme prcdemment,
on commence par construire lensemble de ces partitions :
sage: P5 = Partitions(5); P5
Partitions of the integer 5
puis on demande sa cardinalit :
sage: P5.cardinality()
7
Regardons ces 7 partitions ; lordre nayant pas dimportance, les entres sont
tries, par convention, par ordre dcroissant :
sage: P5.list()
[[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1],
[1, 1, 1, 1, 1]]
15.2. ENSEMBLES NUMRS USUELS 335

Le calcul du nombre de partitions utilise la formule de Rademacher 3 , implante


en C et fortement optimise, ce qui lui confre une grande rapidit :
sage: Partitions(100000).cardinality()
2749351056977569651267751632098635268817342931598005475820312598430214
7328114964173055050741660736621590157844774296248940493063070200461792
7644930335101160793424571901557189435097253124661084520063695589344642
4871682878983218234500926285383140459702130713067451062441922731123899
9702284408609370935531629697851569569892196108480158600569421098519

Les partitions dentiers sont des objets combinatoires naturellement munis de


multiples oprations. Elles sont donc renvoyes sous la forme dobjets plus riches
que de simples listes :
sage: P7 = Partitions(7); p = P7.unrank(5); p
[4, 2, 1]

sage: type(p)
<class 'sage.combinat.partition.Partitions_n_with_category.element_class
'>
On peut les reprsenter graphiquement par un diagramme de Ferrers :
sage: print p.ferrers_diagram()
****
**
*
Nous laissons lutilisateur explorer par introspection les oprations offertes.
On peut aussi construire une partition directement comme suit :
sage: Partition([4,2,1])
[4, 2, 1]
sage: P7([4,2,1])
[4, 2, 1]
Si lon souhaite restreindre les valeurs possibles pour les parts i1 , . . . , i` de la
partition, comme par exemple dans les problmes de rendu de monnaie, on peut
utiliser WeightedIntegerVectors. Par exemple, le calcul suivant :
sage: WeightedIntegerVectors(8, [2,3,5]).list()
[[0, 1, 1], [1, 2, 0], [4, 0, 0]]
indique que pour former 8 dollars partir de billets de 2$, 3$ et 5$, on peut
utiliser un billet de 3$ et un de 5$, ou un billet de 2$ et deux de 3$, ou quatre
billets de 2$.
Les compositions dentiers se manipulent de la mme faon :
sage: C5 = Compositions(5); C5
Compositions of 5
3. Voir http://fr.wikipedia.org/wiki/Partition_d%27un_entier
336 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

sage: C5.cardinality()
16
sage: C5.list()
[[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 2, 1], [1, 1, 3],
[1, 2, 1, 1], [1, 2, 2], [1, 3, 1], [1, 4], [2, 1, 1, 1],
[2, 1, 2], [2, 2, 1], [2, 3], [3, 1, 1], [3, 2], [4, 1], [5]]
Le 16 ci-dessus ne parat pas anodin et suggre lexistence dune ventuelle
formule. Regardons donc le nombre de compositions pour n variant de 0 9 :
sage: [ Compositions(n).cardinality() for n in range(10) ]
[1, 1, 2, 4, 8, 16, 32, 64, 128, 256]
De mme, si lon compte le nombre de compositions de 5 par longueur, on retrouve
une ligne du triangle de Pascal :
sage: x = var('x'); sum( x^len(c) for c in C5 )
x^5 + 4*x^4 + 6*x^3 + 4*x^2 + x
Lexemple ci-dessus utilise une fonctionnalit que lon navait pas encore
croise : C5 tant itrable, on peut lutiliser comme une liste dans une boucle for
ou une comprhension (15.2.4).
Exercice 52. Dmontrer les formules suggres par les exemples ci-dessus pour
le nombre de compositions de n et le nombre de compositions de n de longueur k et
chercher par introspection si Sage utilise ces formules pour le calcul de cardinalit.

15.2.3 Quelques autres ensembles finis numrs


Au final, le principe est le mme pour tous les ensembles finis sur lesquels on
veut faire de la combinatoire avec Sage ; on commence par construire un objet qui
modlise cet ensemble puis on utilise les mthodes idoines qui suivent une interface
uniforme 4 . Nous donnons maintenant quelques autres exemples typiques.
Les intervalles dentiers :
sage: C = IntegerRange(3, 21, 2); C
{3, 5, .., 19}
sage: C.cardinality()
9
sage: C.list()
[3, 5, 7, 9, 11, 13, 15, 17, 19]
Les permutations :
sage: C = Permutations(4); C
Standard permutations of 4
sage: C.cardinality()
24
sage: C.list()

4. Ou en tout cas cela devrait tre le cas ; il reste de nombreux coins nettoyer.
15.2. ENSEMBLES NUMRS USUELS 337

[[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2],


[1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3],
[2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1],
[3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1],
[3, 4, 1, 2], [3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2],
[4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]]

1 2 3 4 5

Figure 15.2 Un ordre partiel sur 8 sommets.

Les partitions ensemblistes :


sage: C = SetPartitions([1,2,3]); C
Set partitions of {1, 2, 3}
sage: C.cardinality()
5
sage: C.list()
[{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{1}, {2},
{3}}]
Les ordres partiels sur 8 sommets, un isomorphisme prs :
sage: C = Posets(8); C
Posets containing 8 vertices
sage: C.cardinality()
16999
Reprsentons graphiquement lun de ces ordres (voir figure 15.2) :
sage: C.unrank(20).plot()
338 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

Figure 15.3 Les graphes simples 5 sommets avec 4 artes ou moins.

Il est aussi possible ditrer parmi tous les graphes un isomorphisme prs. Il
y a par exemple 34 graphes simples 5 sommets :
sage: len(list(graphs(5)))
34
Voici comment obtenir ceux ayant au plus 4 artes (figure 15.3) :
sage: show(graphs(5, lambda G: G.size() <= 4))
Cependant lensemble C de ces graphes nest pas encore modlis dans Sage ;
de ce fait, les commandes suivantes ne sont pas encore implantes :
sage: C = Graphs(5); C.cardinality()
34
sage: Graphs(19).cardinality()
24637809253125004524383007491432768
sage: Graphs(19).random_element()
Graph on 19 vertices
Ce que lon a vu sapplique aussi, en principe, aux structures algbriques finies
comme le groupe dihdral :
sage: G = DihedralGroup(4); G
15.2. ENSEMBLES NUMRS USUELS 339

Dihedral group of order 8 as a permutation group


sage: G.cardinality()
8
sage: G.list()
[(), (2,4), (1,2)(3,4), (1,2,3,4), (1,3), (1,3)(2,4), (1,4,3,2),
(1,4)(2,3)]
ou lalgbre des matrices 2 2 sur le corps fini Z/2Z :

sage: C = MatrixSpace(GF(2), 2); C.list()


[
[0 0] [1 0] [0 1] [0 0] [0 0] [1 1] [1 0] [1 0] [0 1]
[0 0], [0 0], [0 0], [1 0], [0 1], [0 0], [1 0], [0 1], [1 0],

[0 1] [0 0] [1 1] [1 1] [1 0] [0 1] [1 1]
[0 1], [1 1], [1 0], [0 1], [1 1], [1 1], [1 1]
]
Cependant ceci devrait renvoyer 16, mais nest pas encore implant :
sage: C.cardinality()
Traceback (most recent call last):
...
AttributeError: 'MatrixSpace' object has no attribute 'cardinality'
Exercice 53. numrer tous les monmes de degr 5 dans les polynmes en
trois variables (voir IntegerVectors). Manipuler les partitions ensemblistes ordonnes
(OrderedSetPartitions) et les tableaux standard (StandardTableaux).
Exercice 54. numrer les matrices signe alternant (AlternatingSignMatrices)
de taille 3, 4 et 5, et essayer de deviner leur dfinition. La dcouverte et la dmonstration
de la formule de dnombrement de ces matrices (voir la mthode cardinality), motive
par des calculs de dterminants en physique, a t lobjet de toute une pope. En
particulier la premire dmonstration, donne par Zeilberger en 1992, a t produite
automatiquement par un programme, occupe 84 pages, et a ncessit lintervention de
presque cent vrificateurs [Zei96].
Exercice 55. Calculer la main le nombre de vecteurs dans (Z/2Z)5 puis le nombre
de matrices dans GL3 (Z/2Z) (cest--dire le nombre de matrices 3 3 coefficients dans
Z/2Z et inversibles). Vrifier votre rponse avec Sage. Gnraliser GLn (Z/qZ).

15.2.4 Comprhensions et itrateurs


Nous allons maintenant montrer quelques possibilits offertes par Python pour
construire (et itrer sur) des ensembles avec une notation flexible et proche des
mathmatiques, et le profit que lon peut en tirer en combinatoire.
Commenons par construire lensemble fini {i2 | i {1, 3, 7}} :
sage: [ i^2 for i in [1, 3, 7] ]
[1, 9, 49]
puis le mme ensemble avec i variant cette fois entre 1 et 9 :
340 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

sage: [ i^2 for i in range(1,10) ]


[1, 4, 9, 16, 25, 36, 49, 64, 81]
On appelle comprhension une telle construction Python. On peut ajouter un
prdicat pour ne garder que les lments avec i premier :
sage: [ i^2 for i in range(1,10) if is_prime(i) ]
[4, 9, 25, 49]
En combinant plusieurs comprhensions, on peut construire lensemble des
couples (i, j) avec 1 6 j < i < 5 :
sage: [ (i,j) for i in range(1,6) for j in range(1,i) ]
[(2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (4, 3),
(5, 1), (5, 2), (5, 3), (5, 4)]
ou bien afficher le triangle de Pascal :
sage: [[binomial(n, i) for i in range(n+1)] for n in range(10)]
[[1],
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1],
[1, 5, 10, 10, 5, 1],
[1, 6, 15, 20, 15, 6, 1],
[1, 7, 21, 35, 35, 21, 7, 1],
[1, 8, 28, 56, 70, 56, 28, 8, 1],
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]]
Lexcution dune comprhension se fait en deux tapes ; tout dabord un
itrateur est construit, puis une liste est remplie avec les lments renvoys
successivement par litrateur. Techniquement, un itrateur est un objet avec une
mthode next qui renvoie chaque appel une nouvelle valeur, jusqu puisement.
Par exemple, litrateur it suivant :
sage: it = (binomial(3, i) for i in range(4))
renvoie successivement les coefficients binomiaux 3
avec i = 0, 1, 2, 3 :

i

sage: it.next()
1
sage: it.next()
3
sage: it.next()
3
sage: it.next()
1
Lorsque litrateur est finalement puis, une exception est leve :
sage: it.next()
15.2. ENSEMBLES NUMRS USUELS 341

Traceback (most recent call last):


...
StopIteration

Plus gnralement, un itrable est un object Python L (une liste, un ensemble...)


sur les lments duquel on peut itrer ; techniquement, on construit litrateur
avec iter(L). Dans la pratique, on nutilise que trs rarement iter ou next, les
boucles for et les comprhensions fournissant une syntaxe bien plus agrable :
sage: for s in Subsets(3): s
{}
{1}
{2}
{3}
{1, 2}
{1, 3}
{2, 3}
{1, 2, 3}

sage: [ s.cardinality() for s in Subsets(3) ]


[0, 1, 1, 1, 2, 2, 2, 3]

Quel est lintrt dun itrateur ? Considrons lexemple suivant :


sage: sum( [ binomial(8, i) for i in range(9) ] )
256

lexcution, une liste avec 9 lments est construite, puis elle est passe en
argument sum pour les ajouter. Si au contraire on passe directement litrateur
sum (noter labsence de crochets) :
sage: sum( binomial(8, i) for i in xrange(9) )
256

la fonction sum reoit directement litrateur, et peut ainsi court-circuiter la


construction de la liste intermdiaire. Lorsquil y a un grand nombre dlments,
cela vite donc dallouer une grosse quantit de mmoire pour stocker une liste
qui sera immdiatement dtruite 5 .
La plupart des fonctions prenant une liste dlments en entre acceptent un
itrateur (ou un itrable) la place. Et pour commencer, on peut obtenir la liste
(ou le tuple) des lments dun itrateur avec :
sage: list(binomial(8, i) for i in xrange(9))
[1, 8, 28, 56, 70, 56, 28, 8, 1]
sage: tuple(binomial(8, i) for i in xrange(9))
(1, 8, 28, 56, 70, 56, 28, 8, 1)

5. Dtail technique : xrange renvoie un itrateur sur {0,...,8} alors que range en renvoie
la liste. partir de Python 3.0, range se comportera comme xrange, et on pourra oublier ce
dernier.
342 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

Considrons maintenant les fonctions all et any (qui dnotent respectivement


le et et le ou n-aire) :
sage: all([True, True, True, True])
True
sage: all([True, False, True, True])
False
sage: any([False, False, False, False])
False
sage: any([False, False, True, False])
True
Lexemple suivant vrifie que tous les entiers premiers entre 3 et 99 sont
impairs :
sage: all( is_odd(p) for p in xrange(3,100) if is_prime(p) )
True
Les nombres de Mersenne Mp sont les nombres de la forme 2p 1. Ici nous
vrifions, pour p < 1000, que si Mp est premier alors p est premier aussi :
sage: def mersenne(p): return 2^p - 1
sage: [ is_prime(p) for p in range(1000) if is_prime(mersenne(p)) ]
[True, True, True, True, True, True, True, True, True, True,
True, True, True, True]
La rciproque est-elle vraie ?
Exercice 56. Essayer les deux commandes suivantes et expliquer la diffrence
considrable de temps de calcul :
sage: all( [ is_prime(mersenne(p)) for p in range(1000) if is_prime(p)] )
False
sage: all( is_prime(mersenne(p)) for p in range(1000) if is_prime(p) )
False
On cherche maintenant trouver le plus petit contre-exemple. Pour cela on
utilise la fonction Sage exists :
sage: exists( (p for p in range(1000) if is_prime(p)),
....: lambda p: not is_prime(mersenne(p)) )
(True, 11)
Alternativement, on peut construire un itrateur sur tous les contre-exemples :
sage: contre_exemples = (p for p in range(1000) \
....: if is_prime(p) and not is_prime(mersenne(p)))
sage: contre_exemples.next()
11
sage: contre_exemples.next()
23
Exercice 57. Que font les commandes suivantes ?
sage: cubes = [t**3 for t in range(-999,1000)]
15.2. ENSEMBLES NUMRS USUELS 343

sage: exists([(x,y) for x in cubes for y in cubes], lambda (x,y): x+y == 218)
sage: exists(((x,y) for x in cubes for y in cubes), lambda (x,y): x+y == 218)
Laquelle des deux dernires est-elle la plus conome en temps ? En mmoire ? De
combien ?
Exercice 58. Essayer tour tour les commandes suivantes, et expliquer leurs
rsultats. Attention : il sera ncessaire dinterrompre lexcution de certaines de ces
commandes en cours de route.
sage: x = var('x'); sum( x^len(s) for s in Subsets(8) )

sage: sum( x^p.length() for p in Permutations(3) )

sage: factor(sum( x^p.length() for p in Permutations(3) ))

sage: P = Permutations(5)
sage: all( p in P for p in P )

sage: for p in GL(2, 2): print p; print

sage: for p in Partitions(3): print p

sage: for p in Partitions(): print p

sage: for p in Primes(): print p

sage: exists( Primes(), lambda p: not is_prime(mersenne(p)) )

sage: contre_exemples = (p for p in Primes() if not is_prime(mersenne(p)))


sage: for p in contre_exemples: print p

Oprations sur les itrateurs. Python fournit de nombreux utilitaires pour


manipuler des itrateurs ; la plupart dentre eux font partie de la bibliothque
itertools que lon peut importer avec :
sage: import itertools
Nous en montrons quelques applications, en prenant comme point de dpart
lensemble des permutations de 3 :
sage: list(Permutations(3))
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
Nous pouvons numrer les lments dun ensemble en les numrotant,
sage: list(enumerate(Permutations(3)))
[(0, [1, 2, 3]), (1, [1, 3, 2]), (2, [2, 1, 3]),
(3, [2, 3, 1]), (4, [3, 1, 2]), (5, [3, 2, 1])]
slectionner les lments en position 2, 3 et 4 (analogue de l[1:4]),
sage: list(itertools.islice(Permutations(3), 1, 4))
[[1, 3, 2], [2, 1, 3], [2, 3, 1]]
344 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

appliquer une fonction sur tous les lments,


sage: list(itertools.imap(lambda z: z.cycle_type(), Permutations(3)))
[[1, 1, 1], [2, 1], [2, 1], [3], [3], [2, 1]]
ou slectionner les lments vrifiant un certain prdicat :
sage: list(itertools.ifilter(lambda z: z.has_pattern([1,2]),
....: Permutations(3)))
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2]]
Dans toutes ces situations, attrcall peut tre une alternative avantageuse la
cration dune fonction anonyme :
sage: list(itertools.imap(attrcall("cycle_type"), Permutations(3)))
[[1, 1, 1], [2, 1], [2, 1], [3], [3], [2, 1]]

Implantation de nouveaux itrateurs. Il est possible de construire trs


facilement de nouveaux itrateurs, en utilisant le mot clef yield dj vu
en 12.2.2 plutt que return dans une fonction :
sage: def f(n):
....: for i in range(n):
....: yield i
la suite du yield, lexcution nest pas arrte, mais seulement suspendue, et
prte reprendre au mme point. Le rsultat de la fonction est alors un itrateur
sur les valeurs successives renvoyes par yield :
sage: g = f(4)
sage: g.next()
0
sage: g.next()
1
sage: g.next()
2
sage: g.next()
3

sage: g.next()
Traceback (most recent call last):
...
StopIteration
En utilisation courante, cela donnera :
sage: [ x for x in f(5) ]
[0, 1, 2, 3, 4]
Ce paradigme de programmation, appel continuation, est trs utile en combi-
natoire, surtout quand on le combine avec la rcursivit. Voici comment engendrer
tous les mots de longueur ` sur un alphabet donn :
15.2. ENSEMBLES NUMRS USUELS 345

sage: def words(alphabet,l):


....: if l == 0: yield []
....: else:
....: for word in words(alphabet, l-1):
....: for l in alphabet: yield word + [l]
sage: [ w for w in words(['a','b'], 3) ]
[['a', 'a', 'a'], ['a', 'a', 'b'], ['a', 'b', 'a'], ['a', 'b', 'b'],
['b', 'a', 'a'], ['b', 'a', 'b'], ['b', 'b', 'a'], ['b', 'b', 'b']]
On peut les compter avec :
sage: sum(1 for w in words(['a','b','c','d'], 10))
1048576
Compter les mots un par un nest videmment pas une mthode efficace dans
ce cas, puisque lon pourrait utiliser la formule n` ; au moins cela ne consomme
quasiment aucune mmoire.
On considre maintenant les mots de Dyck, cest--dire les mots bien pa-
renthss en les lettres ( et ) . La fonction ci-dessous engendre tous les
mots de Dyck dune longueur donne (o la longueur est le nombre de paires de
parenthses), en utilisant la dfinition rcursive disant quun mot de Dyck est soit
vide, soit de la forme (w1 )w2 avec w1 et w2 des mots de Dyck :
sage: def dyck_words(l):
....: if l == 0: yield ''
....: else:
....: for k in range(l):
....: for w1 in dyck_words(k):
....: for w2 in dyck_words(l-k-1):
....: yield '(' + w1 + ')' + w2
Voici tous les mots de Dyck de longueur 4 :
sage: list(dyck_words(4))
['()()()()', '()()(())', '()(())()', '()(()())', '()((()))',
'(())()()', '(())(())', '(()())()', '((()))()', '(()()())',
'(()(()))', '((())())', '((()()))', '(((())))']
On retrouve, en les comptant, une suite bien connue :
sage: [ sum(1 for w in dyck_words(l)) for l in range(10) ]
[1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862]
Exercice 59. Construire un itrateur sur lensemble Cn des arbres binaires complets
n feuilles (voir 15.1.2).
Indication : Sage 5.9 na pas encore de structure de donne native pour reprsenter
des arbres binaires complets. Une manire simple de reprsenter des arbres est de dfinir
une variable formelle Leaf pour les feuilles et une fonction formelle Node darit 2 :
sage: Leaf = var('Leaf'); Node = function('Node', nargs=2)
Le deuxime arbre de la figure 15.1 peut alors tre reprsent par lexpression :
sage: tree = Node(Node(Leaf, Node(Leaf, Leaf)), Leaf)
346 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

15.3 Constructions
Nous allons voir maintenant comment construire de nouveaux ensembles
partir de briques de base. En fait, nous avons dj commenc le faire lors
de la construction de P(P(P({1, 2, 3, 4}))) dans la section prcdente, ou pour
construire des ensembles de cartes en 15.1.
Considrons un produit cartsien un peu consquent :
sage: C = CartesianProduct(Compositions(8), Permutations(20)); C
Cartesian product of Compositions of 8, Standard permutations of 20
sage: C.cardinality()
311411457046609920000
Il ne serait videmment pas envisageable de construire la liste de tous les lments
de ce produit cartsien.
Pour linstant, la construction CartesianProduct ignore les proprits al-
gbriques de ses arguments. Cela est partiellement corrig en Sage 5.9, avec la
construction cartesian_product. terme, les deux constructions seront fusion-
nes et, dans lexemple suivant, H sera la fois muni des oprations combinatoires
usuelles, mais aussi de sa structure de groupe produit :
sage: G = DihedralGroup(4)
sage: H = cartesian_product([G,G])
Nous construisons maintenant lunion disjointe de deux ensembles :
sage: C = DisjointUnionEnumeratedSets([Compositions(4),Permutations(3)])
sage: C
Disjoint union of Family (Compositions of 4, Standard permutations of 3)
sage: C.cardinality()
14
sage: C.list()
[[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1],
[4], [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
On peut faire une union disjointe de plus de deux ensembles, voire mme dune
infinit dentre eux. Nous allons construire lensemble de toutes les permutations,
vu comme lunion de tous les ensembles Pn des permutations de taille n. On
commence par construire la famille infinie F = (Pn )nN :
sage: F = Family(NonNegativeIntegers(), Permutations); F
Lazy family (Permutations(i))_{i in Non negative integers}
sage: F.keys()
Non negative integers
sage: F[1000]
Standard permutations of 1000
On peut maintenant construire lunion disjointe nN Pn :
S

sage: U = DisjointUnionEnumeratedSets(F); U
Disjoint union of
Lazy family (Permutations(i))_{i in Non negative integers}
15.4. ALGORITHMES GNRIQUES 347

Cest un ensemble infini :


sage: U.cardinality()
+Infinity
ce qui nempche pas ditrer travers ses lments, quoiquil faille bien entendu
interrompre le calcul un moment donn :
sage: for p in U: p
[]
[1]
[1, 2]
[2, 1]
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
...
Note : on aurait pu construire lensemble ci-dessus directement avec :
sage: U = Permutations(); U
Standard permutations

Synthse. En rsum, Sage fournit une bibliothque densembles numrs


usuels, qui peuvent tre combins entre eux par les constructions usuelles, ce
qui donne une bote outils flexible, quoique encore loin dtre aboutie. Il est
de plus possible dajouter en quelques lignes de nouvelles briques dans Sage
(voir le code de FiniteEnumeratedSets().example). Cela est rendu possible par
luniformit des interfaces et le fait que Sage soit bas sur un langage orient
objet. Dautre part, on peut manipuler des ensembles trs grands, voire infinis,
grce aux stratgies dvaluation paresseuse (itrateurs, etc.).
Il ny a rien de magique : en arrire-boutique, Sage se contente dappliquer les
rgles usuelles de calcul (par exemple, la cardinalit de E E vaut |E|2 ) ; la valeur
ajoute provient de la possibilit de manipuler des constructions compliques.
La situation est rapprocher de lanalyse o, pour driver une formule, Sage se
contente dappliquer les rgles usuelles de drivation des fonctions usuelles et de
leur composition, et o la valeur ajoute vient de la possibilit de manipuler des
formules compliques. En ce sens, Sage implante un calculus sur les ensembles
dnombrables.

15.4 Algorithmes gnriques


15.4.1 Gnration lexicographique de listes dentiers
Parmi les ensembles numrs classiques, en particulier en combinatoire al-
gbrique, un certain nombre sont composs de listes dentiers de somme fixe
comme par exemple les partitions, les compositions ou les vecteurs dentiers. Ces
348 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

ensembles peuvent de plus avoir des contraintes supplmentaires. Voici quelques


exemples. Tout dabord, les vecteurs dentiers de somme 10 et de longueur 3,
dont les parts sont entre 2 et 5, et respectivement bornes infrieurement par 2, 4
et 2 :
sage: IntegerVectors(10, 3, min_part = 2, max_part = 5,
....: inner = [2, 4, 2]).list()
[[4, 4, 2], [3, 5, 2], [3, 4, 3], [2, 5, 3], [2, 4, 4]]
Les compositions de 5 dont chaque part est au plus 3, et dont la longueur est
entre 2 et 3 inclus :
sage: Compositions(5, max_part = 3,
....: min_length = 2, max_length = 3).list()
[[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [1, 3, 1],
[1, 2, 2], [1, 1, 3]]
Les partitions de 5 strictement dcroissantes :
sage: Partitions(5, max_slope = -1).list()
[[5], [4, 1], [3, 2]]
Ces ensembles partagent la mme algorithmique sous-jacente, implante dans la
classe plus gnrale et un peu plus lourde dutilisation IntegerListsLex.
Cette dernire permet de modliser des ensembles de vecteurs (`0 , . . . , `k ) dentiers
non ngatifs, avec des contraintes de somme, de longueur et de bornes sur les
parts et sur les diffrences entre parts conscutives. Voici quelques exemples :
sage: IntegerListsLex(10, length=3, min_part = 2, max_part = 5,
....: floor = [2, 4, 2]).list()
[[4, 4, 2], [3, 5, 2], [3, 4, 3], [2, 5, 3], [2, 4, 4]]

sage: IntegerListsLex(5, min_part = 1, max_part = 3,


....: min_length = 2, max_length = 3).list()
[[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [1, 3, 1],
[1, 2, 2], [1, 1, 3]]

sage: IntegerListsLex(5, min_part = 1, max_slope = -1).list()


[[5], [4, 1], [3, 2]]

sage: list(Compositions(5, max_length=2))


[[5], [4, 1], [3, 2], [2, 3], [1, 4]]

sage: list(IntegerListsLex(5, max_length=2, min_part=1))


[[5], [4, 1], [3, 2], [2, 3], [1, 4]]
Lintrt du modle de IntegerListsLex provient du bon compromis entre
gnralit et efficacit de litration. Lalgorithme principal permet en effet ditrer
travers les lments dun ensemble S dans lordre lexicographique inverse, et
en complexit constante amortie (CAT), sauf cas dgnr ; en gros, le temps
ncessaire pour parcourir tous les lments est proportionnel au nombre de ces
15.4. ALGORITHMES GNRIQUES 349

()

(5) (4) (3) (2) (1)

(4, 1) (3, 1) (3, 2) (2, 2) (2, 1) (1, 1)

(3, 1, 1) (2, 2, 1) (2, 1, 1) (1, 1, 1)

(2, 1, 1, 1) (1, 1, 1, 1)

(1, 1, 1, 1, 1)

Figure 15.4 Larbre prfixe des partitions de 5.

lments, ce qui est optimal. De plus, la mmoire utilise est proportionnelle au


plus gros lment rencontr, cest--dire ngligeable en pratique.
Cet algorithme repose sur un principe trs gnral de parcours darbre de
dcision (ou branch and bound) : au plus haut niveau, on parcourt tous les choix
possibles pour la premire part `0 du vecteur ; pour chaque choix pour `0 , on
parcourt rcursivement tous les choix pour `1 , et ainsi de suite. Mathmatiquement
parlant, on a mis une structure darbre prfixe sur les lments de S : un nud
de larbre la profondeur k correspond un prfixe `0 , . . . , `k dun (ou plusieurs)
lments de S (voir figure 15.4).
Le problme usuel dans ce type dapproche est dviter les mauvaises dcisions
amenant sortir de larbre prfixe et lexploration de branches mortes, ce dau-
tant que la croissance du nombre dlments avec la profondeur est exponentielle.
Il se trouve que les contraintes voques ci-dessus sont suffisamment simples pour
garantir la proprit suivante : tant donn un prfixe `0 , . . . , `k de S, lensemble
des `k+1 tels que `0 , . . . , `k+1 est un prfixe de S est soit vide, soit un intervalle
de la forme [a, b], et les bornes a et b peuvent tre calcules en temps linaire en
la longueur du plus long lment de S ayant `0 , . . . , `k comme prfixe.
noter : cet algorithme a t originellement dvelopp et implant dans
MuPAD-Combinat et port lidentique sous Sage ; cette implantation nest pas
robuste en cas dentres subtilement incohrentes, ce qui peut donner des rsultats
surprenants.
Par exemple, lexemple suivant devrait donner lensemble des partitions de 9
croissantes et strictement dcroissantes, ce que [5, 5] ne vrifie clairement pas :
sage: Partitions(9, max_slope=-1, min_slope=0).list()
[[9], [5, 5]]

15.4.2 Points entiers dans les polytopes


Si lalgorithme ditration de IntegerListsLex est efficace, son algorithme de
comptage est naf : il se contente ditrer travers tous les lments.
Il y a une approche alternative pour traiter ce problme : modliser les listes
dentiers dsires comme lensemble des points entiers dun polytope, cest--
dire lensemble des solutions coordonnes entires dun systme dinquations
350 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

linaires. Cest un cadre trs gnral pour lequel il existe des algorithmes de
comptage avancs (par exemple celui de Barvinok), qui sont implants dans des
bibliothques comme LattE. Litration ne pose en principe pas de grosse difficult.
Il y a cependant deux limitations qui justifient lexistence de IntegerListsLex. La
premire est dordre thorique : les points dentiers dun polytope ne permettent
de modliser que des problmes en dimension (longueur) fixe ; la deuxime dordre
pratique : lheure actuelle seule la bibliothque PALP a une interface avec Sage ;
si elle offre de multiples fonctionnalits sur ltude des polytopes, pour ce qui
nous intresse ici elle ne permet que de construire la liste des points entiers, sans
fournir ditrateur ni de comptage non naf :
sage: A = random_matrix(ZZ,3,6,x=7)
sage: L = LatticePolytope(A)
sage: L.points()
[1 6 6 2 5 5 6 5 4 5 4 5 4 2 5 3 4 5 3 4 5 3 3]
[4 4 2 6 4 1 3 2 3 3 4 4 3 4 3 4 4 4 4 4 4 5 5]
[3 1 1 6 5 1 1 2 2 2 2 2 3 3 3 3 3 3 4 4 4 4 5]
sage: L.npoints()
23
Ce polytope peut tre visualis en 3D avec L.plot3d() (voir figure 15.5).

Figure 15.5 Le polytope L et ses points entiers, en vision strographique yeux croiss.

15.4.3 Espces, classes combinatoires dcomposables


En 15.1.2, nous avons montr comment utiliser la dfinition rcursive des
arbres binaires complets pour les dnombrer efficacement au moyen de sries
gnratrices. Les techniques exposes sont trs gnrales, et sappliquent ds quun
ensemble peut tre dfini rcursivement (selon les communauts, un tel ensemble
est appel classe combinatoire dcomposable ou espce combinatoire). Cela inclut
15.4. ALGORITHMES GNRIQUES 351

toutes les varits darbres, mais aussi les permutations, les compositions, les
graphes fonctionnels, etc.
Nous nous contentons ici dillustrer quelques exemples dutilisation de la
bibliothque de Sage sur les espces combinatoires :
sage: from sage.combinat.species.library import *
sage: o = var('o')
Nous commenons par redfinir les arbres binaires complets ; pour cela, on
stipule lquation de rcurrence directement sur les ensembles :
sage: BT = CombinatorialSpecies()
sage: Leaf = SingletonSpecies()
sage: BT.define( Leaf + (BT*BT) )
On peut maintenant construire lensemble des arbres cinq nuds, les nu-
mrer, les compter, etc :
sage: BT5 = BT.isotypes([o]*5); BT5.cardinality()
14
sage: BT5.list()
[o*(o*(o*(o*o))), o*(o*((o*o)*o)), o*((o*o)*(o*o)), o*((o*(o*o))*o),
o*(((o*o)*o)*o), (o*o)*(o*(o*o)), (o*o)*((o*o)*o), (o*(o*o))*(o*o),
((o*o)*o)*(o*o), (o*(o*(o*o)))*o, (o*((o*o)*o))*o, ((o*o)*(o*o))*o,
((o*(o*o))*o)*o, (((o*o)*o)*o)*o]
Les arbres sont construits en utilisant une structure de donne rcursive gnrique ;
laffichage ne peut donc tre fameux ; pour faire mieux, il faudrait fournir Sage
une structure de donne plus spcialise, avec laffichage dsir.
On retrouve la srie gnratrice des nombres de Catalan :
sage: g = BT.isotype_generating_series(); g
x + x^2 + 2*x^3 + 5*x^4 + 14*x^5 + O(x^6)
qui est renvoye sous forme dune srie paresseuse :
sage: g[100]
227508830794229349661819540395688853956041682601541047340
Nous finissons avec les mots de Fibonacci, qui sont les mots binaires sans deux
1 conscutifs (voir 3.2.3). Ils admettent une dfinition rcursive naturelle :
sage: Eps = EmptySetSpecies(); Z0 = SingletonSpecies()
sage: Z1 = Eps*SingletonSpecies()
sage: FW = CombinatorialSpecies()
sage: FW.define(Eps + Z0*FW + Z1*Eps + Z1*Z0*FW)
On reconnat la fameuse suite de Fibonacci, do le nom :
sage: L = FW.isotype_generating_series().coefficients(15); L
[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]

sage: sloane_find(L)
352 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

Searching Sloane's online database...


[[45, 'Fibonacci numbers: F(n) = F(n-1) + F(n-2),
F(0) = 0, F(1) = 1, F(2) = 1, ...',
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ...
ce qui est une consquence directe de lquation de rcurrence. L encore, on peut
aussi gnrer immdiatement tous les mots de Fibonacci dune longueur donne,
avec les mmes limitations de laffichage gnrique :
sage: FW3 = FW.isotypes([o]*3)
sage: FW3.list()
[o*(o*(o*{})), o*(o*(({}*o)*{})), o*((({}*o)*o)*{}),
(({}*o)*o)*(o*{}), (({}*o)*o)*(({}*o)*{})]
En remplaant o par 0, {}*o par 1, en oubliant les parenthses et le dernier {},
on lit respectivement 000, 001, 010, 100 et 101.

15.4.4 Graphes un isomorphisme prs


Nous avons vu en 15.2.3 que Sage pouvait engendrer les graphes et les ordres
partiels un isomorphisme prs. Nous allons maintenant dcrire lalgorithme
sous-jacent, qui est le mme dans les deux cas, et couvre une gamme nettement
plus large de problmes.
Commenons par quelques rappels : un graphe G = (V, E) est la donne
dun ensemble V de sommets et dun ensemble E dartes reliant ces sommets,
une arte tant dcrite par une paire {u, v} de deux sommets distincts de V .
Un tel graphe est dit tiquet ; ses sommets sont typiquement numrots par
V = {1, 2, 3, 4, 5}.
Dans beaucoup de problmes, les tiquettes sur les sommets ne jouent aucun
rle. Typiquement un chimiste voudra rechercher toutes les molcules possibles
ayant une composition donne, mettons un alcane avec n = 8 atomes de carbone
et 2n + 2 = 18 atomes dhydrogne ; il recherche alors tous les graphes avec
8 sommets ayant chacun 4 voisins, et 18 sommets ayant un unique voisin. En
dehors de cela, tous les atomes de carbone sont identiques, et de mme pour les
atomes dhydrogne. Le problme de notre chimiste nest pas anecdotique ; ce
type dapplication est en fait lorigine dune part importante des recherches en
thorie des graphes sur les problmes disomorphisme.
Lorsque lon travaille la main sur un petit graphe on peut, comme dans
lexemple de 15.2.3, en faire un dessin, effacer les tiquettes et oublier
linformation gomtrique sur la disposition des sommets dans le plan. En revanche,
pour reprsenter un graphe dans un programme, on ne peut faire lconomie
dintroduire des tiquettes sur les sommets pour pouvoir dcrire comment sont
connectes les artes. Pour compenser cela, on dit que deux graphes tiquets
sont isomorphes sil existe une bijection des sommets du premier vers les sommets
du second qui envoie les artes du premier sur les artes du second ; un graphe
non tiquet est alors une classe dquivalence de graphes tiquets.
En gnral, tester si deux graphes tiquets sont isomorphes est trs coteux.
Cependant, le nombre de graphes, mme non tiquets, crot trs rapidement ; du
15.4. ALGORITHMES GNRIQUES 353

coup il reste possible dnumrer les graphes non tiquets trs efficacement en
regard de leur nombre. Ainsi, le programme Nauty est capable dnumrer les
12 005 168 graphes simples 10 sommets en 20 secondes.
Comme en 15.4.1, le principe gnral de lalgorithme est dorganiser les objets
numrer selon un arbre que lon parcourt.
Pour cela, dans chaque classe dquivalence de graphes tiquets (cest--dire
pour chaque graphe non tiquet) on choisit convenablement un reprsentant
canonique. Les oprations fondamentales sont alors les suivantes :
1. vrifier si un graphe tiquet est canonique ;
2. calculer le reprsentant canonique dun graphe tiquet.
Ces oprations, invitables, restent coteuses ; on cherche donc en minimiser le
nombre dappels.
Les reprsentants canoniques sont de plus choisis de telle manire que, pour
chaque graphe tiquet canonique G, il existe un choix canonique dune arte dont
la suppression redonne un graphe canonique, nomm le pre de G. Cette proprit
permet dorganiser les reprsentants canoniques des graphes sur un ensemble V de
sommets le long dun arbre : la racine, le graphe avec zro arte ; en dessous son
unique fils, le graphe avec une arte ; puis les graphes avec deux artes, et ainsi
de suite (voir figure 15.6). Lensemble des fils dun graphe G peut tre construit
par augmentation en ajoutant une arte de toutes les faons possibles G, et
en slectionnant parmi les graphes obtenus ceux qui sont encore canoniques 6 .
Rcursivement, on obtient alors tous les graphes canoniques.
En quoi cet algorithme est-il gnrique ? Considrons par exemple les graphes
planaires (graphes que lon peut dessiner dans le plan sans croisement dartes) :
en supprimant une arte dun graphe planaire, on obtient de nouveau un graphe
planaire ; ainsi les graphes planaires forment un sous-arbre de larbre prcdent.
Pour les engendrer, on peut rutiliser exactement le mme algorithme ; il suffit de
ne garder, au fur et mesure, que les fils qui sont planaires :
sage: [len(list(graphs(n, property = lambda G: G.is_planar())))
....: for n in range(7)]
[1, 1, 2, 4, 11, 33, 142]
De manire similaire, on peut engendrer toute famille de graphes close par
suppression darte, et en particulier celles dfinies par sous-graphes interdits.
Cela inclus par exemple
les arbres et forts (graphes sans cycle) ;
les graphes bipartis (graphes sans cycle impair).
Comme application indirecte, on peut citer la gnration :
des ordres partiels, via la bijection avec leurs diagrammes de Hasse, ces
derniers tant les graphes orients sans cycles et sans artes de transitivit
(arte a z entre deux sommets relis par un chemin a b z de
longueur deux ou plus)
6. Dans la pratique, une implantation efficace se doit dexploiter les symtries de G, cest--
dire son groupe dautomorphismes, pour rduire le nombre de fils potentiels, et pour rduire le
cot de chaque test de canonicit.
354 CHAP. 15. DNOMBREMENT ET COMBINATOIRE

2 0

2 0

1 1

2 0 2 0

3 3

1 1 1

2 0 2 0 2 0

3 3 3

1 1

2 0 2 0

3 3

2 0

2 0

Figure 15.6 Larbre de gnration des graphes simples 4 sommets.

des treillis (non implant dans Sage), via la bijection avec les demi-treillis
infrieurs obtenus par suppression du sommet maximal ; il faut de plus
utiliser une augmentation par sommets plutt que par artes.
16
Thorie des graphes

Ce chapitre prsente ltude de la thorie des graphes avec Sage, en dcrivant


tout dabord la classe Graph (16.1) ainsi que ses mthodes (16.2), puis en les uti-
lisant pour rsoudre des problmes pratiques (16.4) ou vrifier exprimentalement
des rsultats thoriques (16.3).

16.1 Construire un graphe


16.1.1 partir de zro
Ici les graphes sont dfinis comme une paire (V, E), o V reprsente un
ensemble de sommets (vertices en anglais) et E un ensemble dartes (edges), cest-
-dire de paires non ordonnes de sommets. Le graphe reprsent en figure 16.1 est
dfini sur lensemble de sommets {0, 1, 2, 5, 9, Madrid, Edimbourg} et a pour
artes (1, 2), (1, 5), (1, 9), (2, 5), (2, 9) ainsi que (Madrid, Edimbourg).
Les graphes sont sans aucune surprise reprsents dans Sage par la classe
Graph :
sage: g = Graph()
Par dfaut, g est un graphe vide. Lexemple suivant illustre comment lui
ajouter sommets et artes : lorsquune arte est cre, les sommets correspondants
sils ne sont pas dj prsents dans le graphe sont silencieusement ajouts.
Nous contrlons le droulement de la procdure avec des mthodes dont les rles
sont faciles deviner :
sage: g.order(), g.size()
(0, 0)
sage: g.add_vertex(0)
356 CHAP. 16. THORIE DES GRAPHES

sage: g.order(), g.size()


(1, 0)
sage: g.add_vertices([1, 2, 5, 9])
sage: g.order(), g.size()
(5, 0)
sage: g.add_edges([(1,5), (9,2), (2,5), (1,9)])
sage: g.order(), g.size()
(5, 4)
sage: g.add_edge("Madrid", "Edimbourg")
sage: g.order(), g.size()
(7, 5)
Ajouter larte (1,2) est quivalent ajouter larte (2,1). On notera de
plus que les mthodes add_vertex et add_edge ont toutes les deux un plu-
riel (add_vertices et add_edges) qui prend une liste en argument et permet
une criture plus compacte (voir par exemple 16.4.1, o lon construit un graphe
aprs avoir gnr lensemble de ses artes).
En gnral, Sage nest pas regardant quant au type des objets quil est possible
dutiliser comme sommets dun graphe. Il acceptera en fait tout objet Python
immuable (et donc pas, au moment de la version 5.9 de Sage, des objets de la
classe Graph eux-mmes), cest--dire tout ce quun dictionnaire pourrait accepter
comme nom de clef (cf. 3.3.9). Il est bien entendu possible de supprimer ensuite
les lments ajouts laide des mthodes delete_* et dnumrer les sommets
ou les artes, sur lesquels nous itrerons souvent.
sage: g.delete_vertex(0)
sage: g.delete_edges([(1,5), (2,5)])
sage: g.order(), g.size()
(6, 3)
sage: g.vertices()
[1, 2, 5, 9, 'Edimbourg', 'Madrid']
sage: g.edges()
[(1, 9, None), (2, 9, None), ('Edimbourg', 'Madrid', None)]
Les artes dun graphe sont en ralit pour Sage des triplets, dont la dernire
entre est une tiquette (ou label). Elle sert la plupart du temps stocker des
valeurs numriques interprtes par exemple par les algorithmes de flot ou
de connectivit comme des capacits, ou comme un poids pour le problme de
couplage (matching) et peut aussi contenir tout objet immuable. Par dfaut,
ltiquette vaut None.
Lorsque lon connat lavance les sommets et artes dun graphe, on peut le
construire de manire compacte avec un dictionnaire associant chaque sommet
la liste de ses voisins :
sage: g = Graph({
....: 0 : [],
....: 1 : [5, 9],
....: 2 : [1, 5, 9],
....: 'Edimbourg' : ['Madrid']})
16.1. CONSTRUIRE UN GRAPHE 357

Figure 16.1 Un graphe dont les sommets sont des entiers ou des chanes de caractres.

L encore, on peut se permettre doublier les lignes correspondant aux sommets


5, 9, ou Madrid, qui sont mentionns comme voisins dautres sommets. On peut
galement se permettre de dire que 1 est un voisin de 2 alors que 2 napparat
pas dans la liste des voisins de 1 : larte (1,2) sera bel et bien cre.
Exercice 60 (Graphes circulants). Le graphe circulant de paramtres n, d est un
graphe n sommets numrots de 0 n 1 (que lon peut se reprsenter disposs le long
dun cercle), tel que deux sommets u et v sont relis par une arte si u v + c mod n,
avec d 6 c 6 d. crire une mthode prenant en paramtres n et d, et renvoyant le
graphe associ.

16.1.2 Les constructeurs disponibles


En dpit des illustrations prcdentes, il est assez rare de saisir une table
dadjacence sous Sage, ou mme dnumrer manuellement une par une ses artes
pour crer un graphe. La plupart du temps, il est plus efficace de les dfinir partir
des lments de base dj disponibles : les mthodes de graphs.* permettent de
construire plus de soixante-dix graphes ou familles de graphes, que nous prsentons
maintenant. Les graphes de Chvtal et de Petersen, par exemple, sont obtenus
sous Sage par les lignes suivantes :
sage: P = graphs.PetersenGraph()
sage: C = graphs.ChvatalGraph()
Commenons cette description par les petits graphes par opposition aux
familles de graphes que nous rencontrerons par la suite.

Petits graphes. Ces graphes portent le plus souvent le nom de leur dcouvreur,
ou dun objet auquel ils ressemblent (une maison, une sucette, un taureau).
Ils apparaissent souvent comme contre-exemples certaines conjectures, ou
comme plus petits graphes satisfaisant telle ou telle proprit. Le graphe de
358 CHAP. 16. THORIE DES GRAPHES

Petits graphes
BullGraph ChvatalGraph ClawGraph
DesarguesGraph DiamondGraph DodecahedralGraph
FlowerSnark FruchtGraph HeawoodGraph
HexahedralGraph HigmanSimsGraph HoffmanSingletonGraph
HouseGraph HouseXGraph IcosahedralGraph
KrackhardtKiteGraph LollipopGraph MoebiusKantorGraph
OctahedralGraph PappusGraph PetersenGraph
TetrahedralGraph ThomsenGraph

Petersen, par exemple, est non-planaire : il possde simultanment les deux


mineurs interdits par le thorme de Kuratowski (K5 et K3,3 ). Cest de plus un
graphe sans triangle (sa maille girth est gale 5), 3-rgulier et de nombre
chromatique 3. Cest aussi un graphe sommet-transitif. Chacun de ces paramtres
peut tre retrouv par Sage laide des mthodes correspondantes :

sage: P = graphs.PetersenGraph()
sage: P.is_planar()
False
sage: P.minor(graphs.CompleteBipartiteGraph(3,3))
{0: [0], 1: [2], 2: [8], 3: [1, 6], 4: [3, 4], 5: [5, 7]}
sage: P.minor(graphs.CompleteGraph(5))
{0: [0, 5], 1: [1, 6], 2: [2, 7], 3: [3, 8], 4: [4, 9]}
sage: P.girth()
5
sage: P.is_regular(3)
True
sage: P.chromatic_number()
3
sage: P.is_vertex_transitive()
True
sage: P.show()
16.1. CONSTRUIRE UN GRAPHE 359

Familles de graphes. Les constructeurs prsents ici dcrivent des familles


de graphes, et prennent donc en argument un ou plusieurs paramtres ( une
exception prs, nauty_geng, qui ne dcrit pas une famille spcifique de graphes
mais lensemble de tous les graphes isomorphisme prs ; voir section 15.4.4).

Familles de graphes
BarbellGraph BubbleSortGraph
CircularLadderGraph DegreeSequence
DegreeSequenceBipartite DegreeSequenceConfigurationModel
DegreeSequenceTree DorogovtsevGoltsevMendesGraph
FibonacciTree FuzzyBallGraph
GeneralizedPetersenGraph Grid2dGraph
GridGraph HanoiTowerGraph
HyperStarGraph KneserGraph
LCFGraph LadderGraph
NKStarGraph NStarGraph
OddGraph ToroidalGrid2dGraph
nauty_geng

Dans cette liste se trouve une gnralisation (en fait, deux) du graphe de
Petersen : le graphe de Kneser. Cegraphe se construit partir de deux paramtres,
n et k, et ses sommets sont les nk sous-ensembles de taille k de {1, . . . , n}. Deux
de ces ensembles sont adjacents si et seulement si ils sont disjoints. Les sommets
du graphe de Petersen correspondent aux sous-ensembles de taille k = 2 dun
ensemble de taille n = 5 :
sage: K = graphs.KneserGraph(5, 2); P = graphs.PetersenGraph()
sage: K.is_isomorphic(P)
True
Par construction, les graphes de Kneser sont eux aussi sommets-transitifs.
Leur nombre chromatique est exactement n 2k + 2, un rsultat surprenant de
Lovsz prouv par lintermdiaire du thorme de Borsuk-Ulam et donc par des
considrations de topologie [Mat03]. Vrifions cela immdiatement, sur quelques
exemples :
sage: all( graphs.KneserGraph(n,k).chromatic_number() == n - 2*k + 2
....: for n in range(5,9) for k in range(2,floor(n/2)) )
True
Exercice 61 (Graphes de Kneser). crire une fonction de deux paramtres n, k
renvoyant le graphe de Kneser associ, si possible sans utiliser de if .

Graphes lmentaires. Les graphes suivants sont les pices fondamentales


les plus courantes en thorie des graphes (graphes complets, bipartis complets,
circulants, chemins, cycles, toiles, etc.). L encore, une exception noter : trees ;
cette mthode permet ditrer sur lensemble des arbres n sommets.

Graphes alatoires. Cette dernire classe de graphes est trs riche en proprits.
On y trouve entre autres les Gn,p et Gn,m , qui sont les deux modles les plus
simples de graphes alatoires.
360 CHAP. 16. THORIE DES GRAPHES

Graphes lmentaires
BalancedTree CirculantGraph CompleteBipartiteGraph
CompleteGraph CubeGraph CycleGraph
EmptyGraph PathGraph StarGraph
WheelGraph&&trees

Les graphes Gn,p sont dfinis par un entier n et un rel 0 6 p 6 1. On obtient


un graphe alatoire Gn,p sur n sommets {0, . . . , n 1} en lanant pour chacune
des n2 paires de sommets i, j une pice de monnaie dont la probabilit de


tomber sur pile est p et en ajoutant au graphe larte correspondante


lorsque pile sort.
On observe que pour tout graphe H fix, la probabilit que Gn,p contienne H
comme sous-graphe induit 1 tend vers 1 lorsque 0 < p < 1 est fix et n tend vers
linfini (voir 16.3.4) :
sage: H = graphs.ClawGraph()
sage: def test():
....: g = graphs.RandomGNP(20,2/5)
....: return not g.subgraph_search(H, induced=True) is None
sage: sum( test() for i in range(100) ) >= 80
True

16.1.3 Unions disjointes


En plus de ces briques fondamentales, Sage permet deffectuer des unions
disjointes de graphes laide de deux oprations simples mais efficaces. Laddition
de deux graphes correspond leur union disjointe :
sage: P = graphs.PetersenGraph()
sage: H = graphs.HoffmanSingletonGraph()
sage: U = P + H; U2 = P.disjoint_union(H)
sage: U.is_isomorphic(U2)
True
Le produit dun graphe G par un entier k renvoie lunion disjointe de k copies
de G :
sage: C = graphs.ChvatalGraph()
sage: U = 3 * C; U2 = C.disjoint_union(C.disjoint_union(C))
sage: U2.is_isomorphic(U)
True
La ligne suivante cre lunion disjointe de trois copies du graphe de Petersen
et de deux copies du graphe de Chvtal :
sage: U = 3*P + 2*C
1. H est un sous-graphe induit de G sil existe un ensemble S V (G) de sommets tel que la
restriction S de G (cest--dire le graphe dont les sommets sont S et les artes sont les artes
de G ne touchant que des sommets de S) est isomorphe H. On note dailleurs ce sous-graphe
induit G[S].
16.1. CONSTRUIRE UN GRAPHE 361

Graphes alatoires
DegreeSequenceExpected RandomBarabasiAlbert RandomBipartite
RandomGNM RandomGNP RandomHolmeKim
RandomInterval RandomLobster RandomNewmanWattsStrogatz
RandomRegular RandomShell RandomTreePowerlaw

Il existe quantit de faons de sassurer de ce rsultat, qui sont autant dexcuses


pour crire quelques lignes de code. Par exemple, en sassurant que chaque
composante connexe est isomorphe lun des deux graphes :

sage: all( (CC.is_isomorphic(P) or CC.is_isomorphic(C))


....: for CC in U.connected_components_subgraphs() )
True

ou en comptant le nombre exact de sous-graphes :

sage: sum( CC.is_isomorphic(P)


....: for CC in U.connected_components_subgraphs() )
3
sage: sum( CC.is_isomorphic(C)
....: for CC in U.connected_components_subgraphs() )
2

Dtails techniques. Il est noter que les oprations daddition et de mul-


tiplication sont en termes de cot en mmoire et en temps, des copies. Cela
peut parfois tre source de lenteurs. En revanche, modifier P ou C la suite de
lexemple prcdent ne modifiera pas U. De plus, ces oprations font perdre deux
informations :

les sommets du graphe final sont renumrots en entiers {0, 1, 2, . . .} ;


les positions (dans le plan) des sommets ne sont pas conserves dans U.

La mthode disjoint_union a un comportement diffrent : si le graphe


g contient un sommet a et le graphe h un sommet b, le graphe renvoy par
g.disjoint_union(h) contient les sommets (0,a) et (1,b). Dans le cas o a ou
b ne sont pas des entiers mais tout autre objet (chane de caractres, tuples...)
lutilisation de cette mthode simplifie grandement le travail sur le graphe rsultant
de lunion.

16.1.4 Affichage des graphes


Un aspect trs apprciable de ltude des graphes sous Sage est la possibilit
de les visualiser. Sans variantes ni fioritures, il suffit dune seule commande :

sage: C = graphs.ChvatalGraph(); C.show()


362 CHAP. 16. THORIE DES GRAPHES

Il sagit l dun outil prcieux pour visualiser le rsultat de certaines fonctions.


Ici, nous mettons en valeur un ensemble indpendant :

sage: C.show(partition = [C.independent_set()])

Largument partition de la mthode show reoit, comme son nom lindique,


une partition de lensemble des sommets. Une couleur est alors attribue chaque
ensemble de la partition, afin de les sparer visuellement. Une dernire couleur est
attribue aux sommets napparaissant pas dans la partition. Dans notre exemple
on a donc en tout deux couleurs.

Il est bien entendu possible de spcifier soi-mme les couleurs que lon souhaite
attribuer aux sommets, laide dun dictionnaire et dune syntaxe plutt naturelle :

sage: C.show(vertex_colors = {
....: "red" : [0, 1, 2], "blue" : [3, 4, 5],
....: "yellow" : [6, 7, 8], "purple" : [9, 10, 11]})
16.1. CONSTRUIRE UN GRAPHE 363

Les couleurs souhaites ntant pas toujours primaires ou secondaires, il est


possible de les spcifier par leur code hexadcimal, comme on le ferait en HTML.
Des mthodes comme coloring sont justement faites pour ces situations :

sage: C.coloring(hex_colors = True)


{'#00ffff': [3, 8, 5], '#7f00ff': [11],
'#ff0000': [0, 2, 7, 10], '#7fff00': [1, 4, 6, 9]}
sage: C.show(vertex_colors = C.coloring(hex_colors = True))

Le comportement de largument edge_colors est identique :

sage: from sage.graphs.graph_coloring import edge_coloring


sage: edge_coloring(C, hex_colors = True)
{'#00ffff': [(0,6), (1,2), (3,9), (4,8), (5,10), (7,11)],
'#7f00ff': [(0,9), (1,7), (2,6), (3,4), (5,11), (8,10)],
'#ff0000': [(0,1), (2,3), (4,5), (6,11), (7,8), (9,10)],
'#7fff00': [(0,4), (1,5), (2,8), (3,7), (6,10), (9,11)]}
sage: C.show(edge_colors = edge_coloring(C, hex_colors = True))
364 CHAP. 16. THORIE DES GRAPHES

Exporter des images. Il est aussi possible dexporter individuellement les


images construites par Sage. Lexemple ci-dessous trace les graphes complets
3, 4, ..., 12 sommets, dans les fichiers graph0.png, ..., graph9.png.
sage: L = [graphs.CompleteGraph(i) for i in range(3,3+10)]
sage: for number, G in enumerate(L):
....: G.plot().save('/tmp/' + 'graph' + str(number) + '.png')

Les options des commandes show et plot sont sans fin, et fort documentes.
Tout au plus mentionnera-t-on loption figsize = 15, qui prcise la rsolution
de limage et se rvlera utile pour les graphes de grande taille.

16.2 Mthodes de la classe Graph


La classe Graph dispose de plus de 250 mthodes, en mettant de ct celles
dfinies exclusivement dans la classe DiGraph, ou celles napparaissant que dans
des modules annexes. Cela fait de Sage une bibliothque expressive et complte
pour la thorie des graphes, permettant de se concentrer sur lessentiel, cest--dire
vitant davoir programmer longueur de temps dautres fonctions que celles
qui nous intressent.
Comme lors de lapprentissage de tout langage de programmation (ou biblio-
thque), il est utile de parcourir au moins une fois la liste de ses fonctions afin de
reprer ce dont il (ou elle) est capable. Cette section (non-exhaustive) tente de les
prsenter succinctement. Il est conseill au lecteur de sacrifier les quelques minutes
ncessaires la lecture du contenu de chaque catgorie et mme de la liste
complte des mthodes disponibles : le temps pass le faire se rvlera infiniment
rentable une fois en face dun problme de graphes ! Il est aussi conseill davoir
prs de soi une session Sage ouverte afin de pouvoir consulter la documentation
des fonctions prsentes (par exemple g.degree_constrained_subgraph?), cer-
taines dentre elles ayant plusieurs options, ou lorsque leur intitul nest pas assez
explicite.
16.2. MTHODES DE LA CLASSE GRAPH 365

16.2.1 Modification de la structure dun graphe


Bien entendu, une grande partie de la classe Graph contient les mthodes
naturelles lies la dfinition et la modification des graphes, ncessaires bien
que napportant pas de fonctionnalit remarquable.

Mthodes daccs et de modification de la classe Graph


add_cycle add_edge add_edges
add_path add_vertex add_vertices
adjacency_matrix allow_loops allow_multiple_edges
allows_loops allows_multiple_edges clear
delete_edge delete_edges delete_multiedge
delete_vertex delete_vertices edge_iterator
edge_label edge_labels edges
edges_incident get_vertex get_vertices
has_edge has_loops has_multiple_edges
has_vertex incidence_matrix latex_options
loop_edges loop_vertices loops
merge_vertices multiple_edges name
neighbor_iterator neighbors networkx_graph
num_edges num_verts number_of_loops
order relabel remove_loops
remove_multiple_edges rename reset_name
save set_edge_label set_latex_options
set_vertex set_vertices size
subdivide_edge subdivide_edges vertex_iterator
vertices weighted weighted_adjacency_matrix

16.2.2 Oprateurs
Dans la mme ligne de mthodes apparaissent les oprateurs, qui renvoient un
objet de type Graph (ou DiGraph). Par exemple, la mthode complement applique
G renvoie un graphe dfini sur le mme ensemble de sommets, dans lequel larte
uv existe si et seulement si uv 6 G. La mthode subgraph permet de son ct
dobtenir partir dun graphe G le sous-graphe induit par un ensemble donn de
sommets (voir dfinition page 360), opration souvent note G[{v1 , . . . , vk }].
Vrifions quelques relations lmentaires. Le complmentaire de P5 (not P5 )
est une maison, et les graphes P4 et C5 sont auto-complmentaires :
sage: P5 = graphs.PathGraph(5); House = graphs.HouseGraph()
sage: P5.complement().is_isomorphic(House)
True
sage: P4 = graphs.PathGraph(4); P4.complement().is_isomorphic(P4)
True
sage: C5 = graphs.CycleGraph(5); C5.complement().is_isomorphic(C5)
True

Sage dfinit aussi (par la mthode ponyme) le line graph de G souvent


not L(G) dont les sommets correspondent aux artes de G, et dans lequel
deux sommets sont adjacents si les artes correspondantes sont incidentes dans
G. On trouve aussi la dfinition de diffrents produits de graphes. Dans chacun
des exemples suivants, on suppose que G est le produit de G1 par G2 , dfini sur
366 CHAP. 16. THORIE DES GRAPHES

lensemble de sommets V (G1 ) V (G2 ). Deux sommets (u, v), (u0 , v 0 ) G sont
adjacents si et seulement si :

Produit cartsien Produit lexicographique


cartesian_product lexicographic_product
u = u0 et vv 0 E(G2 ) uu0 E(G1 )
 
ou ou
uu0 E(G1 ) et v = v 0 u = u0 et vv 0 E(G2 )

Produit disjonctif Produit tensoriel


disjunctive_product tensor_product
uu E(G1 ) uu E(G1 )
 0  0
ou et
vv 0 E(G2 ) vv 0 E(G2 )

Produit fort
strong_product
u = u0 et vv 0 E(G2 )

ou uu0 E(G1 ) et v = v 0
uu0 E(G1 ) et vv 0 E(G2 )

On peut construire la grille carre GridGraph comme le produit cartsien de


deux chemins :
sage: n = 5; Path = graphs.PathGraph(n)
sage: Grid = Path.cartesian_product(Path)
sage: Grid.is_isomorphic(graphs.GridGraph([n,n]))
True

Produits, oprateurs, . . .

cartesian_product categorical_product complement


copy disjoint_union disjunctive_product
kirchhoff_matrix laplacian_matrix line_graph
lexicographic_product strong_product subgraph
to_directed to_simple to_undirected
tensor_product transitive_closure transitive_reduction
union

16.2.3 Parcours de graphes et distances


Sage offre les mthodes habituelles de parcours de graphe, comme les parcours
en profondeur (depth_first_search) et en largeur (breadth_first_search) qui
sont les routines fondamentales des calculs de distances, de flot ou de connectivit.
Il contient aussi une implmentation du moins classique lex_BFS (lexicographic
breadth-first search), utilis par exemple pour la reconnaissance des graphes cor-
daux (cf. is_chordal). Ces mthodes renvoient un ordonnancement des sommets
16.2. MTHODES DE LA CLASSE GRAPH 367

correspondant leur ordre de dcouverte 2 :


sage: g = graphs.RandomGNP(10, .6)
sage: list(g.depth_first_search(0))
[0, 8, 5, 4, 9, 2, 3, 7, 6, 1]
sage: list(g.breadth_first_search(0))
[0, 8, 5, 4, 1, 3, 6, 7, 9, 2]
sage: g.lex_BFS(0)
[0, 8, 5, 4, 1, 6, 7, 3, 9, 2]
On dfinit laide de ces parcours la mthode shortest_path, qui est pro-
bablement la plus utilise de toutes 3 . Sage permet galement de calculer divers
invariants lis aux distances :
eccentricity : associe un sommet v du graphe la distance maximale
entre v et tout autre sommet du graphe ;
center : renvoie un sommet v central du graphe cest--dire dexcentricit
minimale ;
radius : renvoie lexcentricit dun centre ;
diameter : renvoie la distance maximale entre deux sommets ;
periphery : renvoie la liste des sommets dont lexcentricit est gale au
diamtre.

Distances, parcours

average_distance breadth_first_search center


depth_first_search diameter distance
distance_all_pairs distance_graph eccentricity
lex_BFS periphery radius
shortest_path shortest_path_all_pairs shortest_path_length
shortest_path_lengths shortest_paths

16.2.4 Flots, connectivit, couplage (matching)


Sage sait rsoudre les problmes de flot maximum (cf. 17.4.3) laide de la
mthode flow 4 . Grce aux parcours mentionns prcdemment, il contient aussi
plusieurs mthodes lies la connectivit (is_connected, edge_connectivity,
vertex_connectivity, connected_components, . . .) ainsi que les consquences
du thorme de Menger :
Soient G un graphe et u, v deux de ses sommets. Les assertions suivantes sont
quivalentes :
2. Si lex_BFS renvoie bien une liste de sommets, les mthodes depth_first_search et
breadth_first_search sont elles des itrateurs sur les sommets, do lutilisation de la mthode
list.
3. Il est noter que shortest_path ne fait pas ncessairement appel breadth_first_search :
lorsque les artes du graphe sont munies dune distance, des implmentations de lalgorithme de
Dijkstra (standard ou bidirectionnel) prennent le relais.
4. Deux implmentations sont dailleurs disponibles : la premire suit lalgorithme de Ford-
Fulkerson, la seconde est un programme linaire.
368 CHAP. 16. THORIE DES GRAPHES

la valeur du flot maximal entre u et v est k (voir flow) ;


il existe k (mais pas k + 1) chemins arte-disjoints entre u et v (voir
edge_disjoint_paths) ;
il existe un ensemble de k artes dans G qui, une fois retires du graphe,
dconnectent u de v (voir edge_cut).

Les contreparties ces mthodes portant sur la connectivit en terme de


sommets sont flow (grce son option vertex_bound=True), vertex_cut et
vertex_disjoint_paths.
Vrifions par exemple quavec (trs) forte probabilit, la connectivit dun
graphe alatoire Gn,p est gale son degr minimal :

sage: n = 30; p = 0.3; trials = 50


sage: def equality(G):
....: return G.edge_connectivity() == min(G.degree())
sage: sum(equality(graphs.RandomGNP(n,p)) for i in range(trials))/trials
1

On peut aussi obtenir la dcomposition dun graphe en composantes 2-connexes


ou bien son arbre de Gomory-Hu, respectivement par blocks_and_cut_vertices
et gomory_hu_tree.
Puisque cest lune des fonctions fondamentales de la thorie des graphes,
mentionnons ici la mthode matching, qui construit un couplage maximal par
lalgorithme dEdmonds. Les couplages sont galement abords en 16.4.2 et
17.4.2.

Flots, connectivit, . . .

blocks_and_cut_vertices connected_component_containing_vertex
connected_components connected_components_number
connected_components_subgraphs degree_constrained_subgraph
edge_boundary edge_connectivity
edge_cut edge_disjoint_paths
edge_disjoint_spanning_trees flow
gomory_hu_tree is_connected
matching multicommodity_flow
vertex_boundary vertex_connectivity
vertex_cut vertex_disjoint_paths

16.2.5 Problmes NP-complets


Sage contient pour certains problmes NP-complets des algorithmes de rso-
lution exacte. Bien entendu, ces problmes peuvent demander selon les cas de
grands temps de calcul, mais les instances relles ont souvent le bon got dtre
plus faciles rsoudre que les contre-exemples thoriques. Il est par exemple
possible de rsoudre les problmes doptimisation suivants.
16.2. MTHODES DE LA CLASSE GRAPH 369

Figure 16.2 Le graphe de Chvtal et un cycle hamiltonien de celui-ci.

Cliques et ensemble indpendant maximum. Une clique maximum dun


graphe est un ensemble de sommets deux deux adjacents de cardinal maximum
(non-adjacents dans le cas de lensemble indpendant). Une application de ce type
de problme est prsente en 16.4.1. Lalgorithme utilis est celui du programme
Cliquer [NO].
Mthodes : clique_maximum, independent_set

Coloration de sommets, dartes. Une coloration propre des sommets dun


graphe est une affectation de couleurs aux sommets telle que deux sommets adja-
cents possdent des couleurs diffrentes. Sage possde plusieurs fonctions de calcul
exact pour certaines colorations, utilisant la plupart du temps la programmation
linaire ou lalgorithme Dancing Links. Le lecteur trouvera en 16.3.1 lexplication
dun algorithme simple, mais non optimal, de coloration.
Mthodes : chromatic_number, coloring, edge_coloring 1 , grundy_coloring1 .

Ensemble dominant. Un ensemble S de sommets dun graphe est dit dominant


si tout sommet v de G est voisin dun lment de S on dit alors quil est
domin ou sil est lui-mme membre de S. Lensemble de tous les sommets
tant trivialement dominant, le problme associ consiste minimiser la taille
de lensemble S. Ce problme est rsolu dans Sage laide de la programmation
linaire.
Mthode : dominating_set

Cycle hamiltonien, voyageur de commerce. Un graphe G est dit hamilto-


nien sil possde un cycle passant une fois et une seule par chacun des sommets
de G. Contrairement au problme de cycle eulrien le cycle doit alors passer
une fois et une seule par chaque arte de G ce problme est NP-complet, et
se rsout dans Sage par la programmation linaire comme un cas particulier du
problme du voyageur de commerce.
Nous illustrons la fonction hamiltonian_cycle, qui renvoie un cycle hamilto-
nien lorsquun tel cycle existe (figure 16.2) :

1. Ces mthodes ne sont pas directement accessibles par la classe Graph. Pour y accder,
ainsi qu dautres fonctions de coloration, consulter le module graph_coloring.
370 CHAP. 16. THORIE DES GRAPHES

sage: g = graphs.ChvatalGraph(); cycle = g.hamiltonian_cycle()


sage: g.show(vertex_labels = False); cycle.show(vertex_labels = False)
Mthodes : is_hamiltonian, hamiltonian_cycle,
traveling_salesman_problem

Problmes divers. Sage sait aussi calculer le genre dun graphe (genus),
des coupes maximales (max_cut), des arbres de Steiner (steiner_tree), etc. Il
permet aussi de rsoudre des problmes existentiels comme les multiflots entiers
(multicommodity_flow), le test dexistence de mineurs (minor recherche
dun mineur isomorphe un graphe donn) ou la recherche de sous-graphes
(subgraph_search).
Bien que la complexit thorique de ces problmes ne soit pas encore connue,
des algorithmes sont disponibles pour rsoudre le problme disomorphisme de
graphes (is_isomorphic) ainsi que pour calculer les groupes dautomorphisme
dun graphe (automorphism_group).

Problmes NP-complets (ou assimils)

automorphism_group characteristic_polynomial
chromatic_number chromatic_polynomial
coloring disjoint_routed_paths
edge_coloring dominating_set
genus hamiltonian_cycle
independent_set_of_representatives is_hamiltonian
is_isomorphic max_cut
minor multicommodity_flow
multiway_cut subgraph_search
traveling_salesman_problem steiner_tree
vertex_cover

16.2.6 Reconnaissance et test de proprits


Quantit de problmes NP-complets possdent un algorithme de rsolution
efficace (linaire, quadratique...) lorsque les graphes appartiennent une classe
particulire. Il est par exemple trivial de rsoudre un problme de clique maximum
sur un graphe cordal, et il est polynomial (bien que compliqu) de calculer
une coloration optimale des sommets dun graphe parfait. Sage possde des
algorithmes de reconnaissance pour certaines classes lmentaires de graphes :
forts (is_forest), arbres (is_tree), graphes bipartis (is_bipartite), graphes
eulriens (is_eulerian), graphes rguliers (is_regular), etc. Il est galement
possible didentifier les classes suivantes.

Graphes cordaux. Un graphe est dit cordal sil nadmet aucun cycle de
taille suprieure quatre comme sous-graphe induit. De faon quivalente, tout
graphe cordal peut tre dcompos en retirant squentiellement des sommets
dont le voisinage est un graphe complet (cet ordre de dcomposition est appel
ordonnancement dlimination parfaite). Ces graphes sont reconnus laide dun
parcours lexicographique en largeur (lex_BFS).
Mthode : is_chordal
16.2. MTHODES DE LA CLASSE GRAPH 371

Graphes dintervalle. Soit I = {I1 , . . . , In } un ensemble fini dintervalles


de lensemble des rels. On dfinit partir de I un graphe G sur n sommets
{1, . . . , n}, les sommets i et j tant adjacents si et seulement si les intervalles Ii
et Ij ont une intersection non vide. Les graphes dintervalles sont ceux que lon
peut obtenir de cette faon. Ils constituent une sous-classe des graphes cordaux,
reconnaissable en temps linaire grce la structure de PQ-trees.
Mthode : is_interval

Graphes parfaits. Un graphe G est dit parfait si pour tout sous-graphe induit
G0 G le nombre chromatique de G0 est gal la taille maximum dune clique
(i.e., lgalit (G0 ) = (G0 ) est vrifie). Bien que la reconnaissance de ces
graphes soit un problme polynomial, les algorithmes connus sont complexes et
limplmentation de Sage utilise un algorithme exponentiel.
Mthode : is_perfect

Graphes sommets-transitifs. Un graphe G est dit sommet-transitif sil existe


pour toute paire de sommets u et v un isomorphisme h : V (G) 7 V (G) tel que
h(u) = v. Bien que la complexit thorique de ce problme ne soit pas tablie,
limplmentation disponible dans Sage est trs efficace.
Mthode : is_vertex_transitive

Produit cartsien de graphes. Seuls certains graphes sexpriment comme


le produit cartsien dune suite G1 , ..., Gk de graphes. Il est dailleurs possible,
tant donn un graphe G connexe, de trouver lunique faon de lcrire ainsi
laide dun lgant rsultat de caractrisation, facilement traduit en un algorithme
polynomial.
Mthode : is_cartesian_transitive
De nombreuses classes de graphes trouvent, en plus de leur caractrisation
par une construction (les graphes cordaux) ou une proprit particulire (les
graphes parfaits), une formulation quivalente en termes de sous-graphes exclus.
Cela revient dire quun graphe G appartient une classe C si et seulement
sil ne contient aucune occurrence dun graphe parmi {G1 , . . . , Gk }. On peut
dans ce cas crire un algorithme de reconnaissance qui se contente de tester
lexistence de chacun de ces sous-graphes, ce que permet de faire la commande
subgraph_search.

Reconnaissance et tests de proprits

is_bipartite is_chordal is_directed


is_equitable is_eulerian is_even_hole_free
is_forest is_interval is_odd_hole_free
is_overfull is_regular is_split
is_subgraph is_transitively_reduced is_tree
is_triangle_free is_vertex_transitive
372 CHAP. 16. THORIE DES GRAPHES

16.3 Graphes en action


Il est temps de tirer parti des fonctionnalits que nous avons dcouvertes.
Les exemples suivants ont pour motivation un prtexte pratique ou thorique,
et ne sont en gnral pas la meilleure faon dutiliser Sage pour rsoudre les
problmes quils dcrivent. Ils sont souvent brutaux et numratifs, et cest ce
qui leur donne tout leur charme : leur but est bien videmment de constituer une
liste agrable et facile aborder dexemples dutilisation de la bibliothque de
graphes de Sage tout est ici dans la forme, pas dans le fond.

16.3.1 Coloration gloutonne des sommets dun graphe


Colorer les sommets dun graphe consiste affecter chacun dentre eux une
couleur (nous considrerons ici quun nombre entier est une couleur respectable),
de telle faon que chaque sommet possde une couleur diffrente de celles de ses
voisins. Ceci est bien entendu possible : il suffit de choisir autant de couleurs quil
existe de sommets dans notre graphe ; cest pour cette raison que le problme de
coloration est un problme de minimisation : trouver, tant donn un graphe G,
le plus petit nombre (G) de couleurs permettant de colorer ses sommets sous la
contrainte annonce.
Si le calcul du nombre (G) est un problme difficile adoss une impression-
nante littrature, le lecteur aux vues plus pratiques sera ravi dapprendre quil
existe des faons expditives dtre plus proche de loptimal quen utilisant |V |
couleurs. ceux-ci nous proposons lalgorithme suivant : Coloration gloutonne
des sommets dun graphe .
Prenons un sommet au hasard, et donnons-lui comme couleur lentier 0.
Itrativement, prenons un sommet non color et donnons-lui comme couleur le
plus petit entier disponible non utilis par ses voisins.
Cet algorithme ne demande que quelques lignes dexplications, et il en va
de mme pour le faire comprendre Sage. Nous lappliquons ici sur un graphe
alatoire :
sage: n = 100; p = 5/n; g = graphs.RandomGNP(n, p)

sage: # Ensemble de couleurs disponibles.


sage: # Dans le pire des cas, n couleurs suffisent
sage: couleurs_disponibles = Set(range(n))

sage: # Ce dictionnaire contient la couleur associe


sage: # chaque sommet du graphe
sage: couleur = {}
sage: for u in g:
....: interdits = Set([couleur[v] for v in g.neighbors(u)
....: if v in couleur])
....: couleur[u] = min(couleurs_disponibles - interdits)

sage: # Nombre de couleurs utilises


16.3. GRAPHES EN ACTION 373

sage: max(couleur.values()) + 1
6
Cela est sensiblement plus efficace que dutiliser 100 couleurs. Il est cependant
facile damliorer cet algorithme, lorsque lon remarque que la coloration dun
graphe dpend dune inconnue : lordre dans lequel les sommets sont slectionns.
Il est vrai que nous ne gardons avec cet algorithme aucun contrle de cet ordre,
puisque nous nous contentons de les numrer par for u in g ce qui minimise
surtout le temps dcriture du programme. Le chapitre 15, riche en enseignements,
a abord le sujet des ensembles numrs par Sage, dont Permutations fait partie.
Bien mieux que a, cette classe possde une mthode random_element dont nous
pouvons nous servir :
sage: P = Permutations([0,1,2,3]); P.random_element()
[2, 0, 1, 3]
Nous allons donc tenter dobtenir de meilleurs rsultats en colorant 30 fois les
sommets de notre graphe dans lordre donn par des permutations alatoires. Le
rsultat est le code suivant, que nous appliquons au graphe g dj dfini :
sage: couleurs_disponibles = Set(range(n))

sage: nombre_tests = 30
sage: vertices = g.vertices()
sage: P = Permutations(range(n))
sage: meilleure_coloration = {}
sage: meilleur_nombre_chromatique = +oo

sage: for t in range(nombre_tests):


....: # Ordre alatoire sur les sommets
....: p = P.random_element()
....: couleur = {}
....: for i in range(g.order()):
....: u = vertices[p[i]]
....: interdits = Set([couleur[v] for v in g.neighbors(u)
....: if v in couleur])
....: couleur[u] = min(couleurs_disponibles - interdits)
....: # Mise jour de la meilleure coloration
....: if max(couleur.values()) + 1 < meilleur_nombre_chromatique:
....: meilleure_coloration = couleur
....: meilleur_nombre_chromatique = 1 + max(couleur.values())

sage: # Nombre de couleurs utilises


sage: meilleur_nombre_chromatique
4
Soit un gain, tout de mme ! Toute cette artillerie de mise jour de minimum,
cependant, ntait pas ncessaire. Inutile de reprogrammer ce qui lest dj. En
Python, la trs grande majorit des objets et dans le cas prsent les paires
374 CHAP. 16. THORIE DES GRAPHES

entier, dictionnaire sont comparables, et ce dans lordre lexicographique


(on compare dabord les premiers termes un entier puis le second un
dictionnaire ce qui na pas beaucoup de signification ici). En rcrivant nos
premires lignes de code pour en faire une fonction, il est possible dobtenir le
rsultat suivant :
sage: def coloration_gloutonne(G, permutation):
....: n = g.order()
....: couleurs_disponibles = Set(xrange(n))
....: vertices = g.vertices()
....: couleur = {}
....: for i in range(g.order()):
....: u = vertices[permutation[i]]
....: interdits = Set([couleur[v] for v in g.neighbors(u)
....: if v in couleur])
....: couleur[u] = min(couleurs_disponibles - interdits)
....: return max(couleur.values()) + 1, couleur
Une fois cette fonction dfinie, faire 50 essais et rcuprer le minimum est une
trivialit :
sage: P = Permutations(range(g.order()))
sage: nombre_couleurs, coloration = min(
....: coloration_gloutonne(g, P.random_element()) for i in range(50))
sage: nombre_couleurs
4
Pour colorer un graphe en utilisant le nombre minimal de couleurs, il est
prfrable dutiliser la mthode coloring. Ce problme tant NP-complet, il faut
sattendre des temps de calcul plus longs que lors dune coloration gloutonne.
Exercice 62 (Ordre optimal pour la coloration gloutonne). Lalgorithme de colora-
tion gloutonne est capable de colorer un graphe avec le nombre minimum de couleurs
possible (i.e. (G)) sil parcourt les sommets dans le bon ordre. laide de la mthode
coloring, qui calcule une coloration optimale, crire une fonction renvoyant un ordre
sur les sommets partir duquel lalgorithme de coloration gloutonne construit une
coloration optimale.

16.3.2 Gnrer des graphes sous contraintes


Les graphes alatoires Gn,p ont des proprits de connexit trs intressantes.
En particulier, leurs coupes minimales sont presque srement le voisinage dun
sommet : on y trouve donc des coupes dont lune des deux composantes connexes
est un sommet unique. Ceci peut aussi paratre dplaisant : tout ensemble cons-
quent de sommets dfinit une coupe dont la cardinalit est trs grande devant
la coupe minimale. Il est cependant possible, avec beaucoup de patience (pour
obtenir de gros graphes) et quelques lignes de Sage, de produire des graphes
alatoires un peu diffrents. Voici la mthode que nous allons implmenter.
Fixons deux entiers n et k, le premier reprsentant un nombre de sommets
et le second une connectivit. Lalgorithme dbute avec un arbre sur n sommets,
16.3. GRAPHES EN ACTION 375

calcule une coupe minimale et ses deux ensembles correspondants. Tant que cette
coupe minimale est de cardinal infrieur k 0 < k, on ajoute au hasard k k 0
artes entre les deux ensembles.
Comme prcdemment, nous aurons besoin, tant donns deux ensembles S
de gnrer une paire dlments (s, s) S S.
et S, Nous utiliserons pour cela la
classe CartesianProduct et sa mthode random_element.
sage: n = 20; k = 4; g = graphs.RandomGNP(n, 0.5)
sage: g = g.subgraph(edges = g.min_spanning_tree())

sage: while True:


....: _, edges, [S,Sb] = g.edge_connectivity(vertices = True)
....: cardinality = len(edges)
....: if cardinality < k:
....: CP = CartesianProduct(S, Sb)
....: g.add_edges([CP.random_element()
....: for i in range(k - len(edges))])
....: else:
....: break
Tout est dit.

16.3.3 Appliquer un algorithme probabiliste pour trouver


un grand ensemble indpendant
Bien que Sage possde une mthode Graph.independent_set permettant de
trouver dans un graphe un ensemble indpendant (ensemble de sommets deux
deux non adjacents) de taille maximale, rien ne nous interdit dutiliser des
rsultats amusants de thorie des graphes pour dnicher nous-mmes un ensemble
indpendant. On lit par exemple dans le livre The Probabilistic Method [AS00]
quil existe dans tout graphe G un ensemble indpendant S tel que
1
|S| >
X
d(v) + 1
vG

o d(v) reprsente le degr de v. La preuve de ce rsultat tient dans lalgorithme


suivant.
Prenons au hasard une bijection n : V 7 {1, . . . , |V |}, associant chaque
sommet de G un entier unique. Associons maintenant cette fonction un ensemble
indpendant Sn , dfini comme tant lensemble des sommets de G ayant une
image infrieure celle de tous leurs voisins (sommets minimaux). Formellement,
cela scrit :

Sn = {v G : u tel que uv E(G), n(v) < n(u)}.

Cet ensemble est par dfinition un ensemble indpendant, mais comment


sassurer de sa taille ? Il suffit en fait de se demander, pour chaque sommet,
376 CHAP. 16. THORIE DES GRAPHES

avec quelle frquence celui-ci apparat dans lensemble Sn . Si nous considrons


lensemble P des bijections de V vers {1, . . . , |V |}, nous remarquons que
X XX
|Sn | = 1 si v est minimum pour n, 0 sinon
nP nP vG
XX 
= 1 si v est minimum pour n, 0 sinon
vG nP
X |P | X 1
= = |P | .
d(v) + 1 d(v) + 1
vG vG

Par consquent, une


P telle fonction correspond en moyenne un ensemble ind-
pendant de taille vG d(v)+1
1
. Pour esprer obtenir un ensemble de cette taille
sous Sage, nous utiliserons donc des bijections alatoires obtenues par la classe
Permutations, jusqu obtenir lensemble promis par le thorme :
sage: g = graphs.RandomGNP(40, 0.4)
sage: P = Permutations(range(g.order()))
sage: moyenne = sum( 1/(g.degree(v)+1) for v in g )

sage: while True:


....: n = P.random_element()
....: S = [v for v in g if all( n[v] < n[u] for u in g.neighbors(v))]
....: if len(S) >= moyenne:
....: break

16.3.4 Trouver un sous-graphe induit dans un graphe


alatoire
Nous allons ici nous intresser aux graphes alatoires Gn,p , rapidement dcrits
dans la section 16.1.2 portant sur les constructeurs de graphes. Comme nous
lavions alors mentionn, ces graphes possdent la proprit suivante.
Soit H un graphe, et 0 < p < 1. Alors :

lim P [H est un sous-graphe induit de Gn,p ] = 1


n+

ce qui signifie qu H et p fixs, un grand graphe alatoire Gn,p ne


manquera pas de contenir H comme sous-graphe induit (voir dfinition
page 360).
Rendons cela plus clair : tant donn un graphe H et un grand graphe alatoire,
il est possible de trouver une copie de H dans Gn,p , et ce en associant itrativement
chaque sommet vi de V (H) = {v1 , . . . , vk } un reprsentant h(vi ), o chaque vi
est une extension correcte des sommets dj slectionns. Nous suivrons donc
lalgorithme :
associer v1 un sommet alatoire h(v1 ) Gn,p ;
associer v2 un sommet alatoire h(v2 ) Gn,p tel que h(v1 ) est adjacent
h(v2 ) dans G si et seulement si v1 est adjacent v2 dans H ;
16.3. GRAPHES EN ACTION 377

...
aprs j < k tapes, nous avons associ un reprsentant h(vi ) Gn,p tous
les vi (i 6 j), de telle faon que pour tous i, i0 6 j, h(vi )h(vi0 ) E(G) si
et seulement vi vi0 E(H). Nous associons maintenant vj+1 un sommet
alatoire h(vj+1 ) tel que pour tout i 6 j, h(vj+1 ) vrifie que h(vi )h(vj+1 )
E(G) si et seulement vi vj+1 E(H) ;
...
aprs k tapes, le sous-graphe de Gn,p induit par les reprsentants des
sommets v1 , . . . , vk est une copie de H.
Proposition. Quand n devient grand, cette stratgie fonctionne avec haute
probabilit.
Dmonstration. Notons Hj = H[{v1 , . . . , vj }], et notons P [H 7ind Gn,p ] la
probabilit que H soit un sous-graphe induit de Gn,p . Nous pouvons borner
grossirement la probabilit que Hj , mais pas Hj+1 , soit un sous-graphe induit
de Gn,p de la faon suivante :
tant donne une copie de Hj dans un Gn,p , calculons la probabilit quaucun
autre sommet ne puisse complter la copie courante en une copie de Hj+1 .
La probabilit quun sommet soit acceptable tant de
pdHj+1 (vj+1 ) (1 p)jdHj+1 (vj+1 ) > min(p, 1 p)j ,
la probabilit quaucun des n j sommets restants ne soit acceptable est
dau plus
nj
1 min(p, 1 p)j .
Il existe dans notre graphe au maximum j! j copies diffrentes de Hj (en
n


fait nj faons de choisir un ensemble de j sommets, et j! bijections entre




ces sommets et ceux de Hj ).


Puisque 0 < p < 1, nous crivons 0 < = min(p, 1 p) ; par consquent la
probabilit que Hj , mais pas Hj+1 , soit un sous-graphe induit de Gn,p est au
plus, pour tout j 6 k fix,
 
n
j! (1 j )nj 6 j!nj (1 j )nj = o(1/n)
j
qui est asymptotiquement nulle lorsque n grandit. Finalement :
P [H 7ind Gn,p ] > 1 P [H2 7ind Gn,p , H3 67ind Gn,p ]
P [H3 7ind Gn,p , H4 67ind Gn,p ]
...
P [Hk1 7ind Gn,p , Hk 67ind Gn,p ]
Gn,p ] > 1
X
P [H 7ind j!nj (1 j )nj
j6k
1
>1k o .
n
378 CHAP. 16. THORIE DES GRAPHES

De plus, cette dmonstration nous donne un algorithme probabiliste permettant


de trouver une copie dun graphe H dans un graphe alatoire Gn,p . Bien que cet
algorithme ne trouve pas toujours une copie de H si celle-ci existe, la probabilit
quil russisse tend vers 1 lorsque n tend vers linfini.
sage: def trouver_induit(H, G):
....: # la fonction de V(H) vers V(G) que nous cherchons dfinir
....: f = {}
....: # ensemble de sommets de G non encore utiliss par f
....: G_restants = G.vertices()
....: # L'ensemble des sommets pour lesquels nous n'avons
....: # pas encore trouv de reprsentant
....: H_restants = H.vertices()
....: # Tant que la fonction n'est pas complte
....: while H_restants:
....: v = H_restants.pop(0) # cherchons le sommet suivant de H
....: # et ses images potentielles
....: candidats = [u for u in G_restants if
....: all([H.has_edge(h,v) == G.has_edge(f_h,u)
....: for h, f_h in f.iteritems()])]
....: # Si nous n'en trouvons pas, nous abandonnons immdiatement !
....: if not candidats:
....: raise ValueError("No copy of H has been found in G")
....: # Sinon, nous prenons le premier d'entre eux
....: f[v] = candidats[0]
....: G_restants.remove(f[v])
....: return f

En une ligne. Pour trouver une copie dun graphe H dans un graphe G, il est
plus efficace de faire appel la mthode Graph.subgraph_search.

16.4 Quelques problmes modliss par des


graphes
16.4.1 Une nigme du journal Le Monde 2
On pouvait lire dans lexemplaire 609 du Monde 2 lnigme suivante.
Quelle est la taille du plus grand ensemble S [0, ..., 100] qui ne
contient pas deux entiers i, j S tels que |i j| est un carr ?
Ce problme est facilement modlisable dans le formalisme de la thorie des
graphes. La relation |i j| est un carr ? tant binaire et symtrique, nous
commencerons par crer le graphe sur lensemble de sommets [0, . . . , 100] dans
lequel deux sommets sont adjacents (incompatibles) si leur diffrence est un carr.
Nous utiliserons pour cela la classe Subsets qui nous permet dans le cas prsent
ditrer sur les sous-ensembles de taille 2.
16.4. QUELQUES PROBLMES MODLISS PAR DES GRAPHES 379

sage: n = 100; V = range(n+1)


sage: G = Graph()
sage: G.add_edges([
....: (i,j) for i,j in Subsets(V,2) if is_square(abs(i-j)) ])
Puisque nous sommes la recherche dun ensemble maximum dlments
compatibles , nous pouvons faire appel la mthode independent_set, qui
renvoie un sous-ensemble maximum dlments deux deux non-adjacents.
sage: G.independent_set()
[4, 6, 9, 11, 16, 21, 23, 26, 28, 33, 38, 43, 50,
56, 61, 71, 76, 78, 83, 88, 93, 95, 98, 100]
La rponse est donc 24, et pas 42 . Par consquent, lnigme du Monde 2
ntait pas La grande question sur la vie, lunivers et le reste , quil faudra
rechercher ailleurs.

16.4.2 Affectation de tches


Nous sommes maintenant dans la situation suivante : en face dun important
chantier, dix personnes doivent effectuer un total de dix tches. On peut associer
chaque personne une sous-liste de tches qui rentrent dans ses comptences.
Comment distribuer les tches afin que tout soit fait dans les rgles de lart ?
L encore, nous commencerons par modliser le problme par un graphe : il
sera biparti, dfini sur lunion {w0 , . . . , w9 } {t0 , . . . , t9 } des personnes et des
tches, et nous dfinirons ti comme adjacent wj si wj est capable deffectuer ti .
sage: tasks = {0: [2, 5, 3, 7], 1: [0, 1, 4],
....: 2: [5, 0, 4], 3: [0, 1],
....: 4: [8], 5: [2],
....: 6: [8, 9, 7], 7: [5, 8, 7],
....: 8: [2, 5, 3, 6, 4], 9: [2, 5, 8, 6, 1]}
sage: G = Graph()
sage: for i in tasks:
....: G.add_edges(("w" + str(i), "t" + str(j)) for j in tasks[i])
Il ne nous reste plus maintenant qu utiliser la mthode matching, qui nous
renverra un ensemble maximum de tches qui peuvent tre effectues simultan-
ment par des personnes comptentes :
sage: for task, worker,_ in sorted(G.matching()):
....: print task, "peut tre effectue par", worker
t0 peut tre effectue par w2
t1 peut tre effectue par w3
t2 peut tre effectue par w5
t3 peut tre effectue par w8
t4 peut tre effectue par w1
t5 peut tre effectue par w7
t6 peut tre effectue par w9
t7 peut tre effectue par w0
380 CHAP. 16. THORIE DES GRAPHES

t8 peut tre effectue par w4


t9 peut tre effectue par w6

16.4.3 Planifier un tournoi

tant donn un nombre n dquipes participant un tournoi, lors duquel toutes


les paires dquipes doivent se rencontrer, comment peut-on planifier les matches
de la faon la plus rapide possible, sachant que plusieurs matches peuvent avoir
lieu simultanment ?

Ce problme est un cas typique dapplication de la coloration propre dartes


en thorie des graphes. Ce problme consiste, tant donn un graphe G, assigner
une couleur chaque arte afin quaucun sommet ne touche deux artes de mme
couleur. De manire quivalente, ce problme revient trouver une partition des
artes en couplages (union dartes disjointes) de cardinal minimum. Dans le cas
prsent, nous chercherons colorer les artes du graphe complet chacune dentre
elles reprsentant le match devant avoir lieu entre les quipes correspondant ses
deux extrmits :

sage: n = 10
sage: G = graphs.CompleteGraph(n)
sage: from sage.graphs.graph_coloring import edge_coloring
sage: for jour,matches in enumerate(edge_coloring(G)):
....: print "Matches du jour", jour, ":", matches
Matches du jour 0 : [(0, 9), (1, 8), (2, 7), (3, 6), (4, 5)]
Matches du jour 1 : [(0, 2), (1, 9), (3, 8), (4, 7), (5, 6)]
Matches du jour 2 : [(0, 4), (1, 3), (2, 9), (5, 8), (6, 7)]
Matches du jour 3 : [(0, 6), (1, 5), (2, 4), (3, 9), (7, 8)]
Matches du jour 4 : [(0, 8), (1, 7), (2, 6), (3, 5), (4, 9)]
Matches du jour 5 : [(0, 1), (2, 8), (3, 7), (4, 6), (5, 9)]
Matches du jour 6 : [(0, 3), (1, 2), (4, 8), (5, 7), (6, 9)]
Matches du jour 7 : [(0, 5), (1, 4), (2, 3), (6, 8), (7, 9)]
Matches du jour 8 : [(0, 7), (1, 6), (2, 5), (3, 4), (8, 9)]

Il serait ais dadapter cette solution au cas o tous les participants nauraient
pas se rencontrer les uns les autres.

Pour le plaisir, limage suivante, qui reprsente une coloration propre des artes
du graphe complet. Une couleur commune indique que les matches correspondants
ont lieu le mme jour.

sage: g = graphs.CompleteGraph(10)
sage: g.show(edge_colors=edge_coloring(g, hex_colors=True))
16.4. QUELQUES PROBLMES MODLISS PAR DES GRAPHES 381
382 CHAP. 16. THORIE DES GRAPHES
17
Programmation linaire

Le chapitre prsent aborde la programmation linaire (LP), et la programma-


tion linaire en nombres entiers (MILP), avec force illustrations des problmes
quelles permettent de rsoudre. Les exemples donns seront en grande partie
issus de la thorie des graphes, les plus simples pouvant tre compris sans connais-
sance spcifique. En tant quoutil pour la combinatoire, utiliser la programmation
linaire se rduit comprendre comment rcrire un problme dexistence ou
doptimisation sous la forme de contraintes linaires.

17.1 Dfinition
Un programme linaire est un systme dquations linaires dont on cherche
une solution optimale. Formellement, on le dfinit par une matrice A : Rm 7 Rn
et deux vecteurs b Rn et c Rm . Rsoudre un programme linaire revient alors
trouver un vecteur x Rm maximisant une fonction objectif, tout en satisfaisant
un systme de contraintes, i.e.,

ct x = max ct y
y tel que Ay6b

o la relation u 6 u0 entre deux vecteurs indique que les valeurs de u sont


infrieures ou gales aux valeurs de u0 , composante par composante. Nous crirons
aussi :

maximiser : ct x
tel que : Ax 6 b.
384 CHAP. 17. PROGRAMMATION LINAIRE

Le programme linaire suivant admet pour solution x = 4, y = 0, z = 1.6 :

max : x + y + 3z
tel que : x + 2y 6 4
5z y 6 8.

De faon quivalente, nous pourrions dire que rsoudre un programme linaire


revient trouver un point maximisant une fonction linaire dfinie sur un poly-
tope (en loccurrence la primage A1 (6 b)). Ces dfinitions ne nous expliquent
cependant pas encore lintrt de la programmation linaire en combinatoire, ce
qui est lobjet principal du prsent chapitre. Nous verrons donc comment utiliser
ce formalisme pour rsoudre, entre autres, les problmes de sac dos (17.4.1), de
couplage (17.4.2), ou de flot (17.4.3). Dans 17.5, nous utiliserons les gnrations
de contraintes pour rsoudre le problme dexistence de cycle hamiltonien.

17.2 Programmation entire


La dfinition donne linstant saccompagne dune mauvaise nouvelle : la
rsolution dun programme linaire peut tre faite en temps polynomial. Cest une
mauvaise nouvelle, parce que cela signifie qu moins de dfinir des programmes
linaires de taille exponentielle, il ne serait pas possible dutiliser cette mthode
pour rsoudre des problmes NP-complets. Heureusement, tout se complique
lorsque lon ajoute comme contrainte que toutes ou certaines des composantes
de x doivent tre entires, et non relles. On obtient alors, selon les cas, un
programme linaire en nombres entiers (ILP), ou bien si seulement certaines
composantes doivent tre entires, un programme linaire mixte (en anglais Mixed
Integer Linear Program ou MILP).
La rsolution de ILP ou de MILP est elle un problme NP-complet. Nous
pouvons donc en attendre beaucoup.

17.3 En pratique
17.3.1 La classe MixedIntegerLinearProgram
La classe MixedIntegerLinearProgram reprsente dans Sage un ... MILP !
On lutilise cependant aussi pour rsoudre des problmes continus si ncessaire.
Elle possde un nombre trs rduit de mthodes, qui servent dfinir le MILP,
le rsoudre, puis lire la solution obtenue. Il est aussi possible de visualiser son
contenu, ou de lexporter aux formats LP ou MPS tous deux standards.
Pour lillustrer, rsolvons le programme linaire prsent en 17.1. Il faut pour
cela construire un objet de la classe MixedIntegerLinearProgram,
sage: p = MixedIntegerLinearProgram()
les 3 variables dont nous avons besoin,
sage: x, y, z = p['x'], p['y'], p['z']
17.3. EN PRATIQUE 385

la fonction objectif,
sage: p.set_objective( x + y + 3*z )
puis les contraintes :
sage: p.add_constraint( x + 2*y <= 4 )
sage: p.add_constraint( 5*z - y <= 8 )
La mthode solve de MixedIntegerLinearProgram renvoie la valeur optimale
de la fonction objectif :
sage: p.solve()
8.8
On obtient une affectation optimale pour x, y, et z en appelant la mthode
get_values :
sage: p.get_values(x), p.get_values(y), p.get_values(z)
(4.0, 0.0, 1.6)

17.3.2 Variables
Les variables associes une instance de MixedIntegerLinearProgram sont
des objets de type MIPVariable, mais cela ne nous concerne pas vraiment. Dans
lexemple prcdent, nous avons obtenu ces variables par le raccourci p[x],
ce qui est suffisant lorsque le nombre de variables est rduit. Les programmes
linaires que nous dfinirons par la suite demandent rgulirement dassocier des
variables une liste dobjets comme des entiers, les sommets dun graphe, ou
quantit dautres choses. Il est donc ncessaire de pouvoir parler de vecteur de
variables, voire de dictionnaire de variables.
Par exemple, si notre programme linaire ncessite de dfinir des variables
x1 , . . . , x15 , il sera bien plus ais de faire appel la mthode new_variable :
sage: x = p.new_variable()
Il est maintenant possible de dfinir des contraintes en utilisant nos 15 variables :
sage: p.add_constraint( x[1] + x[12] - x[14] >= 8 )
On remarquera quil nest pas ncessaire pour cela de dfinir la taille du
vecteur x. En fait, x acceptera sans discuter toute clef de type immuable (cf. 3.3.7),
exactement comme un dictionnaire. On peut donc se permettre dcrire :
sage: p.add_constraint( x["je_suis_un_indice_valide"] + x["a",pi] <= 3 )
On notera au passage que ce formalismePpermet lutilisation de variables
indices multiples. Pour dfinir la contrainte 06i,j<4 xi,j 6 1 on crira :

sage: p.add_constraint( p.sum(


....: x[i,j] for i in range(4) for j in range(4)) <= 1 )
La notation x[i,j] est quivalente la notation x[(i,j)].
386 CHAP. 17. PROGRAMMATION LINAIRE

Types de variables. Par dfaut, les variables renvoyes par new_variable sont
de type rel positif ou nul. Il est possible de les dfinir comme binaires en utilisant
largument binary = True ou entires avec integer = True. On pourra par la
suite dfinir ou redfinir des bornes minimales et maximales pour les variables
(par exemple pour obtenir des valeurs ngatives) laide des mthodes set_min et
set_max. Il est aussi possible de changer le type dune variable aprs sa cration,
laide des mthodes set_binary, set_integer ou set_real.

17.3.3 Problmes infaisables ou non borns


Certains programmes linaires nont, formellement, pas de solution. Il est en
effet ambitieux de chercher optimiser une fonction mme linaire sur un
ensemble vide, ou linverse sur un domaine si peu contraint que la fonction
objectif ny est pas borne. Dans les deux cas, Sage renverra une exception lors
de lappel de la mthode solve :
sage: p = MixedIntegerLinearProgram()
sage: p.set_objective( p[3] + p[2] )
sage: p.add_constraint( p[3] <= 5 )

sage: p.solve()
Traceback (most recent call last):
...
MIPSolverException: 'GLPK : Solution is undefined'

sage: p.add_constraint( p[2] <= 8 )


sage: p.solve()
13.0

sage: p.add_constraint( p[3] >= 6 ); p.solve()


Traceback (most recent call last):
...
MIPSolverException: 'GLPK : Solution is undefined'
De mme, la contrainte dintgrit dune variable peut rendre le domaine vide :
sage: p = MixedIntegerLinearProgram()
sage: p.set_objective( p[3] )
sage: p.add_constraint( p[3] <= 4.75 ); p.add_constraint( p[3] >= 4.25 )
sage: p.solve()
4.75
sage: p.set_integer(p[3]); p.solve()
Traceback (most recent call last):
...
MIPSolverException: 'GLPK : Solution is undefined'
Quel que soit le cas de figure, il serait draisonnable de stopper net un code sous
prtexte quun programme linaire na pas pu tre rsolu ; certains programmes
linaires ont dailleurs pour unique but de tester lexistence dune solution, et sont
17.4. PREMIRES APPLICATIONS LA COMBINATOIRE 387

donc souvent infaisables. Pour grer ces cas de figure, on utilisera le mcanisme
classique try-except de Python pour linterception des exceptions :
sage: try:
....: p.solve()
....: print "Le problme a une solution !"
....: except:
....: print "Le problme est infaisable !"
Le problme est infaisable !

17.4 Premires applications la combinatoire


Maintenant que les bases sont tablies, passons un aspect plus intressant, la
modlisation. Dans cette section se trouvent plusieurs problmes doptimisation
ou dexistence : on commence par donner leur dfinition abstraite, puis une
modlisation en tant que MILP, permettant dobtenir en quelques lignes de code
un algorithme pour un problme NP-complet.

17.4.1 Sac dos


Le problme dit du sac dos est le suivant. Nous avons en face de nous
une srie dobjets ayant tous un poids propre, ainsi quune utilit mesure
par un rel. Nous souhaitons maintenant choisir certains de ces objets en nous
assurant que la charge totale ne dpasse pas une constante C, la meilleure faon
de le faire tant pour nous doptimiser la somme des utilits des objets contenus
dans le sac.
Pour cela, nous associerons chaque objet o dune liste L une variable binaire
prendre[o], valant 1 si lobjet doit tre mis dans le sac, et 0 sinon. Nous cherchons
donc rsoudre le MILP suivant :
X
max : utilito prendreo
oL

poidso prendreo 6 C.
X
tel que :
oL

Sous Sage, nous associerons aux objets un cot et une utilit :


sage: C = 1
sage: L = ["Casserole", "Livre", "Couteau", "Gourde", "Lampe de poche"]
sage: p = [0.57,0.35,0.98,0.39,0.08]; u = [0.57,0.26,0.29,0.85,0.23]
sage: poids = {}; utilite = {}
sage: for o in L:
....: poids[o] = p[L.index(o)]; utilite[o] = u[L.index(o)]
Nous pouvons maintenant crire le MILP lui-mme.
sage: p = MixedIntegerLinearProgram()
sage: prendre = p.new_variable( binary = True )
388 CHAP. 17. PROGRAMMATION LINAIRE

sage: p.add_constraint(
....: p.sum( poids[o] * prendre[o] for o in L ) <= C )
sage: p.set_objective(
....: p.sum( utilite[o] * prendre[o] for o in L ) )
sage: p.solve()
1.4199999999999999
sage: prendre = p.get_values(prendre)

La solution trouve vrifie bien la contrainte de poids :


sage: sum( poids[o] * prendre[o] for o in L )
0.960000000000000

Faut-il prendre une gourde ?


sage: prendre["Gourde"]
1.0

Exercice 63 (Subset Sum). Le problme calculatoire dnomm Subset Sum consiste


trouver, dans un ensemble dentiers relatifs, un sous-ensemble non vide dlments
dont la somme est nulle. Rsoudre ce problme avec un programme linaire en nombres
entiers sur lensemble {28, 10, 89, 69, 42, 37, 76, 78, 40, 92, 93, 45}.

17.4.2 Couplages
Trouver un couplage dans un graphe, cest trouver un ensemble dartes deux
deux disjointes. Lensemble vide tant un couplage, lattention se porte plutt
sur les couplages maximum : on cherche maximiser le nombre dartes dun
couplage. Le problme de couplage maximum est un problme polynomial, en
vertu dun rsultat de Jack Edmonds [Edm65]. Son algorithme se base sur des
amliorations locales et la preuve que lalgorithme ne sarrte quen prsence dun
couplage maximum. Il ne sagit pas l dun des algorithmes les plus difficiles
implmenter en thorie des graphes, mais il demeure que sa formulation en MILP
ne prend que deux lignes.
Il nous faudra pour cela, comme prcdemment, associer chacun de nos
objets les artes dun graphe une valeur binaire indiquant si oui ou non
cette arte appartient notre couplage.
Il faut ensuite nous assurer que deux artes adjacentes ne peuvent pas se
trouver simultanment dans le couplage. Cela ressemble, mme de trs loin, une
contrainte linaire : si x et y sont deux artes dun mme graphe, et si mx et my
sont les deux variables qui leur sont associes, il suffit dexiger que mx + my 6 1.
Ces deux artes ne pourront pas se trouver simultanment dans notre solution, et
nous sommes donc capables dcrire un programme linaire calculant un couplage
maximum. Il est cependant possible dtre plus expditif, en remarquant que si
deux artes ne peuvent pas tre dans un couplage simultanment, cest parce
quelles passent toutes les deux par un sommet v du graphe. Il est donc plus rapide
de dire que chaque sommet v est touch par au plus une arte dun couplage.
17.4. PREMIRES APPLICATIONS LA COMBINATOIRE 389

Cette contrainte, elle aussi, est linaire.


X
max : me
eE(G)

me 6 1.
X
tel que : v V (G),
eE(G)
e=uv

Sous Sage, un tel MILP se retranscrit facilement :


sage: g = graphs.PetersenGraph()
sage: p = MixedIntegerLinearProgram()
sage: couplage = p.new_variable(binary = True)

sage: p.set_objective(p.sum(couplage[e]
....: for e in g.edges(labels = False)))

sage: for v in g:
....: p.add_constraint(p.sum(couplage[e]
....: for e in g.edges_incident(v, labels = False)) <= 1)
sage: p.solve()
5.0

sage: couplage = p.get_values(couplage)


sage: [e for e, b in couplage.iteritems() if b == 1]
[(0, 1), (6, 9), (2, 7), (3, 4), (5, 8)]
Exercice 64 (Ensemble dominant). Un ensemble dominant dun graphe est un
ensemble S de sommets tel que tout sommet qui nest pas dans S a au moins un voisin
dans S. crire un programme linaire en nombres entiers pour trouver un ensemble
dominant de cardinal minimum dans le graphe de Petersen.

17.4.3 Flot
Cette section prsente un autre algorithme fondamental de la thorie des
graphes : le flot ! Celui-ci consiste, tant donns deux sommets s et t dun graphe
dirig G (cest--dire dont les artes ont une direction, voir figure 17.1), faire
passer de s t un flux (flot) maximum, en utilisant pour cela les artes de G.
Chacune de ces artes possde une capacit maximale i.e., le flux maximal
pouvant les traverser.
La dfinition de ce problme nous offre directement sa formulation en pro-
gramme linaire : nous sommes la recherche dune valeur relle associe
chaque arte, reprsentant lintensit du flot la traversant, et rpondant deux
contraintes :
la quantit de flot arrivant sur un sommet (diffrent de s ou de t) doit tre
gale la quantit de flot quittant ce sommet ;
une arte ne peut pas tre traverse par un flot suprieur sa capacit.
390 CHAP. 17. PROGRAMMATION LINAIRE

Figure 17.1 Un problme de flot sur le graphe de Chvtal.

Ceci tant dit, il ne reste plus qu chercher maximiser la valeur du flot


quittant s : celui-ci ne pourra terminer sa course quau point t, puisque les
autres sommets ne font que retransmettre ce quils reoivent. On formule donc le
problme de flot par le programme linaire suivant (en supposant les capacits
des artes gales 1) :
X
max : fsv
svE(G)
X X
tel que : v V (G)\{s, t}, fvu = fuv
vuE(G) uvE(G)

uv E(G), fuv 6 1.

Nous rsolvons ici le problme de flot sur une orientation du graphe de Chvtal
(cf. figure 17.1), dans lequel les capacits des artes sont toutes gales 1 :
sage: g = graphs.ChvatalGraph()
sage: g = g.minimum_outdegree_orientation()

sage: p = MixedIntegerLinearProgram()
sage: f = p.new_variable()
sage: s, t = 0, 2

sage: for v in g:
....: if v == s or v == t: continue
....: p.add_constraint(
....: p.sum(f[v,u] for u in g.neighbors_out(v)) ==
....: p.sum(f[u,v] for u in g.neighbors_in(v)))

sage: for e in g.edges(labels = False): p.add_constraint( f[e] <= 1 )


17.5. GNRATION DE CONTRAINTES ET APPLICATION 391

sage: p.set_objective(p.sum( f[s,u] for u in g.neighbors_out(s)))

sage: p.solve()
2.0

17.5 Gnration de contraintes application


au problme du voyageur de commerce
Bien que les exemples prcdents puissent donner limpression dune grande
expressivit, linterprtation dun problme doptimisation (ou dexistence)
donne par sa formulation en programme linaire est un choix arbitraire. Un mme
problme peut tre rsolu par diffrentes formulations dont les performances sont
elles aussi trs variables. Ceci nous mne utiliser de faon plus intelligente les
capacits des solveurs de MILP en leur demandant maintenant de rsoudre des
programmes linaires dont ils ne connaissent pas toutes les contraintes, et en
najoutant que celles qui leur sont ncessaires au fur et mesure de la rsolution :
cette technique devient indispensable ds que le nombre de contraintes est trop
grand pour pouvoir tre explicit lors de la cration du programme linaire. Nous
nous apprtons rsoudre le problme de cycle hamiltonien (cas particulier du
voyageur de commerce traveling salesman problem).

Figure 17.2 La grille de taille 4 6 sur laquelle nous testerons nos formulations.

On dit quun cycle C E(G) contenu dans un graphe G est hamiltonien sil
passe par tous les sommets de G. Tester lexistence dun cycle hamiltonien dans
un graphe donn est un problme NP-complet : il ne faut donc pas sattendre
trouver de faon rapide de le rsoudre, ce qui ne doit pas nous empcher de
tenter de le formuler en tant que programme linaire. Une premire formulation
pourrait commencer de la faon suivante :
associer chaque arte une variable binaire be indiquant si larte est incluse
dans le circuit C ;
imposer chaque sommet davoir exactement deux de ses artes incidentes
dans C.
392 CHAP. 17. PROGRAMMATION LINAIRE

Cette formulation nest malheureusement pas exacte. Il est en effet tout fait
possible que la solution obtenue par cette formulation soit lunion disjointe de
plusieurs cycles chaque sommet aurait donc bien deux voisins dans C, mais il
ne serait pas ncessairement possible daller dun sommet v un sommet u en
nutilisant que les artes de C.

Figure 17.3 Une solution possible aux quations de degrs.

Il est cependant possible de trouver une formulation plus complexe et exacte


(dite formulation de Miller-Tucker-Zemlin) :
on associe chaque sommet v du graphe un entier iv reprsentant ltape
laquelle le cycle C le traverse, avec iv0 = 0 pour un sommet v0 fix ;
on associe chaque arte uv de G deux variables binaires buv et bvu indiquant
si larte fait partie du cycle C (et nous indiquant aussi dans quelle direction
cette arte est utilise) ;
on impose chaque sommet davoir une arte sortante et une arte entrante
dans C ;
une arte uv ne peut appartenir C que si iu < iv (les artes vont dans le
sens croissant des ordres de visite).
Cette formulation peut tre transcrite en quations linaires de la faon suivante :

max : pas de fonction optimiser


X
tel que : u V (G), buv = 1
uvE(G)
X
u V (G), bvu = 1
uvE(G)

uv E(G\v0 ), iu iv + |V (G)|buv 6 |V (G)| 1


iv iu + |V (G)|bvu 6 |V (G)| 1
v V (G), iv 6 |V (G)| 1
buv est une variable binaire
iv est une variable entire.
17.5. GNRATION DE CONTRAINTES ET APPLICATION 393

On notera la prsence dun coefficient |V (G)| dans cette formulation, ce qui


est assez frquemment le signe que le solveur ne parviendra pas rapidement
rsoudre le problme linaire. Aussi, nous utiliserons une autre modlisation du
problme de cycle hamiltonien. Son principe est en fait bien plus simple, et repose
sur lobservation suivante : sil existe un cycle hamiltonien C dans notre graphe,
il existe pour tout ensemble propre S de sommets au moins deux artes de C
entrant ou sortant de S. Si lon choisit de noter S lensemble des artes ayant
exactement une seule extrmit dans S, nous obtenons la formulation suivante
(en identifiant les variables buv et bvu ) :

max : pas de fonction optimiser


X
tel que : u V (G), buv = 2
uvE(G)

ve > 2
X
S V (G), =
6 S 6= V (G),

eS
buv est une variable binaire.

Il serait cependant risqu dutiliser aussi directement que prcdemment cette


formulation pour rsoudre un problme de cycle hamiltonien, mme sur un graphe
aussi petit que notre grille 4 6 = 24 lments : les contraintes portant sur
les ensembles S seraient au nombre de 224 2 = 16 777 214. En revanche, la
mthode branch-and-bound (ou branch-and-cut) utilise par les solveurs dinqua-
tions linaires se prte bien la gnration de contraintes durant la rsolution
dun programme linaire 1 . Gnrer des contraintes pour le problme de cycle
hamiltonien consiste donc suivre les tapes suivantes :
crer un programme linaire sans fonction dobjectif ayant une variable
binaire par arte ;
ajouter pour chaque sommet la contrainte imposant un degr de 2 ;
rsoudre le programme linaire ;
tant que la solution courante nest pas un cycle hamiltonien (cest donc un
sous-graphe ayant plusieurs composantes connexes), appeler S lune de ses
composantes connexes et ajouter la contrainte imposant quau moins deux
artes sortent de S.
Heureusement pour nous, il est algorithmiquement rapide de vrifier que
la solution courante est invalide et de gnrer la contrainte correspondante. En
utilisant la gnration de contraintes par Sage, voici comment rsoudre le problme
du cycle hamiltonien sur notre grille :
sage: g = graphs.Grid2dGraph(4, 6)
sage: p = MixedIntegerLinearProgram()
sage: b = p.new_variable(binary = True)

1. Cest--dire quil est possible, une fois un programme linaire rsolu, dajouter une
contrainte additionnelle et de rsoudre le nouveau programme en utilisant une partie des calculs
effectus durant la rsolution qui vient davoir lieu.
394 CHAP. 17. PROGRAMMATION LINAIRE

Figure 17.4 Un cycle hamiltonien calcul par gnration de contraintes.

Pour viter la diffrence entre les variables b[u,v] et b[v,u], il est pratique
de crer une lambda-fonction remplaant le couple x, y par lensemble {x, y} :
sage: B = lambda x,y : b[frozenset([x,y])]
Ajoutons maintenant les contraintes de degr :
sage: for u in g:
....: p.add_constraint( p.sum( B(u,v) for v in g.neighbors(u) ) == 2 )
Il est temps de calculer la premire solution de notre problme et de crer le
graphe la reprsentant,
sage: p.solve()
0.0
sage: h = Graph()
sage: h.add_edges( [(u,v) for u, v in g.edges(labels = False)
....: if p.get_values(B(u,v)) == 1.0 ] )
puis de commencer nos itrations :
sage: while not h.is_connected():
....: S = h.connected_components()[0]
....: p.add_constraint(
....: p.sum( B(u,v) for u,v
....: in g.edge_boundary(S, labels = False))
....: >= 2)
....: zero = p.solve()
....: h = Graph()
....: h.add_edges( [(u,v) for u,v in
....: g.edges(labels = False)
....: if p.get_values(B(u,v)) == 1.0 ] )
En moins dune dizaine ditrations (et donc en ralisant une conomie de
calculs agrable par rapport 224 2) nous obtenons une solution admissible pour
notre grille (cf. figure 17.4). Les performances de cette mthode de rsolution sont
17.5. GNRATION DE CONTRAINTES ET APPLICATION 395

incomparables celles de la formulation de Miller-Tucker-Zemlin. Lorsque lon


implmente les deux programmes linaires sous Sage, on obtient sur un graphe
alatoire G35,0.3 les temps de calcul suivants :
sage: g = graphs.RandomGNP(35, 0.3)
sage: %time MTZ(g)
CPU times: user 51.52 s, sys: 0.24 s, total: 51.76 s
Wall time: 52.84 s
sage: %time constraint_generation(g)
CPU times: user 0.23 s, sys: 0.00 s, total: 0.23 s
Wall time: 0.26 s
396 CHAP. 17. PROGRAMMATION LINAIRE
Annexes
Solutions des exercices
A
A.1 Premiers pas
Exercice 1 page 16. La commande SR.var('u') cre la variable symbolique u
et laffecte la variable informatique u. La variable informatique u reoit ensuite
deux reprises sa valeur courante plus un, soit u + 1 puis u + 2 (o u est toujours
la variable symbolique).
A.2 Analyse et algbre avec Sage
Exercice 2 page 28. (Un calcul de somme par rcurrence)
sage: n = var('n'); pmax = 4; s = [n + 1]
sage: for p in [1..pmax]:
....: s += [factor(((n+1)^(p+1) - sum(binomial(p+1, j) * s[j]
....: for j in [0..p-1])) / (p+1))]
sage: s
On obtient ainsi :
n n
X 1 X 1
k = (n + 1)n, k2 = (n + 1)(2 n + 1)n,
2 6
k=0 k=0
n n
X 1 2
X 1
k 3 = (n + 1) n2 , k4 = (n + 1)(2 n + 1) 3 n2 + 3 n 1 n.

4 30
k=0 k=0

Exercice 3 page 31. (Un calcul symbolique de limite) Pour rpondre la


question, on va utiliser une fonction symbolique, dont on va calculer le polynme
de Taylor en 0 lordre 3.
400 ANNEXE A. SOLUTIONS DES EXERCICES

sage: x, h, a = var('x, h, a'); f = function('f')


sage: g(x) = taylor(f(x), x, a, 3)
sage: phi(h) = (g(a+3*h) - 3*g(a+2*h) + 3*g(a+h) - g(a)) / h^3; phi(h)
D[0, 0, 0](f)(a)
La fonction g diffre de f dun reste qui est ngligeable devant h3 , donc la fonction
phi diffre du quotient tudi dun reste qui est o(1) ; donc phi a pour limite en
zro la limite cherche. En conclusion,
1 000
lim f (a + 3h) 3f (a + 2h) + 3f (a + h) f (a) = f (a).

h0 h3

Cette formule permet notamment deffectuer un calcul approch de la drive


tierce de f en a sans effectuer aucune drivation.
On peut supposer que la formule se gnralise sous la forme suivante :
n
!
1 X
 
nk n
lim (1) f (a + kh) = f (n) (a).
h0 hn k
k=0

Pour tester cette formule pour de plus grandes valeurs de n, on peut alors
facilement adapter ce qui prcde :
sage: n = 7; x, h, a = var('x h a'); f = function('f')
sage: g(x) = taylor(f(x), x, a, n)
sage: sum((-1)^(n-k) * binomial(n,k) * g(a+k*h) for k in (0..n)) / h^n
D[0, 0, 0, 0, 0, 0, 0](f)(a)
Exercice 4 page 32. (Une formule due Gauss)
1. On utilise successivement trig_expand et trig_simplify :
sage: theta = 12*arctan(1/38) + 20*arctan(1/57) \
....: + 7*arctan(1/239) + 24*arctan(1/268)
sage: tan(theta).trig_expand().trig_simplify()
1

2. La fonction tangente est convexe sur I = 0, 4 , donc sa courbe reprsenta-


 

tive est en-dessous de sa corde ; autrement dit x I, tan x 6 4 x.


sage: 12*(1/38) + 20*(1/57) + 7*(1/239) + 24*(1/268)
37735/48039
On en dduit :
1 1 1 1
= 12 arctan + 20 arctan + 7 arctan + 24 arctan
38 57 239 268
1 1 1 1
6 12 + 20 +7 + 24
38 57 239 268
37735 4
= 6 .
48039
Donc I ; or (cf. question 1) tan = 1 = tan 4 et tan est injective sur I.
On en conclut = 4 .
A.2. ANALYSE ET ALGBRE AVEC SAGE 401

3. On substitue le polynme de Taylor dans la formule de Gauss :


sage: x = var('x'); f(x) = taylor(arctan(x), x, 0, 21)
sage: approx = 4 * (12 * f(1/38) + 20 * f(1/57)
....: + 7 * f(1/239) + 24 * f(1/268))
sage: approx.n(digits = 50); pi.n(digits = 50)
3.1415926535897932384626433832795028851616168852864
3.1415926535897932384626433832795028841971693993751
sage: approx.n(digits = 50) - pi.n(digits = 50)
9.6444748591132486785420917537404705292978817080880e-37

Exercice 5 page 33. (Dveloppement asymptotique dune suite) Lencadrement


de xn permet daffirmer xn n, soit xn = n + o(n).
On injecte alors cette galit dans lquation suivante, obtenue partir de
arctan x + arctan(1/x) = /2 :

1
 

xn = n + arctan .
2 xn

On rinjecte ensuite les dveloppements asymptotiques de xn ainsi obtenus


dans cette quation, bis repetita... (mthode des raffinements successifs).
Sachant qu chaque tape, un dveloppement dordre p permet dobtenir un
dveloppement lordre p + 2, on peut obtenir en quatre tapes un dveloppement
dordre 6. En anticipant sur le chapitre 3, on peut effectuer ces quatre tapes
lintrieur dune boucle.
sage: n = var('n'); phi = lambda x: n*pi + pi/2 - arctan(1/x)
sage: x = n*pi
sage: for i in range(4):
....: x = taylor(phi(x), n, infinity, 2*i); x
Au final, on obtient :

1 1 1 1 1 3 2 + 8 1 2 + 8
xn = + n + +
2 n 2 n2 12 3 n3 8 3 n4
1 15 + 240 + 208
4 2
1 3 4 + 80 2 + 208 1
 
+ + O
240 5 n5 96 5 n6 n7

Exercice 6 page 34. (Un contre-exemple d Peano au thorme de Schwarz)


Les applications partielles f (x, 0) et f (0, x) sont identiquement nulles en (0, 0) ;
on en dduit, sans calculs, 1 f (0, 0) = 2 f (0, 0) = 0. On calcule alors les valeurs
des drives partielles secondes en (0, 0) :
sage: h = var('h'); f(x, y) = x * y * (x^2 - y^2) / (x^2 + y^2)
sage: D1f(x, y) = diff(f(x,y), x); limit((D1f(0,h) - 0) / h, h=0)
-1
sage: D2f(x, y) = diff(f(x,y), y); limit((D2f(h,0) - 0) / h, h=0)
1
sage: g = plot3d(f(x, y), (x, -3, 3), (y, -3, 3))
402 ANNEXE A. SOLUTIONS DES EXERCICES

Figure A.1 La surface de Peano.

On en dduit 1 2 f (0, 0) = 1 et 2 1 f (0, 0) = 1. Donc cette fonction fournit un


contre-exemple au thorme de Schwarz (figure A.1).
Exercice 7 page 35. (La formule BBP)
1. On commence par comparer
Z 1/2  
1 n
un = f (t) t8n dt et vn = 8n+1
4 2 1 1
.

8n+4 8n+5 8n+6 16
0

sage: n, t = var('n, t')


sage: v(n) = (4/(8*n+1)-2/(8*n+4)-1/(8*n+5)-1/(8*n+6))*1/16^n
sage: assume(8*n+1>0)
sage: f(t) = 4*sqrt(2)-8*t^3-4*sqrt(2)*t^4-8*t^5
sage: u(n) = integrate(f(t) * t^(8*n), t, 0, 1/sqrt(2))
sage: (u(n)-v(n)).simplify_full()
0

On en dduit un = vn . Par linarit de lintgrale, on obtient :


!
Z 1/ 2 N
X N
X N
X
IN = f (t) t 8n
dt = un = vn = SN .
0 n=0 n=0 n=0

2. La srie entire t8n a pour rayon de convergence 1, donc elle converge


P
h n>0i
sur le segment 0, 12 . Sur ce segment, on peut donc intervertir lintgrale
A.2. ANALYSE ET ALGBRE AVEC SAGE 403

et la limite :
!
Z 1/ 2 N
X
lim SN = lim f (t) t 8n
dt
N N 0 n=0


!
Z 1/ 2 X
= f (t) 8n
t dt
0 n=0

1/ 2
1
Z
= f (t) dt = J.
0 1 t8

3. On procde ensuite au calcul de J :


sage: t = var('t'); J = integrate(f(t) / (1-t^8), t, 0, 1/sqrt(2))
sage: J.simplify_full()
pi + 2*log(sqrt(2) - 1) + 2*log(sqrt(2) + 1)
Pour simplifier cette expression, il faut indiquer Sage de combiner la
somme de logarithmes :
sage: J.simplify_log().simplify_full()
pi
En dfinitive, on obtient la formule demande :
+  n
4 2 1 1 1
X 
= .
n=0
8n + 1 8n + 4 8n + 5 8n + 6 16

laide de cette formule, donnons de nouveau une valeur approche de :


sage: l = sum(v(n) for n in (0..40)); l.n(digits=60)
3.14159265358979323846264338327950288419716939937510581474759
sage: pi.n(digits=60)
3.14159265358979323846264338327950288419716939937510582097494
sage: print "%e" % (l-pi).n(digits=60)
-6.227358e-54
Exercice 8 page 36. (Approximation polynomialeR du sinus) On munit lespace

vectoriel C ([, ]) du produit scalaire hf | gi = f g. Le polynme cherch
est la projection orthogonale de la fonction sinus sur le sous-espace vectoriel
R5 [X]. La dtermination de ce polynme se ramne la rsolution dun systme
linaire : en effet, P est le projet du sinus si et seulement si la fonction (P sin)
est orthogonale chacun des vecteurs de la base canonique de R5 [X]. Voici le
code Sage :
sage: x = var('x'); ps = lambda f, g : integral(f * g, x, -pi, pi)
sage: n = 5; a = var('a0, a1, a2, a3, a4, a5')
sage: P = sum(a[k] * x^k for k in (0..n))
sage: equ = [ps(P - sin(x), x^k) for k in (0..n)]
sage: sol = solve(equ, a)
404 ANNEXE A. SOLUTIONS DES EXERCICES

sage: P = sum(sol[0][k].rhs() * x^k for k in (0..n)); P


105/8*(pi^4 - 153*pi^2 + 1485)*x/pi^6 - 315/4*(pi^4 - 125*pi^2 +
1155)*x^3/pi^8 + 693/8*(pi^4 - 105*pi^2 + 945)*x^5/pi^10
sage: g = plot(P,x,-6,6,color='red') + plot(sin(x),x,-6,6,color='blue')
sage: g.show(ymin = -1.5, ymax = 1.5)
Le polynme cherch est donc :

105 4 153 2 + 1485 315 4 125 2 + 1155 3


P = x x
8 6 4 8
693 4 105 2 + 945 5
+ x .
8 10
On peut ensuite tracer la fonction sinus et son projet orthogonal pour apprcier
la qualit de cette approximation polynomiale (figure A.2).

0.5

-4 -3 -2 -1 1 2 3 4

-0.5

-1

Figure A.2 Approximation du sinus par la mthode des moindres carrs.

Exercice 9 page 36. (Le problme de Gauss) On prouve tout dabord formelle-
ment les relations demandes. Sensuivra lapplication numrique. On commence
par dfinir les vecteurs

ri :
sage: p, e = var('p, e')
sage: theta1, theta2, theta3 = var('theta1, theta2, theta3')
sage: r(theta) = p / (1 - e * cos(theta))
sage: r1 = r(theta1); r2 = r(theta2); r3 = r(theta3)
sage: R1 = vector([r1 * cos(theta1), r1 * sin(theta1), 0])
sage: R2 = vector([r2 * cos(theta2), r2 * sin(theta2), 0])
sage: R3 = vector([r3 * cos(theta3), r3 * sin(theta3), 0])



On vrifie que S + e

D est le vecteur nul,

sage: D = R1.cross_product(R2)+R2.cross_product(R3)+R3.cross_product(R1)
sage: S = (r1 - r3) * R2 + (r3 - r2) * R1 + (r2 - r1) * R3
sage: i = vector([1, 0, 0]); V = S + e * i.cross_product(D)
sage: V.simplify_full()
A.2. ANALYSE ET ALGBRE AVEC SAGE 405

(0, 0, 0)
w
wS w
w
wS w
w w


do la relation demande. On en dduit : e = ww
w = w
ww , puisque D est
D w Dw
normal au plan de lorbite, et donc
.



On vrifie ensuite que est colinaire S D :
sage: S.cross_product(D).simplify_full()[1:3]
(0, 0)
Le rsultat renvoy montre que les deuxime et troisime composantes sont nulles.



De mme, on vrifie que p S + e

N est le vecteur nul,
sage: N = r3 * R1.cross_product(R2) + r1 * R2.cross_product(R3)\
....: + r2 * R3.cross_product(R1)
sage: W = p * S + e * i.cross_product(N)
sage: W.simplify_full()
(0, 0, 0)
do la relation demande. On en dduit :
w
w
w w
w w
w w
w w
w
w N w wN w wN w
w
p=e w www = e w
w w = w
w w ,
w
wS w wS w wD w
w



puisque N est normal au plan de lorbite, et donc .
Daprs le formulaire sur les coniques, on a a = 1e2 .
p

On passe prsent lapplication numrique demande :


sage: R1=vector([0,1,0]); R2=vector([2,2,0]); R3=vector([3.5,0,0])
sage: r1 = R1.norm(); r2 = R2.norm(); r3 = R3.norm()
sage: D = R1.cross_product(R2) + R2.cross_product(R3) \
....: + R3.cross_product(R1)
sage: S = (r1 - r3) * R2 + (r3 - r2) * R1 + (r2 - r1) * R3
sage: N = r3 * R1.cross_product(R2) + r1 * R2.cross_product(R3) \
....: + r2 * R3.cross_product(R1)
sage: e = S.norm() / D.norm(); p = N.norm() / D.norm()
sage: a = p/(1-e^2); c = a * e; b = sqrt(a^2 - c^2)
sage: X = S.cross_product(D); i = X / X.norm()
sage: phi = atan2(i[1], i[0]) * 180 / pi.n()
sage: print("%.3f %.3f %.3f %.3f %.3f %.3f" % (a, b, c, e, p, phi))
2.360 1.326 1.952 0.827 0.746 17.917
En conclusion, on trouve :
a 2.360, b 1.326, c 1.952, e 0.827, p 0.746, 17.917.
Linclinaison du grand axe par rapport laxe des abscisses vaut 17.92.
Exercice 10 page 37. (Bases de sous-espaces vectoriels)
1. Lensemble S des solutions du systme linaire homogne associ A est
un sous-espace vectoriel de R5 , dont on obtient la dimension et une base
grce la fonction right_kernel :
406 ANNEXE A. SOLUTIONS DES EXERCICES

sage: A = matrix(QQ, [[ 2, -3, 2, -12, 33],


....: [ 6, 1, 26, -16, 69],
....: [10, -29, -18, -53, 32],
....: [ 2, 0, 8, -18, 84]])
sage: A.right_kernel()
Vector space of degree 5 and dimension 2 over Rational Field
Basis matrix:
[ 1 0 -7/34 5/17 1/17]
[ 0 1 -3/34 -10/17 -2/17]
S est donc le plan vectoriel engendr par les deux vecteurs ci-dessus (quil
faut lire en ligne, comme plus bas).
2. On extrait de la famille gnratrice donne une base du sous-espace recherch
de la manire suivante. On rduit la matrice A (forme par les colonnes
u1 , u2 , u3 , u4 , u5 ) par rapport aux lignes jusqu la forme dHermite :
sage: H = A.echelon_form(); H

1 0 4 0

3
0 1 2 0 7
0 0 0 1

5
0 0 0 0 0
Soit F = Vect(u1 , u2 , u3 , u4 , u5 ) la famille des vecteurs colonnes de A. Cest
un sous-espace vectoriel de R4 . Sur H, on observe que les pivots sont dans
les colonnes 1, 2 et 4. Plus prcisment, on a :

(u1 , u2 , u4 ) est une famille libre,


(
u3 = 4u1 + 2u2 ,
u5 = 3u1 + 7u2 5u4 .
Donc F = Vect(u1 , u2 , u3 , u4 , u5 ) = Vect(u1 , u2 , u4 ) est engendr par la
famille (u1 , u2 , u4 ) ; or cette famille est libre ; donc (u1 , u2 , u4 ) est une
base de F . On aurait galement pu utiliser, plus directement, la fonction
column_space :
sage: A.column_space()
Vector space of degree 4 and dimension 3 over Rational Field
Basis matrix:
[ 1 0 0 1139/350]
[ 0 1 0 -9/50]
[ 0 0 1 -12/35]
3. On cherche prsent des quations du sous-espace engendr. Pour cela, on
rduit la matrice A augmente dun second membre, en indiquant Sage
quon travaille dans un anneau de polynmes quatre indtermines :
sage: S.<x, y, z, t> = QQ[]
sage: C = matrix(S, 4, 1, [x, y, z, t])
sage: B = block_matrix([A, C], ncols=2)
A.2. ANALYSE ET ALGBRE AVEC SAGE 407

sage: C = B.echelon_form()
sage: C[3,5]*350
1139x + 63y + 120z + 350t
On en dduit que F est lhyperplan de R4 dquation
1139 x + 63 y + 120 z + 350 t = 0.
On aurait galement pu obtenir cette quation en calculant le noyau
gauche de A, qui donne les coordonnes des formes linaires dfinissant F
(ici il ny en a quune) :
sage: K = A.left_kernel(); K
Vector space of degree 4 and dimension 1 over Rational Field
Basis matrix:
[ 1 -63/1139 -120/1139 -350/1139]
Lhyperplan dfini par cette forme linaire a pour base les trois vecteurs
suivants, dj obtenus avec A.column_space() :
sage: matrix(K.0).right_kernel()
Vector space of degree 4 and dimension 3 over Rational Field
Basis matrix:
[ 1 0 0 1139/350]
[ 0 1 0 -9/50]
[ 0 0 1 -12/35]
Exercice 11 page 37. (Une quation matricielle) On commence par dfinir les
matrices A et C :
sage: A = matrix(QQ, [[-2, 1, 1], [8, 1, -5], [4, 3, -3]])
sage: C = matrix(QQ, [[1, 2, -1], [2, -1, -1], [-5, 0, 3]])
Lquation A = BC est une quation linaire, donc lensemble des solutions est
un sous-espace affine de M3 (R). On cherche donc une solution particulire de
notre quation.
sage: B = C.solve_left(A); B
[ 0 -1 0]
[ 2 3 0]
[ 2 1 0]
Ensuite, on dtermine la forme gnrale des solutions de lquation homogne,
autrement dit, le noyau gauche de C.
sage: C.left_kernel()
Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix:
[1 2 1]
Enfin, on donne la forme gnrale des solutions de notre quation :
sage: x, y, z = var('x, y, z'); v = matrix([[1, 2, 1]])
sage: B = B + (x*v).stack(y*v).stack(z*v); B
408 ANNEXE A. SOLUTIONS DES EXERCICES

3
0.5
2.5

2
0.5 1 1.5 2
1.5
-0.5
1

0.5
-1

-1 -0.5 0.5 1 1.5 2 2.5 3

(a) Conchodes de Pascal. (b) tude dune suite rcurrente.

On peut effectuer une vrification rapide :


sage: A == B*C
True
En conclusion, lensemble des solutions est un sous-espace affine de dimension 3 :

x 2x 1 x


y + 2 2 y + 3 y (x, y, z) R3 .

z + 2 2z + 1 z

A.4 Graphiques
Exercice 12 page 81. (Conchodes de Pascal)
sage: t = var('t'); liste = [a + cos(t) for a in srange(0, 2, 0.1)]
sage: g = polar_plot(liste, (t, 0, 2 * pi)); g.show(aspect_ratio = 1)
Exercice 13 page 85. (Trac des termes dune suite rcurrente)
sage: f = lambda x: abs(x**2 - 1/4)
sage: def liste_pts(u0, n):
....: u = u0; liste = [[u0,0]]
....: for k in range(n):
....: v, u = u, f(u)
....: liste.extend([[v,u], [u,u]])
....: return(liste)
sage: g = line(liste_pts(1.1, 8), rgbcolor = (.9,0,0))
sage: g += line(liste_pts(-.4, 8), rgbcolor = (.01,0,0))
sage: g += line(liste_pts(1.3, 3), rgbcolor = (.5,0,0))
sage: g += plot(f, -1, 3, rgbcolor = 'blue')
sage: g += plot(x, -1, 3, rgbcolor = 'green')
A.4. GRAPHIQUES 409

-3 -2 -1 1 2 3

-2

-4

Figure A.3 Courbes intgrales de x2 y 0 y = 0.

sage: g.show(aspect_ratio = 1, ymin = -.2, ymax = 3)


Exercice 14 page 88. (quation diffrentielle linaire, du premier ordre,
rsolue)
sage: x = var('x'); y = function('y')
sage: DE = x^2 * diff(y(x), x) - y(x) == 0
sage: desolve(DE, y(x))
c*e^(-1/x)
sage: g = plot([c*e^(-1/x) for c in srange(-8, 8, 0.4)], (x, -3, 3))
sage: y = var('y')
sage: g += plot_vector_field((x^2, y), (x,-3,3), (y,-5,5))
sage: g.show()
Exercice 15 page 90. (Modle proie-prdateur)
sage: from sage.calculus.desolvers import desolve_system_rk4
sage: f = lambda x, y: [a*x-b*x*y,-c*y+d*b*x*y]
sage: x, y, t = var('x, y, t')
sage: a, b, c, d = 1., 0.1, 1.5, 0.75
sage: P = desolve_system_rk4(f(x,y), [x,y],\
....: ics=[0,10,5], ivar=t, end_points=15)
sage: Ql = [[i,j] for i,j,k in P]; p = line(Ql, color='red')
sage: p += text("Lapins", (12,37), fontsize=10, color='red')
sage: Qr = [[i,k] for i,j,k in P]; p += line(Qr, color='blue')
sage: p += text("Renards", (12,7), fontsize=10, color='blue')
sage: p.axes_labels(["temps", "population"])
sage: p.show(gridlines = True)
On peut aussi refaire le graphe de droite de la figure 4.12 :
410 ANNEXE A. SOLUTIONS DES EXERCICES

-3 -2 -1 1 2 3

-1

-2

Figure A.4 Un systme diffrentiel autonome.

sage: n = 10; L = srange(6, 18, 12 / n); R = srange(3, 9, 6 / n)


sage: def g(x,y): v = vector(f(x, y)); return v / v.norm()
sage: q = plot_vector_field(g(x, y), (x, 0, 60), (y, 0, 36))
sage: for j in range(n):
....: P = desolve_system_rk4(f(x,y), [x,y],
....: ics=[0,L[j],R[j]], ivar=t, end_points=15)
....: Q = [[j,k] for i,j,k in P]
....: q += line(Q, color=hue(.8-j/(2*n)))
sage: q.axes_labels(["lapins", "renards"]); q.show()

Exercice 16 page 90. (Un systme diffrentiel autonome)


sage: from scipy import integrate
sage: def dX_dt(X, t=0): return [X[1], 0.5*X[1] - X[0] - X[1]^3]
sage: t = srange(0, 40, 0.01); x0 = srange(-2, 2, 0.1); y0 = 2.5
sage: CI = [[i, y0] for i in x0] + [[i, -y0] for i in x0]
sage: def g(x,y): v = vector(dX_dt([x, y])); return v / v.norm()
sage: x, y = var('x, y'); n = len(CI)
sage: q = plot_vector_field(g(x, y), (x, -3, 3), (y, -y0, y0))
sage: for j in xrange(n):
....: X = integrate.odeint(dX_dt, CI[j], t)
....: q += line(X, color=(1.7*j/(4*n),1.5*j/(4*n),1-3*j/(8*n)))
sage: X = integrate.odeint(dX_dt, [0.01,0], t)
sage: q += line(X, color = 'red'); q.show()
A.5. DOMAINES 411

Exercice 17 page 90. (coulement autour dun cylindre avec effet Magnus)
Pour rsoudre cet exercice, on peut par exemple utiliser la fonction odeint de
SciPy :
sage: from scipy import integrate
sage: t = srange(0, 40, 0.2)
sage: n = 35; CI_cart = [[4, .2 * i] for i in range(n)]
sage: CI = map(lambda x: [sqrt(x[0]^2+x[1]^2),\
....: pi - arctan(x[1]/x[0])], CI_cart)
sage: for alpha in [0.1, 0.5, 1, 1.25]:
....: dX_dt = lambda X, t=0: [cos(X[1])*(1-1/X[0]^2), \
....: -sin(X[1]) * (1/X[0]+1/X[0]^3) + 2*alpha/X[0]^2]
....: q = circle((0, 0), 1, fill=True, rgbcolor='purple')
....: for j in range(n):
....: X = integrate.odeint(dX_dt, CI[j], t)
....: Y = [[u[0]*cos(u[1]), u[0]*sin(u[1])] for u in X]
....: q += line(Y, xmin = -4, xmax = 4, color='blue')
....: q.show(aspect_ratio = 1, axes = False)

(a) Cas = 0.1. (b) Cas = 0.5. (c) Cas = 1.

Figure A.5 Effet Magnus.

Les solutions correspondantes = 0.1, 0.5, 1 sont reprsentes en figure A.5.

A.5 Domaines
Exercice 18 page 102. La classe de lanneau ZZ sappelle IntegerRing_class,
comme on peut le voir par les commandes suivantes :
sage: print type(ZZ)
<type 'sage.rings.integer_ring.IntegerRing_class'>
sage: ZZ.__class__
<type 'sage.rings.integer_ring.IntegerRing_class'>
Lanneau ZZ est en fait lunique instance de cette classe, que lon se gardera de
confondre avec la catgorie de ZZ,
412 ANNEXE A. SOLUTIONS DES EXERCICES

sage: ZZ.category()
Category of euclidean domains
ou encore avec la classe de ses lments :
sage: ZZ.an_element().__class__
<type 'sage.rings.integer.Integer'>

A.6 Corps finis et thorie lmentaire des


nombres
Exercice 19 page 126. On suppose n = pqr avec p < q < r. Ncessairement
p3 6 n, donc la fonction principale scrit :
sage: def enum_carmichael(N, verbose=True):
....: p = 3; s = 0
....: while p^3 <= N:
....: s += enum_carmichael_p(N, p, verbose); p = next_prime(p)
....: return s
o la fonction enum_carmichael_p compte les nombres de Carmichael multiples
de p, qui sont de la forme a + m avec un entier positif ou nul, a = p et
m = p(p 1), puisque n doit tre multiple de p, et n 1 multiple de p 1 :
sage: def enum_carmichael_p (n, p, verbose):
....: a = p; m = p*(p-1); q = p; s = 0
....: while p*q^2 <= n:
....: q = next_prime(q)
....: s += enum_carmichael_pq(n, a, m, p, q, verbose)
....: return s
La fonction enum_carmichael_pq compte les nombres de Carmichael multiples de
pq, qui sont de la forme a0 + m0 avec un entier positif ou nul, o a0 a mod m
et a0 q mod q(q 1), et m0 est multiple la fois de m = p(p 1) et de q(q 1).
On utilise la fonction crt pour rsoudre les congruences simultanes, en liminant
les cas o il ne peut pas y avoir de solution, sinon Sage provoquerait une erreur.
On impose aussi a0 > pq 2 pour avoir r > q :
sage: def enum_carmichael_pq(n,a,m,p,q,verbose):
....: if (a-q) % gcd(m,q*(q-1)) <> 0: return 0
....: s = 0
....: a = crt (a, q, m, q*(q-1)); m = lcm(m,q*(q-1))
....: while a <= p*q^2: a += m
....: for t in range(a, n+1, m):
....: r = t // (p*q)
....: if is_prime(r) and t % (r-1) == 1:
....: if verbose:
....: print p*q*r, factor(p*q*r)
....: s += 1
....: return s
A.6. CORPS FINIS ET THORIE LMENTAIRE DES NOMBRES 413

Avec ces fonctions, on obtient :

sage: enum_carmichael(10^4)
561 3 * 11 * 17
1105 5 * 13 * 17
2465 5 * 17 * 29
1729 7 * 13 * 19
2821 7 * 13 * 31
8911 7 * 19 * 67
6601 7 * 23 * 41
7
sage: enum_carmichael(10^5, False)
12
sage: enum_carmichael(10^6, False)
23
sage: enum_carmichael(10^7, False)
47

Exercice 20 page 128. On commence par crire une fonction aliq calculant la
suite aliquote partant de n, et sarrtant ds quon atteint 1 ou un cycle :

sage: def aliq(n):


....: l = [n]
....: while n <> 1:
....: n = sigma(n) - n
....: if n in l: break
....: l.append(n)
....: return l
sage: l = aliq(840)
sage: len(l), l[:5], l[-5:]
(748, [840, 2040, 4440, 9240, 25320], [2714, 1606, 1058, 601, 1])
sage: points([(i, log(l[i])/log(10)) for i in range(len(l))])
414 ANNEXE A. SOLUTIONS DES EXERCICES

40

30

20

10

100 200 300 400 500 600 700

Exercice 21 page 129. (Constante de Masser-Gramain) Pour la question 1,


soit C le cercle frontire dun plus petit disque. Sans restriction de gnralit
on peut supposer que lorigine O est sur le cercle en effet, il y a au moins
un point de Z2 sur le cercle, sinon le disque nest pas optimal. On peut aussi
supposer que le centre du cercle est dans le premier quadrant (par rotation du
disque dun multiple de /2 autour de O). On admettra quon a galement deux
points A et B du premier quadrantp sur le cercle, et donc le cercle C est circonscrit
au triangle OAB. La borne rk < p k/ permet de dlimiter les points A et B,
car leur distance O est au plus 2 k/. On peut supposer quun des points
A et B, par exemple A, est dans le second octant (sils sont tous deux dans le
premier octant, par symtrie par rapport la droite x = y on les ramne dans
le second octant). On peut aussi supposer que langle en A du triangle OAB
est aigu (en changeant A et B au besoin, aprs une symtrie par rapport la
droite p
x = y sils sont dans des octants diffrents). p Labscisse de A vrifie donc
xA < 2k/, sonp ordonne vrifie xA 6 yA < 4k/ x2A . Pour le point B,
on a 0 6 xB < 2 k/, et 0 6 xA yB + yA xB 6 x2A + yA 2
(angle aigu en A).
Cela donne le code suivant, o la routine rk_aux calcule le nombre de points
dans le disque de centre (xc /d, yc /d), et de rayon r2 /d, o xc , yc , d, r2 sont tous
entiers.
sage: def rk_aux(xc, yc, d, r2):
....: s = 0
....: xmin = ceil((xc - sqrt(r2))/d)
....: xmax = floor((xc + sqrt(r2))/d)
....: for x in range(xmin,xmax+1):
....: r3 = r2 - (d*x-xc)^2 # (d*y-yc)^2 <= r2 - (d*x-xc)^2
....: ymin = ceil((yc - sqrt(r3))/d)
....: ymax = floor((yc + sqrt(r3))/d)
....: s += ymax + 1 - ymin
....: return s
A.6. CORPS FINIS ET THORIE LMENTAIRE DES NOMBRES 415

sage: def rk(k): # renvoie (r_k^2, xc, yc)


....: if k == 2: return 1/4, 1/2, 0
....: dmax = (2*sqrt(k/pi)).n(); xamax = (sqrt(2*k/pi)).n()
....: sol = (dmax/2)^2, 0, 0, 0
....: for xa in range(0, floor(xamax)+1):
....: # si xa=0, ya > 0 car A ne peut tre en O
....: yamin = max(xa, 1)
....: for ya in range(yamin, floor(sqrt(dmax^2-xa^2))+1):
....: xbmin = 0 # on veut xb*ya <= xa^2+ya^2
....: if xa == 0:
....: xbmin = 1 # O, A, B ne doivent pas tre aligns
....: xbmax = min(floor(dmax), floor((xa*xa+ya*ya)/ya))
....: for xb in range(xbmin, xbmax+1):
....: ybmax = floor(sqrt(dmax^2-xb^2))
....: if xa > 0: # on veut xb*ya+yb*xa <= xa^2+ya^2
....: tmp = floor((xa*xa+ya*ya-xb*ya)/xa)
....: ybmax = min(ybmax, tmp)
....: # si xb=0, yb > 0 car B doit tre distinct de O
....: ybmin = 0
....: if xb == 0:
....: ybmin = 1
....: for yb in range(ybmin,ybmax+1):
....: d = 2*abs(xb*ya - xa*yb)
....: if d <> 0:
....: ra2 = xa^2+ya^2; rb2 = xb^2+yb^2
....: xc = abs(ra2*yb - rb2*ya)
....: yc = abs(rb2*xa - ra2*xb)
....: r2 = ra2*rb2*((xa-xb)^2+(ya-yb)^2)
....: m = rk_aux(xc,yc,d,r2)
....: if m >= k and r2/d^2 < sol[0]:
....: sol = r2/d^2, xc/d, yc/d
....: return sol

sage: for k in range(2,10): print k, rk(k)


2 (1/4, 1/2, 0)
3 (1/2, 1/2, 1/2)
4 (1/2, 1/2, 1/2)
5 (1, 0, 1)
6 (5/4, 1/2, 1)
7 (25/16, 3/4, 1)
8 (2, 1, 1)
9 (2, 1, 1)

Pour la question 2, une solution est la suivante :


sage: def plotrk(k):
....: r2, x0, y0 = rk(k); r = n(sqrt(r2))
....: var('x, y')
....: c = implicit_plot((x-x0)^2+(y-y0)^2-r2,
....: (x, x0-r-1/2, x0+r+1/2),(y, y0-r-1/2, y0+r+1/2))
....: center = points([(x0,y0)], pointsize=50, color='black')
416 ANNEXE A. SOLUTIONS DES EXERCICES

....: # on veut (i-x0)^2+(j-y0)^2 <= r2


....: # donc |i-x0| <= r et |j-y0| <= r2 - (i-x0)^2
....: l = [(i, j) for i in range(ceil(x0-r), floor(x0+r)+1)
....: for j in range(ceil(y0-sqrt(r^2-(i-x0)^2)),
....: floor(y0+sqrt(r2-(i-x0)^2))+1)]
....: d = points(l, pointsize=100)
....: return (c+center+d).show(aspect_ratio=1, axes=True)
Pj
La question 3 demande un peu de rflexion. Notons Si,j = k=i 1/(rk2 ).
Partant de la borne suprieure (6.2) pour rk , on obtient rk2 < (k 1)/, donc
PN R N +1
1/(rk2 ) > 1/(k 1), et Sn,N > k=n 1/(k 1) > n dk/k = log((N + 1)/n).
La borne infrieure de (6.2) donne 1/(rk ) < 1/k + 2/k 3/2 pour k > 407, qui
2
RN
conduit pour n > 407 Sn,N < k=n (1/k + 2/k 3/2 ) < n1 (1/k + 2/k 3/2 )dk =
PN

log(N/(n 1)) + 4/ n 1 4/ N , do :

S2,n1 + log(1/n) 6 6 S2,n1 + log(1/(n 1)) + 4/ n 1.

sage: def bound(n):


....: s = sum(1/pi/rk(k)[0] for k in range(2,n+1))
....: return float(s+log(1/n)), float(s+log(1/(n-1))+4/sqrt(n-1))
sage: bound(60)
(1.7327473659779615, 2.2703101282176377)

On en dduit 1.73 < < 2.28, soit lapproximation 2.00 avec une erreur
borne par 0.28.
Exercice 22 page 130. On reprend ici les mmes notations que dans larticle
de Beauzamy. On pose si = 1 xi xk avec sk+1 = 1. On doit donc avoir
x1 + + xi1 6 si , et en particulier x2 6 x1 6 s2 . Soit

1
Z s2
C1 = xn1 1 dx1 = (sn2 1 +1 xn2 1 +1 ).
x1 =x2 n 1+1

sage: x1, x2, s2 = var('x1, x2, s2')


sage: n1 = 9; C1 = integrate(x1^n1, x1, x2, s2); C1
1/10*s2^10 - 1/10*x2^10
Ensuite on a x3 6 x2 6 s3 = s2 + x2 , donc en remplaant s2 par s3 x2 dans C1 ,
et en intgrant pour x2 allant de x3 s3 /2 car x1 + x2 6 s3 et x2 6 x1 on
obtient :
sage: x3, s3 = var('x3, s3')
sage: n2 = 7; C2 = integrate(C1.subs(s2=s3-x2)*x2^n2, x2, x3, s3/2); C2
44923/229417943040*s3^18 - 1/80*s3^10*x3^8 + 1/9*s3^9*x3^9 - 9/20*s3^8*x3^10
+ 12/11*s3^7*x3^11 - 7/4*s3^6*x3^12 + 126/65*s3^5*x3^13 - 3/2*s3^4*x3^14
+ 4/5*s3^3*x3^15 - 9/32*s3^2*x3^16 + 1/17*s3*x3^17
A.7. POLYNMES 417

et ainsi de suite. chaque itration Ci est un polynme en xi+1 et si+1


coefficients rationnels, homogne et de degr total n1 + . . . + ni + i. Pour la
dernire variable, on intgre entre xk = 0 et xk = 1/k.
En supposant connue une borne sur le numrateur et le dnominateur de I,
on peut calculer I modulo p pour diffrents nombres premiers ne divisant pas le
dnominateur de I, puis en dduire par restes chinois la valeur de I modulo le
produit de ces nombres premiers, et enfin par reconstruction rationnelle la valeur
exacte de I.

A.7 Polynmes
Exercice 23 page 133.
1. On peut par exemple (il y a beaucoup dautres solutions) prendre
sage: x = polygen(QQ, 'y'); y = polygen(QQ, 'x')
Rappelons la diffrence, en Sage, entre variables Python et variables ma-
thmatiques. Les variables Python sont des noms qui servent la pro-
grammation et dsignent des emplacements en mmoire. Les variables
mathmatiques, dont font partie les indtermines des polynmes, sont
de nature compltement diffrente : ce sont des objets Sage, qui peuvent
tre stocks dans des variables Python. Quand on cre une indtermine
appele 'x', rien noblige la stocker dans la variable Python x et rien
nempche dy ranger plutt 'y'.
2. On commence par affecter la variable Python x lindtermine 'x' des
polynmes coefficients rationnels. Lexpression x+1 svalue alors en le
polynme x + 1 Q[x], que lon affecte la variable p. Puis lon affecte
lentier 2 la variable x. Cela na pas deffet sur p, qui vaut toujours x + 1 :
ce x-l (lindtermine) na plus rien voir avec la variable Python qui vaut
maintenant 2. ce stade p+x svalue en x + 3, et donc la valeur finale de p
est x + 3.
Exercice 24 page 139. Une solution simple consiste effectuer des divisions
euclidiennes successives par les polynmes de Tchebycheff pris par degrs dcrois-
sants : si le polynme p rcrire sur la base de Tchebycheff est de degr n, on pose
p = cn Tn +Rn1 avec cn Q et deg Rn1 6 n1, puis Rn1 = cn1 Tn1 +Rn2 ,
et ainsi de suite.
Dans le code Sage suivant, plutt que de renvoyer les coefficients cn obtenus
comme une simple liste, on a choisi de construire une expression symbolique o
le polynme Tn est reprsent comme une fonction inerte (cest--dire garde
sous forme non value) T(n,x).
sage: T = sage.symbolic.function_factory.function('T', nargs=2)
sage: def to_chebyshev_basis(pol):
....: (x,) = pol.variables()
....: res = 0
....: for n in xrange(pol.degree(), -1, -1):
....: quo, pol = pol.quo_rem(chebyshev_T(n, x))
....: res += quo * T(n, x)
418 ANNEXE A. SOLUTIONS DES EXERCICES

....: return res


Testons cette fonction. Pour vrifier les rsultats, il suffit de substituer notre
fonction inerte T la fonction qui calcule les polynmes de Tchebycheff, et de
dvelopper :
sage: p = QQ['x'].random_element(degree=6); p
4*x^6 + 4*x^5 + 1/9*x^4 - 2*x^3 + 2/19*x^2 + 1
sage: p_cheb = to_chebyshev_basis(p); p_cheb
1069/456*T(0, x) + T(1, x) + 2713/1368*T(2, x) + 3/4*T(3, x)
+ 55/72*T(4, x) + 1/4*T(5, x) + 1/8*T(6, x)
sage: p_cheb.substitute_function(T, chebyshev_T).expand()
4*x^6 + 4*x^5 + 1/9*x^4 - 2*x^3 + 2/19*x^2 + 1

Exercice 25 page 139. Une traduction directe de lalgorithme en Sage donne


quelque chose comme :
sage: def mydiv(u, v, n):
....: v0 = v.constant_coefficient()
....: quo = 0; rem = u
....: for k in xrange(n+1):
....: c = rem[0]/v0
....: rem = (rem - c*v) >> 1 # dcalage des coefficients
....: quo += c*x^k
....: return quo, rem
(On pourra chronomtrer cette fonction sur des exemples un peu gros, et essayer
de rendre le code plus efficace sans changer lalgorithme.)
Mais le quotient dans la division par les puissances croissantes jusqu lordre n
est simplement le dveloppement en srie de la fraction rationnelle u/v, tronqu
lordre n + 1. En utilisant la division de sries formelles (voir 7.5), on peut donc
calculer la division suivant les puissances croissantes comme suit.
sage: def mydiv2(u, v, n):
....: x = u.parent().gen()
....: quo = (u / (v + O(x^(n+1)))).polynomial()
....: rem = (u - quo*v) >> (n+1)
....: return quo, rem
La ligne quo = ... utilise, premirement, quajouter un O() un polynme le
convertit automatiquement en srie tronque, et deuximement, que la division
dun polynme par une srie se fait par dfaut la prcision du diviseur.
Exercice 26 page 141. Tout dabord, on sattend ce que u1010000 ait de lordre
de 1010000 chiffres. Il est donc compltement hors de question de chercher le
calculer entirement. Puisquon ne sintresse quaux cinq derniers chiffres, ce
nest pas vraiment un problme : on fera tout le calcul modulo 105 . La mthode
par exponentiation rapide prsente en 3.2.4 demande alors quelques dizaines de
milliers de multiplications de matrices 1000 1000 coefficients dans Z/105 Z.
Chacun de ces produits de matrices revient un milliard de multiplications modulo
A.7. POLYNMES 419

105 , ou un peu moins avec un algorithme rapide. Ce nest pas compltement


inaccessible, mais un essai sur une seule multiplication laisse penser que le calcul
avec Sage prendrait une bonne heure :
sage: Mat = MatrixSpace (IntegerModRing(10^5), 1000)
sage: m1, m2 = (Mat.random_element() for i in (1,2))
sage: %time m1*m2
CPU times: user 0.24 s, sys: 0.02 s, total: 0.26 s
Wall time: 0.26 s
Il est possible de faire beaucoup mieux du point de vue algorithmique. Notons S
loprateur de dcalage (an )nN 7 (an+1 )nN . Lquation satisfaite par u =
(un )nN se rcrit P (S) u = 0, o P (x) = x1000 23x729 + 5x2 12x 7 ; et pour
tout N (notamment N = 10100 ), le terme uN est le premier de la suite S N u.
Soit R le reste de la division euclidienne de xN par P . Comme P (S) u = 0, on a
S N u = R(S)u. Il suffit donc de calculer limage de xN dans (Z/105 Z) [x]/hP (x)i.
On aboutit au code suivant, qui, sur la mme machine, sexcute en une trentaine
de secondes :
sage: Poly.<x> = Integers(10^5)[]
sage: P = x^1000 - 23*x^729 + 5*x^2 - 12*x - 7
sage: Quo.<s> = Poly.quo(P)
sage: op = s^(10^10000)
sage: add(op[n]*(n+7) for n in range(1000))
63477
Les cinq chiffres cherchs sont donc 63477. Lcart entre les deux versions en
termes de temps de calcul grandit rapidement avec lordre de la rcurrence.
Exercice 27 page 151.
Pas un+s + as1 un+s1 + + a0 un = 0 pour tout n > 0, et notons
1. Supposons
u(z) = n=0 un z n . Soit Q(z) = as + as1 z + + a0 z s . Alors

X
S(z) = Q(z) u(z) = (as un + as1 un1 + + a0 uns )z n ,
n=0

avec la convention que un = 0 pour n < 0. Le coefficient de z n dans S(z)


est nul pour n > s, donc S(z) est un polynme, et u(z) = S(z)/Q(z). Le
dnominateur Q(z) est le polynme rciproque du polynme caractristique
de la rcurrence, et le numrateur code les conditions initiales.
2. Les quelques premiers coefficients suffisent pour deviner une rcurrence
dordre 3 que satisfont manifestement les coefficients donns. En faisant
appel rational_reconstruct, on obtient une fraction rationnelle quil
suffit de dvelopper en srie pour retrouver tous les coefficients donns, et
des coefficients suivants vraisemblables :
sage: p = previous_prime(2^30); ZpZx.<x> = Integers(p)[]
sage: s = ZpZx([1, 1, 2, 3, 8, 11, 34, 39, 148, 127, 662, 339])
sage: num, den = s.rational_reconstruct(x^12, 6, 6)
sage: S = ZpZx.completion(x)
420 ANNEXE A. SOLUTIONS DES EXERCICES

sage: map(lift_sym, S(num)/S(den))


[1, 1, 2, 3, 8, 11, 34, 39, 148, 127, 662, 339, 3056, 371,
14602, -4257, 72268, -50489, 369854, -396981]

(La fonction lift_sym est celle dfinie dans le texte du chapitre. Les 20
premiers coefficients de la suite sont largement infrieurs 229 , de sorte
quon peut se permettre de drouler la rcurrence modulo 230 puis de
remonter le rsultat dans Z plutt que le contraire.)
Avec berlekamp_massey, le rsultat est le polynme caractristique de la
rcurrence, directement coefficients dans Z :
sage: berlekamp_massey([1, 1, 2, 3, 8, 11, 34, 39, 148, 127])
x^3 - 5*x + 2

On vrifie que tous les coefficients donns satisfont un+3 = 5un+1 2un , et
lon devine partir de l les coefficients manquants 72268 = 5146022371,
50489 = 5 (4257) 2 14602, et ainsi de suite.
Exercice 28 page 151. On commence par calculer un polynme de degr 3
qui satisfait la condition dinterpolation donne. Cela fournit une solution avec
deg p = 3 :
sage: R.<x> = GF(17)[]
sage: pairs = [(0,-1), (1,0), (2,7), (3,5)]
sage: s = R(QQ['x'].lagrange_polynomial(pairs)); s
6*x^3 + 2*x^2 + 10*x + 16
sage: [s(i) for i in range(4)]
[16, 0, 7, 5]
On sest ainsi ramen au problme de reconstruction rationnelle

p/q s mod x(x 1)(x 2)(x 3).

Comme s nest pas inversible modulo x(x 1)(x 2)(x 3) (car s(1) = 0), il ny
a pas de solution avec p constant. Avec deg p = 1, on trouve :
sage: s.rational_reconstruct(mul(x-i for i in range(4)), 1, 2)
(15*x + 2, x^2 + 11*x + 15)
Exercice 29 page 155. Le raisonnement Rx est le mme que dans lexemple du
texte : on rcrit lquation tan x = 0 (1 + tan2 t) dt, et lon cherche un point
fixe en partant de la condition initiale tan(0) = 0.
sage: S.<x> = PowerSeriesRing(QQ)
sage: t = S(0)
sage: for i in range(7): # ici t est correct jusqu'au degr 2i+1
....: # le O(x^15) vite que l'ordre de troncature ne grandisse
....: t = (1+t^2).integral() + O(x^15)
sage: t
x + 1/3*x^3 + 2/15*x^5 + 17/315*x^7 + 62/2835*x^9 + 1382/155925*x^11
+ 21844/6081075*x^13 + O(x^15)
A.8. ALGBRE LINAIRE 421

A.8 Algbre linaire


Exercice 30 page 175. (Polynme minimal de vecteurs)
1. A est un polynme annulateur de tous les vecteurs ei de la base. Il est donc
un commun multiple des A,ei . Soit le ppcm des A,ei . Donc |A . Par
ailleurs, (A) = (A)e1 . . . (A)en = 0 est annulateur de la matrice


A. Do A |. Comme ces polynmes sont unitaires, ils sont gaux.


2. Dans ce cas, tous les A,ei sont sous la forme `i , o est un polynme
irrductible. Daprs la question prcdente, A concide donc avec celui
des `i ayant la puissance `i maximale.
3. Soit un polynme annulateur de e = ei + ej et 1 = A,ei , 2 = A,ej . On
a 2 (A)(A)ei = 2 (A)(A)e(A)2 (A)ej = 0. Donc 2 est annulateur
de ei et est donc divisible par 1 . Or 1 et 2 tant premiers entre eux, on
a 1 |. De la mme faon on montre que 2 |, donc est un multiple de
1 2 . Or 1 2 est annulateur de e, donc = 1 2 .
4. P1 et P2 tant premiers entre eux, il existe deux polynmes et tels que
1 = P1 + P2 . Ainsi pour tout x, on a x = (A)P1 (A)x + (A)P2 (A)x =
x2 + x1 , o x1 = (A)P2 (A)x et x2 = (A)P1 (A)x. Comme A = P1 P2 ,
P1 est annulateur de x1 = (A)P2 (A)x (de mme P2 est annulateur de
x2 ). Si pour tout x, x1 = 0, alors P2 est annulateur de A et est donc
un multiple de P1 P2 , do 1 = P1 ( + P2 ), qui implique deg P1 = 0. Il
existe donc un x1 non nul tel que P1 soit un polynme annulateur de x1 .
Montrons que P1 est minimal pour x1 : soit P1 un polynme annulateur de
x1 . Alors P1 (A)P2 (A)x = P2 (A)P1 (A)x1 + P1 (A)P2 (A)x2 = 0, donc P1 P2
est un multiple de A = P1 P2 . Ainsi P1 |P1 et P1 est donc le polynme
minimal de x1 . Le raisonnement est identique pour x2 .
5. Pour chaque facteur mi , il existe un vecteur xi dont i
i mi
est le polynme
minimal et le vecteur x1 + + xk a A pour polynme minimal.
6. On calcule dabord le polynme minimal de la matrice A.
sage: A = matrix(GF(7),[[0,0,3,0,0],[1,0,6,0,0],[0,1,5,0,0],
....: [0,0,0,0,5],[0,0,0,1,5]])
sage: P = A.minpoly(); P
x^5 + 4*x^4 + 3*x^2 + 3*x + 1
sage: P.factor()
(x^2 + 2*x + 2) * (x^3 + 2*x^2 + x + 4)

Il est de degr maximal.


sage: e1 = identity_matrix(GF(7),5)[0]
sage: e4 = identity_matrix(GF(7),5)[3]
sage: A.transpose().maxspin(e1)
[(1, 0, 0, 0, 0), (0, 1, 0, 0, 0), (0, 0, 1, 0, 0)]
sage: A.transpose().maxspin(e4)
[(0, 0, 0, 1, 0), (0, 0, 0, 0, 1)]
sage: A.transpose().maxspin(e1 + e4)
422 ANNEXE A. SOLUTIONS DES EXERCICES

[(1, 0, 0, 1, 0), (0, 1, 0, 0, 1), (0, 0, 1, 5, 5),


(3, 6, 5, 4, 2), (1, 5, 3, 3, 0)]

La fonction maxspin itre un vecteur gauche. On lapplique donc sur


la transpose de la matrice afin dobtenir la liste des itrs de Krylov
linairement indpendants partir des vecteurs e1 et e4 . Le polynme
minimal de e1 a donc degr 3, celui de e4 a degr 2, et celui de e1 + e4 a
degr 5.
On note que la forme particulire de la matrice fait que les vecteurs e1 et
e4 engendrent comme itrs dautres vecteurs de la base canonique. Cette
forme est appele la forme normale de Frobenius (voir 8.2.3). Elle dcrit
de quelle manire la matrice dcompose lespace en sous-espaces cycliques
invariants qui sont engendrs par des vecteurs de la base canonique.
Exercice 31 page 182. (Test si deux matrices sont semblables)
sage: def Semblables(A, B):
....: F1, U1 = A.frobenius(2)
....: F2, U2 = B.frobenius(2)
....: if F1 == F2:
....: return True, ~U2*U1
....: else:
....: return False, F1 - F2
sage: B = matrix(ZZ, [[0,1,4,0,4],[4,-2,0,-4,-2],[0,0,0,2,1],
....: [-4,2,2,0,-1],[-4,-2,1,2,0]])
sage: U = matrix(ZZ, [[3,3,-9,-14,40],[-1,-2,4,2,1],[2,4,-7,-1,-13],
....: [-1,0,1,4,-15],[-4,-13,26,8,30]])
sage: A = (U^-1 * B * U).change_ring(ZZ)
sage: ok, V = Semblables(A, B); ok
True
sage: V
[ 1 2824643/1601680 -6818729/1601680
-43439399/11211760 73108601/11211760]
[ 0 342591/320336 -695773/320336
-2360063/11211760 -10291875/2242352]
[ 0 -367393/640672 673091/640672
-888723/4484704 15889341/4484704]
[ 0 661457/3203360 -565971/3203360
13485411/22423520 -69159661/22423520]
[ 0 -4846439/3203360 7915157/3203360
-32420037/22423520 285914347/22423520]
sage: ok, V = Semblables(2*A, B); ok
False

A.9 Systmes polynomiaux


Exercice 32 page 184. tant donn un anneau de polynmes ring, la fonction
test_poly renvoie la somme de tous les monmes de degr total born par la
A.9. SYSTMES POLYNOMIAUX 423

valeur du paramtre deg. Son code est relativement compact, mais procde avec
quelques contorsions.
La premire instruction construit et affecte la variable locale monomials
un ensemble (reprsent par un objet spcifique SubMultiset, voir 15.2) de
listes chacune deg lments dont le produit constitue un terme du polynme :

sage: ring = QQ['x,y,z']; deg = 2


sage: tmp1 = [(x,)*deg for x in (1,) + ring.gens()]; tmp1
[(1, 1), (x, x), (y, y), (z, z)]
sage: tmp2 = flatten(tmp1); tmp2
[1, 1, x, x, y, y, z, z]
sage: monomials = Subsets(tmp2, deg, submultiset=True); monomials
SubMultiset of [1, 1, z, z, y, y, x, x] of size 2
sage: monomials.list()
[[1, 1], [1, z], [1, y], [1, x], [z, z], [z, y], [z, x], [y, y],
[y, x], [x, x]]
Pour cela, on commence par adjoindre 1 au tuple des indtermines, et remplacer
chaque lment du rsultat par un tuple de deg copies de lui-mme, et regrouper
ces tuples dans une liste. Remarquons lusage de la syntaxe (x,) qui dnote
un tuple un seul lment, ainsi que des oprateurs de concatnation + et
de rptition * des tuples. La liste de tuples obtenue est aplatie par flatten
en une liste contenant exactement deg fois chacune des indtermines et la
constante 1. La fonction Subsets avec loption submultiset=True calcule ensuite
lensemble des parties de cardinal deg du multiensemble (collection sans ordre
mais avec rptitions) des lments de cette liste. Lobjet monomials est itrable :
ainsi, (mul(m) for m in monomials) est un gnrateur Python qui parcourt
les monmes fabriqus en passant mul les listes reprsentant les parties. Ce
gnrateur est finalement pass add.
La dernire ligne pourrait tre remplace par add(map(mul, monomials)).
On peut aussi crire ((1,) + ring.gens())*deg pour simplifier lexpression
[(x,)*deg for x in (1,) + ring.gens()].
Exercice 33 page 185. Un exemple de la page daide PolynomialRing? suggre
une solution : pour obtenir une famille dindtermines complique ici, indexe
par les nombres premiers on passe PolynomialRing une liste fabrique par
comprhension (voir 3.3.2) :
sage: ['x%d' % n for n in [2,3,5,7]]
['x2', 'x3', 'x5', 'x7']
sage: R = PolynomialRing(QQ, ['x%d' % n for n in primes(40)])
sage: R.inject_variables()
Defining x2, x3, x5, x7, x11, x13, x17, x19, x23, x29, x31, x37
La mthode inject_variables initialise des variables Python x2, x3, ... contenant
chacune le gnrateur correspondant de R.
Exercice 34 page 190. On vrifie que (3, 2, 1) est lunique solution relle, par
exemple via
424 ANNEXE A. SOLUTIONS DES EXERCICES

sage: R.<x,y,z> = QQ[]


sage: J = R.ideal(x^2*y*z-18, x*y^3*z-24, x*y*z^4-6)
sage: J.variety(AA)
[{x: 3, z: 1, y: 2}]
ou encore par
sage: V = J.variety(QQbar)
sage: [u for u in V if all(a in AA for a in u.values())]
[{z: 1, y: 2, x: 3}]
Une substitution de la forme (x, y, z) 7 ( a x, b y, c z) avec k = 1 laisse le
systme invariant si et seulement si (a, b, c) est solution modulo k du systme
linaire homogne de matrice
sage: M = matrix([ [p.degree(v) for v in (x,y,z)]
....: for p in J.gens()]); M
[2 1 1]
[1 3 1]
[1 1 4]
En calculant son dterminant
sage: M.det()
17
on voit que k = 17 convient. Il ny a plus qu trouver un lment non nul du
noyau :
sage: M.change_ring(GF(17)).right_kernel()
Vector space of degree 3 and dimension 1 over Finite Field of size 17
Basis matrix:
[1 9 6]
Exercice 35 page 203. Cest presque immdiat :
sage: L.<a> = QQ[sqrt(2-sqrt(3))]; L
Number Field in a with defining polynomial x^4 - 4*x^2 + 1
sage: R.<x,y> = QQ[]
sage: J1 = (x^2 + y^2 - 1, 16*x^2*y^2 - 1)*R
sage: J1.variety(L)
[{y: 1/2*a, x: 1/2*a^3 - 2*a}, {y: 1/2*a, x: -1/2*a^3 + 2*a},
{y: -1/2*a, x: 1/2*a^3 - 2*a}, {y: -1/2*a, x: -1/2*a^3 + 2*a},
{y: 1/2*a^3 - 2*a, x: 1/2*a}, {y: 1/2*a^3 - 2*a, x: -1/2*a},
{y: -1/2*a^3 + 2*a, x: 1/2*a}, {y: -1/2*a^3 + 2*a, x: -1/2*a}]
Ainsi, par exemple pour la premire solution ci-dessus, on a :
1 1
q q
x = (2 3)3/2 2 2 3, y= 2 3.
2 2
Exercice 36 page 207. Nous avons vu comment obtenir une base B du Q-espace
vectoriel Q[x, y]/J2 :
A.9. SYSTMES POLYNOMIAUX 425

sage: R.<x,y> = QQ[]; J2 = (x^2+y^2-1, 4*x^2*y^2-1)*R


sage: basis = J2.normal_basis(); basis
[x*y^3, y^3, x*y^2, y^2, x*y, y, x, 1]
On calcule ensuite limage de B par mx , et on en dduit la matrice de mx dans
la base B :
sage: xbasis = [(x*p).reduce(J2) for p in basis]; xbasis
[1/4*y, x*y^3, 1/4, x*y^2, -y^3 + y, x*y, -y^2 + 1, x]
sage: mat = matrix([ [xp[q] for q in basis]
....: for xp in xbasis])
sage: mat
[ 0 0 0 0 0 1/4 0 0]
[ 1 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 1/4]
[ 0 0 1 0 0 0 0 0]
[ 0 -1 0 0 0 1 0 0]
[ 0 0 0 0 1 0 0 0]
[ 0 0 0 -1 0 0 0 1]
[ 0 0 0 0 0 0 1 0]
Le polynme x et ses racines sont alors donns par (voir chapitres 2 et 8) :
sage: charpoly = mat.characteristic_polynomial(); charpoly
x^8 - 2*x^6 + 3/2*x^4 - 1/2*x^2 + 1/16
sage: solve(SR(charpoly), SR(x))
[x == -1/2*sqrt(2), x == 1/2*sqrt(2)]
On peut observer sur cet exemple que les racines de sont les abscisses des points
de V (J2 ).
Pour un idal J quelconque, supposons () = 0 avec C. Cest donc que
est une valeur propre de mx . Soit p Q[x, y] \ J un reprsentant dun vecteur
propre associ : on a xp = p + q pour un certain q J. Comme p / J, on
peut trouver (x0 , y0 ) V (J) tel que p(x0 , y0 ) 6= 0, et lon a alors

(x0 ) p(x0 , y0 ) = q(x0 , y0 ) = 0,

do = x0 .
Exercice 37 page 217. Les expressions sin, cos, sin(2) et cos(2) sont lies
par les formules trigonomtriques classiques

sin2 + cos2 = 1, sin(2) = 2(sin )(cos ), cos(2) = cos2 sin2 .

Posons pour allger les notations c = cos et s = sin . Lidal

hu (s + c), v (2sc + c2 s2 ), s2 + c2 1i

de Q[s, c, u, v] traduit les dfinitions de u() et v() de lnonc ainsi que la relation
entre sinus et cosinus. Pour un ordre monomial qui limine prioritairement s et c,
la forme canonique de s6 modulo cet idal donne le rsultat recherch.
426 ANNEXE A. SOLUTIONS DES EXERCICES

sage: R.<s, c, u, v> = PolynomialRing(QQ, order='lex')


sage: Rel = ideal(u-(s+c), v-(2*s*c+c^2-s^2), s^2+c^2-1)
sage: Rel.reduce(s^6)
1/16*u^2*v^2 - 3/8*u^2*v + 7/16*u^2 + 1/8*v^2 - 1/8*v - 1/8

A.10 quations diffrentielles et suites dfinies


par une relation de rcurrence
Exercice 38 page 227. (quations diffrentielles variables sparables)
1. Utilisons la mme mthode que dans la section 10.1.2 :
sage: x = var('x')
sage: y = function('y',x)
sage: ed = (desolve(y*diff(y,x)/sqrt(1+y^2) == sin(x),y)); ed
sqrt(y(x)^2 + 1) == c - cos(x)
Le mme problme apparat. On impose que c-cos(x) soit positif :
sage: c = ed.variables()[0]
sage: assume(c-cos(x) > 0)
sage: sol = solve(ed,y) ; sol
[y(x) == -sqrt(c^2 - 2*c*cos(x) + cos(x)^2 - 1),
y(x) == sqrt(c^2 - 2*c*cos(x) + cos(x)^2 - 1)]

sage: P = Graphics()
sage: for j in [0,1]:
....: for k in range(0,20,2):
....: P += plot(sol[j].subs_expr(c == 2+0.25*k).rhs(),
....: x,-3,3)
sage: P

6
4
2

-3 -2 -1 1 2 3
-2
-4
-6

2. Mme mthode :
sage: solu = desolve(diff(y,x) == sin(x)/cos(y),y,\
....: show_method = True)
sage: solu
[sin(y(x)) == c - cos(x), 'separable']
sage: solve(solu[0],y)
A.11. NOMBRES VIRGULE FLOTTANTE 427

[y(x) == -arcsin(-c + cos(x))]

Exercice 39 page 229. (quations homognes) On vrifie que lquation


xyy 0 = x2 + y 2 dfinie sur ]0, +[ et sur ], 0[ est bien homogne, puis
on essaie de la rsoudre par le changement de fonction inconnue indiqu dans
lexemple trait la section 10.1.2.
sage: x = var('x')
sage: y = function('y',x)
sage: id(x) = x
sage: u = function('u',x)
sage: d = diff(u*id,x)
sage: DE = (x*y*d == x**2+y**2).subs_expr(y == u*id)
sage: equ = desolve(DE,u)
sage: solu = solve(equ,u)
sage: solu
[u(x) == -sqrt(2*c + 2*log(x)),
u(x) == sqrt(2*c + 2*log(x))]
sage: Y = [x*solu[0].rhs() , x*solu[1].rhs()]
sage: Y[0]
-sqrt(2*c + 2*log(x))*x
On peut ajouter des conditions sur x (avec assume) pour se rappeler que
lquation nest pas dfinie en 0.
A.11 Nombres virgule flottante
Exercice 40 page 246. On propose deux solutions.
1. Effectuons le calcul sans utiliser les mthodes de la classe RealField qui
donnent la mantisse et lexposant dun nombre. On vrifie dabord que
299 < 1030 < 2100 (on remarque que 1030 = (103 )10 ' (210 )10 ).
sage: R100=RealField(100)
sage: x=R100(10^30)
sage: x>2^99
True
sage: x<2^100
True
On calcule ensuite la mantisse de x :
sage: e=2^100
sage: s1=10^30
sage: mantisse=[]
sage: nbchiffres=0 # compteur du nombre de chiffres ncessaires
sage: while s1>0:
....: e/=2
....: if e<=s1:
....: mantisse.append(1)
....: s1-=e
428 ANNEXE A. SOLUTIONS DES EXERCICES

....: else:
....: mantisse.append(0)
....: nbchiffres+=1
sage: print mantisse
[1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0,
1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1,
1, 1, 1, 0, 1, 0, 1, 0, 0, 1]
sage: print "nombre de chiffres ncessaires ",nbchiffres
nombre de chiffres ncessaires 70
Les chiffres binaires de la mantisse au-del du soixante-dixime sont nuls.
Le nombre le plus proche de 1030 est donc obtenu en ajoutant 2100 la
mantisse, do le rsultat, x.ulp() vaut : 2100 2100 = 1.
2. En utilisant la mthode sign_mantissa_exponent() de la classe RealField,
on a directement :
sage: R100=RealField(100)
sage: x=R100(10^30)
sage: s,m,e = x.sign_mantissa_exponent()
sage: print s,m,e
1 1000000000000000000000000000000 0
La commande m.binary() permet de constater quon obtient bien la mme
mantisse dans les deux cas.
Exercice 41 page 249.
1. Cherchons dabord les valeurs de , et dans la formule :

100n+1 + 6n+1 + 5n+1


un = . (A.1)
100n + 6n + 5n
Pourquoi ne pas utiliser Sage pour cela ? On se sert des valeurs de u0 , u1
et u2 pour obtenir et rsoudre un systme dquations, dont les inconnues
sont , et . Dfinissons la rcurrence et la solution gnrale :
sage: var("u0 u1 u2 alpha beta gamma n")
(u0, u1, u2, alpha, beta, gamma, n)
sage: recurrence = lambda a,b: 111-1130/a+3000/(a*b)
sage: gener1 = lambda n :(alpha*100^n+beta*6^n+gamma*5^n)
sage: solGen = lambda n: gener1(n+1)/gener1(n)
Calculons u2 en fonction de u1 et u0 et posons le systme :
sage: u2 = recurrence(u1,u0)
sage: s = [u2==solGen(2),u1==solGen(1),u0==solGen(0)]
sage: t = [s[i].substitute(u0=2,u1=-4) for i in range(0,3)]
puis rsolvons-le :
sage: solve(t,alpha,beta,gamma)
A.11. NOMBRES VIRGULE FLOTTANTE 429

[[alpha == 0, beta == -3/4*r1, gamma == r1]]


Le calcul nous montre que reste indtermin.
Nous devons vrifier que nous obtenons bien une solution gnrale, cest--
dire que lquation (A.1) est vrifie pour tout n :
sage: alpha=0
sage: beta = -3/4*gamma
sage: final=solGen(n)-recurrence(solGen(n-1),solGen(n-2))
sage: print final.simplify_full()
0
On peut prendre nimporte quelle valeur pour , par exemple = 4, et lon
a alors = 3 et = 0.
2. On dfinit une procdure qui implmente la rcurrence, avec des coefficients
exacts afin de pouvoir la rutiliser diffrentes prcisions :
sage: def recur(x1,x0):
....: return 111 - 1130/x1 + 3000/(x0*x1)
Les conditions initiales en revanche sont prises dans RealField(), de sorte
que le calcul a lieu dans ce domaine :
sage: u0 = 2.
sage: u1 = -4.
sage: for i in range(1,25):
....: x = recur(u1,u0)
....: print i,x
....: u0 = u1
....: u1 = x
1 18.5000000000000
2 9.37837837837838
3 7.80115273775217
4 7.15441448097533
5 6.80678473692481
6 6.59263276872179
..................
23 99.9999986592167
24 99.9999999193218
La suite converge visiblement vers 100 !
3. Lexplication du comportement du programme tient ce que les valeurs un
ne sont pas calcules exactement : si lon considre la rcurrence dfinie en
prenant pour conditions initiales les termes un1 et un2 , calculs avec une
erreur darrondi, la formule (A.1) ne donne plus la solution gnrale.
Cherchons les valeurs stationnaires de la rcurrence :
sage: var("x")
x
430 ANNEXE A. SOLUTIONS DES EXERCICES

sage: solve(x==recurrence(x,x),x)
[x == 100, x == 5, x == 6]
Il y a 3 valeurs stationnaires : 100, 5 et 6. La convergence vers 100 observe
en prsence derreurs darrondi provient de considrations de stabilit de
ces 3 valeurs (considrations qui sont hors des limites de cet exercice).
4. Augmenter la prcision ne sert rien, la suite converge toujours vers 100 :
sage: RL = RealField(5000)
sage: u0 = RL(2)
sage: u1 = RL(-4)
sage: for i in range(1,2500):
....: x = recur(u1,u0)
....: u0 = u1
....: u1= x
sage: x
100.00000000000000000000000000000000000000000000000000000...
Il suffit quun seul des ui ne soit pas calcul exactement, pour que la suite
diverge ( nest plus nul).
5. Le programme ne subit que peu de modifications. On fait en sorte que les
variables u0 et u1 soient initialiss comme entires :
sage: u0 = 2
sage: u1 = -4
sage: for i in range(1,2500):
....: x = recur(u1,u0)
....: u0 = u1
....: u1 = x
sage: float(x)
6.0
On trouve bien la valeur 6.0, mais si on imprime x, on voit lnorme quantit
dinformation utilise par le calcul (impression non reproduite ici !). En
imprimant x-6, on vrifie que la limite na pas t atteinte : la taille occupe
par reprsentation machine de x na aucune raison de diminuer si on poursuit
les itrations.

A.12 quations non linaires


Exercice 42 page 267. On a vu que le mot cl return termine lexcution de
la fonction. Il suffit donc de tester si f(u) est nul ou pas. Pour viter dvaluer la
fonction f en u plusieurs reprises, on stocke sa valeur dans une variable. Aprs
modification on obtient donc la fonction suivante.
sage: def intervalgen(f, phi, s, t):
....: assert (f(s) * f(t) < 0), \
....: 'Wrong arguments: f(%s) * f(%s) >= 0)'%(s, t)
A.12. QUATIONS NON LINAIRES 431

....: yield s
....: yield t
....: while 1:
....: u = phi(s, t)
....: yield u
....: fu = f(u)
....: if fu == 0:
....: return
....: if fu * f(s) < 0:
....: t = u
....: else:
....: s = u
Testons cette fonction avec une quation dont on connat une solution, par
exemple construite partir dune fonction linaire.
sage: f(x) = 4 * x - 1
sage: a, b = 0, 1
sage: phi(s, t) = (s + t) / 2
sage: list(intervalgen(f, phi, a, b))
[0, 1, 1/2, 1/4]

Exercice 43 page 267. La fonction phi passe en paramtre de intervalgen


dtermine le point o diviser un intervalle. Il suffit donc de donner cette fonction
la dfinition adquate.
sage: f(x) = 4 * sin(x) - exp(x) / 2 + 1
sage: a, b = RR(-pi), RR(pi)
sage: def phi(s, t): return RR.random_element(s, t)
sage: random = intervalgen(f, phi, a, b)
sage: iterate(random, maxit=10000)
After 19 iterations: 2.15848379485564
Exercice 44 page 276. Il est naturel de vouloir faire les calculs avec Polynomial
Ring(SR, 'x'). Une difficult technique vient de ce que cet objet nimplante pas
la mthode roots().
sage: basering.<x> = PolynomialRing(SR, 'x')
sage: p = x^2 + x
sage: p.parent()
Univariate Polynomial Ring in x over Symbolic Ring
sage: p.roots(multiplicities=False)
Traceback (most recent call last):
...
NotImplementedError
La fonction solve() nest pas non plus prvue pour fonctionner avec lobjet
PolynomialRing(SR, 'x'). Une alternative serait dutiliser SR, qui implante ces
mthodes, mais il noffre pas dquivalent de la mthode lagrange_polynomial()
432 ANNEXE A. SOLUTIONS DES EXERCICES

de PolynomialRing(SR, 'x'). On est donc amen faire des conversions entre


ces objets.
sage: from collections import deque
sage: basering = PolynomialRing(SR, 'x')
sage: q, method = None, None
sage: def quadraticgen(f, r, s):
....: global q, method
....: t = r - f(r) / f.derivative()(r)
....: method = 'newton'
....: yield t
....: pts = deque([(p, f(p)) for p in (r, s, t)], maxlen=3)
....: while True:
....: q = basering.lagrange_polynomial(pts)
....: p = sum([c*x^d for d, c in enumerate(q.list())])
....: roots = [r for r in p.roots(x,multiplicities=False) \
....: if CC(r).is_real()]
....: approx = None
....: for root in roots:
....: if (root - pts[2][0]) * (root - pts[1][0]) < 0:
....: approx = root
....: break
....: elif (root - pts[0][0]) * (root - pts[1][0]) < 0:
....: pts.pop()
....: approx = root
....: break
....: if approx:
....: method = 'quadratic'
....: else:
....: method = 'dichotomy'
....: approx = (pts[1][0] + pts[2][0]) / 2
....: pts.append((approx, f(approx)))
....: yield pts[2][0]
Il est maintenant possible dafficher les premiers termes de la suite dfinie par
la mthode de Brent. Attention, les calculs sont relativement longs effectuer (et
les rsultats impossibles afficher sur une page de ce livre...).
sage: basering = PolynomialRing(SR, 'x')
sage: a, b = pi/2, pi
sage: f(x) = 4 * sin(x) - exp(x) / 2 + 1
sage: generator = quadraticgen(f, a, b)
sage: print generator.next()
1/2*pi - (e^(1/2*pi) - 10)*e^(-1/2*pi)
En excutant le code suivant, le lecteur patient pourra visualiser les arcs de
paraboles utiliss dans les calculs des premiers termes de la suite.
sage: generator = quadraticgen(f, a, b)
A.13. ALGBRE LINAIRE NUMRIQUE 433

sage: g = plot(f, a, b, rgbcolor='blue')


sage: g += point((a, 0), rgbcolor='red', legend_label='0')
sage: g += point((b, 0), rgbcolor='red', legend_label='1')
sage: data = {'2': 'blue', '3': 'violet', '4': 'green'}
sage: for l, color in data.iteritems():
....: u = RR(generator.next())
....: print u, method
....: g += point((u, 0), rgbcolor=color, legend_label=l)
....: if method == 'quadratic':
....: q = sum([c*x^d for d, c in enumerate(q.list())])
....: g += plot(q, 0, 5, rgbcolor=color)
2.64959209030252 newton
2.17792417785919 quadratic
2.15915701248844 quadratic
sage: g.show()

A.13 Algbre linaire numrique


Exercice 45 page 284. Daprs la formule de Sherman et Morrison, la rsolution
de Bx = f quivaut celle de Ax = (I + u t v A1 )f avec = (1 + t v A1 u)1 .
On procde alors de la manire suivante.
1. On calcule w solution de Aw = u, puis = (1 + t v w)1 .
2. On calcule z solution de Az = f puis g = t v z (qui est un scalaire).
3. On calcule alors h = (f gu) et on rsout Ax = h ; x est bien la solution
de Bx = f .
On remarque quon a rsolu 3 systmes linaires avec la matrice factorise A,
soit la rsolution de 6 systmes linaires matrice triangulaire. Chacune de
ces rsolutions cote de lordre de n2 oprations, bien moins que le cot dune
factorisation (qui est de lordre de n3 ). Pour vrifier la formule de Sherman et
Morrison, il suffit de multiplier ( droite) le second membre de la formule par
A + u t v puis de vrifier que cette expression est gale la matrice identit.
Exercice 46 page 288. On considre la factorisation de Cholesky A = C t C,
puis la dcomposition en valeurs singulires de C : C = U t V . Alors, X = U t U .
En effet : A = C t C = (U t V )(V t U ) = U t U U t U = X 2 .
Fabriquons une matrice alatoire symtrique dfinie positive :
sage: m = random_matrix(RDF,4)
sage: a = transpose(m)*m
sage: c = a.cholesky()
sage: U,S,V = c.SVD()
sage: X = U*S*transpose(U)
Vrifions que X 2 a est nulle (modulo erreurs numriques) :
sage: M = (X*X-a)
sage: all(abs(M[i,j]) < 10^-14
....: for i in range(4) for j in range(4) )
434 ANNEXE A. SOLUTIONS DES EXERCICES

True

A.14 Intgration numrique et quations


diffrentielles
Exercice 47 page 314. (Calcul des coefficients de Newton-Cotes)
1. En remarquant que Pi est de degr n 1 (donc la formule (14.1) sapplique)
et que Pi (j) = 0 pour j {0, . . . , n 1} et j 6= i, on en dduit
Z n1
Pi (x) dx = wi Pi (i)
0

soit R n1
Pi (x) dx
wi = 0
.
Pi (i)
2. Le calcul des poids sen dduit simplement :
sage: x = var('x')
sage: def NCRule(n):
....: P = prod([x - j for j in xrange(n)])
....: return [integrate(P / (x-i), x, 0, n-1) \
....: / (P/(x-i)).subs(x=i) for i in xrange(n)]
3. Par un simple changement de variable :
Z b
b a n1
 
ba
Z
f (x) dx = f a+ u du.
a n1 0 n1

4. En appliquant la formule prcdente, on trouve le programme suivant :


sage: def QuadNC(f, a, b, n):
....: W = NCRule(n)
....: ret = 0
....: for i in xrange(n):
....: ret += f(a + (b-a)/(n-1)*i) * W[i]
....: return (b-a)/(n-1)*ret
Avant de comparer la prcision de cette mthode avec dautres, nous pouvons
dj vrifier quelle ne renvoie pas de rsultats incohrents :
sage: QuadNC(lambda u: 1, 0, 1, 12)
1
sage: N(QuadNC(sin, 0, pi, 10))
1.99999989482634
Comparons succinctement la mthode obtenue avec les fonctions de GSL
sur les intgrales I2 et I3 :
sage: numerical_integral(x * log(1+x), 0, 1)
(0.25, 2.7755575615628914e-15)
A.15. DNOMBREMENT ET COMBINATOIRE 435

sage: N(QuadNC(lambda x: x * log(1+x), 0, 1, 19))


0.250000000000000
sage: numerical_integral(sqrt(1-x^2), 0, 1)
(0.785398167726482..., 9.042725224567119...e-07)
sage: N(pi/4)
0.785398163397448
sage: N(QuadNC(lambda x: sqrt(1-x^2), 0, 1, 20))
0.784586419900198

Remarquons que la qualit du rsultat dpend du nombre de points utiliss :


sage: [N(QuadNC(lambda x: x * log(1+x), 0, 1, n) - 1/4)
....: for n in [2, 8, 16]]
[0.0965735902799726, 1.17408932943930e-7, 2.13546194616221e-13]
sage: [N(QuadNC(lambda x: sqrt(1-x^2), 0, 1, n) - pi/4)
....: for n in [2, 8, 16]]
[-0.285398163397448, -0.00524656673640445, -0.00125482109302663]

Une comparaison plus intressante entre les diffrentes fonctions dintgra-


tion de Sage et notre mthode QuadNC demanderait de la convertir en une
mthode adaptative qui subdivise automatiquement lintervalle considr
comme le fait numerical_integral.

A.15 Dnombrement et combinatoire


Exercice 48 page 326. (Probabilit de tirer un carr au Poker) Construisons
lensemble des carrs :
sage: Symboles = FiniteEnumeratedSet(
....: ["Coeur","Carreau","Pique","Trefle"])
sage: Valeurs = FiniteEnumeratedSet([2, 3, 4, 5, 6, 7, 8, 9, 10,
....: "Valet", "Dame", "Roi", "As"])
sage: Carres = CartesianProduct((Arrangements(Valeurs,2)), Symboles)
Nous avons utilis FiniteEnumeratedSet plutt que Set afin de spcifier lordre
des symboles, des valeurs, et donc des carrs :
sage: Carres.list()
[[[2, 3], 'Coeur'],
[[2, 3], 'Carreau'],
...
[['As', 'Roi'], 'Trefle']]
La liste prcdente commence par un carr de deux complt par un 3 de cur,
et termine par un carr das complt par un roi de trfle. Au total, il y a 624
carrs :
sage: Carres.cardinality()
624
436 ANNEXE A. SOLUTIONS DES EXERCICES

Rapport au nombre de mains, on obtient une probabilit dune chance sur 4165
dobtenir un carr lorsque lon tire une main au hasard :
sage: Cartes = CartesianProduct(Valeurs, Symboles).map(tuple)
sage: Mains = Subsets(Cartes, 5)
sage: Carres.cardinality() / Mains.cardinality()
1/4165
Exercice 49 page 326. (Probabilit de tirer une quinte flush et une couleur au
Poker) Choisir une quinte flush revient choisir par exemple sa plus petite carte
(entre 1 et 10) et son symbole. Il y en a donc 40.
sage: QuinteFlush = CartesianProduct(srange(1, 11), Symboles)
sage: QuinteFlush.cardinality()
40
Il y a donc 5108 couleurs :
sage: ToutesCouleurs = CartesianProduct(Subsets(Valeurs,5),Symboles)
sage: ToutesCouleurs.cardinality() - QuinteFlush.cardinality()
5108
Au final la probabilit dobtenir une couleur en tirant une main au hasard est
denviron deux sur mille :
sage: _ / Mains.cardinality()
1277/649740
sage: float(_)
0.0019654015452334776
Il serait satisfaisant deffectuer le calcul prcdent par opration ensem-
bliste, en construisant explicitement lensemble des couleurs comme diffrence
de ToutesCouleurs et de QuinteFlush. Cependant il nexiste pas dalgorithme
gnrique efficace pour calculer la diffrence A \ B de deux ensembles : sans infor-
mation supplmentaire, il ny a gure mieux que de parcourir tous les lments
de A et de tester sils sont dans B. Dans le calcul ci-dessus, nous avons utilis
le fait que B est inclus dans A, ce que Sage ne peut deviner priori. Un autre
obstacle, quoique facile dpasser, est quil faudrait que les lments de B et de
A soient reprsents de la mme faon.
Exercice 50 page 326. Nous nous contenterons dillustrer le cas de la main
pleine, forme dun brelan et dune paire. Commenons par implanter une fonction
testant si une main est pleine. Pour une criture concise, nous utilisons la mthode
suivante permettant de compter les rptitions des lettres dun mot :
sage: Word(['a','b','b','a','a','b','a']).evaluation_dict()
{'a': 4, 'b': 3}

sage: def est_main_pleine(main):


....: symboles = Word([valeur for (valeur, symbole) in main])
....: repetitions = sorted(symboles.evaluation_dict().values())
....: return repetitions == [2,3]
A.15. DNOMBREMENT ET COMBINATOIRE 437

sage: est_main_pleine({(5, 'Carreau'), (6, 'Carreau'), (6, 'Coeur'),


....: (5, 'Pique'), (1, 'Pique')})
False
sage: est_main_pleine({(3, 'Trefle'), (3, 'Pique'), (3, 'Coeur'),
....: (2, 'Trefle'), (2, 'Pique')})
True
Nous automatisons maintenant lestimation de la proportion de mains pleines. Plus
gnralement, la fonction suivante estime la proportion dlments de lensemble
fini ensemble satisfaisant predicat. Elle fait lhypothse que lensemble est muni
dune mthode random_element implantant un tirage alatoire uniforme.
sage: def estimation_proportion(ensemble, predicat, n):
....: compteur = 0
....: for i in range(n):
....: if predicat(ensemble.random_element()):
....: compteur += 1
....: return compteur/n

sage: float(estimation_proportion(Mains, est_main_pleine, 10000))


0.0009999999999999998
Faisons maintenant le calcul symboliquement. Choisir une main pleine revient
choisir un couple de valeurs distinctes, lune pour le brelan, lautre pour la
paire, ainsi quun ensemble de trois symboles pour le brelan et un autre de deux
symboles pour la paire :
sage: MainsPleines = CartesianProduct(Arrangements(Valeurs, 2),
....: Subsets(Symboles, 3), Subsets(Symboles, 2))
Voici par exemple, une main pleine avec un brelan de deux et une paire de trois :
sage: MainsPleines.first()
[[2, 3], {'Trefle', 'Pique', 'Carreau'}, {'Pique', 'Trefle'}]
La probabilit de tirer une main pleine est de :
sage: float(MainsPleines.cardinality() / Mains.cardinality())
0.0014405762304921968
Exercice 51 page 326. (Comptage manuel des arbres binaires complets) Il y a
un arbre binaire complet avec une feuille et un avec deux feuilles. Pour n = 3, 4 et
5 feuilles, on trouve respectivement 2, 5 et 14 arbres (pour n = 4, voir Figure 15.1).
Exercice 52 page 336. Les compositions de n k parts sont en bijection avec
les sous ensembles de taille k de {1, . . . , n} : lensemble {i1 , i2 , . . . , ik } o i1 <
i2 < < ik , on associe la composition (i1 , i2 i1 , . . . , n ik ), et rciproquement.
Les formules de dnombrement en dcoulent : il y a 2n compositions de n, et parmi
elles k compositions k parts. Pour retrouver si ces formules sont utilises, on
n


peut regarder limplantation de la mthode cardinality :


sage: C = Compositions(5)
sage: C.cardinality??
438 ANNEXE A. SOLUTIONS DES EXERCICES

Dans le deuxime cas, le nom de la mthode utilise en interne, _cardinality_


from_iterator, donne dj linformation : la cardinalit est calcule ineffica-
cement en itrant travers toute les compositions.
sage: C = Compositions(5,length=3)
sage: C.cardinality
<bound method IntegerListsLex...._cardinality_from_iterator ...>
Exercice 53 page 339. Quelques exemples :
sage: IntegerVectors(5,3).list()
[[5, 0, 0], [4, 1, 0], [4, 0, 1], [3, 2, 0], [3, 1, 1], [3, 0, 2],
...
[0, 4, 1], [0, 3, 2], [0, 2, 3], [0, 1, 4], [0, 0, 5]]

sage: OrderedSetPartitions(3).cardinality()
13
sage: OrderedSetPartitions(3).list()
[[{1}, {2}, {3}], [{1}, {3}, {2}], [{2}, {1}, {3}], [{3}, {1}, {2}],
...
[{1, 2}, {3}], [{1, 3}, {2}], [{2, 3}, {1}], [{1, 2, 3}]]
sage: OrderedSetPartitions(3,2).random_element()
[{1, 3}, {2}]

sage: StandardTableaux([3,2]).cardinality()
5
sage: StandardTableaux([3,2]).an_element()
[[1, 3, 5], [2, 4]]
Exercice 54 page 339. En petite taille, on obtient les matrices de permutation :
sage: list(AlternatingSignMatrices(1))
[[1]]
sage: list(AlternatingSignMatrices(2))
[
[1 0] [0 1]
[0 1], [1 0]
]
Le premier nouvel lment apparat pour n = 3 :
sage: list(AlternatingSignMatrices(3))
[
[1 0 0] [0 1 0] [1 0 0] [ 0 1 0] [0 0 1] [0 1 0] [0 0 1]
[0 1 0] [1 0 0] [0 0 1] [ 1 -1 1] [1 0 0] [0 0 1] [0 1 0]
[0 0 1], [0 0 1], [0 1 0], [ 0 1 0], [0 1 0], [1 0 0], [1 0 0]
]
En regardant les exemples pour n plus grand, on peut voir quil sagit de toutes
les matrices coefficients dans {1, 0, 1} telles que, sur chaque ligne et chaque
A.15. DNOMBREMENT ET COMBINATOIRE 439

colonne, les coefficients non nuls alternent entre 1 et 1, en commenant et


finissant par 1.
Exercice 55 page 339. Il y a 25 vecteurs dans (Z/2Z)5 :
sage: GF(2)^5
Vector space of dimension 5 over Finite Field of size 2
sage: _.cardinality()
32
Pour construire une matrice inversible 3 3 coefficient dans Z/2Z, il suffit de
choisir un premier vecteur ligne non nul (23 1 choix), puis un deuxime vecteur
qui ne soit pas dans la droite engendr par le premier (23 2 choix), puis un
troisime vecteur ligne qui ne soit pas dans le plan engendr par les deux premiers
(23 22 ). Cela fait :
sage: (2^3-2^0)*(2^3-2)*(2^3-2^2)
168
Et en effet :
sage: GL(3,2)
General Linear Group of degree 3 over Finite Field of size 2
sage: _.cardinality()
168
Le mme raisonnement donne la formule gnrale qui sexprime naturellement au
moyen de la q-factorielle :
n1
Y qn
(q n q k ) = [n]q !
(q 1)n
k=0

Ainsi :
sage: from sage.combinat.q_analogues import q_factorial
sage: q = 2; n = 3
sage: q^n/(q-1)^n *q_factorial(n,q)
168
Exercice 56 page 342. Dans le premier cas, Python commence par construire la
liste de tous les rsultats avant de la passer all. Dans le second cas, litrateur
fournit les rsultats all au fur et mesure ; ce dernier peut donc arrter
litration ds quun contre-exemple est trouv.
Exercice 57 page 342. La premire ligne donne la liste des tous les cubes
dentiers t entre 999 et 999 inclus. Les deux suivantes cherchent une paire de
cubes dont la somme est 218. La dernire ligne est plus efficace en temps car elle
sarrte ds quune solution est trouve :
sage: cubes = [t**3 for t in range(-999,1000)]
sage: %time exists([(x,y) for x in cubes for y in cubes],
....: lambda (x,y): x+y == 218)
440 ANNEXE A. SOLUTIONS DES EXERCICES

CPU times: user 1.28 s, sys: 0.07 s, total: 1.35 s


Wall time: 1.35 s
(True, (-125, 343))
sage: %time exists(((x,y) for x in cubes for y in cubes),
....: lambda (x,y): x+y == 218)
CPU times: user 0.88 s, sys: 0.02 s, total: 0.90 s
Wall time: 0.86 s
(True, (-125, 343))
Surtout, elle est plus efficace en mmoire : si n est la longueur de la liste de cubes,
la quantit de mmoire utilise est de lordre de n au lieu de n2 . Cela devient
particulirement sensible lorsque lon dcuple n.
Exercice 58 page 343.
Calcule la srie gnratrice sS x|s| des sous-ensembles de {1, . . . , 8} en
P
fonction de leur cardinalit.
Calcule la srie gnratrice des permutations de {1, 2, 3} en fonction de leur
nombre dinversions.
Vrifie la tautologie x P, x P pour P lensemble des permutations de
{1, 2, 3, 4, 5}. Cest un trs bon test de cohrence interne entre les fonctions
ditration et de test dappartenance sur un mme ensemble. Il est dailleurs
inclus dans les tests gnriques de Sage ; voir :
sage: P = Partitions(5)
sage: P._test_enumerated_set_contains??
La tautologie x / P serait fort utile pour complter le test dappar-
/ P, x
tenance. Cependant il faudrait prciser lunivers ; et surtout il faudrait un
itrateur sur le complmentaire de P dans cet univers, ce qui nest pas une
opration usuelle.
Affiche tous les matrices 2 2 inversible sur Z/2Z.
Affiche toutes les partitions de lentier 3.
Affiche toutes les partitions dentiers (ne sarrte pas !).
Affiche tous les nombres premiers (ne sarrte pas !).
Recherche un nombre premier dont le nombre de Mersenne associ nest
pas premier.
Itre parmi tous les nombres premiers dont le nombre de Mersenne associ
nest pas premier.
Exercice 59 page 345. Construisons Leaf et Node comme suggr :
sage: Leaf = var('Leaf'); Node = function('Node', nargs=2)
Puis dfinissons rcursivement notre itrateur :
sage: def C(n):
....: if n == 1:
....: yield Leaf
....: elif n > 1:
A.16. THORIE DES GRAPHES 441

....: for k in range(1,n):


....: for t1 in C(k):
....: for t2 in C(n-k):
....: yield Node(t1, t2)
Voici les petits arbres :
sage: list(C(1))
[Leaf]
sage: list(C(2))
[Node(Leaf, Leaf)]
sage: list(C(3))
[Node(Leaf, Node(Leaf, Leaf)), Node(Node(Leaf, Leaf), Leaf)]
sage: list(C(4))
[Node(Leaf, Node(Leaf, Node(Leaf, Leaf))),
Node(Leaf, Node(Node(Leaf, Leaf), Leaf)),
Node(Node(Leaf, Leaf), Node(Leaf, Leaf)),
Node(Node(Leaf, Node(Leaf, Leaf)), Leaf),
Node(Node(Node(Leaf, Leaf), Leaf), Leaf)]
On retrouve bien la suite de Catalan :
sage: [len(list(C(n))) for n in range(9)]
[0, 1, 1, 2, 5, 14, 42, 132, 429]

A.16 Thorie des graphes


Exercice 60 page 357. (Graphes circulants) Deux boucles sont suffisantes !
sage: def circulant(n,d):
....: g = Graph(n)
....: for u in range(n):
....: for c in range(d):
....: g.add_edge(u,(u+c)%n)
....: return g
Exercice 61 page 359. (Graphes de Kneser) Le plus simple est dutiliser lobjet
Subsets de Sage. On numre ensuite toutes les paires de sommets pour dtecter
les adjacences, mais cela demande beaucoup de calculs inutiles.
sage: def kneser(n,k):
....: g = Graph()
....: g.add_vertices(Subsets(n,k))
....: for u in g:
....: for v in g:
....: if not u & v:
....: g.add_edge(u,v)
....: return g
On peut cependant gagner du temps en nnumrant que les sommets adjacents.
442 ANNEXE A. SOLUTIONS DES EXERCICES

sage: def kneser(n,k):


....: g = Graph()
....: sommets = Set(range(n))
....: g.add_vertices(Subsets(sommets,k))
....: for u in g:
....: for v in Subsets(sommets - u,k):
....: g.add_edge(u,v)
....: return g
Exercice 62 page 374. (Ordre optimal pour la coloration gloutonne) La mthode
coloring renvoie une coloration comme une liste de listes : la liste des sommets
de couleur 0, la liste des sommets de couleur 1, etc. Afin dobtenir un ordre sur les
sommets qui par lalgorithme glouton produit une coloration optimale, il suffit de
lister les sommets de couleur 0 (dans nimporte quel ordre), puis ceux de couleur
1, et ainsi de suite ! Ainsi, pour le graphe de Petersen, on obtient :
sage: g = graphs.PetersenGraph()
sage: def ordre_optimal(g):
....: ordre = []
....: for classe_de_couleur in g.coloring():
....: for v in classe_de_couleur:
....: ordre.append(v)
....: return ordre
sage: ordre_optimal(g)
[1, 3, 5, 9, 0, 2, 6, 4, 7, 8]

A.17 Programmation linaire


Exercice 63 page 388. (Subset Sum) On associe chaque lment de lensemble
une variable binaire indiquant si llment est inclus on non dans lensemble de
somme nulle, ainsi que deux contraintes :
La somme des lments inclus dans lensemble doit tre nulle.
Lensemble ne doit pas tre vide.
Cest ce que fait le code suivant :
sage: l = [28, 10, -89, 69, 42, -37, 76, 78, -40, 92, -93, 45]
sage: p = MixedIntegerLinearProgram()
sage: b = p.new_variable(binary = True)
sage: p.add_constraint(p.sum([ v*b[v] for v in l ]) == 0)
sage: p.add_constraint(p.sum([ b[v] for v in l ]) >= 1)
sage: p.solve()
0.0
sage: b = p.get_values(b)
sage: print [v for v in b if b[v] == 1]
[-93, 10, 45, 78, -40]

On note quil nest pas ncessaire de dfinir une fonction objectif.


A.17. PROGRAMMATION LINAIRE 443

Exercice 64 page 389. (Ensemble dominant) Les contraintes de ce programme


linaire en nombres entiers correspondent un problme de couverture : un
ensemble S de sommets dun graphe est un ensemble dominant si et seulement si,
pour tout sommet v du graphe on a {v} NG (v) S 6= , o NG (v) dsigne
lensemble des voisins de v dans G. On en dduit le code suivant :
sage: g = graphs.PetersenGraph()
sage: p = MixedIntegerLinearProgram(maximization = False)
sage: b = p.new_variable(binary = True)
sage: for v in g:
....: p.add_constraint( p.sum([b[u] for u in g.neighbors(v)])
....: + b[v] >= 1)
sage: p.set_objective( p.sum([ b[v] for v in g ]) )
sage: p.solve()
3.0
sage: b = p.get_values(b)
sage: print [v for v in b if b[v] == 1]
[0, 2, 6]
444 ANNEXE A. SOLUTIONS DES EXERCICES
B
Bibliographie

[AP98] Uri M. Ascher et Linda R. Petzold, Computer Methods for Ordinary


Differential Equations and Differential-Algebraic Equations. Society
for Industrial and Applied Mathematics, 1998, ISBN 0898714128.
[AS00] Noga Alon et Joel H. Spencer, The Probabilistic Method. Wiley-
Interscience, 2000, ISBN 0471370460.
[Bea09] Bernard Beauzamy, Robust Mathematical Methods for Extremely
Rare Events. En ligne, 2009. http://www.scmsa.eu/RMM/BB_rare_
events_2009_08.pdf, 20 pages.
[BZ10] Richard P. Brent et Paul Zimmermann, Modern Computer Arith-
metic. Cambridge University Press, 2010, ISBN 0521194693. http:
//www.loria.fr/~zimmerma/mca/pub226.html.
[Cia82] Philippe G. Ciarlet, Introduction lanalyse numrique matricielle
et loptimisation. Mathmatiques appliques pour la matrise.
Masson, 1982, ISBN 2225688931.
[CLO07] David Cox, John Little et Donal OShea, Ideals, Varieties, and
Algorithms. Undergraduate Texts in Mathematics. Springer-Verlag,
3e dition, 2007, ISBN 0387946802.
[CM84] Michel Crouzeix et Alain L. Mignot, Analyse numrique des quations
diffrentielles. Mathmatiques appliques pour la matrise. Masson,
1984, ISBN 2225773416.
[Coh93] Henri Cohen, A Course in Computational Algebraic Number Theory.
Numro 138 dans Graduate Texts in Mathematics. Springer-Verlag,
1993, ISBN 3540556400.
[CP01] Richard Crandall et Carl Pomerance, Prime Numbers: A Computa-
tional Perspective. Springer-Verlag, 2001, ISBN 0387947779.
446 ANNEXE B. BIBLIOGRAPHIE

[DGSZ95] Philippe Dumas, Claude Gomez, Bruno Salvy et Paul Zimmermann,


Calcul formel : mode demploi. Masson, 1995, ISBN 2225847800.
[Edm65] Jack Edmonds, Paths, Trees, and Flowers. Canadian Journal of
Mathematics, 17(3):449467, 1965.
[EM07] Mohamed Elkadi et Bernard Mourrain, Introduction la rsolu-
tion des systmes polynomiaux. Numro 59 dans Mathmatiques et
Applications. Springer-Verlag, 2007, ISBN 3540716467.
[FS09] Philippe Flajolet et Robert Sedgewick, Analytic Combinatorics. Cam-
bridge University Press, 2009, ISBN 0521898065.
[FSED09] Jean Charles Faugre et Mohab Safey El Din, De lalgbre linaire
la rsolution des systmes polynomiaux. Dans Jacques Arthur
Weil et Alain Yger (rdacteurs), Mathmatiques appliques L3, pages
331388. Pearson Education, 2009, ISBN 2744073520.
[Gan90] Flix Rudimovich Gantmacher, Thorie des Matrices. ditions
Jacques Gabay, 1990, ISBN 2876470357.
[Gol91] David Goldberg, What Every Computer Scientist Should Know About
Floating Point Arithmetic. ACM Computing Surveys, 23(1):548,
1991.
[GVL96] Gene H. Golub et Charles F. Van Loan, Matrix Computations. Johns
Hopkins Studies in the Mathematical Sciences. Johns Hopkins Uni-
versity Press, 3e dition, 1996, ISBN 0801854149.
[Hig93] Nicholas J. Higham, The Accuracy of Floating Point Summa-
tion. SIAM Journal on Scientific Computing, 14(4):783799, 1993,
ISSN 1064-8275.
[HLW02] Ernst Hairer, Christian Lubich et Gerhard Wanner, Geometric Nu-
merical Integration. Springer-Verlag, 2002, ISBN 3662050200.
[HT04] Florent Hivert et Nicolas M. Thiry, MuPAD-Combinat, an Open-
Source Package for Research in Algebraic Combinatorics. Smi-
naire lotharingien de combinatoire, 51:B51z, 2004. http://www.mat.
univie.ac.at/~slc/wpapers/s51thiery.html.
[LA04] Henri Lombardi et Journadi Abdeljaoued, Mthodes matri-
cielles Introduction la complexit algbrique. Springer, 2004,
ISBN 3540202471.
[LT93] Patrick Lascaux et Raymond Thodor, Analyse numrique matri-
cielle applique lart de lingnieur, tome 1. Masson, 2e dition,
1993, ISBN 2225841225.
[LT94] Patrick Lascaux et Raymond Thodor, Analyse numrique matri-
cielle applique lart de lingnieur, tome 2. Masson, 2e dition,
1994, ISBN 2225845468.
[Mas13] Thierry Massart, Syllabus INFO-F-101 Programmation. En ligne,
2013. http://www.ulb.ac.be/di/verif/tmassart/Prog/, ver-
sion 3.2.
447

[Mat03] Ji Matouek, Using the Borsuk-Ulam Theorem: Lectures on Topo-


logical Methods in Combinatorics and Geometry. Springer-Verlag,
2003, ISBN 3540003625.
[MBdD+ 10] Jean Michel Muller, Nicolas Brisebarre, Florent de Dinechin, Claude
Pierre Jeannerod, Vincent Lefvre, Guillaume Melquiond, Nathalie
Revol, Damien Stehl et Serge Torres, Handbook of floating-point
arithmetic. Birkhuser, 2010, ISBN 0817647049.
[Mor05] Masatake Mori, Discovery of the Double Exponential Transformation
and Its Developments. Publications of the Research Institute for
Mathematical Sciences, 41:897935, 2005.
[NO] Sampo Niskanen et Patric R. J. stergrd, Cliquer Routines for
Clique Searching. http://users.tkk.fi/pat/cliquer.html.
[PWZ96] Marko Petkovek, Herbert S. Wilf et Doron Zeilberger, A = B. A K
Peters Ltd., 1996, ISBN 1568810636.
[Sch91] Michelle Schatzman, Analyse numrique. InterEditions, 1991,
ISBN 2729603731.
[Swi09] Grard Swinnen, Apprendre programmer avec Python. Eyrolles,
2009, ISBN 2212124743. http://inforef.be/swi/python.htm.
[Swi12] Grard Swinnen, Apprendre programmer avec Python 3. Eyrolles,
2012, ISBN 2212134346. http://inforef.be/swi/python.htm.
[TMF00] Grald Tenenbaum et Michel Mends France, Les nombres premiers.
Que sais-je ? P.U.F., 2000, ISBN 2130483992.
[TSM05] Kenichiro Tanaka, Masaaki Sugihara et Kazuo Murota, Numerical
Indefinite Integration by Double Exponential sinc Method. Mathe-
matics of Computation, 74(250):655679, 2005.
[Vie07] Xavier Viennot, Leonhard Euler, pre de la combinatoire contem-
poraine. Expos la journe Leonhard Euler, mathmati-
cien universel , IHS, Bures-sur-Yvette, mai 2007. http://www.
xavierviennot.org/xgv/exposes_files/Euler_IHES_web.pdf.
[vzGG03] Joachim von zur Gathen et Jrgen Gerhard, Modern Computer Alge-
bra. Cambridge University Press, 2e dition, 2003, ISBN 0521826462.
http://www-math.uni-paderborn.de/mca.
[Zei96] Doron Zeilberger, Proof of the Alternating Sign Matrix Conjecture.
Electronic Journal of Combinatorics, 3(2), 1996.
448 ANNEXE B. BIBLIOGRAPHIE
C Index

**, 43 de multiplication rapide, 158


+, 43, 59, 73, 164, 360 aliasing, 70
.., 46 all, 65, 342, 439
;, 42 AlternatingSignMatrices, 339
=, 43 and, 108
==, 17, 44 animate, 78
?, 13, 43 animation, 78
#, 42 anneau dentiers, 119121, 125
_, 14 anneau de polynmes, 112, 132, 183
\, 42, 172 une infinit dindtermines, 186
~, 164 any, 65, 342
append, 68, 273
AA, 105, 274 approximation de Pad, 149
abs, 10, 98, 107 approximation numrique, 10, 47, 129, 144,
acclration de convergence, 275 252, 278
add, 64 quations diffrentielles, 315320
__add__, 98 intgrales, 303315
add_constraint, 385 limites, 32
add_edge, 355 solutions dquations, 2526, 144,
add_edges, 355, 378 206, 247, 255276
add_vertex, 355 arbre, 359, 370
affectation, 14, 43, 50, 70 de Steiner, 370
affichage, 59, 78, 361 arbre dexpression, 17
aide, 8, 13, 100 arte (graphe), 355
AlgebraicField, 105 arithmtique
AlgebraicRealField, 105 des polynmes, 137, 187
algbre linaire, 3539, 159182 lmentaire, 8, 106107
numrique, 277301 modulaire, 119121
algorithme par intervalles, 256
dEdmonds, 368 Arrangements, 326
de Dijkstra, 367 arrondi, 242, 246, 251
de Ford-Fulkerson, 367 assert, 42, 263
450 ANNEXE C. INDEX

assume, 22, 231 characteristic_polynomial, 38, 166


ATLAS, 296 charpoly, 141, 166, 176
attrcall, 344 chemins dans un graphe
augment, 160 arte-disjoints, 368
automatic_names, 16 sommet-disjoints, 368
automorphism_group, 370 chromatic_number, 358, 369
Axiom, 101, 132 CIF, 144, 256, 274
circle, 92, 94
bar_chart, 83, 94 class, 42
base (espace vectoriel), 37, 160 classe, 97, 101
base de Grbner, 194, 196, 207, 210219, clique, 368
332 clique_maximum, 369
cot du calcul, 217 Cliquer (programme), 369
dfinition, 212 clture de Zariski, 197
rduite, 216 CoCoA, 207
base_extend, 160, 164 coefficient
base_ring, 120, 133, 160, 273 matrice, 162
basis, 160 polynme, 135, 185
basis_is_groebner, 212 coefficient binomial, 10
berlekamp_massey, 151, 420 coefficient de tte, 185, 187, 208
binomial, 10, 333 coefficients, 135, 185
BLAS, 296 coeffs, 135
bloc dinstructions, 45 coercition, 99
bloc de Jordan, 180 collect, 19, 20, 134
bloc-notes, 5, 8 collections, 273
block_diagonal_matrix, 162 colonne dune matrice, 162
block_matrix, 160, 162 coloration de graphe, 369, 372, 380
bogues, iii coloring, 363, 369, 374
bool, 17, 105 column_space, 38, 406
boolens, 13, 108 combine, 20
boucle combstruct, 330
for (numration), 45 commentaire, 42
infinie, 66, 266 comparaison, 44
interruption prmature, 48 de deux expressions, 17
while (tant que), 46 compensation catastrophique, voir catas-
breadth_first_search, 366 trophic cancellation
break, 48 complement, 365
CompleteBipartiteGraph, 358
calcul de , 31, 32, 35 CompleteGraph, 358
calcul formel, 3, 113 compltion automatique, 13, 101
et calcul numrique, 12, 261 complex_plot, 81, 94
cardinality, 339, 437 ComplexDoubleField, 251, 256
cartesian_product, 346 ComplexField, 105, 252, 253, 256
CartesianProduct, 258, 346 ComplexIntervalField, 256
catalan, 13 composante connexe, 367
Catalan, constante de, 13 comprhension, 63
catastrophic cancellation, 246 concatnation, 70
catgorie, 103, 138 conchode, 80
categories, 138 condition initiale, 222
category, 103 conditionnement, 278281, 284, 285, 286,
CC, 105, 256, 274 299
CDF, 251, 253, 256, 274 conjugate, 137, 165
center, 367 connected_components, 367
cercle osculateur, 93 connexit, 367, 368, 371, 374
chane de caractres, 59, 69 constante de Masser-Gramain, 128
change_ring, 135, 160, 164, 213 constantes, 252
changement de variable, 228 prdfinies, 13
characteristic, 120 content, 136, 137
451

continue, 48 dveloppe dune courbe, 91


contrib_ode, 223 dveloppement limit, 30, 31, 110, 155
conventions, 8 dveloppeurs de Sage, 4
convergence, 33, 51, 248, 249, 264, 274 devinette, 151
acclration de, 275 diagonalisation, 38, 166
conversion, 99, 102, 106, 136, 244 diagramme, 83, 94
coordonnes polaires, 36, 80 diameter, 367
copy, 71, 164, 291, 366 diamtre dun graphe, 367
corps de nombres, 39, 114, 141 dichotomie, 265
corps fini, 105, 109, 119122, 125 dict, 74, 135
compos, 121 dictionnaire, 74, 185, 356
cos, 21, 252 diff, 31, 33, 135, 235, 401
couleur, 77, 362 DiGraph, 364, 365
count, 68 dimension
coupe (graphe), 370, 374 dun idal, 189, 197, 203, 215
couplage, 368, 379, 388 dune varit, 215
courbe intgrale, 87, 94 dimension, 189, 197, 198
courbe paramtre, 80, 91, 94, 200 discriminant, 143
dans lespace, 96 discriminant dun polynme, 26, 146
cover_ring, 141 disjoint_union, 360, 361
Cox, David A., 183 distance (dans un graphe), 367
cross_product, 36, 404 divides, 137, 189
crt, 124, 137 division, 9
cryptologie, 121, 196 entiers, 10
CSV (comma-separated values), 83 polynmes, 137, 140, 188, 209, 214
cycle hamiltonien, 369, 391 suivant les puissances croissantes, 139
Cyclic, 195 documentation, 8
domaine de calcul, 23, 103115
decomposableObjects, 330 dominating_set, 369
decomposition, 178 dot_product, 36
dcomposition double prcision, 243, 251, 276
de matrice, voir factorisation de ma-
trice e, 13
en lments simples, 20, 147, 232 eccentricity, 367
sans carr, 143 chappement, 42
triangulaire (dun idal), 204 echelon_form, 38, 166, 169, 170, 406
dcorateur, 56 echelonize, 166, 169
def, 42, 53 edge_coloring, 369
degree, 135, 185 edge_connectivity, 367, 368
del, 68, 74 edge_cut, 368
delete_edge, 356 edge_disjoint_paths, 368
delete_vertex, 356 Edmonds, Jack, 388
denominator, 148, 331 effet Magnus, 90
depth_first_search, 366 eigenmatrix_left, 166, 180
deque, 273 eigenmatrix_right, 166, 180
derivative, 33, 135, 185, 261 eigenspaces_left, 166, 179
drive eigenspaces_right, 166, 179
dune expression, 31, 33, 66 eigenvalues, 38, 179
partielle, 34, 185, 222 eigenvectors_left, 166, 179
dun polynme, 135, 185 eigenvectors_right, 38, 166, 179
desolve, 24, 222, 235 elementary_divisors, 166, 171
desolve_laplace, 232, 235 elementwise_product, 164
desolve_rk4, 87, 94 elif, 53
desolve_system, 233 limination
dessin, 84, 94 algbrique, 188, 197, 201, 216
de graphe, 361 de Gauss, 165, 166
det, 171 de Gauss-Jordan, 166, 168
dterminant, 166, 171, 174 elimination_ideal, 198
452 ANNEXE C. INDEX

Elkadi, Mohamed, 183 nullit, 23


ellipse, 36 extend, 68
else, 52 extension, 39
ensemble, 73
ensemble dominant, 369, 389 facteur invariant, 170, 178
ensemble indpendant, 362, 368, 375, 379 factor, 11, 20, 98, 106, 142, 143, 188, 189
enveloppe dune famille de courbes, 92, 200 factor_list, 20
quation, 12, 2427 factorial, 10, 21, 106
commandes de rsolution, 24 factorielle, 10
dune courbe, 80, 81, 200 programmation, 55
dune surface, 96 factorisation
linaire, 22, 24, 25, 172 entier, 98, 127, 142
polynomiale, 143 polynme, 113, 125, 136, 142
rsolution numrique, 25, 255276 factorisation de matrice
quation aux drives partielles, 222 de Cholesky, 283, 288
de la chaleur, 230 de Gauss-Jordan, 168
quation diffrentielle, 24, 87, 154, 221234, LU, 169, 281283, 290
303, 315 QR, 283, 285, 291
coefficients constants, 230, 232, 233 False, 13, 108
paramtre, 229 Faugre, Jean-Charles, 183
variables sparables, 223, 225, 227 fermeture de Zariski, 197, 199, 202
de Bernoulli, 223 feuille de travail, 5
de Clairaut, 224 FieldIdeal, 195
de Lagrange, 224 Fields, 103
de Riccati, 224 filter, 63, 68, 70, 72
exacte, 224 finance, 83
homogne, 224, 227, 229 find_root, 24, 25, 276
linaire dordre 1, 223, 225 FiniteEnumeratedSet, 435
systme, voir systme dquations FiniteEnumeratedSets, 347
trac dune solution, voir graphe FiniteField, 105, 121
dune fonction Firefox, 5
quation fonctionnelle, 154 flatten, 65, 70
quations normales, 285, 286 float, 105
quirpartition, 85 floor, 10
quivalence (matrices), 165, 168 flot, 367, 368, 370, 389
escalier, 211, 212 flottant, voir nombre virgule flottante
espace invariant, 174 flow, 367
espace propre, 166, 174 fonction lmentaire, 21
espace vectoriel, 38 fonction harmonique, 34
tiquette (graphe), 356, 361 fonction objectif, 385
tude de fonction, 22 fonction Python, 43, 53
euler_gamma, 13 anonyme, 63
excentricit, 367 fonction symbolique, 19, 235, 399, 417
exec, 42 fonction trigonomtrique, 10, 11, 21, 252
exists, 342 for, 42, 45, 63, 65, 336, 341
exp, 21 forget, 22
expand, 19, 20 forme
expand_trig, 21 de Frobenius, 174, 177
exponentiation, 9 de Hermite, 169, 406
binaire, 56, 141 de Jordan, 38, 174, 180
modulaire, 121, 126 de Smith, 170
export dune figure, 78, 364 chelonne, 38, 167, 168
exposant dun flottant, 241244, 251 triangulaire, 38, 167, 180
Expression, 258 forme normale
expression rgulire, 70 expression, 20, 23, 103, 115, 132
expression symbolique, 1117, 107, 110 matrice, 165, 168170, 177
112, 114, 132, 157 modulo un idal, 194
fonction, 19 primaire, 182
453

formule solution dquation diffrentielle, 87,


de Bailey-Borwein-Plouffe, 35 226, 318
de Cramer, 281 Graphics, 87, 94
de Leibniz, 66 graphique, 16, 7796
de Machin, 31 groupe, 103
de Sherman et Morrison, 433 de Galois, 146
formule close, 191 linaire GLn , 161
fourier_series_partial_sum, 79 GSL, 87, 310, 311, 317319, 434
Frac, 148 guessing, 151
fraction rationnelle, 20, 139, 147
frozenset, 394 hamiltonian_cycle, 369, 370
function, 19, 222, 235 hermite_form, 170
function_factory, 417 histogramme, 83, 94
histoire de Sage, 4
galois_group, 143, 146 historique de commandes, 14
gcd, 137, 189 homogenize, 185, 195
gen, 132, 197
gnrateur, 121, 133, 270 i (unit imaginaire), 13, 107
dun anneau de polynmes, 183 ideal, 140, 141, 189, 195
espace vectoriel, 160 idal
programmation, voir itrateur polynmes, 188, 192
gnricit, 99 polynmes une infinit dindtermi-
genre, 198, 370 nes, 186
gens, 160, 184 identificateur, 42
genus, 198, 370 identity_matrix, 160, 290
IEEE 754, 242
gomtrie, 200, 202
if, 52, 63
algbrique, 207
imag, 107
get_values, 385
image, voir graphique
GF, 105, 121, 125
dune application linaire, 172
gfun, 330
dune fonction, 75
GL, 161
image, 166, 172
global, 54
immuabilit, 72, 73, 164, 356, 385
GMP, 256
implicit_plot, 81, 94
GMRES, 299, 301
implicit_plot3d, 96
GNU MPFR, 244, 295 import, 14, 42
GNU/Linux, 6 in, 61, 73, 74
gradient conjugu, 299 indentation, 8, 45, 47
Graph, 355, 356, 364, 365, 369 independent_set, 362, 369, 379
graphe index, 68
adjoint, voir line graph inquation, 25, 383
alatoire, 359, 368, 374, 376 systme polynomial, 202
biparti, 359, 370 infini, 13, 244
circulant, 357, 359 InfinitePolynomialRing, 185, 186
complet, 359 Infinity, 28, 334
cordal, 366, 370 inject_variables, 423
dintervalles, 370 insert, 68
de Kneser, 359 instance, 97
de Petersen, 357, 358 instruction conditionnelle, 52
eulrien, 370 int, 105, 334
familles de graphes, 358 Integer, 106, 256
k-connexe, 367 integer_kernel, 166, 173
parfait, 371 IntegerListsLex, 348350
petits graphes, 357 IntegerModRing, 105, 108, 119, 125
planaire, 358 IntegerRing, 105
sommet-transitif, 358, 371 Integers, 105, 119
graphe dune fonction, 77, 94 IntegerVectors, 339
complexe, 81 integral, 34
454 ANNEXE C. INDEX

integrate, 31, 34, 310 lambda, 42, 63, 68


integrate_numerical, 35 Lapack, 291, 295
intgration laplace, 235
numrique, 35, 303315 LATEX, 78
symbolique, 31, 34 LattE, 350
interpolation de Cauchy, 151 LaurentSeriesRing, 148
interreduced_basis, 216 LazyPowerSeriesRing, 155, 328
intersection, 195, 197 lc, 185
intervalle, 46 lcm, 123, 137, 189
arithmtique, voir arithmtique par leading_coefficient, 135
intervalles left_kernel, 37, 38, 166, 173
introspection, 100, 335 left_solve, 24
invariant de similitude, 174, 176, 178 lemme de Dickson, 212
inverse len, 60, 70, 73, 334
compositionnel dune srie, 148 lex_BFS, 366, 370
dune matrice, 165 lhs, 24, 229, 235
modulaire, 120 lift, 120, 140, 141, 194, 195
inverse_laplace, 232, 235 ligne dune matrice, 162
invite de commande, 8 ligne de commande, 6
irrelevant_ideal, 195 lim, 28
is_bipartite, 370 limit, 28, 31, 401
is_cartesian_transitive, 371
limite, 31
is_chordal, 366, 370
approximation numrique, 49
is_connected, 367
line, 84, 87, 94
is_constant, 135
line graph, 365
is_eulerian, 370
line3d, 96
is_exact, 274
linarisation (trigonomtrie), 21
is_hamiltonian, 370
Linux, 6
is_integral_domain, 133
liste, 60
is_interval, 371
liste de diffusion, 8
is_irreducible, 142, 143
is_isomorphic, 360, 370 Little, John B., 183
is_monic, 135 lm, 185
is_noetherian, 138 log, 21, 128, 252
is_perfect, 371 logarithme discret, 127128
is_prime, 125 logique, 108
is_pseudoprime, 125 lt, 185
is_regular, 358
is_ring, 138 Mac OS X, 6
is_squarefree, 189 Macaulay2, 207
is_tree, 370 Machin, John, 31
is_vertex_transitive, 358, 371 Magma, 101, 132
is_zero, 23, 261 maille (graphe), 358
isomorphisme de graphes, 370 mantisse, 241244, 251
iter, 341 manuel, 8
itrateur, 45, 46, 266, 336, 341, 344, 367 map, 62, 65, 70, 72
itertools, 343 map_coefficients, 185
Maple, 15, 132, 330
jacobi, 127 marche alatoire, 84
jacobian_ideal, 195 Massart, Thierry, 41
jordan_block, 160, 166, 181 matching, 379
jordan_form, 38, 181 matrice, 37, 38, 109, 159182, 277301, 383
compagnon, 175, 180
Kash, 101 dadjacence, 161, 356
kernel, 166, 173 de Hilbert, 279, 293
keys, 74, 346 de Jordan, 181
de passage, 170
lagrange_polynomial, 137, 272, 305 de transposition, 165
455

quivalence, voir quivalence (ma- multicommodity_flow, 370


trices) multiplication rapide, 158
norme, voir norme de matrice multiplicit, 193, 255, 261
par blocs, 162 MuPAD, 101, 132
similitude, voir similitude (matrices) MuPAD-Combinat, 330, 349
unimodulaire, 169 mutabilit, voir immuabilit
matrix, 37, 38, 109, 141
matrix_block, 38 n, voir numerical_approx
MatrixGroup, 160 n-uplet, voir tuple
MatrixSpace, 105, 109, 159, 160 NaN (Not a Number), 244
max_cut, 370 new_variable, 386, 389
max_symbolic, 313 next, 340, 341
Maxima, 15, 132, 228, 260, 311, 318, 319 next_prime, 124
maxspin, 166, 176 nud, 96
membre dune galit, 24 nombre
Mends France, Michel, 85 virgule flottante, 25, 106, 241
mthode algbrique, 39, 111, 114, 136, 141, 144,
dEuler, 316 149, 189
de Brent, 276 complexe, 107, 233
de dichotomie, 265 de Carmichael, 126
de Dormand et Prince, 316 de Mersenne, 342
de Gauss-Kronrod, 304, 306 dcimal, 106
de Gauss-Legendre, 306 entier, 105
de Gear, 316 entier modulaire, 108, 119121
de la fausse position, 267 p-adique, 144
de la scante, 270 premier, 124127
de Muller, 271 rationnel, 106
de Newton, 269 nombre chromatique, 358, 359
de Newton-Cotes, 305 nombre harmonique, 123, 249
de Runge-Kutta, 316 None, 43, 54
de sparation des variables, 230 norm, 36
de Steffensen, 275 normal_basis, 198, 207
des rectangles, 305 norme
des trapzes, 307 de vecteur, 36
doublement exponentielle, 304, 307 de matrice, 278, 279, 284, 286, 287
QR, 291 norme IEEE 754, 242
mthode (programmation), 43, 98 not, 108
Microsoft Windows, 6 notebook, voir bloc-notes
mineur dun graphe, 370 NotImplementedError, 136
interdit, 358 noyau, 37, 38, 166, 172
mineur dune matrice, 166 nth_root, 21
minimal_polynomial, 38, 166 nuage de points, 84
minor, 370 Nullstellensatz, 194
minpoly, 141, 166 number_field, 141
MixedIntegerLinearProgram, 384, 385 NumberField, 39, 111, 141
mod, 120, 141, 188, 195 numer, 98
modle de Verhulst, 229 numerator, 148
modle proie-prdateur, 89 numerical_approx, 10, 13, 23, 107
module dun nombre complexe, 10, 107 NumPy, 89, 274, 295
monme de tte, 185, 187, 208
Mourrain, Bernard, 183 objet, 97
moyenne arithmtico-harmonique, 50, 54 ode_contrib, 224
MPFR, voir GNU MPFR ode_solver, 87, 317
MPolynomial, 185 odeint, 87, 94, 411
mq, 196 one, 160
Muller, David E., 272 oprations arithmtiques, 8, 17, 99
Muller, Jean-Michel, 249 corps finis, 121
__mult__, 98 matrices, 164
456 ANNEXE C. INDEX

modulo n, 120 de Legendre, 306


polynmes, 134, 187 de Tchebycheff, 139
optimisation, 383395 polynme caractristique, 38, 166, 174, 177
or, 108 polynme minimal
order, 355 matrice, 38, 166, 175
OrderedSetPartitions, 339 nombre algbrique, 191
ordre rcurrence linaire, 141
additif, 120 vecteur, 175
multiplicatif, 121 polynomial, 185, 186
ordre des variables, 184 polynomial_sequence, 196
ordre lexicographique, 66, 209 PolynomialRing, 105, 133, 184, 185
ordre monomial, 185, 187, 188, 208 pop, 68, 74
changement dordre, 217 PowerSeriesRing, 110, 148
OS X, voir Mac OS X prec, 152
OShea, Donal, 183 prcision
arbitraire vs fixe, 243, 253
PALP, 350 calcul numrique, 206
parametric_plot, 80, 94 flottant, 241244, 246, 247, 249
paramtrisation, 91, 200 perte de, 246
parcours de graphe, 366, 367 srie, 152
parent, 101, 103, 133, 138 primalit, voir nombre premier
parent, 120 prime_range, 126
paresseux, 155 primitive, 31
PARI, 101, 274, 309, 312, 313 print, 42, 55, 59
partage de donnes, 70 probabilit, 360
partial_fraction, 20, 232 problme de Gauss, 36
partial_fraction_decomposition, 148 procdure, 43, 53
partie entire, 10, 21 prod, 64
pass, 42 produit, 64
periphery, 367 cartsien, 65, 102
Permutations, 373 de graphes, 365, 371
pgcd scalaire, 36
entiers, 120, 122, 123 vectoriel, 36
polynmes, 137, 261 profil de rang, 166, 171
phnomne de Gibbs, 79 programmation, 4175, 339345
phnomne de Runge, 305 oriente objet, 97100
(constante dArchimde), 13 programmation linaire, 367, 369, 383395
calcul, voir calcul de en nombres entiers, 384
pi, 13 projection, 199
piecewise, 79 pseudo-division, 139
pivot de Gauss, 167 pseudo-primalit, 125
pivot_rows, 166, 171 pseudo_divrem, 137
pivots, 166, 171 puissance, 9
plot, 16, 31, 77, 94, 226, 258, 304, 364 programmation, 56
plot3d, 16, 93 puissance inverse, 289
plot_histogram, 83, 94 puissance itre, 289290, 300301
plot_points, 77 Python 3, 41
plot_vector_field, 89
plus court chemin (graphe), 367 q-factorielle, 439
point, 84 QQ, 105, 256, 274
point dcimal, 10 QQbar, 105, 144, 189, 274
point fixe, 154 QUADPACK, 311
points, 94 quadrature, 305
polar_plot, 80, 94 quit, 43
polygen, 132 quo, 140, 141, 195
polygon, 94 quo_rem, 137, 188
polymorphisme, 99 quotient
polynme, 131158, 183219 anneau de polynmes, 193, 206
457

numrique, voir oprations arithm- restes chinois, 123


tiques resultant, 143, 189, 198
Z/nZ, 119 rsultant, 145, 201
quotient, 195, 197 return, 42, 48, 54, 266, 344
reverse, 66, 134, 135
raccourci clavier, 8 reversion, 148
racine dun polynme, 143, 246, 255263 rhs, 24, 235
isolation, 262 RIF, 144, 256, 274
racine n-ime, 10, 21 right_kernel, 37, 38, 166, 173, 405
radical, 143, 195 right_solve, 24
radical dun idal, 194 RisingFactorial, 238
radius, 367 root_field, 257
Ramanujan, Srinivasa, 32 roots, 24, 26, 143, 203, 255, 260, 261, 276
random, 84 row_space, 38
random_element, 135, 373 RR, 105, 256, 274
random_matrix, 160 rsolve, 237
randrange, 83
rang dune matrice, 166, 171, 174, 284286 sac dos (problme du), 387
range, 46, 341 Safey El Din, Mohab, 183
rank, 171 sage-support, iii
Rational, 97, 98 sage:, 8
rational_argument, 191 sagemath.org, 8
rational_reconstruct, 148, 149 sagenb.org, voir serveur public
rational_reconstruction, 122 satellite, 36
RationalField, 105 save, 78
raw_input, 60 SciPy, 87, 88, 276, 295, 298, 301, 411
rayon dun graphe, 367 squence, voir tuple
RDF, 136, 243, 253, 256, 274 srie, 28, 31, 32, 249
real, 107 alterne, 50
real_root_intervals, 143 de Fourier, 79
real_roots, 143, 274, 276 de Riemann, 32, 51
RealField, 105, 243, 253, 256 srie formelle, 110, 148, 149, 151, 418
RealIntervalField, 256 series, 31, 110
reconstruction rationnelle, 122, 129, 148, serveur public, 56
149 Set, 73, 435
rcurrence, voir suite rcurrente set_binary, 386
reduce set_immutable, 164
liste, 64 set_integer, 386
modulo, 140, 148, 194, 195 set_max, 386
reduce_trig, 21 set_min, 386
rduction des endomorphismes, 38, 166 set_objective, 385
rduction retarde, 121 set_real, 386
rcriture, 210 shortest_path, 367
rgle de Descartes, 262 show, 78, 94, 361, 362, 364, 380
relation de Bzout, 140 significande, voir mantisse
remove, 68 similitude (matrices), 174, 177, 182
reprsentation des polynmes simplification, 11, 2123, 113
creuse, 156, 185 simplify, 11, 20, 111
dense, 156 simplify_exp, 20
factorise, 112 simplify_factorial, 21, 22
rcursive, 134, 186 simplify_full, 22
rsidu quadratique, 127 simplify_radical, 21, 22
rsolution simplify_rational, 2022, 331
quations numriques, 2427, 255 simplify_trig, 2123
276 sin, 21, 252
programmation linaire, 385 Singular, 185, 207
systmes linaires, 36, 166, 172 size, 355
systmes polynomiaux, 188 SL, 161
458 ANNEXE C. INDEX

sloane_find, 327 surface paramtre, 94


smith_form, 166, 171 SVD (singular value decomposition), voir
Solaris, 6 valeur singulire
solve, 22, 24, 91, 188, 228, 385, 386 swap_columns, 166
solve_left, 37, 38, 166, 172 swap_rows, 166
solve_right, 37, 38, 166, 172 Swinnen, Grard, 41
sommation sxrange, 46
numrique compense, 250 symbole de Jacobi, 127
programmation, 48 symbole de Pochhammer, 238
symbolique, 27, 31 SymPy, 237
somme de sous-ensembles, 388 systme dquations, 25, 36, 172, 183, 383
sommet (graphe), 355 diffrentielles, 233
sort, 66
sorted, 67 table dadjacence, 356
sous-graphe induit, 360, 376 table de hachage, 73, 74
sous-matrice, 163 tableau de variations, 22
split, 70 tableur, 83
sqrt, 21, 22, 39 tabulation, 13
squarefree_decomposition, 143 tangente
SR, 105, 157, 258 une courbe, 269
SR.var, voir var taylor, 31, 150, 399
srange, 46 Tenenbaum, Grald, 85
SSP (subset sum problem), 388 terme de tte, 185, 187, 208
stable (graphe), voir ensemble indpen- test, 52
dant test de Fermat, 125
stack, 160 test de nullit, 23
StandardTableaux, 339 test_poly, 184
Stein, William, 4 text, 94
steiner_tree, 370 thorme
str, 70, 105 de Borsuk-Ulam, 359
structure algbrique, 101103 de Cayley-Hamilton, 177
subgraph, 365 de dAlembert-Gauss, 257
subgraph_search, 360, 370, 371, 378 de Kuratowski, 358
submatrix, 160 de Menger, 367
SubMultiset, 423 de Pocklington, 125
subs, 18, 135, 185, 187 de Schwarz, 34
subs_expr, 18 timeit, 121
subset sum, 388 TimeSeries, 83
Subsets, 423, 441 trac.sagemath.org, iii
substitute_function, 418 trace, 278, 287
suite trace, 141
de Fibonacci, 5559 transformed_basis, 191, 217
de Syracuse, 52 transforme de Laplace, 231
hypergomtrique, 238 transpose, 165, 283, 285, 288
logistique, 235 transpose, 165
suite aliquote, 128 transvection, 165, 166
suite de Krylov, 174 traveling_salesman_problem, 370
suite de Sturm, 262 tree, 359
suite numrique, 29 tri, 66
quirpartie, 85 triangular_decomposition, 191, 198, 204
suites adjacentes, 49 trig_expand, 400
suite rcurrente, 45, 4756, 141, 151, 235 trig_simplify, 400
238 trigonalisation, voir forme triangulaire
stabilit numrique, 247 trigonomtrie, 217
trac, 85, 236 troncature dune srie, 148
sum, 27, 31, 64, 341 True, 13, 108
Sun OS, 6 truncate, 31
surface de Cassini, 96 try, 42, 84
459

tuple, 72 vecteur, 36
type de base, 105 construction, 161
vecteur cyclique, 175
ulp, 245 vecteur propre, 38, 166, 179
ulp (unit in the last place), 245 vector, 36, 161
union vector_space_dimension, 198
ensembles, 73, 327, 346 VectorSpace, 159
graphes, 360 vertex_connectivity, 367
vertex_cut, 368
valeur absolue, 10 vertex_disjoint_paths, 368
valeur caractristique, 174 voyageur de commerce, 369, 391
valeur dadhrence, 236
valeur propre, 38, 166, 174, 179, 233 WeightedIntegerVectors, 335
valeur singulire, 284, 286, 287 while, 42
valuation, 137 Windows, 6
values, 74
with, 42
Vandermonde (dterminant de), 112
worksheet, voir feuille de travail
var, 15, 235
variable
Python, 1314, 43, 54 x (variable symbolique), 15
symbolique, 1516, 22 xgcd, 137
variable xrange, 46, 341
dpendante, 222
indpendante, 222 yield, 42, 266, 344
variable_name, 135
variable_names_recursive, 185 zero, 160
variables, 135, 235 (fonction zta de Riemann), 32, 52
varit algbrique, 192 zip, 72
variety, 189, 198, 203 ZZ, 105, 120, 256, 274
Sage est un logiciel libre de calcul mathmatique sappuyant sur le
langage de programmation Python. Ses auteurs, une communaut
internationale de centaines denseignants et de chercheurs, se sont
donn pour mission de fournir une alternative viable aux logiciels
Magma, Maple, Mathematica et Matlab. Sage fait appel pour cela
de multiples logiciels libres existants, comme GAP, Maxima, PARI
et diverses bibliothques scientifiques pour Python, auxquels il ajoute
des milliers de nouvelles fonctions. Il est disponible gratuitement et
fonctionne sur les systmes dexploitation usuels.
Pour les lycens, Sage est une formidable calculatrice scientifique et
graphique. Il assiste efficacement ltudiant de premier cycle universitaire
dans ses calculs en analyse, en algbre linaire, etc. Pour la suite du
parcours universitaire, ainsi que pour les chercheurs et les ingnieurs,
Sage propose les algorithmes les plus rcents dans diverses branches
des mathmatiques. De ce fait, de nombreuses universits enseignent
Sage ds le premier cycle pour les travaux pratiques et les projets.
Ce livre est le premier ouvrage gnraliste sur Sage, toutes langues
confondues. Cocrit par des enseignants et chercheurs intervenant tous
les niveaux (IUT, classes prparatoires, licence, master, doctorat), il met
laccent sur les mathmatiques sous-jacentes une bonne comprhension
du logiciel. En cela, il correspond plus un cours de mathmatiques
effectives illustr par des exemples avec Sage qu un mode demploi
ou un manuel de rfrence.
La premire partie est accessible aux lves de licence. Le contenu des
parties suivantes sinspire du programme de lpreuve de modlisation
de lagrgation de mathmatiques.
Ce livre est diffus sous licence libre Creative Commons. Il peut tre
tlcharg gratuitement ou imprim la demande prix modique depuis
http://sagebook.gforge.inria.fr/

cba

Vous aimerez peut-être aussi