Académique Documents
Professionnel Documents
Culture Documents
Sagebook Web 20130530 PDF
Sagebook Web 20130530 PDF
SAGE
Calcul mathmatique avec Sage
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
Nancy, France
Paul Zimmermann
Mai 2013
Table des matires
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
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
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
IV Combinatoire 321
Annexes 399
B Bibliographie 445
C Index 449
xii TABLE DES MATIRES
Premire partie
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
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.
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
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 + 1050 ) 1050 .
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
sage: y = 1 + 2
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
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
5. En fait, la variable symbolique x est prdfinie dans Sage. Mais cest la seule.
16 CHAP. 1. PREMIERS PAS
+ *
^ * 2 + +
x 2 3 x 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
Fonctions symboliques
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
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)
(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
Le problme de la simplification
quations numriques
Rsolution symbolique solve
Rsolution (avec multiplicit) roots
Rsolution numrique find_root
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 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
sage: eq.rhs()
0
2 cos()2 11 2 cos()2 1+1
z= cos() , z = cos()
xy 3 z = 24,
xyz 4 = 3.
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
(0.226698825758202 + 1.46771150871022 I, 1)
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
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
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
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 .
sage: taylor((1+arctan(x))**(1/x), x, 0, 3)
16 x e + 8 x e 2 xe + e
1 3 1 2 1
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)
sage: (ln(2*sin(x))).series(x==pi/6, 3)
2
3
( 3)( 16 + x) + (2)( 16 + x) + O 216
1
( 6 x)
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.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)
(x, y) |--> x
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)
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
Z 1/ 2
f (t)
2. Pour N N, on pose J = dt. Montrer lim SN = J.
0
1 t8 N +
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
A1 ( 01 ) , A2 ( 22 ) , A3 ( 3.5
0 ), O ( 00 ) .
3 12
2 2 33
6 1 26 16 69
A= .
10 29 18 53 32
2 0 8 18 84
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
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
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.
= 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
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
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 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.
1
u0 = 1, n N un+1 = .
1 + u2n
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
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
Dans ce cas,
(-0.901543155458595, -0.901542184868447)
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
p= 0 1 2 3 4 5 6 7 8 9 10
up = 6 3 10 5 16 8 4 2 1 4 2
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.
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
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
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
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.
ainsi :
u2 = a 2 , u4 = u22 = a4 , u5 = a a4 = a5 ,
u10 = u25 = a10 , u11 = a a10 = a11 .
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.
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
0 1
un
A= , Xn = , AXn = Xn+1 An X0 = Xn .
1 1 un+1
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: 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 :
[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.
sage: map (N, map (cos, [0, pi/6, pi/4, pi/3, pi/2]))
[1.00000000000000, 0.866025403784439, 0.707106781186548,
0.500000000000000, 0.000000000000000]
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
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]]
dun lment :
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
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]
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
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.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 :
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 :
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.
0.8
0.6
0.4
0.2
1
Figure 4.1 Graphe de x 7 x sin x
.
2 4
1.5 3
1 2
0.5 1
0.5
-8 -6 -4 -2 2 4 6 8
-0.5
-1
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
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
-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).
1
2
1 0.5
-3 -2 -1 1 2 3 -1 -0.5 0.5 1
-1 -0.5
-2
-1
-3
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.
-3
4.1. COURBES EN 2D 83
9 350
8
300
7
6 250
5 200
4 150
3
100
2
1 50
2 4 6 8 10 5 10 15
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
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
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) :
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
-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
1 1
0.5 0.5
-1 -1
(a) Rsolution symbolique. (b) Rsolution numrique.
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.
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
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).
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 .
12
10
-8 -6 -4 -2 2 4 6 8
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
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
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
0.4
0.2
-4 -3 -2 -1 1 2 3 4
-0.2
-0.4
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)
<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
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
sage: parent(5)
Integer Ring
sage: parent(5/1)
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
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)
fields
euclidean domains
gcd domains
integral domains
rings
rngs semirings
sets
objects
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
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'>
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
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
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.
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]
Les oprations sur les matrices symboliques sont dcrites au chapitre 8, lalgbre
linaire numrique au chapitre 13.
110 CHAP. 5. DOMAINES DE CALCUL
a0 + a1 x + a2 x2 + + an xn + O(xn+1 )
sage: (1 / f).series(x == 0, 6)
1 + 12 x2 + 5 4
+ O x6
24 x
5.4. EXPRESSIONS VERSUS DOMAINES DE CALCUL 111
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
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
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
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
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
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.
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
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
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.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
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
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
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
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
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
r7 = 5/4, r8 = r9 = 2 :
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 ] =
1, 1, 2, 3, 8, 11, 39...?
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
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
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()
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.
Divers
interpolation p(xi ) = yi p = R.lagrange_polynomial([(x1,y1), ...])
contenu de p Z[x] p.content()
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.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
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
ak p = qd + r.
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 !
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()
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
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()
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
p = pm (x 1 ) . . . (x m )
Y
Res(p, q) = pm qn
n m
(i j ),
q = qn (x 1 ) . . . (x n ).
i,j
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
: B[a1 , . . . , ak ] K
q(a1 , . . . , ak ) 7 q(1 , . . . , k ).
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
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)
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].
1, 1, 2, 3, 8, 11, 34, 39, 148, 127, 662, 339, 3056, 371, 14602, 4257, . . . ,
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 :
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 :
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
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
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
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.
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.
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.
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)
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).
[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.
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
12 13 14 15
sage: A.matrix_from_rows_and_columns([0,2,3],[1,2])
1 2
9 10
13 14
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.
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
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.
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)
i j
1
1
.. ..
.
.
0 1
1 s i
Ti,j = , Ci,j,s = .
.. ..
.
.
1
1 0
j
..
.. .
.
1
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
6 2 2
5 4 4
6 4 5
5 1 3
5 0 0 1 0 4 6
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
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.
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
sage: A.elementary_divisors()
[1, 1, 3, 6]
sage: S == U*A*V
True
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
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
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 :
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
0 0 1 10
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-
Ck
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,
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: 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.
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
(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
0 0 0 2
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.
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
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()
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
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.
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.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
xy 3 z = 24 (9.1)
xyz 4 = 6.
9.2. SYSTMES POLYNOMIAUX ET IDAUX 189
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 .
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
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
Des formules closes. Une expression explicite des solutions est donc possible
en ayant recours la notation exponentielle des complexes :
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]
z 17 = 1 y = 2z 10 x = 3z 3 ,
1 1
0.5 0.5
x2 + y 2 = 1 x2 + y 2 = 1
( (
(S1 ) (S2 ) (9.3)
16 x2 y 2 = 1 4 x2 y 2 = 1.
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
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()
On a
V ( J) = V (J)
196 CHAP. 9. SYSTMES POLYNOMIAUX
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.
V (I + J) = V (I) V (J).
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
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
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.
sage: J1.gens()
[x^2 + y^2 - 1, 16*x^2*y^2 - 1]
Figure 9.2 Une portion de la courbe en (x, y, t) dfinie par (9.6) et sa projection sur le
plan t = 0.
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
Ingalits
x2 + y 2 = (1 x)2 + y 2 .
sage: eq.derivative(t).resultant(eq, t)
x^2 - y^2 - 1/2
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.
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
1 1
0.5 0.5
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
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).
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.
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].
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
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.
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]
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)
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
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]
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
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
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.
y 0 + P (x)y = Q(x),
P (x) = y 0 Q(y),
y 0 + P (x)y = Q(x)y ,
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
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
-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
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
dy y+ y 2 + x2 N (y, x)
p
= = ,
dx x M (y, x)
228 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES
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 ,
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
80
60
40
20
0.5 1 1.5 2 2.5 3
-20
-40
-60
-80
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
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
z(x, t) = f (x)g(t).
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
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 :
3 2
4
A= , c= .
1 3 0
Avec Sage :
soit : (
y1 (x) = 2 cos(2x)e3x
y2 (x) = sin(2x)e3x .
234 CHAP. 10. QUATIONS DIFFRENTIELLES ET RCURRENCES
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
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()
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
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 :
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
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.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 . . . dp 2e ,
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).
Nous pouvons en dduire que les diffrents arrangements possibles des calculs
dans un programme ne sont pas sans importance sur le rsultat !
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.
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 !
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
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
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.
p = (x )q + r.
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)]
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)
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)]
vrifiant 3uv + p = 0.
-3 -2 -1 1 2 3
-2
-4
-6
-8
-10
....: 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
-3 -2 -1 1 2 3
-2
-4
-6
-8
-10
ba
a f (a) .
f (b) f (a)
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
-2
-4
-6
-8
-10
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
-2
-4
-6
-8
-10
-2
-4
-6
-8
-10
P = a0 + a1 x + . . . + ad1 xd1 + xd .
0 0 0 ... 0
a0
1 0 0 . . . 0 a1
A= 0 1 0 0
. . . a2 .
. . . . . . . . . . . . . . . . . . . . . . . . .
0 0 0 . . . 1 ad1
(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 ()
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
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
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).
13.2.3 La dcomposition LU
Ln1 . . . L2 L1 A = U.
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
A1 u t v A1
(A + u t v)1 = A1 .
1 + t v A1 u
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 .
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 :
Bien noter ici que la dcomposition de Cholesky est cache et que la rsolution
Z.solve_right(R) utilise cette dcomposition, sans la recalculer.
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)
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
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
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)
sage: Q
[ 0.76737943398 0.641193265954]
[-0.641193265954 0.76737943398]
sage: R
[ 0.764842187284 0.644217687238]
[-0.644217687238 0.764842187284]
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
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],
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 :
0.8
0.6
0.4
0.2
20 40 60 80
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
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.
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
.
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
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
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
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).
2 cosh t
0 (t) =
cosh2 ( 2 sinh t)
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.
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
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.
(u) = 1 pour 0 6 u 6 1.
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 :
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
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
2
1.5
1
0.5
20 40 60 80 100
-0.5
-1
-1.5
-2
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
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)]
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
F F F F
F F F F
F F F F F F F F F F F F
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.
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
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) :
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(200)
1290131580644291140012229076696766751343495305527288824998
10851598901419013348319045534580850847735528275750122188940
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
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
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 :
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
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}}}
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.
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 5
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
[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).
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
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
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
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: P = Permutations(5)
sage: all( p in P for p in P )
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
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
()
(2, 1, 1, 1) (1, 1, 1, 1)
(1, 1, 1, 1, 1)
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.
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
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
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
Figure 16.1 Un graphe dont les sommets sont des entiers ou des chanes de caractres.
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
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
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 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
Graphes alatoires
DegreeSequenceExpected RandomBarabasiAlbert RandomBipartite
RandomGNM RandomGNP RandomHolmeKim
RandomInterval RandomLobster RandomNewmanWattsStrogatz
RandomRegular RandomShell RandomTreePowerlaw
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 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.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
lensemble de sommets V (G1 ) V (G2 ). Deux sommets (u, v), (u0 , v 0 ) G sont
adjacents si et seulement si :
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 )
Produits, oprateurs, . . .
Distances, parcours
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
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
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).
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
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 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
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
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())
...
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
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.
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
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
maximiser : ct x
tel que : Ax 6 b.
384 CHAP. 17. PROGRAMMATION LINAIRE
max : x + y + 3z
tel que : x + 2y 6 4
5z y 6 8.
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 :
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.
sage: p.solve()
Traceback (most recent call last):
...
MIPSolverException: 'GLPK : Solution is undefined'
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 !
poidso prendreo 6 C.
X
tel que :
oL
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)
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
me 6 1.
X
tel que : v V (G),
eE(G)
e=uv
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
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
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: p.solve()
2.0
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.
ve > 2
X
S V (G), =
6 S 6= V (G),
eS
buv est une variable binaire.
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
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
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
1
xn = n + arctan .
2 xn
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
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
0.5
-4 -3 -2 -1 1 2 3 4
-0.5
-1
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
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 :
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
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
-3 -2 -1 1 2 3
-1
-2
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.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'>
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 :
40
30
20
10
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
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
(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
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
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 :
do = x0 .
Exercice 37 page 217. Les expressions sin, cos, sin(2) et cos(2) sont lies
par les formules trigonomtriques classiques
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: 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
....: 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 :
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.
....: 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]
True
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
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: 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
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
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