Tutoriel Sage pour Canterbury
Tutoriel Sage pour Canterbury
Version 10.6
02 avril 2025
Table des matières
1 Introduction 3
1.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Les différentes manières d’utiliser Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Objectifs à long terme de Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 Visite guidée 7
2.1 Affectation, égalité et arithmétique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Obtenir de l’aide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3 Fonctions, indentation et itération . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4 Algèbre de base et calcul infinitésimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.5 Graphiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.6 Problèmes fréquents concernant les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.7 Anneaux de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.8 Polynômes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
2.9 Parents, conversions, coercitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.10 Algèbre linéaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
2.11 Groupes finis, groupes abéliens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
2.12 Théorie des nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.13 Quelques mathématiques plus avancées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4 Interfaces 107
4.1 GP/PARI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.2 GAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
4.3 Singular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
4.4 Maxima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
i
5 Sage, LaTeX et compagnie 117
5.1 Vue d’ensemble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
5.2 Utilisation de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
5.3 Personnaliser le code LaTeX produit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
5.4 Personnaliser le traitement du code par LaTeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.5 Example : rendu de graphes avec tkz-graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
5.6 Une installation TeX pleinement opérationnelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
5.7 Programmes externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
6 Programmation 129
6.1 Charger et attacher des fichiers Sage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
6.2 Écrire des programmes compilés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
6.3 Scripts Python/Sage autonomes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
6.4 Types de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
6.5 Listes, n-uplets et séquences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
6.6 Dictionnaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
6.7 Ensembles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
6.8 Itérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
6.9 Boucles, fonctions, structures de contrôle et comparaisons . . . . . . . . . . . . . . . . . . . . . . . . 141
6.10 Profilage (profiling) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
8 Postface 151
8.1 Pourquoi Python ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
8.2 Comment puis-je contribuer ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
8.3 Comment citer Sage ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
9 Annexe 155
9.1 Priorité des opérateurs arithmétiques binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
10 Bibliographie 157
Bibliographie 161
Index 163
ii
Tutoriel Sage, Version 10.6
Sage est un logiciel mathématique libre destiné à la recherche et à l’enseignement en algèbre, géométrie, arithmétique,
théorie des nombres, cryptographie, calcul scientifique et dans d’autres domaines apparentés. Le modèle de développement
de Sage comme ses caractéristiques techniques se distinguent par un souci extrême d’ouverture, de partage, de coopération
et de collaboration : notre but est de construire la voiture, non de réinventer la roue. L’objectif général de Sage est de créer
une alternative libre viable à Maple, Mathematica, Magma et MATLAB.
Ce tutoriel est la meilleure façon de se familiariser avec Sage en quelques heures. Il est disponible en versions HTML
et PDF, ainsi que depuis le notebook Sage (cliquez sur Help, puis sur Tutorial pour parcourir le tutoriel de façon
interactive depuis Sage).
Ce document est distribué sous licence Creative Commons Paternité-Partage des conditions initiales à l’identique 3.0
Unported.
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 License.
Introduction
Explorer ce tutoriel en entier devrait vous prendre au maximum trois à quatre heures. Vous pouvez le lire en version
HTML ou PDF, ou encore l’explorer interactivement à l’intérieur de Sage en cliquant sur Help puis sur Tutorial depuis
le notebook (il est possible que vous tombiez sur la version en anglais).
Sage est écrit en grande partie en Python, mais aucune connaissance de Python n’est nécessaire pour lire ce tutoriel. Par
la suite, vous souhaiterez sans doute apprendre Python, et il existe pour cela de nombreuses ressources libres d’excellente
qualité : le Python Beginner’s Guide [PyB] répertorie de nombreuses options. Mais si ce que vous voulez est découvrir
rapidement Sage, ce tutoriel est le bon endroit où commencer. Voici quelques exemples :
sage: 2 + 2
4
sage: factor(-2007)
-1 * 3^2 * 223
sage: factor([Link]())
x^2 * (x^2 - 30*x - 80)
sage: E = EllipticCurve([1,2,3,4,5]);
sage: E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5
(suite sur la page suivante)
3
Tutoriel Sage, Version 10.6
>>> factor([Link]())
x^2 * (x^2 - 30*x - 80)
>>> E = EllipticCurve([Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]);
>>> E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5
over Rational Field
>>> [Link](Integer(10))
[0, 1, 1, 0, -1, -3, 0, -1, -3, -3, -3]
>>> [Link]()
1
4 Chapitre 1. Introduction
Tutoriel Sage, Version 10.6
1.1 Installation
Si Sage n’est pas installé sur votre ordinateur, vous pouvez essayer quelques commandes en ligne à l’adresse [Link]
[Link].
Des instructions pour installer Sage sur votre ordinateur sont disponibles dans le guide d’installation (Installation Guide),
dans la section documentation de la page web principale de Sage [SA]. Nous nous limiterons ici à quelques remarques.
1. La version téléchargeable de Sage vient avec ses dépendances. Autrement dit, bien que Sage utilise Python, IPy-
thon, PARI, GAP, Singular, Maxima, NTL, GMP, etc., vous n’avez pas besoin de les installer séparément, ils sont
fournis dans la distribution Sage. En revanche, pour utiliser certaines des fonctionnalités de Sage, par exemple
Macaulay ou KASH, il vous faudra d’abord avoir le logiciel correspondant installé sur votre ordinateur.
2. La version binaire pré-compilée de Sage (disponible sur le site web) est souvent plus facile et plus rapide à installer
que la distribution en code source. Pour l’installer, décompressez l’archive et lancez simplement le programme
sage.
3. Si vous souhaitez utiliser SageTeX (qui permet d’insérer automatiquement dans un document LaTeX les résultats
de calculs effectués avec Sage), vous devrez faire en sorte que votre distribution LaTeX le trouve (et, plus précisé-
ment, en trouve la version correspondant à la version de Sage que vous utilisez). Pour ce faire, consultez la section
« Make SageTeX known to TeX » dans le guide d’installation (Sage installation guide, ce lien devrait pointer vers
une copie locale). L’installation est facile : il suffit de copier un fichier dans un répertoire que TeX examine, ou de
régler une variable d’environnement.
La documentation de SageTeX se trouve dans le répertoire $SAGE_ROOT/venv/share/texmf/tex/latex/
sagetex/, où « $SAGE_ROOT » est le répertoire où vous avez installé Sage, par exemple /opt/sage-9.6.
1.1. Installation 5
Tutoriel Sage, Version 10.6
avez la garantie que vos lecteurs auront accès librement à Sage et à son code source, et vous pouvez même archiver
et redistribuer vous-même la version de Sage que vous utilisez.
— Être facile à compiler : le code source de Sage devrait être facile à compiler pour les utilisateurs de Linux, d’OS
X et de Windows. Cela rend le système plus flexible pour les utilisateurs qui souhaiteraient le modifier.
— Favoriser la coopération : fournir des interfaces robustes à la plupart des autres systèmes de calcul formel,
notamment PARI, GAP, Singular, Maxima, KASH, Magma, Maple et Mathematica. Sage cherche à unifier et
étendre les logiciels existants.
— Être bien documenté : tutoriel, guide du programmeur, manuel de référence, guides pratiques, avec de nombreux
exemples et une discussion des concepts mathématiques sous-jacents.
— Être extensible : permettre de définir de nouveaux types de données ou des types dérivés de types existants, et
d’utiliser du code écrit dans différents langages.
— Être convivial : il doit être facile de comprendre quelles fonctionnalités sont disponibles pour travailler avec un
objet donné, et de consulter la documentation et le code source. Également, arriver à un bon niveau d’assistance
utilisateur.
6 Chapitre 1. Introduction
CHAPITRE 2
Visite guidée
Cette partie présente une sélection des possibilités actuellement offertes par Sage. Pour plus d’exemples, on se reportera
à Sage Constructions (« Construction d’objets en Sage »), dont le but est de répondre à la question récurrente du type «
Comment faire pour construire … ? ».
On consultera aussi le Sage Reference Manual (« Manuel de référence pour Sage »), qui contient des milliers d’exemples
supplémentaires. Notez également que vous pouvez explorer interactivement ce tutoriel — ou sa version en anglais — en
cliquant sur Help à partir du notebook de Sage.
(Si vous lisez ce tutoriel à partir du notebook de Sage, appuyez sur maj-enter pour évaluer le contenu d’une cellule. Vous
pouvez même éditer le contenu avant d’appuyer sur maj-entrée. Sur certains Macs, il vous faudra peut-être appuyer sur
maj-return plutôt que maj-entrée).
sage: a = 5
sage: a
5
sage: 2 == 2
True
sage: 2 == 3
False
sage: 2 < 3
True
sage: a == 5
True
7
Tutoriel Sage, Version 10.6
1
sage: 10/4
5/2
sage: 10//4 # pour des arguments entiers, // renvoie le quotient dans la division␣
˓→euclidienne
2
sage: 4 * (10 // 4) + 10 % 4 == 10
True
sage: 3^2*4 + 2%5
38
1
>>> Integer(10)/Integer(4)
5/2
>>> Integer(10)//Integer(4) # pour des arguments entiers, // renvoie le quotient␣
˓→dans la division euclidienne
2
>>> Integer(4) * (Integer(10) // Integer(4)) + Integer(10) % Integer(4) == Integer(10)
True
>>> Integer(3)**Integer(2)*Integer(4) + Integer(2)%Integer(5)
38
Le calcul d’une expression telle que 3^2*4 + 2%5 dépend de l’ordre dans lequel les opérations sont effectuées ; ceci est
expliqué dans l’annexe Priorité des opérateurs arithmétiques binaires Priorité des opérateurs arithmétiques binaires.
Sage fournit également un grand nombre de fonctions mathématiques usuelles ; en voici quelques exemples choisis :
sage: sqrt(3.4)
1.84390889145858
sage: sin(5.135)
-0.912021158525540
sage: sin(pi/3)
1/2*sqrt(3)
Comme le montre le dernier de ces exemples, certaines expressions mathématiques renvoient des valeurs “exactes” plutôt
que des approximations numériques. Pour obtenir une approximation numérique, on utilise au choix la fonction n ou la
méthode n (chacun de ces noms possède le nom plus long numerical_approx, la fonction N est identique à n). Celles-ci
acceptent, en argument optionnel, prec, qui indique le nombre de bits de précisions requis, et digits, qui indique le
nombre de décimales demandées ; par défaut, il y a 53 bits de précision.
sage: exp(2)
e^2
sage: n(exp(2))
7.38905609893065
sage: sqrt(pi).numerical_approx()
1.77245385090552
sage: sin(10).n(digits=5)
-0.54402
sage: N(sin(10),digits=10)
-0.5440211109
sage: numerical_approx(pi, prec=200)
3.1415926535897932384626433832795028841971693993751058209749
Python est doté d’un typage dynamique. Ainsi la valeur à laquelle fait référence une variable est toujours associée à un
type donné, mais une variable donnée peut contenir des valeurs de plusieurs types Python au sein d’une même portée :
sage: a = 5 # a est un entier
sage: type(a)
(suite sur la page suivante)
Le langage de programmation C, qui est statiquement typé, est bien différent : une fois déclarée de type int, une variable
ne peut contenir que des int au sein de sa portée.
sage: tan?
Type: <class '[Link].Function_tan'>
Definition: tan( [noargspec] )
Docstring:
EXAMPLES:
sage: tan(pi)
0
sage: tan(3.1415)
-0.0000926535900581913
sage: tan(3.1415/4)
0.999953674278156
sage: tan(pi/4)
1
sage: tan(1/2)
tan(1/2)
sage: RR(tan(1/2))
0.546302489843790
sage: log2?
Type: <class '[Link].Log2'>
Definition: log2( [noargspec] )
Docstring:
(suite sur la page suivante)
EXAMPLES:
sage: log2
log2
sage: float(log2)
0.69314718055994529
sage: RR(log2)
0.693147180559945
sage: R = RealField(200); R
Real Field with 200 bits of precision
sage: R(log2)
0.69314718055994530941723212145817656807550013436025525412068
sage: l = (1-log2)/(1+log2); l
(1 - log(2))/(log(2) + 1)
sage: R(l)
0.18123221829928249948761381864650311423330609774776013488056
sage: maxima(log2)
log(2)
sage: maxima(log2).float()
.6931471805599453
sage: gp(log2)
0.6931471805599453094172321215 # 32-bit
0.69314718055994530941723212145817656807 # 64-bit
sage: sudoku?
File: sage/local/lib/python2.5/site-packages/sage/games/[Link]
Type: <... 'function'>
Definition: sudoku(A)
Docstring:
EXAMPLE:
sage: A = matrix(ZZ,9,[5,0,0, 0,8,0, 0,4,9, 0,0,0, 5,0,0,
0,3,0, 0,6,7, 3,0,0, 0,0,1, 1,5,0, 0,0,0, 0,0,0, 0,0,0, 2,0,8, 0,0,0,
0,0,0, 0,0,0, 0,1,8, 7,0,0, 0,0,4, 1,5,0, 0,3,0, 0,0,2,
0,0,0, 4,9,0, 0,5,0, 0,0,3])
sage: A
[5 0 0 0 8 0 0 4 9]
[0 0 0 5 0 0 0 3 0]
[0 6 7 3 0 0 0 0 1]
[1 5 0 0 0 0 0 0 0]
[0 0 0 2 0 8 0 0 0]
[0 0 0 0 0 0 0 1 8]
[7 0 0 0 0 4 1 5 0]
[0 3 0 0 0 2 0 0 0]
[4 9 0 0 5 0 0 0 3]
sage: sudoku(A)
[5 1 3 6 8 7 2 4 9]
[8 4 9 5 2 1 6 3 7]
[2 6 7 3 4 9 5 8 1]
(suite sur la page suivante)
EXAMPLES:
>>> tan(pi)
0
>>> tan(RealNumber('3.1415'))
-0.0000926535900581913
>>> tan(RealNumber('3.1415')/Integer(4))
0.999953674278156
>>> tan(pi/Integer(4))
1
>>> tan(Integer(1)/Integer(2))
tan(1/2)
>>> RR(tan(Integer(1)/Integer(2)))
0.546302489843790
>>> log2?
Type: <class '[Link].Log2'>
Definition: log2( [noargspec] )
Docstring:
EXAMPLES:
>>> log2
log2
>>> float(log2)
0.69314718055994529
>>> RR(log2)
0.693147180559945
>>> R = RealField(Integer(200)); R
Real Field with 200 bits of precision
>>> R(log2)
0.69314718055994530941723212145817656807550013436025525412068
>>> l = (Integer(1)-log2)/(Integer(1)+log2); l
(1 - log(2))/(log(2) + 1)
>>> R(l)
0.18123221829928249948761381864650311423330609774776013488056
>>> maxima(log2)
log(2)
(suite sur la page suivante)
EXAMPLE:
>>> A = matrix(ZZ,Integer(9),[Integer(5),Integer(0),Integer(0), Integer(0),Integer(8),
˓→Integer(0), Integer(0),Integer(4),Integer(9), Integer(0),Integer(0),Integer(0),␣
˓→Integer(5),Integer(0),Integer(0),
0,3,0, 0,6,7, 3,0,0, 0,0,1, 1,5,0, 0,0,0, 0,0,0, 0,0,0, 2,0,8, 0,0,0,
0,0,0, 0,0,0, 0,1,8, 7,0,0, 0,0,4, 1,5,0, 0,3,0, 0,0,2,
0,0,0, 4,9,0, 0,5,0, 0,0,3])
>>> A
[5 0 0 0 8 0 0 4 9]
[0 0 0 5 0 0 0 3 0]
[0 6 7 3 0 0 0 0 1]
[1 5 0 0 0 0 0 0 0]
[0 0 0 2 0 8 0 0 0]
[0 0 0 0 0 0 0 1 8]
[7 0 0 0 0 4 1 5 0]
[0 3 0 0 0 2 0 0 0]
[4 9 0 0 5 0 0 0 3]
>>> sudoku(A)
[5 1 3 6 8 7 2 4 9]
[8 4 9 5 2 1 6 3 7]
[2 6 7 3 4 9 5 8 1]
[1 5 8 4 6 3 9 7 2]
[9 7 4 2 1 8 3 6 5]
[3 2 6 7 9 5 4 1 8]
[7 8 2 9 3 4 1 5 6]
[6 3 5 1 7 2 8 9 4]
[4 9 1 8 5 6 7 2 3]
Sage dispose aussi de la complétion de ligne de commande, accessible en tapant les quelques premières lettres du nom
d’une fonction puis en appuyant sur la touche tabulation. Ainsi, si vous tapez ta suivi de TAB, Sage affichera tachyon,
tan, tanh, taylor. C’est une façon commode de voir quels noms de fonctions et d’autres structures sont disponibles
en Sage.
Remarque : suivant la version du notebook que vous utilisez, il est possible que vous voyez trois points ....: au début
de la deuxième ligne de l’exemple. Ne les entrez pas, ils servent uniquement à signaler que le code est indenté.
Les types des paramètres ne sont pas spécifiés dans la définition de la fonction. Il peut y avoir plusieurs paramètres, chacun
accompagné optionnellement d’une valeur par défaut. Par exemple, si la valeur de divisor n’est pas donnée lors d’un
appel à la fonction ci-dessous, la valeur par défaut divisor=2 est utilisée.
Il est possible de spécifier un ou plusieurs des paramètres par leur nom lors de l’appel de la fonction ; dans ce cas, les
paramètres nommés peuvent apparaître dans n’importe quel ordre :
En Python, contrairement à de nombreux autres langages, les blocs de code ne sont pas délimités par des accolades ou
des mots-clés de début et de fin de bloc. Au lieu de cela, la structure des blocs est donnée par l’indentation, qui doit être
la même dans tout le bloc. Par exemple, le code suivant déclenche une erreur de syntaxe parce que l’instruction return
n’est pas au même niveau d’indentation que les lignes précédentes.
Il n’y a pas besoin de placer des points-virgules en fin de ligne ; une instruction est en général terminée par un passage à la
ligne. En revanche, il est possible de placer plusieurs instructions sur la même ligne en les séparant par des points-virgules :
sage: a = 5; b = a + 3; c = b^2; c
64
Pour continuer une instruction sur la ligne suivante, placez une barre oblique inverse en fin de ligne :
sage: 2 + \
....: 3
5
Pour compter en Sage, utilisez une boucle dont la variable d’itération parcourt une séquence d’entiers. Par exemple, la
première ligne ci-dessous a exactement le même effet que for(i=0; i<3; i++) en C++ ou en Java :
Le troisième paramètre contrôle le pas de l’itération. Ainsi, ce qui suit est équivalent à for(i=1;i<6;i+=2).
Vous souhaiterez peut-être regrouper dans un joli tableau les résultats numériques que vous aurez calculés avec Sage.
Une façon de faire commode utilise les chaînes de format. Ici, nous affichons une table des carrés et des cubes en trois
colonnes, chacune d’une largeur de six caractères.
La structure de données de base de Sage est la liste, qui est — comme son nom l’indique — une liste d’objets arbitraires.
Voici un exemple de liste :
Comme dans de nombreux langages de programmation, les listes sont indexées à partir de 0.
sage: v[0]
1
sage: v[3]
sin(x^3)
La fonction len(v) donne la longueur de v…. :[Link](obj) ajoute un nouvel objet à la fin de v ; et del v[i]
supprime l’élément d’indice i de v.
sage: len(v)
4
sage: [Link](1.5)
sage: v
[1, 'hello', 2/3, sin(x^3), 1.50000000000000]
sage: del v[1]
sage: v
[1, 2/3, sin(x^3), 1.50000000000000]
Une autre structure de données importante est le dictionnaire (ou tableau associatif). Un dictionnaire fonctionne comme
une liste, à ceci près que les indices peuvent être presque n’importe quels objets (les objets mutables sont interdits) :
sage: d = {'hi':-2, 3/8:pi, e:pi}
sage: d['hi']
-2
sage: d[e]
pi
Vous pouvez définir de nouveaux types de données en utilisant les classes. Encapsuler les objets mathématiques dans
des classes représente une technique puissante qui peut vous aider à simplifier et organiser vos programmes Sage. Dans
l’exemple suivant, nous définissons une classe qui représente la liste des entiers impairs strictement positifs jusqu’à n.
Cette classe dérive du type interne list.
sage: class Evens(list):
....: def __init__(self, n):
....: self.n = n
....: list.__init__(self, range(2, n+1, 2))
(suite sur la page suivante)
La méthode __init__ est appelée à la création de l’objet pour l’initialiser ; la méthode __repr__ affiche l’objet. À la
seconde ligne de la méthode __init__, nous appelons le constructeur de la classe list. Pour créer un objet de classe
Evens, nous procédons ensuite comme suit :
sage: e = Evens(10)
sage: e
Even positive numbers up to n.
Notez que e s’affiche en utilisant la méthode __repr__ que nous avons définie plus haut. Pour voir la liste de nombres
sous-jacente, on utilise la fonction list :
sage: list(e)
[2, 4, 6, 8, 10]
Il est aussi possible d’accéder à l’attribut n, ou encore d’utiliser e en tant que liste.
sage: e.n
10
sage: e[2]
6
sage: x = var('x')
sage: solve(x^2 + 3*x + 2, x)
[x == -2, x == -1]
L’exemple suivant, qui utilise Sage pour la résolution d’un système d’équations non-linéaires, a été proposé par Jason
Grout. D’abord, on résout le système de façon symbolique :
(La fonction n affiche une approximation numérique ; son argument indique le nombre de bits de précision.)
sage: u = var('u')
sage: diff(sin(u), u)
cos(u)
sage: diff(sin(x^2), x, 4)
16*x^4*sin(x^2) - 48*x^2*cos(x^2) - 12*sin(x^2)
sage: x, y = var('x,y')
sage: f = x^2 + 17*y^2
(suite sur la page suivante)
sage: integral(x*sin(x^2), x)
-1/2*cos(x^2)
sage: integral(x/(x^2+1), x, 0, 1)
1/2*log(2)
sage: f = 1/((1+x)*(x-1))
sage: f.partial_fraction(x)
-1/2/(x + 1) + 1/2/(x - 1)
Ceci utilise l’interface de Sage vers Maxima [Max], aussi il se peut que la sortie diffère un peu des sorties habituelles de
Sage. Dans notre cas, le résultat indique que la solution générale à l’équation différentielle est 𝑥(𝑡) = 𝑒−𝑡 (𝑒𝑡 + 𝐶).
Il est aussi possible de calculer des transformées de Laplace. La transformée de Laplace de 𝑡2 𝑒𝑡 − sin(𝑡) s’obtient comme
suit :
sage: s = var("s")
sage: t = var("t")
sage: f = t^2*exp(t) - sin(t)
sage: [Link](t,s)
-1/(s^2 + 1) + 2/(s - 1)^3
Voici un exemple plus élaboré. L’élongation à partir du point d’équilibre de ressorts couplés attachés à gauche à un mur
|------\/\/\/\/\---|masse1|----\/\/\/\/\/----|masse2|
ressort1 ressort2
où 𝑚𝑖 est la masse de l’objet i, 𝑥𝑖 est l’élongation à partir du point d’équilibre de la masse i, et 𝑘𝑖 est la constante de raideur
du ressort i.
Exemple : Utiliser Sage pour résoudre le problème ci-dessus avec 𝑚1 = 2, 𝑚2 = 1, 𝑘1 = 4, 𝑘2 = 2, 𝑥1 (0) = 3,
𝑥′1 (0) = 0, 𝑥2 (0) = 3, 𝑥′2 (0) = 0.
Solution : Considérons la transformée de Laplace de la première équation (avec les notations 𝑥 = 𝑥1 , 𝑦 = 𝑥2 ) :
(où la transformée de Laplace d’une fonction notée par une lettre minuscule telle que 𝑥(𝑡) est désignée par la majuscule
correspondante 𝑋(𝑠)). Considérons la transformée de Laplace de la seconde équation :
Ceci signifie
Injectons les conditions initiales pour 𝑥(0), 𝑥′ (0), 𝑦(0) et 𝑦 ′ (0) et résolvons les deux équations qui en résultent :
cos(2*t) + 2*cos(t)
>>> inverse_laplace((Integer(3)*s**Integer(3) + Integer(15)*s)/(s**Integer(4) +␣
˓→Integer(5)*s**Integer(2) + Integer(4)),s,t)
-cos(2*t) + 4*cos(t)
sage: t = var('t')
sage: P = parametric_plot((cos(2*t) + 2*cos(t), 4*cos(t) - cos(2*t) ),
....: (t, 0, 2*pi), rgbcolor=hue(0.9))
sage: show(P)
sage: t = var('t')
sage: p1 = plot(cos(2*t) + 2*cos(t), (t, 0, 2*pi), rgbcolor=hue(0.3))
sage: p2 = plot(4*cos(t) - cos(2*t), (t, 0, 2*pi), rgbcolor=hue(0.6))
sage: show(p1 + p2)
Les fonctions de tracé de graphes sont décrites dans la section Graphiques de ce tutoriel. On pourra aussi consulter
[NagleEtAl2004], §5.5 pour plus d’informations sur les équations différentielles.
𝑦(𝑥 + ℎ) − 𝑦(𝑥)
𝑦 ′ (𝑥) ≈ ,
ℎ
𝑦(𝑥+ℎ)−𝑦(𝑥)
où ℎ > 0 est fixé et petit. Ceci, combiné à l’équation différentielle, donne 𝑓 (𝑥, 𝑦(𝑥)) ≈ ℎ . Aussi 𝑦(𝑥 + ℎ)
s’écrit :
Si nous notons ℎ · 𝑓 (𝑥, 𝑦(𝑥)) le « terme de correction » (faute d’un terme plus approprié), et si nous appelons 𝑦(𝑥) «
l’ancienne valeur de 𝑦 » et 𝑦(𝑥 + ℎ) la « nouvelle valeur de 𝑦 », cette approximation se réécrit
𝑥 𝑦 ℎ · 𝑓 (𝑥, 𝑦)
𝑎 𝑐 ℎ · 𝑓 (𝑎, 𝑐)
𝑎+ℎ 𝑐 + ℎ · 𝑓 (𝑎, 𝑐) …
𝑎 + 2ℎ …
…
𝑏 = 𝑎 + 𝑛ℎ ??? …
Le but est est de remplir tous les trous du tableau, ligne après ligne, jusqu’à atteindre le coefficient « ??? », qui est l’ap-
proximation de 𝑦(𝑏) au sens de la méthode d’Euler.
L’idée est la même pour les systèmes d’équations différentielles.
Exemple : Rechercher une approximation numérique de 𝑧(𝑡) en 𝑡 = 1 en utilisant 4 étapes de la méthode d’Euler, où
𝑧 ′′ + 𝑡𝑧 ′ + 𝑧 = 0, 𝑧(0) = 1, 𝑧 ′ (0) = 0.
Il nous faut réduire l’équation différentielle d’ordre 2 à un système de deux équations différentielles d’ordre 1 (en posant
𝑥 = 𝑧, 𝑦 = 𝑧 ′ ) et appliquer la méthode d’Euler :
t x h*f(t,x,y) y h*g(t,x,y)
0 1 0.00 0 -0.25
1/4 1.0 -0.062 -0.25 -0.23
(suite sur la page suivante)
Arrivé à ce point, P conserve en mémoire deux graphiques : P[0], le graphe de 𝑥 en fonction de 𝑡, et P[1], le graphique
de 𝑦 par rapport à 𝑡. On peut tracer les deux graphiques simultanément par :
Pour l’instant, ces fonctions n’ont été adaptées à Sage que pour une utilisation numérique. Pour faire du calcul formel, il
faut utiliser l’interface Maxima directement, comme le présente l’exemple suivant :
2.5 Graphiques
Sage peut produire des graphiques en deux ou trois dimensions.
Il est aussi possible de créer un cercle en l’affectant à une variable ; ceci ne provoque pas son affichage.
sage: [Link]()
sage: [Link](aspect_ratio=1)
La commande show(c, aspect_ratio=1) produit le même résultat. On peut enregistrer l’image avec cette option par
la commande [Link]('[Link]', aspect_ratio=1).
Il est très facile de tracer le graphique de fonctions de base :
sage: x = var('x')
sage: parametric_plot((cos(x),sin(x)^3),(x,0,2*pi),rgbcolor=hue(0.6))
Graphics object consisting of 1 graphics primitive
sage: x = var('x')
sage: p1 = parametric_plot((cos(x),sin(x)),(x,0,2*pi),rgbcolor=hue(0.2))
sage: p2 = parametric_plot((cos(x),sin(x)^2),(x,0,2*pi),rgbcolor=hue(0.4))
sage: p3 = parametric_plot((cos(x),sin(x)^3),(x,0,2*pi),rgbcolor=hue(0.6))
sage: show(p1+p2+p3, axes=false)
2.5. Graphiques 29
Tutoriel Sage, Version 10.6
>>> p2 = parametric_plot((cos(x),sin(x)**Integer(2)),(x,Integer(0),Integer(2)*pi),
˓→rgbcolor=hue(RealNumber('0.4')))
>>> p3 = parametric_plot((cos(x),sin(x)**Integer(3)),(x,Integer(0),Integer(2)*pi),
˓→rgbcolor=hue(RealNumber('0.6')))
Une manière commode de tracer des formes pleines est de préparer une liste de points (L dans l’exemple ci-dessous) puis
d’utiliser la commande polygon pour tracer la forme pleine dont le bord est formé par ces points. Par example, voici un
deltoïde vert :
sage: L = [[-1+cos(pi*i/100)*(1+cos(pi*i/100)),
....: 2*sin(pi*i/100)*(1-cos(pi*i/100))] for i in range(200)]
sage: polygon(L, rgbcolor=(1/8,3/4,1/2))
Graphics object consisting of 1 graphics primitive
sage: L = [[6*cos(pi*i/100)+5*cos((6/2)*pi*i/100),
....: 6*sin(pi*i/100)-5*sin((6/2)*pi*i/100)] for i in range(200)]
sage: p = polygon(L, rgbcolor=(1/8,1/4,1/2))
sage: t = text("hypotrochoid", (5,4), rgbcolor=(1,0,0))
sage: show(p+t)
... Integer(6)*sin(pi*i/Integer(100))-Integer(5)*sin((Integer(6)/Integer(2))*pi*i/
˓→Integer(100))] for i in range(Integer(200))]
>>> show(p+t)
En cours d’analyse, les professeurs font souvent le dessin suivant au tableau : non pas une mais plusieurs branches de la
fonction arcsin, autrement dit, le graphe d’équation 𝑦 = sin(𝑥) pour 𝑥 entre −2𝜋 et 2𝜋, renversé par symétrie par rapport
à la première bissectrice des axes. La commande Sage suivante réalise cela :
>>> line(v)
Graphics object consisting of 1 graphics primitive
Comme les valeurs prises par la fonction tangente ne sont pas bornées, pour utiliser la même astuce pour représenter la
fonction arctangente, il faut préciser les bornes de la coordonnée x :
Sage sait aussi tracer des graphiques en coordonnées polaires, des lignes de niveau et (pour certains types de fonctions)
des champs de vecteurs. Voici un exemple de lignes de niveau :
sage: u, v = var('u,v')
sage: fx = u*v
sage: fy = u
sage: fz = v^2
sage: parametric_plot3d([fx, fy, fz], (u, -1, 1), (v, -1, 1),
....: frame=False, color="yellow")
Graphics3d Object
2.5. Graphiques 31
Tutoriel Sage, Version 10.6
Une fois évaluée la commande parametric_plot3d, qui affiche le graphique, il est possible de cliquer et de le tirer
pour faire pivoter la figure.
Le bonnet croisé (cf. [Link] ou [Link]
[Link]) :
sage: u, v = var('u,v')
sage: fx = (1+cos(v))*cos(u)
sage: fy = (1+cos(v))*sin(u)
sage: fz = -tanh((2/3)*(u-pi))*sin(v)
sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, 2*pi),
....: frame=False, color="red")
Graphics3d Object
Un tore tordu :
sage: u, v = var('u,v')
sage: fx = (3+sin(v)+cos(u))*cos(2*v)
sage: fy = (3+sin(v)+cos(u))*sin(2*v)
sage: fz = sin(u)+2*cos(v)
sage: parametric_plot3d([fx, fy, fz], (u, 0, 2*pi), (v, 0, 2*pi),
....: frame=False, color="red")
Graphics3d Object
Remarquez la syntaxe de la dernière ligne. Écrire plutôt plot(f(z), 0, 2) provoquerait une erreur : en effet, le z
qui apparaît dans la définition de f est une variable muette qui n’a pas de sens en dehors de la définition. Un simple
f(z) déclenche la même erreur. En l’occurrence, faire de z une variable symbolique comme dans l’exemple ci-dessous
fonctionne, mais cette façon de faire soulève d’autres problèmes (voir le point 4 ci-dessous), et il vaut mieux s’abstenir de
l’utiliser.
sage: var('z') # on définit z comme variable symbolique
z
sage: f(z)
z^2
sage: plot(f(z), 0, 2)
Graphics object consisting of 1 graphics primitive
L’appel de fonction f(z) renvoie ici l’expression symbolique z^2, qui est alors utilisée par la fonction plot.
2. Définir une expression symbolique fonctionnelle (« appelable »). Une telle expression représente une fonction dont on
peut tracer le graphe, et que l’on peut aussi dériver ou intégrer symboliquement
Notez que, si g est une expression symbolique fonctionnelle (x |--> x^2), l’objet g(x) (x^2) est d’une nature un peu
différente. Les expressions comme g(x) peuvent aussi être tracées, dérivées, intégrées, etc., avec cependant quelques
difficultés illustrées dans le point 5 ci-dessous.
sage: g(x)
x^2
sage: type(g(x))
<class '[Link]'>
sage: g(x).derivative()
2*x
sage: plot(g(x), 0, 2)
Graphics object consisting of 1 graphics primitive
3. Utiliser une fonction usuelle prédéfinie de Sage. Celles-ci peuvent servir à tracer des courbes, et, indirectement, être
dérivées ou intégrées
sage: type(sin)
<class '[Link].Function_sin'>
sage: plot(sin, 0, 2)
Graphics object consisting of 1 graphics primitive
sage: type(sin(x))
<class '[Link]'>
sage: plot(sin(x), 0, 2)
Graphics object consisting of 1 graphics primitive
Il n’est pas possible de dériver la fonction sin tout court pour obtenir cos
sage: f = sin
sage: [Link]()
Traceback (most recent call last):
...
AttributeError: ...
Une possibilité est de remplacer f = sin par f = sin(x), mais il est généralement préférable de définir une expression
symbolique fonctionnelle f(x) = sin(x)
Problème : plot(h(x), 0, 4) trace la droite 𝑦 = 𝑥 − 2, et non pas la fonction affine par morceaux définie par h.
Pourquoi ? Lors de l’exécution, plot(h(x), 0, 4) évalue d’abord h(x) : la fonction Python h est appelée avec le
paramètre x, et la condition x < 2 est donc évaluée.
Or, l’évaluation d’une inégalité symbolique renvoie False quand la condition n’est pas clairement vraie. Ainsi, h(x)
s’évalue en x - 2, et c’est cette expression-là qui est finalement tracée.
Solution : Il ne faut pas utiliser plot(h(x), 0, 4), mais plutôt
sage: f = x
sage: g = [Link]()
sage: g
1
Problème : g(3) déclenche une erreur avec le message « ValueError : the number of arguments must be less than or equal
to 0 ».
sage: type(f)
<class '[Link]'>
sage: type(g)
<class '[Link]'>
En effet, g n’est pas une fonction, mais une constante, sans variable en laquelle on peut l’évaluer.
Solution : il y a plusieurs possibilités.
— Définir f comme une expression symbolique fonctionnelle
>>> g = [Link]()
>>> g
x |--> 1
>>> g(Integer(3))
1
>>> type(g)
<class '[Link]'>
— Ou, sans changer la définition de f, définir g comme une expression symbolique fonctionnelle
sage: f = x
sage: g(x) = [Link]() # au lieu de 'g = [Link]()'
sage: g
x |--> 1
sage: g(3)
1
sage: type(g)
<class '[Link]'>
>>> g
x |--> 1
>>> g(Integer(3))
1
>>> type(g)
<class '[Link]'>
— Ou encore, avec f et g définies comme dans l’exemple de départ, donner explicitement la variable à remplacer par
sa valeur
sage: f = x
sage: g = [Link]()
sage: g
1
sage: g(x=3) # au lieu de 'g(3)'
1
Nous terminons en mettant encore une fois en évidence la différence entre les dérivées des expressions f définies par f =
x et par f(x) = x
sage: f(x) = x
sage: g = [Link]()
sage: [Link]() # variables apparaissant dans g
()
sage: [Link]() # paramètres auxquels on peut donner une valeur dans g
(x,)
sage: f = x
sage: h = [Link]()
sage: [Link]()
()
sage: [Link]()
()
Comme l’illustre cet exemple, h n’accepte pas de paramètres. C’est pour cela que h(3) déclenche une erreur.
sage: RationalField()
Rational Field
sage: QQ
Rational Field
sage: 1/2 in QQ
True
Le nombre décimal 1.2 est considéré comme un élément de QQ, puisqu’il existe une application de coercition entre les
réels et les rationnels :
sage: 1.2 in QQ
True
Néanmoins, il n’y a pas d’application de coercition entre le corps fini à 3 éléments et les rationnels :
sage: pi in QQ
False
Le symbole I représente la racine carrée de −1 ; i est synonyme de I. Bien entendu, I n’appartient pas aux rationnels :
sage: i # i^2 = -1
I
sage: i in QQ
False
À ce propos, d’autres anneaux sont prédéfinis en Sage : l’anneau des entiers relatifs ZZ, celui des nombres réels RR et celui
des nombres complexes CC. Les anneaux de polynômes sont décrits dans Polynômes.
Passons maintenant à quelques éléments d’arithmétique.
0.766666666666667
>>> RealNumber('0.1') + Integer(2)/Integer(3) # les règles de coercition sont␣
˓→symétriques en Sage
0.766666666666667
Il y a une subtilité dans la définition des nombres complexes. Comme mentionné ci-dessus, le symbole i représente une
racine carrée de −1, mais il s’agit d’une racine carrée formelle de −1, comme élément d’un corps de nombres quadratique.
L’appel CC(i) renvoie la racine carrée de −1 comme nombre complexe en virgule flottante.
2.8 Polynômes
Dans cette partie, nous expliquons comment créer et utiliser des polynômes avec Sage.
Ceci crée un anneau de polynômes et indique à Sage d’utiliser (la chaîne de caractère) “t” comme indéterminée lors de
l’affichage à l’écran. Toutefois, ceci ne définit pas le symbole t pour son utilisation dans Sage. Aussi, il n’est pas possible
de l’utiliser pour saisir un polynôme (comme 𝑡2 + 1) qui appartient à R.
Une deuxième manière de procéder est
sage: S = QQ['t']
sage: S == R
True
2.8. Polynômes 41
Tutoriel Sage, Version 10.6
ou
ou même
L’effet secondaire de ces dernières instructions est de définir la variable t comme l’indéterminée de l’anneau de polynômes.
Ceci permet de construire très aisément des éléments de R, comme décrit ci-après. (Noter que cette troisième manière
est très semblable à la notation par constructeur de Magma et que, de même que dans Magma, ceci peut servir pour une
très large classe d’objets.)
Quelle que soit la méthode utilisée pour définir l’anneau de polynômes, on récupère l’indéterminée comme le 0-ième
générateur :
Notez que les nombres complexes peuvent être construits de façon similaire : les nombres complexes peuvent être vus
comme engendrés sur les réels par le symbole i. Aussi, on dispose de :
sage: CC
Complex Field with 53 bits of precision
sage: CC.0 # 0ième générateur CC
1.00000000000000*I
Pour un anneau de polynômes, on peut obtenir à la fois l’anneau et son générateur ou juste le générateur au moment de la
création de l’anneau comme suit :
sage: R, t = QQ['t'].objgen()
sage: t = QQ['t'].gen()
sage: R, t = objgen(QQ['t'])
sage: t = gen(QQ['t'])
sage: R, t = QQ['t'].objgen()
sage: f = 2*t^7 + 3*t^2 - 15/19
sage: f^2
4*t^14 + 12*t^9 - 60/19*t^7 + 9*t^4 - 90/19*t^2 + 225/361
sage: cyclo = R.cyclotomic_polynomial(7); cyclo
t^6 + t^5 + t^4 + t^3 + t^2 + t + 1
sage: g = 7 * cyclo * t^5 * (t^5 + 10*t + 2)
sage: g
7*t^16 + 7*t^15 + 7*t^14 + 7*t^13 + 77*t^12 + 91*t^11 + 91*t^10 + 84*t^9
+ 84*t^8 + 84*t^7 + 84*t^6 + 14*t^5
sage: F = factor(g); F
(7) * t^5 * (t^5 + 10*t + 2) * (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1)
sage: [Link]()
7
sage: list(F)
[(t, 5), (t^5 + 10*t + 2, 1), (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1, 1)]
2.8. Polynômes 43
Tutoriel Sage, Version 10.6
>>> g
7*t^16 + 7*t^15 + 7*t^14 + 7*t^13 + 77*t^12 + 91*t^11 + 91*t^10 + 84*t^9
+ 84*t^8 + 84*t^7 + 84*t^6 + 14*t^5
>>> F = factor(g); F
(7) * t^5 * (t^5 + 10*t + 2) * (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1)
>>> [Link]()
7
>>> list(F)
[(t, 5), (t^5 + 10*t + 2, 1), (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1, 1)]
On remarquera que la factorisation prend correctement en compte le coefficient dominant, et ne l’oublie pas dans le
résultat.
S’il arrive que vous utilisiez intensivement, par exemple, la fonction R.cyclotomic_polynomial dans un projet de
recherche quelconque, en plus de citer Sage, vous devriez chercher à quel composant Sage fait appel pour calculer en réalité
ce polynôme cyclotomique et citer ce composant. Dans ce cas particulier, en tapant R.cyclotomic_polynomial??
pour voir le code source, vous verriez rapidement une ligne telle que f = [Link](n) ce qui signifie que PARI
est utilisé pour le calcul du polynôme cyclotomique. Pensez à citer PARI dans votre travail.
La division d’un polynôme par un autre produit un élément du corps des fractions, que Sage crée automatiquement.
sage: x = QQ['x'].0
sage: f = x^3 + 1; g = x^2 - 17
sage: h = f/g; h
(x^3 + 1)/(x^2 - 17)
sage: [Link]()
Fraction Field of Univariate Polynomial Ring in x over Rational Field
En utilisant des séries de Laurent, on peut calculer des développements en série dans le corps des fractions de QQ[x] :
sage: R.<x> = LaurentSeriesRing(QQ); R
Laurent Series Ring in x over Rational Field
sage: 1/(1-x) + O(x^10)
1 + x + x^2 + x^3 + x^4 + x^5 + x^6 + x^7 + x^8 + x^9 + O(x^10)
Si l’on nomme les variables différemment, on obtient un anneau de polynômes univariés différent.
L’anneau est déterminé par sa variable. Notez que créer un autre anneau avec la même variable x ne renvoie pas de nouvel
anneau.
Sage permet aussi de travailler dans des anneaux de séries formelles et de séries de Laurent sur un anneau de base quel-
conque. Dans l’exemple suivant, nous créons un élément de F7 [[𝑇 ]] et effectuons une division pour obtenir un élément de
2.8. Polynômes 45
Tutoriel Sage, Version 10.6
F7 ((𝑇 )).
On peut aussi créer des anneaux de séries formelles en utilisant des doubles crochets :
sage: GF(7)[['T']]
Power Series Ring in T over Finite Field of size 7
De même que pour les polynômes à une seule variable, les variantes suivantes sont autorisées :
Si l’on désire de simples lettres comme noms de variables, on peut utiliser les raccourcis suivants :
On peut aussi utiliser des notations plus mathématiques pour construire un anneau de polynômes.
sage: R = GF(5)['x,y,z']
sage: x,y,z = [Link]()
sage: QQ['x']
Univariate Polynomial Ring in x over Rational Field
sage: QQ['x,y'].gens()
(x, y)
sage: QQ['x'].objgens()
(Univariate Polynomial Ring in x over Rational Field, (x,))
Sous Sage, les polynômes multivariés sont implémentés en représentation « distributive » (par opposition à récursive), à
l’aide de dictionnaires Python. Sage a souvent recours à Singular [Si], par exemple, pour le calcul de pgcd ou de bases de
2.8. Polynômes 47
Tutoriel Sage, Version 10.6
Gröbner d’idéaux.
Créons ensuite l’idéal (𝑓, 𝑔) engendré par 𝑓 et 𝑔, en multipliant simplement (f,g) par R (nous pourrions aussi bien écrire
ideal([f,g]) ou ideal(f,g)).
En passant, la base de Gröbner ci-dessus n’est pas une liste mais une suite non mutable. Ceci signifie qu’elle possède un
univers, un parent, et qu’elle ne peut pas être modifiée (ce qui est une bonne chose puisque changer la base perturberait
d’autres routines qui utilisent la base de Gröbner).
sage: [Link]()
Multivariate Polynomial Ring in x, y over Rational Field
sage: B[1] = x
Traceback (most recent call last):
...
ValueError: object is immutable; please change a copy instead.
Un peu (comprenez : pas assez à notre goût) d’algèbre commutative est disponible en Sage. Ces routines font appel à
Singular. Par exemple, il est possible de calculer la décomposition en facteurs premiers et les idéaux premiers associés de
𝐼:
sage: I.primary_decomposition()
[Ideal (x^2) of Multivariate Polynomial Ring in x, y over Rational Field,
Ideal (y^2, x^6) of Multivariate Polynomial Ring in x, y over Rational Field]
sage: I.associated_primes()
[Ideal (x) of Multivariate Polynomial Ring in x, y over Rational Field,
Ideal (y, x) of Multivariate Polynomial Ring in x, y over Rational Field]
2.9.1 Éléments
Une première approximation en Python de la notion mathématique d’anneau pourrait consister à définir une classe pour
les éléments X de l’anneau concerné, de fournir les méthodes « double-underscore » nécessaires pour donner un sens aux
opérations de l’anneau, par exemple __add__, __sub__ et __mul__, et naturellement de s’assurer qu’elles respectent
les axiomes de la structure d’anneau.
Python étant un language (dynamiquement) fortement typé, on pourrait s’attendre à devoir implémenter une classe pour
chaque anneau. Après tout, Python définit bien un type <int> pour les entiers, un type <float> pour les réels, et ainsi de
suite. Mais cette approche ne peut pas fonctionner : il y a une infinité d’anneaux différents, et l’on ne peut pas implémenter
une infinité de classes !
Une autre idée est de créer une hiérarchie de classes destinées à implémenter les éléments des structures algébriques
usuelles : éléments de groupes, d’anneaux, d’algèbres à division, d’anneaux commutatifs, de corps, d’algèbres, etc.
Mais cela signifie que des éléments d’anneaux franchement différents peuvent avoir le même type.
On pourrait aussi vouloir avoir des classes Python différentes pour fournir plusieurs implémentations d’une même structure
mathématique (matrices denses contre matrices creuses par exemple).
<class '[Link].polynomial_ring.PolynomialRing_integral_domain_with_
˓→category.element_class'>
<class '[Link].polynomial_integer_dense_ntl.Polynomial_integer_dense_
˓→ntl'>
<class '[Link].polynomial_ring.PolynomialRing_integral_domain_with_
˓→category.element_class'>
<class '[Link].polynomial_integer_dense_ntl.Polynomial_integer_dense_
˓→ntl'>
Deux problèmes se posent alors. D’une part, si deux éléments sont instances de la même classe, on s’attend à ce que leur
méthode __add__ soit capable de les additionner, alors que ce n’est pas ce que l’on souhaite si les éléments appartiennent
en fait à des anneaux différents. D’autre part, si l’on a deux éléments qui appartiennent à des implémentations différentes
d’un même anneau, on veut pouvoir les ajouter, et ce n’est pas immédiats s’ils ne sont pas instances de la même classe.
La solution à ces difficultés est fournie par le mécanisme de coercition décrit ci-dessous.
Mais avant tout, il est essentiel que chaque élément « sache » de quoi il est élément. Cette information est donnée par la
méthode parent().
sage: isinstance(QQ,Field)
True
sage: isinstance(QQ, Ring)
True
sage: isinstance(ZZ,Field)
False
sage: isinstance(ZZ, Ring)
True
Or en algèbre, on regroupe les objets qui partagent le même genre de structure algébrique en ce que l’on appelle des
catégories. Il y a donc un parallèle approximatif entre la hiérarchie des classes de Sage et la hiérarchie des catégories.
Mais cette correspondance n’est pas parfaite, et Sage implémente par ailleurs les catégories en tant que telles :
sage: Rings()
Category of rings
sage: [Link]()
Join of Category of Dedekind domains
and Category of euclidean domains
and Category of noetherian rings
and Category of infinite enumerated sets
and Category of metric spaces
sage: [Link]().is_subcategory(Rings())
True
sage: ZZ in Rings()
True
sage: ZZ in Fields()
False
sage: QQ in Fields()
True
Tandis que la hiérarchie des classes est déterminée avant tout par des considérations de programmation, l’infrastructure
des catégories cherche plutôt à respecter la structure mathématique. Elle permet de munir les objets d’une catégorie de
méthodes et de tests génériques, qui ne dépendent pas de l’implémentation particulière d’un objet donné de la catégorie.
Les parents en tant qu’objets Python doivent être uniques. Ainsi, lorsqu’un anneau de polynômes sur un anneau donné et
avec une liste donnée de générateurs est construit, il est conservé en cache et réutilisé par la suite :
sage: M = Matrix(ZZ,2,2); M
[0 0]
[0 0]
sage: isinstance(M, RingElement)
False
Si les parents sont censés être uniques, des éléments égaux d’un parent ne sont pas nécessairement identiques. Le compor-
tement de Sage diffère ici de celui de Python pour certains entiers (pas tous) :
Il faut bien comprendre que les éléments d’anneaux différents ne se distinguent généralement pas par leur type, mais par
leur parent :
sage: a = GF(2)(1)
sage: b = GF(5)(1)
sage: type(a) is type(b)
True
sage: parent(a)
Finite Field of size 2
sage: parent(b)
Finite Field of size 5
Ainsi, le parent d’un élément est plus important que son type du point de vue algébrique.
sage: a = GF(2)(1)
sage: b = GF(5)(1)
sage: GF(5)(a) == b
True
sage: GF(2)(b) == a
True
Cependant, une conversion implicite (c’est-à-dire automatique) n’est possible que si elle peut se faire systématiquement et
de manière cohérente. Il faut ici absolument faire preuve de rigueur.
Une telle conversion implicite s’appelle une coercition. Si une coercition est définie entre deux parents, elle doit coïncider
avec la conversion. De plus, les coercitions doivent obéir aux deux conditions suivantes :
1. Une coercition de P1 dans P2 doit être un morphisme (par exemple un morphisme d’anneaux). Elle doit être
définie pour tous les éléments de P1, et préserver la structure algébrique de celui-ci.
2. Le choix des applications de coercition doit être fait de manière cohérente. Si P3 est un troisième parent, la
composée de la coercition choisie de P1 dans P2 et de celle de P2 dans P3 doit être la coercition de P1 dans P3.
En particulier, s’il existe des coercitions de P1 dans P2 et de P2 dans P1, leur composée doit être l’identité sur P1.
Ainsi, bien qu’il soit possible de convertir tout élément de GF(2) en un élément de GF(5), la conversion ne peut être une
coercition, puisque il n’existe pas de morphisme d’anneaux de GF(2) dans GF(5).
Le second point — la cohérence des choix — est un peu plus compliqué à expliquer. Illustrons-le sur l’exemple des anneaux
de polynômes multivariés. Dans les applications, il s’avère utile que les coercitions respectent les noms des variables. Nous
avons donc :
En l’absence d’un morphisme d’anneau qui préserve les noms de variable, la coercition entre anneaux de polynômes
multivariés n’est pas définie. Il peut tout de même exister une conversion qui envoie les variables d’un anneau sur celle de
l’autre en fonction de leur position dans la liste des générateurs :
sage: R3 = ZZ['z','x']
sage: R3.has_coerce_map_from(R1)
False
sage: R3(x)
z
sage: R3(y)
x
sage: [Link](y)
Traceback (most recent call last):
...
TypeError: no canonical coercion
from Multivariate Polynomial Ring in x, y over Integer Ring
to Multivariate Polynomial Ring in z, x over Integer Ring
Mais une telle conversion ne répond pas aux critères pour être une coercition : en effet, en composant l’application de
ZZ['x','y'] dans ZZ['y','x'] avec celle qui préserve les positions de ZZ['y','x'] dans ZZ['a','b'], nous
obtiendrions une application qui ne préserve ni les noms ni les positions, ce qui viole la règle de cohérence.
Lorsqu’une coercition est définie, elle est souvent utilisée pour comparer des éléments d’anneaux différents ou pour effec-
tuer des opérations arithmétiques. Cela est commode, mais il faut être prudent en étendant la relation d’égalité == au-delà
des frontières d’un parent donné. Par exemple, si == est bien censé être une relation d’équivalence entre éléments d”un
anneau, il n’en va pas forcément de même quand on compare des éléments d’anneaux différents. Ainsi, les éléments 1 de
ZZ et d’un corps fini sont considérés comme égaux, puisqu’il existe une coercition canonique des entiers dans tout corps
fini. En revanche, il n’y a en général pas de coercition entre deux corps finis quelconques. On a donc
sage: GF(5)(1) == 1
True
sage: 1 == GF(2)(1)
True
sage: GF(5)(1) == GF(2)(1)
False
(suite sur la page suivante)
De même, on a
Une autre conséquence de la condition de cohérence est que les coercitions ne sont possibles que des anneaux exacts
(comme les rationnels QQ) vers les anneaux inexacts (comme les réels à précision donnée RR), jamais l’inverse. En effet,
pour qu’une conversion de RR dans QQ puisse être une coercition, il faudrait que la composée de la coercition de QQ dans
RR et de cette conversion soit l’identité sur QQ, ce qui n’est pas possible puisque des rationnels distincts peuvent très bien
être envoyés sur le même élément de RR :
True
>>> Integer(1)/Integer(10)**Integer(200)+Integer(1)/Integer(10)**Integer(100) ==␣
˓→Integer(1)/Integer(10)**Integer(100)
False
Lorsque l’on compare des éléments de deux parents P1 et P2, il peut arriver qu’il n’existe pas de coercition entre P1 et
P2, mais qu’il y ait un choix canonique de parent P3 tel que P1 et P2 admettent tous deux des coercitions dans P3. Dans
ce cas aussi, la coercition a lieu. Un exemple typique de ce mécanisme est l’addition d’un rationnel et d’un polynôme à
Notons qu’en principe, on aurait très bien pu choisir pour P3 le corps des fractions de ZZ['x']. Cependant, Sage tente de
choisir un parent commun canonique aussi naturel que possible (ici QQ['x']). Afin que cela fonctionne de façon fiable,
Sage ne se contente pas de prendre n’importe lequel lorsque plusieurs candidats semblent aussi naturels les uns que les
autres. La manière dont le choix est fait est décrite dans le tutoriel spécifique déjà mentionné.
Dans l’exemple suivant, il n’y a pas de coercition vers un parent commun :
En effet, Sage refuse de choisir entre les candidats QQ['x']['y'], QQ['y']['x'], QQ['x','y'] et QQ['y','x'],
car ces quatre structures deux à deux distinctes semblent toutes des parents communs naturels, et aucun choix canonique
ne s’impose.
sage: A = Matrix([[1,2,3],[3,2,1],[1,1,1]])
sage: w = vector([1,1,-4])
sage: w*A
(0, 0, 0)
sage: A*w
(-9, 1, -2)
sage: kernel(A)
Free module of degree 3 and rank 1 over Integer Ring
Echelon basis matrix:
[ 1 1 -4]
>>> w = vector([Integer(1),Integer(1),-Integer(4)])
>>> w*A
(0, 0, 0)
>>> A*w
(-9, 1, -2)
>>> kernel(A)
Free module of degree 3 and rank 1 over Integer Ring
Echelon basis matrix:
[ 1 1 -4]
Notez bien qu’avec Sage, le noyau d’une matrice 𝐴 est le « noyau à gauche », c’est-à-dire l’espace des vecteurs 𝑤 tels que
𝑤𝐴 = 0.
La résolution d’équations matricielles est facile et se fait avec la méthode solve_right. L’évaluation de A.
solve_right(Y) renvoie une matrice (ou un vecteur) 𝑋 tel que 𝐴𝑋 = 𝑌 :
sage: A.solve_right(w)
Traceback (most recent call last):
...
ValueError: matrix equation has no solutions
(La sortie de eigenvectors_left est une liste de triplets (valeur propre, vecteur propre, multiplicité).) Sur QQ et RR,
on peut aussi utiliser Maxima (voir la section Maxima ci-dessous).
Comme signalé en Anneaux de base, l’anneau sur lequel une matrice est définie a une influence sur les propriétés de la
matrice. Dans l’exemple suivant, le premier argument de la commande matrix indique à Sage s’il faut traiter la matrice
comme une matrice d’entier (ZZ), de rationnels (QQ) ou de réels (RR) :
Pour le calcul de valeurs propres et vecteurs propres sur les nombres à virgule flottante réels ou complexes, la matrice
doit être respectivement à coefficients dans RDF (Real Double Field, nombres réels à précision machine) ou CDF (Complex
Double Field). Lorsque l’on définit une matrice avec des coefficients flottants sans spécifier explicitement l’anneau de base,
ce ne sont pas RDF ou CDF qui sont utilisés par défaut, mais RR et CC, sur lesquels ces calculs ne sont pas implémentés
dans tous les cas :
sage: ARDF = matrix(RDF, [[1.2, 2], [2, 3]])
sage: [Link]() # rel tol 8e-16
[-0.09317121994613098, 4.293171219946131]
sage: ACDF = matrix(CDF, [[1.2, I], [2, 3]])
sage: ACDF.eigenvectors_right() # rel tol 3e-15
[(0.8818456983293743 - 0.8209140653434135*I, [(0.7505608183809549, -0.616145932704589␣
˓→+ 0.2387941530333261*I)], 1),
(Pour indiquer l’espace des matrices 3 par 4, il faudrait utiliser MatrixSpace(QQ,3,4). Si le nombre de colonnes est
omis, il est égal par défaut au nombre de lignes. Ainsi MatrixSpace(QQ,3) est un synonyme de MatrixSpace(QQ,
3,3)). L’espace des matrices est muni de sa base canonique :
sage: B = [Link]()
sage: len(B)
(suite sur la page suivante)
sage: A = M(range(9)); A
[0 1 2]
[3 4 5]
[6 7 8]
sage: A.echelon_form()
[ 1 0 -1]
[ 0 1 2]
[ 0 0 0]
sage: [Link]()
Vector space of degree 3 and dimension 1 over Rational Field
Basis matrix:
[ 1 -2 1]
Puis nous illustrons les possibilités de calcul de matrices définies sur des corps finis :
sage: M = MatrixSpace(GF(2),4,8)
sage: A = M([1,1,0,0, 1,1,1,1, 0,1,0,0, 1,0,1,1,
....: 0,0,1,0, 1,1,0,1, 0,0,1,1, 1,1,1,0])
sage: A
[1 1 0 0 1 1 1 1]
[0 1 0 0 1 0 1 1]
[0 0 1 0 1 1 0 1]
[0 0 1 1 1 1 1 0]
sage: rows = [Link]()
sage: [Link]()
[(1, 0, 0, 0), (1, 1, 0, 0), (0, 0, 1, 1), (0, 0, 0, 1),
(1, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)]
sage: rows
[(1, 1, 0, 0, 1, 1, 1, 1), (0, 1, 0, 0, 1, 0, 1, 1),
(0, 0, 1, 0, 1, 1, 0, 1), (0, 0, 1, 1, 1, 1, 1, 0)]
˓→Integer(0),Integer(1),Integer(1),
˓→Integer(1),Integer(1),Integer(0)])
>>> A
[1 1 0 0 1 1 1 1]
[0 1 0 0 1 0 1 1]
[0 0 1 0 1 1 0 1]
[0 0 1 1 1 1 1 0]
>>> rows = [Link]()
>>> [Link]()
[(1, 0, 0, 0), (1, 1, 0, 0), (0, 0, 1, 1), (0, 0, 0, 1),
(1, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)]
>>> rows
[(1, 1, 0, 0, 1, 1, 1, 1), (0, 1, 0, 0, 1, 0, 1, 1),
(0, 0, 1, 0, 1, 1, 0, 1), (0, 0, 1, 1, 1, 1, 1, 0)]
Nous créons le sous-espace engendré sur F2 par les vecteurs lignes ci-dessus.
sage: V = VectorSpace(GF(2),8)
sage: S = [Link](rows)
sage: S
Vector space of degree 8 and dimension 4 over Finite Field of size 2
Basis matrix:
[1 0 0 0 0 1 0 0]
[0 1 0 0 1 0 1 1]
[0 0 1 0 1 1 0 1]
[0 0 0 1 0 0 1 1]
sage: A.echelon_form()
[1 0 0 0 0 1 0 0]
[0 1 0 0 1 0 1 1]
[0 0 1 0 1 1 0 1]
[0 0 0 1 0 0 1 1]
La base de 𝑆 utilisée par Sage est obtenue à partir des lignes non nulles de la matrice des générateurs de 𝑆 réduite sous
forme échelonnée en lignes.
L’algorithme multi-modulaire présent dans Sage fonctionne bien pour les matrices carrées (mais moins pour les autres) :
On peut obtenir la table des caractères (au format LaTeX) à partir de Sage :
>>> latex(G.character_table())
\left(\begin{array}{rrrr}
1 & 1 & 1 & 1 \\
1 & -\zeta_{3} - 1 & \zeta_{3} & 1 \\
1 & \zeta_{3} & -\zeta_{3} - 1 & 1 \\
3 & 0 & 0 & -1
\end{array}\right)
Sage inclut aussi les groupes classiques ou matriciels définis sur des corps finis :
sage: MS = MatrixSpace(GF(7), 2)
sage: gens = [MS([[1,0],[-1,1]]),MS([[1,1],[0,1]])]
sage: G = MatrixGroup(gens)
sage: G.conjugacy_classes_representatives()
(
[1 0] [0 6] [0 4] [6 0] [0 6] [0 4] [0 6] [0 6] [0 6] [4 0]
[0 1], [1 5], [5 5], [0 6], [1 2], [5 2], [1 0], [1 4], [1 3], [0 2],
[5 0]
[0 3]
)
sage: G = Sp(4,GF(7))
sage: G
Symplectic Group of degree 4 over Finite Field of size 7
sage: G.random_element() # élément du groupe tiré au hasard (random)
[5 5 5 1]
[0 2 6 3]
[5 0 1 0]
[4 6 3 4]
sage: [Link]()
276595200
>>> G = MatrixGroup(gens)
>>> G.conjugacy_classes_representatives()
(
[1 0] [0 6] [0 4] [6 0] [0 6] [0 4] [0 6] [0 6] [0 6] [4 0]
[0 1], [1 5], [5 5], [0 6], [1 2], [5 2], [1 0], [1 4], [1 3], [0 2],
<BLANKLINE>
[5 0]
[0 3]
)
>>> G = Sp(Integer(4),GF(Integer(7)))
>>> G
Symplectic Group of degree 4 over Finite Field of size 7
>>> G.random_element() # élément du groupe tiré au hasard (random)
[5 5 5 1]
[0 2 6 3]
[5 0 1 0]
[4 6 3 4]
>>> [Link]()
276595200
On peut aussi effectuer des calculs dans des groupes abéliens (infinis ou finis) :
sage: R = IntegerModRing(97)
sage: a = R(2) / R(3)
sage: a
33
sage: a.rational_reconstruction()
2/3
sage: b = R(47)
sage: b^20052005
50
sage: [Link]()
97
sage: b.is_square()
True
Sage contient les fonctions standards de théorie des nombres. Par exemple,
sage: gcd(515,2005)
5
sage: factor(2005)
5 * 401
sage: c = factorial(25); c
15511210043330985984000000
sage: [valuation(c,p) for p in prime_range(2,23)]
[22, 10, 6, 3, 2, 1, 1, 1]
sage: next_prime(2005)
2011
sage: previous_prime(2005)
2003
sage: divisors(28); sum(divisors(28)); 2*28
[1, 2, 4, 7, 14, 28]
56
56
6
56
1050
Nous illustrons à présent l’algorithme d’Euclide de recherche d’une relation de Bézout, l’indicatrice d’Euler 𝜑 et le théorème
des restes chinois :
sage: K = Qp(11); K
11-adic Field with capped relative precision 20
sage: a = K(211/17); a
4 + 4*11 + 11^2 + 7*11^3 + 9*11^5 + 5*11^6 + 4*11^7 + 8*11^8 + 7*11^9
+ 9*11^10 + 3*11^11 + 10*11^12 + 11^13 + 5*11^14 + 6*11^15 + 2*11^16
+ 3*11^17 + 11^18 + 7*11^19 + O(11^20)
sage: b = K(3211/11^2); b
10*11^-2 + 5*11^-1 + 4 + 2*11 + O(11^18)
Beaucoup de travail a été accompli afin d’implémenter l’anneau des entiers dans des corps 𝑝-adiques ou des corps de
nombres distincts de Q. Le lecteur intéressé est invité à poser ses questions aux experts sur le groupe Google sage-sup-
port pour plus de détails.
Un certain nombre de méthodes associées sont d’ores et déjà implémentées dans la classe NumberField.
sage: K.galois_group()
Galois group 3T2 (S3) with order 6 of x^3 + x^2 - 2*x + 8
sage: K.polynomial_quotient_ring()
Univariate Quotient Polynomial Ring in a over Rational Field with modulus
x^3 + x^2 - 2*x + 8
sage: [Link]()
(-3*a^2 - 13*a - 13,)
sage: [Link]()
-503
sage: K.class_group()
Class group of order 1 of Number Field in a with
defining polynomial x^3 + x^2 - 2*x + 8
sage: K.class_number()
1
Nous pouvons également trouver tous les points d’intersection des deux courbes en les intersectant et en calculant les
composantes irréductibles.
sage: V = [Link](C3)
sage: V.irreducible_components()
[Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:
y - 1,
x,
Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:
y,
x - 1,
Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:
x + y + 2,
2*y^2 + 4*y + 3]
Ainsi, par exemple, (1, 0) et (0, 1) appartiennent aux deux courbes (ce dont on pouvait directement s’apercevoir) ; il en
va de même des points (quadratiques), dont la coordonnée en 𝑦 satisfait à l’équation 2𝑦 2 + 4𝑦 + 3 = 0.
Sage peut calculer l’idéal torique de la cubique gauche dans l’espace projectif de dimension 3.
les isogénies, beaucoup de nouveau code pour les courbes sur Q et une partie du code de descente algébrique de Denis
Simon.
La commande EllipticCurve permet de créer une courbe elliptique avec beaucoup de souplesse :
— EllipticCurve([𝑎1 , 𝑎2 , 𝑎3 , 𝑎4 , 𝑎6 ]) : renvoie la courbe elliptique
𝑦 2 + 𝑎1 𝑥𝑦 + 𝑎3 𝑦 = 𝑥3 + 𝑎2 𝑥2 + 𝑎4 𝑥 + 𝑎6 ,
où les 𝑎𝑖 ’s sont convertis par coercition dans le parent de 𝑎1 . Si tous les 𝑎𝑖 ont pour parent Z, ils sont convertis
par coercition dans Q.
— EllipticCurve([𝑎4 , 𝑎6 ]) : idem avec 𝑎1 = 𝑎2 = 𝑎3 = 0.
— EllipticCurve(label) : Renvoie la courbe elliptique sur Q de la base de données de Cremona selon son nom dans la
(nouvelle !) nomenclature de Cremona. Les courbes sont étiquetées par une chaîne de caractère telle que "11a"
ou "37b2". La lettre doit être en minuscule (pour faire la différence avec l’ancienne nomenclature).
— EllipticCurve(j) : renvoie une courbe elliptique de 𝑗-invariant 𝑗.
— EllipticCurve(R, [𝑎1 , 𝑎2 , 𝑎3 , 𝑎4 , 𝑎6 ]) : Crée la courbe elliptique sur l’anneau 𝑅 donnée par les coefficients 𝑎𝑖
comme ci-dessus.
Illustrons chacune de ces constructions :
sage: EllipticCurve([0,0,1,-1,0])
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
sage: EllipticCurve([GF(5)(0),0,1,-1,0])
Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
sage: EllipticCurve([1,2])
Elliptic Curve defined by y^2 = x^3 + x + 2 over Rational Field
sage: EllipticCurve('37a')
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
sage: EllipticCurve_from_j(1)
Elliptic Curve defined by y^2 + x*y = x^3 + 36*x + 3455 over Rational Field
>>> EllipticCurve([GF(Integer(5))(Integer(0)),Integer(0),Integer(1),-Integer(1),
˓→Integer(0)])
Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
>>> EllipticCurve([Integer(1),Integer(2)])
Elliptic Curve defined by y^2 = x^3 + x + 2 over Rational Field
>>> EllipticCurve('37a')
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
>>> EllipticCurve_from_j(Integer(1))
Elliptic Curve defined by y^2 + x*y = x^3 + 36*x + 3455 over Rational Field
Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
Le couple (0, 0) est un point de la courbe elliptique 𝐸 définie par 𝑦 2 + 𝑦 = 𝑥3 − 𝑥. Pour créer ce point avec Sage, il
convient de taper E([0,0]). Sage peut additionner des points sur une telle courbe elliptique (rappelons qu’une courbe
elliptique possède une structure de groupe additif où le point à l’infini représente l’élément neutre et où trois points alignés
de la courbe sont de somme nulle) :
sage: E = EllipticCurve([0,0,1,-1,0])
sage: E
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
sage: P = E([0,0])
sage: P + P
(1 : 0 : 1)
sage: 10*P
(161/16 : -2065/64 : 1)
sage: 20*P
(683916417/264517696 : -18784454671297/4302115807744 : 1)
sage: [Link]()
37
Les courbes elliptiques sur les nombres complexes sont paramétrées par leur 𝑗-invariant. Sage calcule le 𝑗-invariant comme
suit :
sage: E = EllipticCurve([0,0,0,-4,2]); E
Elliptic Curve defined by y^2 = x^3 - 4*x + 2 over Rational Field
sage: [Link]()
2368
sage: E.j_invariant()
110592/37
Si l’on fabrique une courbe avec le même 𝑗-invariant que celui de 𝐸, elle n’est pas nécessairement isomorphe à 𝐸. Dans
l’exemple suivant, les courbes ne sont pas isomorphes parce que leur conducteur est différent.
sage: F = EllipticCurve_from_j(110592/37)
sage: [Link]()
37
sage: G = F.quadratic_twist(2); G
Elliptic Curve defined by y^2 = x^3 - 4*x + 2 over Rational Field
sage: [Link]()
2368
sage: G.j_invariant()
110592/37
sage: E = EllipticCurve([0,0,1,-1,0])
sage: [Link](30)
[0, 1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4,
3, 10, 2, 0, -1, 4, -9, -2, 6, -12]
sage: v = [Link](10000)
Il faut à peine quelques secondes pour calculer tous les coefficients 𝑎𝑛 pour 𝑛 ≤ 105 :
Les courbes elliptiques peuvent être construites en utilisant leur nom dans la nomenclature de Cremona. Ceci charge
par avance la courbe elliptique avec les informations la concernant, telles que son rang, son nombre de Tamagawa, son
régulateur, etc.
sage: E = EllipticCurve("37b2")
sage: E
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational
Field
sage: E = EllipticCurve("389a")
sage: E
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
sage: [Link]()
2
sage: E = EllipticCurve("5077a")
sage: [Link]()
3
Les objets extraits de la base de données ne sont pas de type EllipticCurve, mais de simples entrées de base de données
formées de quelques champs. Par défaut, Sage est distribué avec une version réduite de la base de données de Cremona
qui ne contient que des informations limitées sur les courbes elliptiques de conducteur ≤ 10000. Il existe également en
option une version plus complète qui contient des données étendues portant sur toute les courbes de conducteur jusqu’à
120000 (à la date d’octobre 2005). Une autre - énorme (2GB) - base de données optionnelle, fournie dans un package
séparé, contient des centaines de millions de courbes elliptiques de la bases de donnée de Stein-Watkins.
sage: G = DirichletGroup(12)
sage: [Link]()
[Dirichlet character modulo 12 of conductor 1 mapping 7 |--> 1, 5 |--> 1,
Dirichlet character modulo 12 of conductor 4 mapping 7 |--> -1, 5 |--> 1,
Dirichlet character modulo 12 of conductor 3 mapping 7 |--> 1, 5 |--> -1,
Dirichlet character modulo 12 of conductor 12 mapping 7 |--> -1, 5 |--> -1]
sage: [Link]()
(Dirichlet character modulo 12 of conductor 4 mapping 7 |--> -1, 5 |--> 1,
Dirichlet character modulo 12 of conductor 3 mapping 7 |--> 1, 5 |--> -1)
sage: len(G)
4
Une fois le groupe créé, on crée aussitôt un élément et on calcule avec lui.
sage: G = DirichletGroup(21)
sage: chi = G.1; chi
Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> zeta6
sage: [Link]()
[0, 1, zeta6 - 1, 0, -zeta6, -zeta6 + 1, 0, 0, 1, 0, zeta6, -zeta6, 0, -1,
0, 0, zeta6 - 1, zeta6, 0, -zeta6 + 1, -1]
sage: [Link]()
7
sage: [Link]()
(suite sur la page suivante)
Il est possible aussi de calculer l’action d’un groupe de Galois Gal(Q(𝜁𝑁 )/Q) sur l’un de ces caractères, de même qu’une
décomposition en produit direct correspondant à la factorisation du module.
sage: chi.galois_orbit()
[Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> -zeta6 + 1,
Dirichlet character modulo 21 of conductor 7 mapping 8 |--> 1, 10 |--> zeta6]
sage: go = G.galois_orbits()
sage: [len(orbit) for orbit in go]
[1, 2, 2, 1, 1, 2, 2, 1]
sage: [Link]()
[Group of Dirichlet characters modulo 3 with values in Cyclotomic Field of order 6␣
˓→and degree 2,
>>> go = G.galois_orbits()
>>> [len(orbit) for orbit in go]
[1, 2, 2, 1, 1, 2, 2, 1]
Construisons à present le groupe de caractères de Dirichlet modulo 20, mais à valeur dans Q(𝑖) :
sage: [Link]()
(Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1,
Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> i)
sage: G.unit_gens()
(11, 17)
sage: [Link]()
i
sage: G.zeta_order()
4
>>> G.unit_gens()
(11, 17)
>>> [Link]()
i
>>> G.zeta_order()
4
Dans cet exemple, nous créons un caractère de Dirichlet à valeurs dans un corps de nombres. Nous spécifions ci-dessous
explicitement le choix de la racine de l’unité par le troisième argument de la fonction DirichletGroup.
Ici, NumberField(x^4 + 1, 'a') indique à Sage d’utiliser le symbole « a » dans l’affichage de ce qu’est K (un corps
de nombre en « a » défini par le polynôme 𝑥4 + 1). Le nom « a » n’est pas déclaré à ce point. Une fois que a = K.0
(ou de manière équivalente a = [Link]()) est évalué, le symbole « a » représente une racine du polynôme générateur
𝑥4 + 1.
Nous illustrons ci-dessous le calcul des opérateurs de Hecke sur un espace de symboles modulaires de niveau 1 et de poids
12.
sage: M = ModularSymbols(1,12)
sage: [Link]()
([X^8*Y^2,(0,0)], [X^9*Y,(0,0)], [X^10,(0,0)])
sage: t2 = M.T(2)
sage: t2
Hecke operator T_2 on Modular Symbols space of dimension 3 for Gamma_0(1)
of weight 12 with sign 0 over Rational Field
sage: [Link]()
[ -24 0 0]
[ 0 -24 0]
[4860 0 2049]
sage: f = [Link]('x'); f
x^3 - 2001*x^2 - 97776*x - 1180224
sage: factor(f)
(x - 2049) * (x + 24)^2
sage: M.T(11).charpoly('x').factor()
(x - 285311670612) * (x - 534612)^2
sage: ModularSymbols(11,2)
Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign
0 over Rational Field
sage: ModularSymbols(Gamma1(11),2)
Modular Symbols space of dimension 11 for Gamma_1(11) of weight 2 with
sign 0 over Rational Field
Voici un autre exemple montrant comment Sage peut calculer l’action d’un opérateur de Hecke sur un espace de formes
modulaires.
sage: T = ModularForms(Gamma0(11),2)
sage: T
Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of
weight 2 over Rational Field
sage: [Link]()
2
sage: [Link]()
11
sage: [Link]()
Congruence Subgroup Gamma0(11)
sage: [Link]()
2
sage: T.cuspidal_subspace()
Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for
Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
sage: T.eisenstein_subspace()
Eisenstein subspace of dimension 1 of Modular Forms space of dimension 2
for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
sage: M = ModularSymbols(11); M
Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign
0 over Rational Field
sage: [Link]()
2
sage: [Link]()
((1,0), (1,8), (1,9))
sage: [Link]()
(suite sur la page suivante)
Notons 𝑇𝑝 les opérateurs de Hecke usuels (𝑝 premier). Comment agissent les opérateurs de Hecke 𝑇2 , 𝑇3 , 𝑇5 sur l’espace
des symboles modulaires ?
sage: M.T(2).matrix()
[ 3 0 -1]
[ 0 -2 0]
[ 0 0 -2]
sage: M.T(3).matrix()
[ 4 0 -1]
[ 0 -1 0]
[ 0 0 -1]
sage: M.T(5).matrix()
[ 6 0 -1]
[ 0 1 0]
[ 0 0 1]
Dans la plus grande partie de ce tutoriel, nous supposons que vous avez lancé l’interpréteur Sage avec la commande
sage. Cela démarre une version adaptée du shell (interpréteur de commandes) IPython et importe un grand nombre
de fonctions et de classes qui sont ainsi prêtes à l’emploi depuis l’invite de commande. D’autres personnalisations sont
possibles en éditant le fichier $SAGE_ROOT/ipythonrc. Au démarrage, le shell Sage affiche un message de ce genre :
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage:
sage: quit
Exiting Sage (CPU time 0m0.00s, Wall time 0m0.89s)
L’indication wall time donne le temps écoulé à votre montre (ou l’horloge suspendue au mur) pendant l’exécution. C’est
une donnée pertinente car le temps processeur (CPU time) ne tient pas compte du temps utilisé par les sous-processus
comme GAP et Singular.
(Il vaut mieux éviter de tuer un processus Sage depuis un terminal avec kill -9, car il est possible que Sage ne tue
pas ses processus enfants, par exemple des processus Maple qu’il aurait lancés, ou encore qu’il ne nettoie pas les fichiers
temporaires de $HOME/.sage/tmp.)
87
Tutoriel Sage, Version 10.6
_ : dernière entrée
__ : avant-dernière entrée
_oh : liste de toutes les entrées précédentes
Voici un exemple :
sage: factor(100)
_1 = 2^2 * 5^2
sage: kronecker_symbol(3,5)
_2 = -1
sage: %hist #Fonctionne depuis le shell mais pas depuis le bloc-note.
1: factor(100)
2: kronecker_symbol(3,5)
3: %hist
sage: _oh
_4 = {1: 2^2 * 5^2, 2: -1}
sage: _i1
_5 = 'factor(ZZ(100))\n'
sage: eval(_i1)
_6 = 2^2 * 5^2
sage: %hist
1: factor(100)
2: kronecker_symbol(3,5)
3: %hist
4: _oh
5: _i1
6: eval(_i1)
7: %hist
Dans la suite de ce tutoriel et le reste de la documentation de Sage, nous omettrons la numérotation des sorties.
Il est possible de créer (pour la durée d’une session) une macro qui rappelle une liste de plusieurs lignes d’entrée.
sage: E = EllipticCurve([1,2,3,4,5])
sage: M = ModularSymbols(37)
sage: %hist
1: E = EllipticCurve([1,2,3,4,5])
2: M = ModularSymbols(37)
3: %hist
sage: %macro em 1-2
Macro `em` created. To execute, type its name (without quotes).
sage: E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
sage: E = 5
sage: M = None
sage: em
Executing Macro...
sage: E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over
Rational Field
Depuis le shell interactif Sage, il est possible d’exécuter une commande Unix en la faisant précéder d’un point d’exclama-
tion !. Par exemple,
sage: !ls
auto [Link] [Link] t tmp [Link] [Link]
sage: !gp
Reading GPRC: /etc/gprc ...Done.
toutes les entrées que vous tapez, toutes les sorties, et de rejouer ces entrées dans une session future (en rechargeant le
fichier journal).
was@form:~$ sage
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.7, Release Date: 2022-01-10 │
│ Using Python 3.10.4. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage: load("setup")
Loading log file <setup> one line at a time...
Finished replaying log file <setup>
sage: E
Elliptic Curve defined by y^2 + x*y = x^3 - x^2 + 4*x + 3 over Rational
Field
sage: x*y
x*y
sage: G
[(2 : 3 : 1)]
Si vous utilisez le terminal Konsole de KDE, vous pouvez aussi sauver votre session comme suit : après avoir lancé Sage
dans la konsole, ouvrez le menu « Configuration » et choisissez « Historique… » puis comme nombre de lignes « Illimité
». Ensuite, lorsque vous souhaitez enregistrer l’état de votre session, sélectionnez « Enregistrer l’historique sous… » dans
le menu « Édition » et entrez le nom d’un fichier où enregistrer le texte de votre session. Une fois le fichier sauvegardé,
vous pouvez par exemple l’ouvrir dans un éditeur comme xemacs et l’imprimer.
sage: 2^10
1024
sage: sage: sage: 2^10
1024
sage: >>> 2^10
1024
Le calcul a pris 0.66 seconde, pendant un intervalle de wall time (le temps de votre montre) lui aussi de 0.66 seconde.
Si d’autres programmes qui s’exécutent en même temps que Sage chargent l’ordinateur avec de gros calculs, le wall time
peut être nettement plus important que le temps processeur.
Chronométrons maintenant le calcul de la même puissance avec le type Integer de Sage, qui est implémenté (en Cython)
en utilisant la bibliothèque GMP :
GMP est plus rapide, mais de peu (ce n’est pas une surprise, car la version de PARI incluse dans Sage utilise GMP pour
l’arithmétique entière).
Il est aussi possible de chronométrer tout un bloc de commandes avec la commande cputime, comme dans l’exemple
suivant :
sage: t = cputime()
sage: a = int(1938)^int(99484)
sage: b = 1938^99484
sage: c = pari(1938)^pari(99484)
sage: cputime(t) #random
0.64
sage: cputime?
...
Return the time in CPU second since Sage started, or with optional
argument t, return the time since time t.
INPUT:
t -- (optional) float, time in CPU seconds
OUTPUT:
float -- time in CPU seconds
La commande walltime fonctionne comme cputime, à ceci près qu’elle mesure le temps total écoulé « à la montre ».
Nous pouvons aussi faire faire le calcul de puissance ci-dessus à chacun des systèmes de calcul formel inclus dans Sage.
Dans chaque cas, nous commençons par lancer une commande triviale dans le système en question, de façon à démarrer
son serveur. La mesure la plus pertinente est le wall time. Cependant, si la différence entre celui-ci et le temps processeur
est importante, cela peut indiquer un problème de performance qui mérite d’être examiné.
Nous voyons que GAP et Maxima sont les plus lents sur ce test (lancé sur la machine [Link]).
Mais en raison du surcoût de l’interface pexpect, la comparaison avec Sage, qui est le plus rapide, n’est pas vraiment
équitable.
def some_function(n):
return n**2 + 3*n + 2
puis enregistrer le fichier et quitter l’éditeur. La fonction some_function est désormais disponible dans votre
session Sage, et vous pouvez la modifier en saisissant edit some_function à l’invite de commande.
— Si vous souhaitez reprendre une version modifiée du résultat d’un calcul dans une nouvelle commande, tapez %rep
après avoir fait le calcul. Cela récupère le texte du résultat et le place sur la ligne de commande, prêt à être modifié.
Ainsi, après les commandes ci-dessus, la commande %rep fournit un nouvel invite de commande pré-rempli avec
le texte -sin(x) et le curseur en fin de ligne.
Pour plus d’information, entrez la commande %quickref pour un résumé des possibilités de IPython. Au moment où
cette documentation est écrite (avril 2011), Sage emploie IPython 0.9.1. La documentation des commandes magiques est
disponible en ligne, et divers aspects un peu plus avancés de leur fonctionnement sont décrits ici.
sage: 3_2
------------------------------------------------------------
File "<console>", line 1
ZZ(3)_2
^
SyntaxError: invalid ...
sage: EllipticCurve([0,infinity])
------------------------------------------------------------
Traceback (most recent call last):
...
TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational
>>> EllipticCurve([Integer(0),infinity])
------------------------------------------------------------
Traceback (most recent call last):
...
TypeError: Unable to coerce Infinity (<class 'sage...Infinity'>) to Rational
Le débogueur interactif est parfois utile pour comprendre ce qu’il s’est passé. Il s’active ou se désactive avec %pdb (et
est désactivé par défaut). L’invite ipdb>> du débogueur apparaît si une exception a lieu alors que celui-ci est actif. Le
débogueur permet d’afficher l’état de n’importe quelle variable locale et de monter ou descendre dans la pile d’exécution.
Par exemple :
sage: %pdb
Automatic pdb calling has been turned ON
sage: EllipticCurve([1,infinity])
---------------------------------------------------------------------------
<class '[Link]'> Traceback (most recent call last)
...
ipdb>
ipdb>
Pour obtenir une liste des commandes disponibles dans le débogueur, tapez ? à l’invite ipdb> :
ipdb> ?
Undocumented commands:
======================
retval rv
sage: V = VectorSpace(QQ,3)
sage: V
Vector space of dimension 3 over Rational Field
sage: V = QQ^3
Tapez ensuite le début d’une commande, puis Ctrl-p (ou flèche vers le haut) pour passer en revue les lignes qui com-
mencent par les mêmes lettres parmi celles que vous avez entrées jusque-là. Cela fonctionne même si vous avez quitté et
relancé Sage entre-temps. Vous pouvez aussi rechercher une portion de commande en remontant dans l’historique avec
Ctrl-r. Toutes ces fonctionnalités reposent sur la bibliothèque readline, qui existe pour la plupart des variantes de
Linux.
La complétion de ligne de commande permet d’obtenir facilement la liste des fonctions membres de 𝑉 : tapez simplement
V. puis appuyez sur la touche tabulation.
Si vous tapez les quelques premières lettres d’un nom de fonction avant d’appuyer sur tab, vous n’obtiendrez que les
fonctions qui commencent par ces quelques lettres :
Si vous cherchez à savoir ce que fait une fonction, par exemple la fonction coordinates, [Link]? affiche un
message d’aide et [Link]?? le code source de la fonction, comme expliqué dans la section suivante.
sage: V = QQ^3
sage: [Link]?
Type: instancemethod
(suite sur la page suivante)
EXAMPLES:
sage: M = FreeModule(IntegerRing(), 2); M0,M1=[Link]()
sage: W = [Link]([M0 + M1, M0 - 2*M1])
sage: [Link](2*M0-M1)
[2, -1]
EXAMPLES:
>>> M = FreeModule(IntegerRing(), Integer(2)); M0,M1=[Link]()
>>> W = [Link]([M0 + M1, M0 - Integer(2)*M1])
>>> [Link](Integer(2)*M0-M1)
[2, -1]
Comme nous pouvons le voir ci-dessus, la sortie indique le type de l’objet, le nom du fichier où il est défini, et donne une
description de l’effet de la fonction, avec des exemples que vous pouvez copier dans votre session Sage. Pratiquement tous
ces exemples sont automatiquement testés régulièrement pour s’assurer qu’ils se comportent exactement comme indiqué.
Une autre fonctionnalité, nettement dans l’esprit du caractère ouvert de Sage, est que lorsque f est une fonction Python,
sage: V = QQ^3
sage: [Link]??
Type: instancemethod
...
Source:
def coordinates(self, v):
"""
Write $v$ in terms of the basis for self.
...
"""
return self.coordinate_vector(v).list()
Nous voyons que la fonction coordinates ne fait qu’appeler coordinate_vector et transformer le résultat en une
liste. Mais alors, que fait la fonction coordinate_vector ?
sage: V = QQ^3
sage: V.coordinate_vector??
...
def coordinate_vector(self, v):
...
return self.ambient_vector_space()(v)
La fonction coordinate_vector convertit son entrée en un élément de l’espace ambiant, ce qui a pour effet de calculer
le vecteur des coefficients de 𝑣 dans 𝑉 . L’espace 𝑉 est déjà « l’espace ambiant » puisque c’est simplement Q3 . Il y a aussi
une fonction coordinate_vector différente pour les sous-espaces. Créons un sous-espace et examinons-là :
(Si vous pensez que cette implémentation est inefficace, venez nous aider à optimiser l’algèbre linéaire !)
Vous pouvez aussi taper help(commande) ou help(classe) pour appeler une sorte de page de manuel relative à une
commande ou une classe.
sage: help(VectorSpace)
Help on function VectorSpace in module [Link].free_module:
::
sage: V = VectorSpace(FractionField(PolynomialRing(ZZ,'x')),3)
sage: V
Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x
over Integer Ring
sage: [Link]()
[
(1, 0, 0),
(0, 1, 0),
--More--
::
>>> V = VectorSpace(FractionField(PolynomialRing(ZZ,'x')),Integer(3))
>>> V
Vector space of dimension 3 over Fraction Field of Univariate Polynomial Ring in x
over Integer Ring
>>> [Link]()
[
(1, 0, 0),
(0, 1, 0),
--More--
Pour quitter la page d’aide, appuyez sur q. Votre session revient à l’écran comme elle était : contrairement à la sortie de
fonction?, celle de help n’encombre pas votre session. Une possibilité particulièrement utile est de consulter l’aide
d’un module entier avec help(nom_du_module. Par exemple, les espaces vectoriels sont définis dans [Link].
free_module, et on accède à la documentation de ce module en tapant help([Link].free_module).
Lorsque vous lisez une page de documentation avec la commande help, vous pouvez faire des recherches en avant en
tapant / et en arrière en tapant ?.
sage: A = MatrixSpace(QQ,3)(range(9))^2
sage: A
[ 15 18 21]
[ 42 54 66]
(suite sur la page suivante)
sage: A = load('A')
sage: A
[ 15 18 21]
[ 42 54 66]
[ 69 90 111]
Vous pouvez faire de même avec des objets plus compliqués, par exemple des courbes elliptiques. Toute l’information en
cache sur l’objet est stockée avec celui-ci :
sage: E = EllipticCurve('11a')
sage: v = [Link](100000) # prend un moment
sage: save(E, 'E')
sage: quit
Ainsi, la version sauvegardée de E prend 153 kilo-octets car elle contient les 100000 premiers 𝑎𝑛 .
~/tmp$ ls -l [Link]
-rw-r--r-- 1 was was 153500 2006-01-28 19:23 [Link]
~/tmp$ sage [...]
sage: E = load('E')
sage: v = [Link](100000) # instantané !
(En Python, les sauvegardes et rechargements s’effectuent à l’aide du module pickle. En particulier, on peut sauver un
objet Sage x par la commande [Link](x, 2). Attention au 2 !)
Sage n’est pas capable de sauvegarder les objets créés dans d’autres systèmes de calcul formel comme GAP, Singular,
Maxima etc. : au rechargement, ils sont dans un état marqué « invalide ». Concernant GAP, un certain nombre d’objets
sont affichés sous une forme qui permet de les reconstruire, mais d’autres non, aussi la reconstruction d’objets GAP à
partir de leur affichage est intentionnellement interdite.
sage: a = libgap(2)
sage: [Link]('a')
sage: load('a')
Traceback (most recent call last):
...
ValueError: The session in which this object was defined is no longer
running.
Les objets GP/PARI, en revanche, peuvent être sauvegardés et rechargés, puisque la forme imprimée d’un objet suffit à
reconstruire celui-ci.
sage: a = gp(2)
sage: [Link]('a')
sage: load('a')
2
Un objet sauvegardé peut être rechargé y compris sur un ordinateur doté d’une architecture ou d’un système d’exploitation
différent. Ainsi, il est possible de sauvegarder une immense matrice sur un OS-X 32 bits, la recharger sur un Linux 64 bits,
l’y mettre en forme échelon et rapatrier le résultat. Bien souvent, un objet peut même être rechargé avec une version de
Sage différente de celle utilisée pour le sauver, pourvu que le code qui gère cet objet n’ait pas trop changé d’une version sur
l’autre. Sauver un objet enregistre tous ses attributs ainsi que la classe à laquelle il appartient (mais pas son code source). Si
cette classe n’existe plus dans une version ultérieure de Sage, l’objet ne peut pas y être rechargé. Mais il demeure possible
de le charger dans l’ancienne version pour récupérer son dictionnaire (avec x.__dict__), sauver celui-ci, et le recharger
dans la nouvelle version.
sage: E = EllipticCurve('11a')
sage: M = ModularSymbols(37)
sage: a = 389
sage: t = M.T(2003).matrix(); [Link]().factor()
_4 = (x - 2004) * (x - 12)^2 * (x + 54)^2
Nous sauvons maintenant notre session, ce qui a pour effet d’enregistrer dans un même fichier toutes les variables ci-dessus.
Nous pouvons constater que le fichier fait environ 3 ko.
sage: save_session('misc')
Saving a
Saving M
Saving t
Saving E
sage: quit
was@form:~/tmp$ ls -l [Link]
-rw-r--r-- 1 was was 2979 2006-01-28 19:47 [Link]
Enfin, nous redémarrons Sage, nous définissons une nouvelle variable, et nous rechargeons la session précédente.
sage: b = 19
sage: load_session('misc')
Loading a
Loading M
Loading E
Loading t
Toutes les variables sauvegardées sont à nouveau disponibles. En outre, la variable b n’a pas été écrasée.
sage: M
Full Modular Symbols space for Gamma_0(37) of weight 2 with sign 0
and dimension 5 over Rational Field
sage: E
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational
Field
sage: b
19
sage: a
389
Interfaces
L’un des aspects essentiels de Sage est qu’il permet d’effectuer des calculs utilisant des objets issus de nombreux systèmes
de calcul formel de façon unifiée, avec une interface commune et un langage de programmation sain.
Les méthodes console et interact d’une interface avec un programme externe font des choses tout-à-fait différentes.
Prenons l’exemple de GAP :
1. [Link]() : Cette commande ouvre la console GAP. Cela transfère le contrôle à GAP ; Sage n’est dans ce
cas qu’un moyen commode de lancer des programmes, un peu comme le shell sous Unix.
2. [Link]() : Cette commande permet d’interagir avec une instance de GAP en cours d’exécution, et
éventuellement « remplie d’objets Sage ». Il est possible d’importer des objets Sage dans la session GAP (y compris
depuis l’interface interactive), etc.
4.1 GP/PARI
PARI est un programme C compact, mature, fortement optimisé et spécialisé en théorie des nombres. Il possède deux
interfaces très différentes utilisables depuis Sage :
— gp – l’interpréteur PARI, et
— pari – la bibliothèque C PARI.
Ainsi, les deux commandes suivantes font le même calcul de deux façons différentes. Les deux sorties ont l’air identiques,
mais elles ne le sont pas en réalité, et ce qui ce passe en coulisses est radicalement différent.
sage: gp('znprimroot(10007)')
Mod(5, 10007)
sage: pari('znprimroot(10007)')
Mod(5, 10007)
107
Tutoriel Sage, Version 10.6
Dans le premier exemple, on démarre une instance de l’interpréteur GP et on lui envoie la chaîne
'znprimroot(10007)'. Il l’évalue, et affecte le résultat à une variable GP (ce qui occupe un espace qui ne
sera pas libéré dans la mémoire du processus fils GP). La valeur de la variable est ensuite affichée. Dans le second cas,
nul programme séparé n’est démarré, la chaîne 'znprimroot(10007)' est évaluée par une certaine fonction de la
bibliothèque C PARI. Le résultat est stocké sur le tas de l’interpréteur Python, et la zone de mémoire utilisée est libérée
lorsque son contenu n’est plus utilisé. Les objets renvoyés par ces deux commandes sont de types différents :
sage: type(gp('znprimroot(10007)'))
<class '[Link]'>
sage: type(pari('znprimroot(10007)'))
<class '[Link]'>
Alors, laquelle des interfaces utiliser ? Tout dépend de ce que vous cherchez à faire. L’interface GP permet de faire
absolument tout ce que vous pourriez faire avec la ligne de commande GP/PARI habituelle, puisqu’elle fait appel à celle-ci.
En particulier, vous pouvez l’utiliser pour charger et exécuter des scripts PARI compliqués. L’interface PARI (via la
bibliothèque C) est nettement plus restrictive. Tout d’abord, toutes les méthodes ne sont pas implémentées. Deuxièmement,
beaucoup de code utilisant par exemple l’intégration numérique ne fonctionne pas via l’interface PARI. Ceci dit, l’interface
PARI est souvent considérablement plus rapide et robuste que l’interface GP.
(Si l’interface GP manque de mémoire pour évaluer une ligne d’entrée donnée, elle double silencieusement la taille de la
pile et réessaie d’évaluer la ligne. Ainsi votre calcul ne plantera pas même si vous n’avez pas évalué convenablement l’es-
pace qu’il nécessite. C’est une caractéristique commode que l’interpréteur GP habituel ne semble pas fournir. L’interface
PARI, quant à elle, déplace immédiatement les objets créés hors de la pile de PARI, de sorte que celle-ci ne grossit pas.
Cependant, la taille de chaque objet est limitée à 100 Mo, sous peine que la pile ne déborde à la création de l’objet. Par
ailleurs, cette copie supplémentaire a un léger impact sur les performances.)
En résumé, Sage fait appel à la bibliothèque C PARI pour fournir des fonctionnalités similaires à celle de l’interpréteur
PARI/GP, mais depuis le langage Python, et avec un gestionnaire de mémoire plus perfectionné.
Commençons par créer une liste PARI à partir d’une liste Python.
sage: v = pari([1,2,3,4,5])
sage: v
[1, 2, 3, 4, 5]
sage: type(v)
<class '[Link]'>
En Sage, les objets PARI sont de type Gen. Le type PARI de l’objet sous-jacent est donné par la méthode type.
sage: [Link]()
't_VEC'
Pour créer une courbe elliptique en PARI, on utiliserait ellinit([1,2,3,4,5]). La syntaxe Sage est semblable, à ceci
près que ellinit devient une méthode qui peut être appelée sur n’importe quel objet PARI, par exemle notre t_VEC 𝑣.
sage: e = [Link]()
sage: [Link]()
't_VEC'
sage: pari(e)[:13]
[1, 2, 3, 4, 5, 9, 11, 29, 35, -183, -3429, -10351, 6128487/10351]
À présent que nous disposons d’une courbe elliptique, faisons quelques calculs avec.
sage: [Link]()
[1, [], []]
sage: [Link]()
[10351, [1, -1, 0, -1], 1, [11, 1; 941, 1], [[1, 5, 0, 1], [1, 5, 0, 1]]]
sage: f = [Link]([1,-1,0,-1])
sage: f[:5]
[1, -1, 0, 4, 3]
4.2 GAP
Pour les mathématiques discrètes effectives et principalement la théorie des groupes, Sage utilise GAP.
Voici un exemple d’utilisation de la fonction GAP IdGroup, qui nécessite une base de données optionnelle de groupes
de petit ordre, à installer séparément comme décrit plus bas.
On peut faire le même calcul en SAGE sans invoquer explicitement l’interface GAP comme suit :
sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
sage: [Link]()
Subgroup generated by [()] of (Permutation Group with generators [(3,4), (1,2,3)(4,
˓→5)])
sage: G.group_id()
[120, 34]
sage: n = [Link](); n
120
>>> [Link]()
Subgroup generated by [()] of (Permutation Group with generators [(3,4), (1,2,3)(4,
˓→5)])
>>> G.group_id()
[120, 34]
>>> n = [Link](); n
120
Pour utiliser certaines fonctionnalités de GAP, vous devez installer un paquet Sage optionnel. Cela peut être fait avec la
commande :
sage -i gap_packages
4.3 Singular
Singular fournit une bibliothèque consistante et mature qui permet, entre autres, de calculer des pgcd de polynômes de
plusieurs variables, des factorisations, des bases de Gröbner ou encore des bases d’espaces de Riemann-Roch de courbes
planes. Considérons la factorisation de polynômes de plusieurs variables à l’aide de l’interface à Singular fournie par Sage
(n’entrez pas les ....:) :
sage: [Link]()
Singular
sage: F = [Link](); F
[1]:
_[1]=9
_[2]=x^6-2*x^3*y^2-x^2*y^3+y^4
_[3]=-x^5+y^2
[2]:
1,1,2
sage: F[1][2]
x^6-2*x^3*y^2-x^2*y^3+y^4
>>> [Link]()
Singular
>>> F = [Link](); F
[1]:
_[1]=9
_[2]=x^6-2*x^3*y^2-x^2*y^3+y^4
_[3]=-x^5+y^2
[2]:
(suite sur la page suivante)
Comme avec GAP dans la section GAP, nous pouvons aussi calculer la factorisation sans utiliser explicitement l’interface
Singular (Sage y fera tout de même appel en coulisses pour le calcul).
˓→Integer(9)*x**Integer(6)*y**Integer(4)
... + Integer(18)*x**Integer(7)*y**Integer(5) +␣
˓→Integer(36)*x**Integer(8)*y**Integer(4) + Integer(9)*x**Integer(10)*y**Integer(4) -␣
˓→Integer(18)*x**Integer(11)*y**Integer(2) - Integer(9)*x**Integer(12)*y**Integer(3)
4.4 Maxima
Le système de calcul formel Maxima est fourni avec Sage accompagné d’une implémentation du langage Lisp. Le logiciel
gnuplot (que Maxima utilise par défaut pour tracer des graphiques) est disponible comme paquet optionnel. Maxima
fournit notamment des routines de calcul sur des expressions formelles. Il permet de calculer des dérivées, primitives
et intégrales, de résoudre des équations différentielles d’ordre 1 et souvent d’ordre 2, et de résoudre par transformée de
Laplace les équations différentielles linéaires d’ordre quelconque. Maxima dispose aussi d’un grand nombre de fonctions
spéciales, permet de tracer des graphes de fonctions via gnuplot, et de manipuler des matrices (réduction en lignes, valeurs
propres, vecteurs propres…) ou encore des équations polynomiales.
Utilisons par exemple l’interface Sage/Maxima pour construire la matrice dont le coefficient d’indice 𝑖, 𝑗 vaut 𝑖/𝑗, pour
𝑖, 𝑗 = 1, . . . , 4.
Un deuxième exemple :
sage: M = MatrixSpace(QQ,3,3)
sage: AA = M([[1,0,0],[1, - 1,0],[1,3, - 2]])
sage: b1 = v1.base_ring()
sage: AA*v1 == b1(lambda1)*v1
True
sage: b2 = v2.base_ring()
sage: AA*v2 == b2(lambda2)*v2
True
sage: b3 = v3.base_ring()
sage: AA*v3 == b3(lambda3)*v3
True
>>> M = MatrixSpace(QQ,Integer(3),Integer(3))
>>> AA = M([[Integer(1),Integer(0),Integer(0)],[Integer(1), - Integer(1),Integer(0)],
˓→[Integer(1),Integer(3), - Integer(2)]])
>>> b1 = v1.base_ring()
(suite sur la page suivante)
Voici enfin quelques exemples de tracés de graphiques avec openmath depuis Sage. Un grand nombre de ces exemples
sont des adaptations de ceux du manuel de référence de Maxima.
Tracé en 2D de plusieurs fonctions (n’entrez pas les ....:) :
Un graphique 3D interactif, que vous pouvez déplacer à la souris (n’entrez pas les ....:) :
sage: maxima.plot3d ("2^(-u^2 + v^2)", "[u, -3, 3]", "[v, -2, 2]", # not tested
....: '[plot_format, openmath]')
sage: maxima.plot3d("atan(-x^2 + y^3/4)", "[x, -4, 4]", "[y, -4, 4]", # not tested
....: "[grid, 50, 50]",'[plot_format, openmath]')
117
Tutoriel Sage, Version 10.6
sage: var('z')
z
sage: latex(z^12)
z^{12}
sage: latex(integrate(z^4, z))
\frac{1}{5} \, z^{5}
sage: latex('a string')
\text{\texttt{a{ }string}}
sage: latex(QQ)
\Bold{Q}
sage: latex(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]]))
\left(\begin{array}{rrr}
2 & 4 & 6 \\
-1 & -1 & -1
\end{array}\right)
\left(\begin{array}{rrr}
2 & 4 & 6 \\
-1 & -1 & -1
\end{array}\right)
L’utilisation de base de MathJax dans le bloc-notes est largement automatique. Nous pouvons tout de même en voir
quelques exemples en employant la classe MathJax. La méthode eval de celle-ci convertit un objet Sage en sa repré-
sentation LaTeX, puis emballe le résultat dans du code HTML qui fait possède la classe CSS « math », laquelle indique
de faire appel à MathJax.
sage: pretty_print(x^12)
x^12
sage: pretty_print(integrate(sin(x), x))
-cos(x)
Le bloc-notes dispose de deux autres fonctionnalités pour appeler LaTeX. Premièrement, lorsque la case « Typeset »
(juste au-dessus de la première cellule d’une feuille de travail, à droite des quatre listes déroulantes) est cochée, le résultat
de l’évaluation d’une cellule est automatiquement interprété par MathJax et affiché sous forme de formule plutôt que de
texte brut. Les sorties déjà affichées ne sont pas modifiées tant que l’on ne ré-évalue pas les cellules correspondantes.
Cocher la case « Typeset » revient essentiellement à appeler view() sur le résultat de chaque cellule.
Deuxièmement, le bloc-notes permet d’annoter une feuille de travail en saisissant du TeX. Un clic en tenant la touche
Maj enfoncée sur la barre bleue qui apparaît lorsque l’on place le curseur de la souris entre deux cellules ouvre un
mini-traitement de texte appelé TinyMCE. Cela permet de saisir du texte pour commenter la feuille de travail, et de
le mettre en forme avec un éditeur WYSIWIG de HTML et CSS. Mais le texte placé entre signes dollar simples ou
doubles est interprété par MathJax, respectivement comme formule composée en ligne ou hors texte.
sage: latex(QQ)
\Bold{Q}
sage: from [Link] import MathJax
sage: mj=MathJax()
sage: mj(QQ)
<html>\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]</html>
sage: latex.blackboard_bold(True)
sage: mj(QQ)
<html>\[\newcommand{\Bold}[1]{\mathbb{#1}}\Bold{Q}\]</html>
sage: latex.blackboard_bold(False)
On peut aussi définir de nouvelles macros TeX ou charger des packages supplémentaires. L’exemple suivant montre com-
ment ajouter des macros qui seront utilisées à chaque fois que MathJax interprète un fragment de TeX dans le bloc-notes.
sage: latex.extra_macros()
''
sage: latex.add_macro("\\newcommand{\\foo}{bar}")
sage: latex.extra_macros()
'\\newcommand{\\foo}{bar}'
sage: var('x y')
(x, y)
sage: latex(x+y)
x + y
sage: from [Link] import MathJax
sage: mj=MathJax()
sage: mj(x+y)
<html>\[\newcommand{\foo}{bar}x + y\]</html>
Ces macros supplémentaires sont disponibles aussi quand Sage appelle TeX pour compiler un fragment de document
trop gros pour MathJax. C’est la fonction latex_extra_preamble, appelée pour préparer le préambule du document
LaTeX, qui les définit, comme l’illustre l’exemple suivant. Notons à nouveau le dédoublement des \ dans les chaînes
Python.
sage: latex.extra_macros('')
sage: latex.extra_preamble('')
sage: from [Link] import latex_extra_preamble
sage: print(latex_extra_preamble())
\newcommand{\ZZ}{\Bold{Z}}
...
\newcommand{\Bold}[1]{\mathbf{#1}}
sage: latex.add_macro("\\newcommand{\\foo}{bar}")
sage: print(latex_extra_preamble())
\newcommand{\ZZ}{\Bold{Z}}
...
\newcommand{\Bold}[1]{\mathbf{#1}}
\newcommand{\foo}{bar}
On peut aussi charger des packages LaTeX, ou ajouter n’importe quelle autre commande au préam-
bule, grâce à la méthode latex.add_package_to_preamble. Sa variante plus spécialisée latex.
add_package_to_preamble_if_available vérifie qu’un package donné est disponible avant de l’ajouter au
préambule si c’est bien le cas.
Dans l’exemple suivant, nous ajoutons au préambule la commande qui charge le package geometry, puis nous l’utili-
sons pour régler la taille de la zone de texte (et donc indirectement les marges) du document TeX. Une fois encore, les
Voici enfin comment ajouter un package en vérifiant sa disponibilité, et ce qu’il se passe quand le package n’existe pas.
sage: latex.extra_preamble('')
sage: latex.extra_preamble()
''
sage: latex.add_to_preamble('\\usepackage{foo-bar-unchecked}')
sage: latex.extra_preamble()
'\\usepackage{foo-bar-unchecked}'
sage: latex.add_package_to_preamble_if_available('foo-bar-checked')
sage: latex.extra_preamble()
'\\usepackage{foo-bar-unchecked}'
Supposons maintenant que, dans le bloc-notes, un appel à view() ou l’évaluation d’une cellule lorsque la case « Typeset »
est cochée produise un résultat dont le mécanisme décrit ci-dessus détermine qu’il doit être passé au moteur LaTeX
externe. Comme en ligne de commande, l’exécutable spécifié par [Link]() traite alors le document. Cependant,
au lieu d’appeler une visionneuse externe pour afficher le document produit, Sage tente de recadrer le document en rognant
les zones blanches, et de le convertir en une image qui est ensuite insérée dans le bloc-notes comme sortie associée à la
cellule.
Plusieurs facteurs influencent la conversion, principalement le moteur TeX choisi et la palette d’utilitaires de conversion
disponibles sur le système. Les convertisseurs suivants couvrent à eux quatre toutes les situations : dvips, ps2pdf,
dvipng et convert (de la collection ImageMagick). Dans tous les cas, il s’agit d’arriver à produire une image PNG à
insérer dans la feuille de travail. Lorsque le moteur LaTeX produit un fichier dvi, le programme dvipng suffit en général
à effectuer la conversion. Il peut cependant arriver que le fichier dvi contienne des instructions spécifiques à un pilote
(commande TeX \special) que dvipng est incapable d’interpréter, auquel cas on utilise dvips pour créer un fichier
PostScript. Celui-ci, de même que le fichier PDF produit par le moteur le cas échéant, est ensuite converti en image png
avec convert. Les commandes have_dvipng() et have_convert() permettent de tester la présence sur le système
des utilitaires en question.
Toutes ces conversions sont automatiques lorsque les outils nécessaires sont installés. Dans le cas contraire, un message
d’erreur indique ce qu’il manque et où le télécharger.
La section suivante (Example : rendu de graphes avec tkz-graph) présente un exemple concret de traitement d’expressions
LaTeX complexes, en l’occurrence pour obtenir un rendu de qualité de graphes grâce au package LaTeX tkz-graph.
Les tests inclus dans Sage contiennent d’autres exemples. On y accède en important l’objet prédéfini [Link].
latex.latex_examples, instance de la classe [Link], comme illustré ci-dessous. Les
exemples fournis actuellement couvrent les types d’objets suivants : diagrammes commutatifs (utilisant le package 𝑥𝑦),
graphes combinatoires (𝑡𝑘𝑧 − 𝑔𝑟𝑎𝑝ℎ), nœuds (𝑥𝑦𝑝𝑖𝑐), schémas pstricks (𝑝𝑠𝑡𝑟𝑖𝑐𝑘𝑠). Pour obtenir la liste des exemples,
utilisez la complétion de ligne de commande après avoir importé latex_examples. Chaque exemple affiche quand on
l’appelle des instructions sur la configuration nécessaire pour qu’il fonctionne correctement. Une fois le préambule, le
moteur LaTeX etc. configurés comme indiqué, il suffit d’appeler la commande view() pour visualiser l’exemple.
To use, try to view this object -- it will not work. Now try
'latex.add_to_preamble("\\usepackage[matrix,arrow,curve,cmtip]{xy}")',
and try viewing again. You should get a picture (a part of the diagram arising
from a filtered chain complex).
pdflatex comme moteur TeX. Après ces réglages, une instruction du genre view([Link](4))
saisie dans l’interface en ligne de commande doit produire un fichier PDF contenant un dessin du graphe complet 𝐾4 .
Pour que la même chose fonctionne dans le bloc-notes, il faut de plus désactiver l’interprétation du code LaTeX pro-
duisant le graphe par MathJax, à l’aide de la liste de motifs exclus. Le nom de l’environnement tikzpicture, dans
lequel sont placés les graphes, est un bon choix de chaîne à exclure. Une fois cela fait, la commande view(graphs.
CompleteGraph(4)) dans une feuille de travail du bloc-notes appelle pdflatex pour produire un fichier PDF, puis
convert pour en extraire une image PNG à placer dans la zone de sortie de la feuille de travail. Les commandes sui-
vantes reprennent l’ensemble des étapes de configuration.
La mise en forme du graphe est faite en traitant des commandes tkz-graph qui le décrivent avec pdflatex. Diverses
options pour influencer ce rendu, qui sortent du cadre de cette section, sont décrites dans la section intitulée « LaTeX
Options for Graphs » du manuel de référence de Sage.
sorties LaTeX associées comme étape intermédiaire de la compilation d’un document LaTeX. Par exemple, on peut ima-
giner de maintenir la correspondance entre questions et réponses dans un sujet d’examen en utilisant Sage pour calculer
les unes à partir des autres. Sagetex est décrit plus en détail en section Utiliser SageTeX de ce document.
Programmation
print("Hello World")
print(2^3)
Nous pouvons lire et exécuter le contenu du fichier [Link] en utilisant la commande load.
sage: load("[Link]")
Hello World
8
Nous pouvons aussi attacher un fichier Sage à la session en cours avec la commande attach :
sage: attach("[Link]")
Hello World
8
L’effet de cette commande est que si nous modifions maintenant [Link] et entrons une ligne vierge (i.e. appuyons
sur entrée), le contenu de [Link] sera automatiquement rechargé dans Sage.
129
Tutoriel Sage, Version 10.6
Avec attach, le fichier est rechargé automatiquement dans Sage à chaque modification, ce qui est pratique pour déboguer
du code ; tandis qu’avec load il n’est chargé qu’une fois.
Lorsque Sage lit [Link], il le convertit en un programme Python qui est ensuite exécuté par l’interpréteur Python.
Cette conversion est minimale, elle se résume essentiellement à encapsuler les littéraux entiers dans des Integer() et les
littéraux flottants dans des RealNumber(), à remplacer les ^ par des **, et à remplacer par exemple R.2 par [Link](2).
La version convertie en Python de [Link] est placée dans le même répertoire sous le nom [Link].
Elle contient le code suivant :
print("Hello World")
print(Integer(2)**Integer(3))
On voit que les littéraux entiers ont été encapsulés et que le ^ a été remplacé par ** (en effet, en Python, ^ représente le
ou exclusif et ** l’exponentiation).
(Ce prétraitement est implémenté dans le fichier sage/misc/[Link].)
On peut coller dans Sage des blocs de code de plusieurs lignes avec des indentations pourvu que les blocs soient délimités
par des retours à la ligne (cela n’est pas nécessaire quand le code est dans un fichier). Cependant, la meilleure façon d’entrer
ce genre de code dans Sage est de l’enregistrer dans un fichier et d’utiliser la commande attach comme décrit ci-dessus.
import [Link]
def foo(n):
return [Link](n)
int add_one(int n) {
return n + 1;
}
def test(n):
return add_one(n)
sage: attach("[Link]")
Compiling (...)/[Link]...
sage: test(10)
11
Si la compilation du code C généré à partir d’un fichier Cython nécessite une bibliothèque supplémentaire foo, ajoutez
au source Cython la ligne clib foo. De même, il est possible d’ajouter un fichier C supplémentaire bar aux fichiers à
compiler avec la déclaration cfile bar.
#!/usr/bin/env sage
import sys
if len([Link]) != 2:
print("Usage: %s <n>" % [Link][0])
print("Outputs the prime factorization of n.")
[Link](1)
print(factor(sage_eval([Link][1])))
Pour utiliser ce script, votre répertoire SAGE_ROOT doit apparaître dans la variable d’environnement PATH. Supposons
que le script ci-dessus soit appelé factor, il peut alors être utilisé comme dans l’exemple suivant :
Sage ajoute de nombreux autres types. Par exemple, les espaces vectoriels :
Seules certaines fonctions peuvent être appelées sur V. Dans d’autres logiciels mathématiques, cela se fait en notation
« fonctionnelle », en écrivant foo(V,...). En Sage, certaines fonctions sont attachés au type (ou classe) de l’objet et
appelées avec une syntaxe « orientée objet » comme en Java ou en C++, par exemple [Link](...). Cela évite de polluer
l’espace de noms global avec des dizaines de milliers de fonctions, et cela permet d’avoir plusieurs fonctions appelées
foo, avec des comportements différents, sans devoir se reposer sur le type des arguments (ni sur des instructions case)
pour décider laquelle appeler. De plus, une fonction dont vous réutilisez le nom demeure disponible : par exemple, si vous
appelez quelque chose zeta et si ensuite vous voulez calculer la valeur de la fonction zêta de Riemann au point 0.5, vous
pouvez encore écrire s=.5; [Link]().
sage: zeta = -1
sage: s=.5; [Link]()
-1.46035450880959
La notation fonctionnelle usuelle est aussi acceptée dans certains cas courants, par commodité et parce que certaines
expressions mathématiques ne sont pas claires en notation orientée objet. Voici quelques exemples.
sage: n = 2; [Link]()
sqrt(2)
sage: sqrt(2)
sqrt(2)
sage: V = VectorSpace(QQ,2)
sage: [Link]()
[(1, 0), (0, 1)]
sage: basis(V)
[(1, 0), (0, 1)]
sage: M = MatrixSpace(GF(7), 2); M
Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 7
sage: A = M([1,2,3,4]); A
[1 2]
[3 4]
sage: [Link]('x')
x^2 + 2*x + 5
sage: charpoly(A, 'x')
x^2 + 2*x + 5
Pour obtenir la liste de toutes les fonctions membres de 𝐴, utilisez la complétion de ligne de commande : tapez A., puis
appuyez sur la touche [tab] de votre clavier, comme expliqué dans la section Recherche en arrière et complétion de ligne
de commande.
Lors d’un accès à une liste, l’index n’a pas besoin d’être un entier Python. Un entier (Integer) Sage (ou un Rational, ou
n’importe quoi d’autre qui a une méthode __index__) fait aussi l’affaire.
sage: v = [1,2,3]
sage: v[2]
3
sage: n = 2 # Integer (entier Sage)
sage: v[n] # ça marche !
3
sage: v[int(n)] # Ok aussi
3
La fonction range crée une liste d’entiers Python (et non d’entiers Sage) :
Les n-uplets ressemblent aux listes, à ceci près qu’ils sont non mutables, ce qui signifie qu’ils ne peuvent plus être modifiés
sage: v = (1,2,3,4); v
(1, 2, 3, 4)
sage: type(v)
<... 'tuple'>
sage: v[1] = 5
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment
Les séquences sont un troisième type Sage analogue aux listes. Contrairement aux listes et aux n-uplets, il ne s’agit pas
d’un type interne de Python. Par défaut, les séquences sont mutables, mais on peut interdire leur modification en utilisant
la méthode set_immutable de la classe Sequence, comme dans l’exemple suivant. Tous les éléments d’une séquence
ont un parent commun, appelé l’univers de la séquence.
sage: v = Sequence([1,2,3,4/5])
sage: v
[1, 2, 3, 4/5]
sage: type(v)
<class '[Link].Sequence_generic'>
sage: type(v[1])
<class '[Link]'>
sage: [Link]()
Rational Field
sage: v.is_immutable()
False
sage: v.set_immutable()
sage: v[0] = 3
Traceback (most recent call last):
...
ValueError: object is immutable; please change a copy instead.
Les séquences sont des objets dérivés des listes, et peuvent être utilisées partout où les listes peuvent l’être :
sage: v = Sequence([1,2,3,4/5])
sage: isinstance(v, list)
True
sage: list(v)
[1, 2, 3, 4/5]
sage: type(list(v))
<... 'list'>
Autre exemple : les bases d’espaces vectoriels sont des séquences non mutables, car il ne faut pas les modifier.
6.6 Dictionnaires
Un dictionnaire (parfois appelé un tableau associatif) est une correspondance entre des objets « hachables » (par exemple
des chaînes, des nombres, ou des n-uplets de tels objets, voir [Link] et [Link]
org/lib/[Link] dans la documentation de Python pour plus de détails) vers des objets arbitraires.
La troisième clé utilisée ci-dessus, l’anneau des entiers relatifs, montre que les indices d’un dictionnaire peuvent être des
objets compliqués.
Un dictionnaire peut être transformé en une liste de couples clé-objet contenant les mêmes données :
sage: list([Link]())
[(1, 5), ('sage', 17), (Integer Ring, Finite Field of size 7)]
Le parcours itératifs des paires d’un dictionnaire est un idiome de programmation fréquent :
Comme le montre la dernière sortie ci-dessus, un dictionnaire stocke ses éléments sans ordre particulier.
6.7 Ensembles
Python dispose d’un type ensemble intégré. Sa principale caractéristique est qu’il est possible de tester très rapidement si
un élément appartient ou non à un ensemble. Le type ensemble fournit les opérations ensemblistes usuelles.
Sage a son propre type ensemble, qui est (dans certains cas) implémenté au-dessus du type Python, mais offre quelques
fonctionnalités supplémentaires utiles à Sage. Pour créer un ensemble Sage, on utilise Set(...). Par exemple,
6.8 Itérateurs
Les itérateurs sont un ajout récent à Python, particulièrement utile dans les applications mathématiques. Voici quelques
exemples, consultez [PyT] pour plus de détails. Fabriquons un itérateur sur les carrés d’entiers positifs jusqu’à 10000000.
Nous créons maintenant un itérateur sur les nombres premiers de la forme 4𝑝 + 1 où 𝑝 est lui aussi premier, et nous
examinons les quelques premières valeurs qu’il prend.
>>> w
<generator object <genexpr> at 0x...>
>>> next(w)
13
>>> next(w)
29
>>> next(w)
53
Certains anneaux, par exemple les corps finis et les entiers, disposent d’itérateurs associés :
Notez bien les deux points à la fin de l’instruction for (il n’y a pas de « do » ou « od » comme en Maple ou en GAP)
ainsi que l’indentation du corps de la boucle, formé de l’unique instruction print(i). Cette indentation est significative,
c’est elle qui délimite le corps de la boucle. Depuis la ligne de commande Sage, les lignes suivantes sont automatiquement
indentées quand vous appuyez sur entrée après un signe « : », comme illustré ci-dessous.
Retenez bien que l’indentation détermine la structure en blocs des instructions if, for et while :
sage: legendre(2,7)
1
sage: legendre(3,7)
-1
>>> legendre(Integer(2),Integer(7))
1
>>> legendre(Integer(3),Integer(7))
-1
Naturellement, l’exemple précédent n’est pas une implémentation efficace du symbole de Legendre ! Il est simplement
destiné à illustrer différents aspects de la programmation Python/Sage. La fonction {kronecker} fournie avec Sage calcule
le symbole de Legendre efficacement, en appelant la bibliothèque C de PARI.
Remarquons aussi que les opérateurs de comparaison numériques comme ==, !=, <=, >=, >, < convertissent automati-
quement leurs deux membres en des nombres du même type lorsque c’est possible :
True
True
sage: x < x + 1
x < x + 1
sage: bool(x < x + 1)
True
Lorsque l’on cherche à comparer des objets de types différents, Sage essaie le plus souvent de trouver une coercition
canonique des deux objets dans un même parent (voir la section Parents, conversions, coercitions pour plus de détails).
Si cela réussit, la comparaison est faite entre les objets convertis ; sinon, les objets sont simplement considérés comme
différents. Pour tester si deux variables font référence au même objet, on utilise l’opérateur is. Ainsi, l’entier Python
(int) 1 est unique, mais pas l’entier Sage 1 :
sage: 1 is 2/2
False
sage: 1 is 1
False
sage: 1 == 2/2
True
Dans les deux lignes suivantes, la première égalité est fausse parce qu’il n’y a pas de morphisme canonique Q → F5 , et
donc pas de manière canonique de comparer l’élément 1 de F5 à 1 ∈ Q. En revanche, il y a une projection canonique
Z → F5 , de sorte que la deuxième comparaison renvoie « vrai ». Remarquez aussi que l’ordre des membres de l’égalité
n’a pas d’importance.
False
False
>>> GF(Integer(5))(Integer(1)) == ZZ(Integer(1)); ZZ(Integer(1)) ==␣
˓→GF(Integer(5))(Integer(1))
True
True
>>> ZZ(Integer(1)) == QQ(Integer(1))
True
ATTENTION : La comparaison est plus restrictive en Sage qu’en Magma, qui considère 1 ∈ F5 comme égal à 1 ∈ Q.
Ici, ncalls désigne le nombre d’appels, tottime le temps total passé dans une fonction (sans compter celui pris par les
autres fonctions appelées par la fonction en question), percall est le rapport tottime divisé par ncalls. cumtime
donne le temps total passé dans la fonction en comptant les appels qu’elle effectue, la deuxième colonne percall est le
quotient de cumtime par le nombre d’appels primitifs, et filename:lineno(function) donne pour chaque fonction
le nom de fichier et le numéro de la ligne où elle est définie. En règle générale, plus haut la fonction apparaît dans ce
tableau, plus elle est coûteuse — et donc intéressante à optimiser.
Comme d’habitude, prun? donne plus d’informations sur l’utilisation du profileur et la signification de sa sortie.
Il est possible d’écrire les données de profilage dans un objet pour les étudier de plus près :
Remarque : entrer stats = prun -r A\*A à la place des deux premières lignes ci-dessus provoque une erreur de
syntaxe, car prun n’est pas une fonction normale mais une commande du shell IPython.
Pour obtenir une jolie représentation graphique des données de profilage, vous pouvez utiliser le profileur hotshot, un petit
script appelé hotshot2cachetree et (sous Unix uniquement) le programme kcachegrind. Voici le même exemple
que ci-dessus avec le profileur hotshot :
sage: [Link]("A*A")
<[Link] instance at 0x414c11ec>
sage: [Link]()
À ce stade le résultat est dans un fichier [Link] dans le répertoire de travail courant. Convertissons-le au
format cachegrind pour le visualiser.
Dans le shell du système d’exploitation, tapez
Le fichier [Link].42 peut maintenant être examiné avec kcachegrind. Notez qu’il est important de res-
pecter la convention de nommage [Link].
Utiliser SageTeX
Le paquet SageTeX permet d’inclure dans un document LaTeX les résultats de calculs effectués avec Sage. Il est fourni
avec Sage, mais pour l’utiliser, vous aurez besoin de l’ajouter à votre installation TeX. Cette opération se résume à copier
un fichier ; voyez la section Installation du présent tutoriel ainsi que « Make SageTeX known to TeX » dans le guide
d’installation de Sage (Sage installation guide, ce lien devrait conduire à une copie locale) pour plus de détails.
Voici un bref exemple d’utilisation de SageTeX. La documentation complète se trouve dans SAGE_ROOT/venv/share/
texmf/tex/latex/sagetex, où SAGE_ROOT désigne le répertoire racine de votre installation Sage. Elle est accom-
pagnée d’un fichier exemple et de scripts Python potentiellement utiles.
Pour essayer SageTeX, suivez les instructions d’installation puis copiez le texte suivant dans un fichier st_example.tex :
Exclamation-Triangle Avertissement
Attention, tel qu’il est affiché dans la version interactive de l’aide de Sage, l’exemple suivant provoque des erreurs lors
de la compilation par LaTeX. Consultez la version statique de la documentation pour voir le texte correct.
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[frenchb]{babel}
\usepackage{sagetex}
\begin{document}
149
Tutoriel Sage, Version 10.6
\begin{sageblock}
f(x) = exp(x) * sin(2*x)
\end{sageblock}
\[
\frac{\mathrm{d}^{2}}{\mathrm{d}x^{2}} \sage{f(x)} =
\sage{diff(f, x, 2)(x)}.
\]
\end{document}
Lancez LaTeX pour compiler st_example.tex comme à l’accoutumée. LaTeX va afficher un certain nombre de mes-
sages d’avertissement, dont :
En plus des fichiers habituellement produits par LaTeX, le répertoire où vous travaillez contient maintenant un fichier
st_example.sage. Il s’agit d’un script Sage produit par la compilation du fichier LaTeX. L’avertissement précédent
vous demande de lancer Sage sur st_example.sage, faites-le. Un nouveau message vous demande de relancer LaTeX
sur st_example.tex, mais avant de le faire, observez qu’un nouveau fichier st_example.sout a été créé. C’est ce
fichier qui contient le résultat des calculs effectués par Sage, dans un format que LaTeX est capable de lire pour insérer
les résultats dans votre document. Un nouveau répertoire contenant un fichier EPS avec votre graphique est également
apparu. Après une nouvelle exécution de LaTeX, les résultats des commandes Sage sont présents dans votre document
compilé.
Les macros LaTeX utilisées dans l’exemple ci-dessus ne sont guère compliquées à comprendre. Un environnement sa-
geblock compose le code qu’il contient verbatim, et le fait exécuter par Sage. Avec \sage{toto}, le résultat placé
dans votre document est celui de la commande Sage latex(toto). Les commandes de tracé de graphiques sont un peu
plus compliquées. L’exemple ci-dessus utilise la forme la plus simple, \sageplot{toto}, qui insère dans le document
l’image obtenue sous Sage par [Link]('[Link]').
Pour utiliser SageTeX, la procédure est donc la suivante :
— lancez LaTeX sur votre fichier .tex ;
— lancez Sage sur le fichier .sage produit pas LaTeX ;
— lancez LaTeX une seconde fois.
(Il n’est pas nécessaire de lancer Sage si vous recompilez un document LaTeX sans avoir modifié les commandes Sage
qu’il contient depuis la compilation précédente.)
SageTeX offre bien d’autres possibilités. Puisque Sage comme LaTeX sont des outils complexes et puissants, le mieux est
sans doute de consulter la documentation complète de SageTeX, qui se trouve dans SAGE_ROOT/venv/share/texmf/
tex/latex/sagetex.
Postface
151
Tutoriel Sage, Version 10.6
>>> 2^8
10
>>> 3^2
1
>>> 3**2
9
Cette utilisation de ^ peut paraître étrange et surtout inefficace pour une utilisation purement mathématique
puisque le ou exclusif n’est que rarement utilisé. Par commodité, Sage prétraite chaque ligne de commande avant
de la transmettre à Python, en remplaçant par exemple les apparitions de ^ (en dehors des chaînes de caractères)
par des ** :
sage: 2^8
256
sage: 3^2
9
sage: "3^2"
'3^2'
::
sage: 3^^2
1
sage: a = 2
sage: a ^^= 8
sage: a
10
sage: 2/3
2/3
sage: (2/3).parent()
Rational Field
sage: 2//3
0
— Entiers longs : Python possède nativement un support pour les entiers de précision arbitraire, en plus des int du
langage C. Les entiers longs Python sont significativement plus lents que ceux que GMP fournit et sont marqués
à l’affichage par un L qui les distingue des int (il est pas prévu de changer cela à court terme). Sage implémente
les entiers en précision arbitraire en utilisant la bibliothèque C GMP. Les entiers longs GMP utilisés par Sage
s’affichent sans le L.
Plutôt que de modifier l’interpréteur Python (comme l’ont fait certaines personnes pour leurs projets internes), nous uti-
lisons le langage Python exactement comme il est et rajoutons un pré-parseur pour IPython de sorte que la ligne de
commande de IPython se comporte comme l’attend un mathématicien. Ceci signifie que tout code Python existant peut
être utilisé sous Sage. Toutefois, il faut toujours respecter les règles standards de Python lorsque l’on écrit des packages à
importer dans Sage.
(Pour installer une bibliothèque Python, trouvée sur Internet par exemple, suivez les instructions mais exécutez sage
-python au lieu de python. La plupart du temps, ceci signifie concrètement qu’il faut taper sage -python setup.
py install.)
dans votre bibliographie (en remplaçant 8.7 par la version de Sage que vous avez utilisée). De plus, pensez à rechercher
les composants de Sage que vous avez utilisés pour vos calculs, par exemple PARI, GAP, Singular, Maxima et citez
également ces systèmes. Si vous vous demandez quel logiciel votre calcul utilise, n’hésitez pas à poser la question sur le
groupe Google sage-devel. Voir Polynômes univariés pour une discussion plus approfondie de ce point.
Si vous venez de lire d’une traite ce tutoriel et que vous avez une idée du temps qu’il vous a fallu pour le parcourir, merci
de nous le faire savoir sur le groupe Google sage-devel.
Amusez-vous bien avec Sage !
Annexe
Opérateur Description
or ou booléen
and et booléen
not négation booléenne
in, not in appartenance
is, is not test d’identité
>, <=, >, >=, ==, != comparaisons
+, - addition, soustraction
*, /, % multiplication, division, reste
**, ^ exponentiation
Ainsi, pour calculer 3^2*4 + 2%5, Sage « met les parenthèses » comme suit : ((3^2)*4) + (2%5). Il calcule donc
d’abord 3^2, ce qui fait 9, puis (3^2)*4 et 2%5, et enfin ajoute les valeurs de ces deux dernières expressions.
155
Tutoriel Sage, Version 10.6
Bibliographie
157
Tutoriel Sage, Version 10.6
Index et tables
— genindex
— modindex
— search
159
Tutoriel Sage, Version 10.6
161
Tutoriel Sage, Version 10.6
162 Bibliographie
Index
E
EDITOR, 95
V
variable d'environnement
EDITOR, 95
163