Séance 5#
Objectifs
Introduction à Sagemath
Calcul exact : entiers, rationnels, complexes
Notions sur le calcul symbolique
Notion de méthode et de classe
Sagemath#
Sagemath est un logiciel de calcul formel dont la syntaxe est celle du langage python. Les notions vues dans 4 premières séances de cours vous seront donc essentielles pour utiliser ce logiciel.
Sagemath peut être utilisé en ligne de commande (comme python), mais également dans un notebook Jupyter. C’est ce dernier choix qui a été effectué pour ce cours. Vous utiliserez donc le même environnement de travail que lors des 4 premières séances.
Note
Lorsque vous ouvrez un notebook Jupyter, pour vérifier que c’est bien le « noyau » Sagemath (et non python) qui est lancé, observez ce qui est indiqué en haut à droite de votre fichier.
Sagemath regroupe de nombreuses bibliothèques et de nombreux logiciels sous un même envrionnement. En particulier, les bibliothèques math, matplotlib et random de python sont déjà incluses dans Sagemath, et importées à son ouverture. Vous n’aurez donc pas besoin de les importer, ni de les mentionner.
print(randint(0, 1000))
883
Avertissement
Certaines de ces fonctions (par exemple, plot ou sqrt) ont été modifiées pour les simplifier, ou pour permettre d’accéder à d’autres fonctionnalités.
Par exemple, l’affichage graphique d’une liste de points ne se fera plus sous la forme suivante (qui provoque une erreur) :
X = [ i for i in range(12) ]
Y = [ 2*x-5 for x in X ]
plot(X, Y)
mais peut se faire sous la forme suivante :
points = [ (X[i],Y[i]) for i in range(len(X))]
list_plot(points)
Nous verrons ces subtilités dans une prochaine séance (ce n’est pas nécessaire de retenir la syntaxe ci-dessus pour l’instant).
Entiers#
Déclaration et manipulation élémentaire#
Avec Sagemath, on peut déclarer et utiliser les entiers comme en python.
a = 1
print(a)
1
x = 17
print(((x % 5)**123 + 3*x - 2)//8)
1329227995784915872903807060280344582
On peut également appliquer des fonctions externes sur ces entiers, par exemple la fonction gcd qui calcule un pgcd, ou la fonction xgcd qui calcule également les coefficients de Bezout. En revanche, contrairement à python, ces fonctions ne nécessitent pas d’import, elles sont directement incluses dans Sagemath.
gcd(12, 27)
3
xgcd(12, 27)
(3, -2, 1)
Remarque importante : Pour savoir comment utiliser une fonction, on peut s’aider de l’aide interactive de Sagemath. Pour cela, il faut taper le nom de la fonction suivi de ?. Une mini-fenêtre s’ouvre alors, avec l’aide (en anglais) associée à la fonction. Exemple (ne s’affiche pas sur la page web) :
xgcd?
Fonctions spécifiques à Sagemath#
Un avantage de Sagemath est qu’il contient une quantité importante de fonctions qui sont absentes de la bibliothèque math de python. Prenons l’exemple de la fonction factor, qui permet d’obtenir la factorisation d’un entier :
print(factor(12))
2^2 * 3
factor(1234567890)
2 * 3^2 * 5 * 3607 * 3803
On peut également penser à la fonction next_prime(a) qui retourne le plus petit nombre premier strictement supérieur à a :
next_prime(100)
101
Il existe beaucoup d’autres fonctions à appliquer directement sur des entiers… à vous de les chercher/tester !
Retour aux entiers : la classe Integer#
Un changement majeur entre python et sagemath provient de la manière dont les entiers sont créés et stockés. Leur type a changé : ce sont maintenant des objets provenant d’une classe appelée Integer.
type(a)
<class 'sage.rings.integer.Integer'>
Note
En informatique, la notion de classe permet de représenter une catégorie d’objets ayant des attributs, des propriétés ou des méthodes (au sens de fonction applicable à un objet) en commun. La classe est une sorte de « moule » dans lequel on peut créer des objets similares, qu’on appelle instances de classe.
La classe Integer est donc le « moule » des entiers, et elle attache à ses objets (les entiers) de nombreuses propriétés et fonctions. On peut s’en apercevoir en tapant a.<Tab> après avoir créé un entier a. Sagemath va alors lister tous les attributs de a et toutes les méthodes que l’on peut lui appliquer. Exemple :
a = 12
# a.<Tab>
Note
Cette technique vous sera très utile, pour retrouver le nom d’une méthode, ou pour compléter automatiquement (et correctement !) un nom de méthode déjà entamé.
Pour des raisons de commodité, Sagemath a créé des fonctions du même nom que certaines méthodes de la classe Integer. L’intérêt est de pouvoir les appliquer directement sur l’écriture entière, sans passer par une variable. Par exemple, l’instruction factorial(4) existe et a le même comportement que a.factorial() où la variable a a été assignée à la valeur \(4\).
Autre exemple : on obtient le coefficient binomial \(\binom{n}{k}\) par l’appel à la fonction binomial(n, k), mais également par l’utilisation de la méthode de classe n.binomial(k) :
n = 5
k = 2
print(n.binomial(k))
print(binomial(n, k))
10
10
Néanmoins, si ces « raccourcis » sont assez fréquents pour les entiers, ils le seront beaucoup moins pour les objets que nous verrons par la suite. Retenez-donc plutôt l’approche par méthode de classe.
Tableau récapitulatif des méthodes ou fonctions sur les entiers :
Méthode (où |
Description |
Syntaxe équivalente |
|---|---|---|
|
Calcule \(n!\), la factorielle de l’entier \(n\). |
|
|
Calcule le coefficient binomial \(\binom{n}{k}\). |
|
|
Retourne le pgcd de la paire \((n, k)\). |
|
|
Retourne le triplet formé du pgcd et des coefficients de Bezout de la paire \((n, k)\). |
|
|
Calcule la paire (quotient, reste) de la division euclidienne de \(n\) par \(k\). |
|
|
Calcule l’inverse de \(n\) modulo \(k\). |
|
|
Teste si l’entier \(n\) est divisible par \(k\). |
|
|
Teste si \(n\) est premier. |
|
|
Teste si \(n\) est un carré parfait. |
|
|
Retourne la factorisation de \(n\). |
|
|
Retourne la liste des diviseurs de \(n\). |
|
|
Retourne la liste des coefficients de la décomposition binaire de \(n\) (en commençant par le bit de poids faible). |
pas d’équivalent direct |
Quelques exemples :
n = 9
print(n.factorial())
print(n.divides(36))
print(n.is_prime())
print(n.is_square())
print(n.inverse_mod(17))
print(n.quo_rem(4))
362880
True
False
True
2
(2, 1)
Observons ici que Sagemath n’est pas gêné pour le calcul d’entiers de taille importante.
m = 100
print(m.factorial())
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Notion de classe parente#
Pour finir, Sagemath permet de manipuler non seulement les entiers, mais également l’ensemble des entiers, vus comme une structure algébrique (on sait que cet ensemble a une structure d’anneau).
La variable ZZ a été prédéfinie dans Sagemath pour stocker cet anneau. L’instruction IntegerRing() permet aussi d’y accéder.
ZZ
Integer Ring
Sagemath a donc lié les entiers à leur anneau par une relation de parenté : l’anneau ZZ est un parent de tout objet de la classe Integer. C’est une manière de représenter la relation d’appartenance à une structure.
Pour observer cela, on peut demander à Sagemath le parent d’un entier a quelconque, ou simplement tester l’appartenance de a à l’objet ZZ :
a = -2
print(a.parent())
print(a in ZZ)
Integer Ring
True
Nombres rationnels#
Création et classes associées#
Contrairement à python, Sagemath permet de stocker des nombres rationnels sous forme exacte et réduite. Si a et b sont deux entiers, alors le rationnel \(\frac{a}{b}\) peut être construit avec a/b.
x = 4/6
x
2/3
Avertissement
L’opérateur / a donc un comportement différent sous Sagemath et sous python !
Un rationnel est un élément de la classe Rational.
print(type(x))
<class 'sage.rings.rational.Rational'>
Sa classe parente est le corps des rationnels, affiché Rational Field, à laquelle on accède par la variable prédéfinie QQ ou par le constructeur RationalField().
print(parent(x))
print(x in QQ)
Rational Field
True
Opérations élémentaires#
On peut effectuer des opérations élémentaires sur les rationnels, et ce, avec les mêmes opérateurs que sur les entiers :
x = 2/3
print(x + 1/2)
print(3*x)
print(x**2)
print(-3/x)
7/6
2
4/9
-9/2
Comme pour les entiers, il existe des méthodes à appliquer aux rationnels. Par exemple, on peut accéder au numérateur et au dénominateur de la fraction réduite :
a = 4/-6
p = a.numerator()
q = a.denominator()
print(p)
print(q)
-2
3
On observe que le numérateur et le dénominateur sont des objets de la classe Integer :
print(type(p))
print(isinstance(p, Integer)) # teste si p est une instance de la classe Integer
<class 'sage.rings.integer.Integer'>
True
Conversion de type#
Enfin, il peut être utile de convertir un objet de la classe Rational en un objet de la class Integer. On parle de coercion.
Attention, ce n’est pas un arrondi : on transfère les informations d’une classe à une autre, autrement dit, on transforme simplement le type de l’objet.
Dans l’exemple suivant, la variable b contient la valeur \(1\), vue comme un rationnel :
a = 1/3
b = a + 2/3
print(b)
print(isinstance(b, Rational))
print(isinstance(b, Integer))
1
True
False
On peut ensuite la convertir en un entier :
c = Integer(b)
print(c)
print(isinstance(c, Integer))
print(b == c)
1
True
True
Bien entendu, pour être effective, cette conversion doit être possible, sinon on obtient une erreur :
x = 1/3
y = Integer(x)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_116844/2720979961.py in <module>
1 x = Integer(1)/Integer(3)
----> 2 y = Integer(x)
/usr/lib/python3/dist-packages/sage/rings/integer.pyx in sage.rings.integer.Integer.__init__ (build/cythonized/sage/rings/integer.c:5816)()
656 otmp = getattr(x, "_integer_", None)
657 if otmp is not None:
--> 658 set_from_Integer(self, otmp(the_integer_ring))
659 return
660
/usr/lib/python3/dist-packages/sage/rings/rational.pyx in sage.rings.rational.Rational._integer_ (build/cythonized/sage/rings/rational.cpp:24315)()
2969 """
2970 if not mpz_cmp_si(mpq_denref(self.value), 1) == 0:
-> 2971 raise TypeError("no conversion of this rational to integer")
2972 cdef Integer n = Integer.__new__(Integer)
2973 n.set_from_mpz(mpq_numref(self.value))
TypeError: no conversion of this rational to integer
Tableau récapitulatif des méthodes ou fonctions sur les rationnels :
Méthode (où |
Description |
|---|---|
|
Retourne de dénominateur de \(r \in \mathbb{Q}\) |
|
Retourne de numérateur de \(r \in \mathbb{Q}\) |
Nombres complexes#
Dans Sagemath, on peut également manipuler des nombres complexes sous une forme exacte. Pour cela, il suffit d’avoir accès à une variable qui stocke \(i\), le nombre imaginaire pur. Dans Sagemath, c’est la variable prédéfinie I.
print(I)
print(I**2)
I
-1
La classe parente de la variable prédéfinie I a varié suivant les versions de Sagemath, et peut vous paraître obscure pour certaines (« corps de nombres défini par le polynôme \(x^2+1\) » pour la version 10.1), mais pourra peut-être s’expliquer dans vos prochaines années d’études en mathématiques.
print(parent(I))
Number Field in I with defining polynomial x^2 + 1 with I = 1*I
Avertissement
Il faut donc faire attention à ne jamais écraser la variable I !
Opérations élémentaires#
On peut effectuer des opérations élémnentaires sur les complexes d’une manière similaire à celles faites sur les entiers ou les rationnels.
x = 3 - I/2
print(I * (x - 1))
print(x**2)
print(x / (2 + I))
2*I + 1/2
-3*I + 35/4
-4/5*I + 11/10
Certaines méthodes permettent d’accéder à la partie réelle, la partie imaginaire, le conjugué et le module (au carré ou non) d’un nombre complexe.
z = 1 - 2*I
print(z.real_part())
print(z.imag_part())
print(z.conjugate())
print(z.norm())
print(z.abs())
1
-2
2*I + 1
5
2.23606797749979
Enfin, on peut accéder à l’argument principal d’un nombre complexe \(z\) grâce à la fonction arg. Il n’existe pas de méthode équivalente, car la classe parente I manipule aussi des éléments qui n’ont pas d’argument.
print(arg(z))
-arctan(2)
Tableau récapitulatif des méthodes ou fonctions sur les rationnels :
Méthode ou fonction |
Description |
|---|---|
|
Retourne la partie réelle de \(z\). |
|
Retourne la partie imaginaire de \(z\). |
|
Retourne la conjugué complexe de \(z\). |
|
Retourne le module au carré de \(z\). |
|
Retourne le module de \(z\). |
|
Retourne l’argument de \(z\). |
Fonctions et constantes classiques#
Sagemath permet la manipulation exacte de fonctions et de constantes classiques en mathématiques. Pour cela, certains de ces objets doivent être vus de manière symbolique (et non numérique).
Prenons l’exemple de la fonction sinus et de la constante \(\pi\). Lorsqu’on demande la valeur de \(\sin(\pi)\) à Sagemath, aucun calcul numérique n’est effectué ; simplement, on applique les propriétés symboliques de ces objets, parmi lesquelles on retrouve le fait que \(\sin(\pi)\) vaut exactement \(0\).
sin(pi)
0
De la même manière, \(\sqrt{2}\) n’est pas stockée comme sa valeur approchée \(1.414...\) mais comme le nombre positif qui, lorsqu’il est élevé au carré, donne \(2\).
a = sqrt(2)
print(a)
print(a**2)
sqrt(2)
2
On peut d’ailleurs remarquer que la classe parente de tous ces nombres (\(\pi\), \(e\), \(\zeta(3)\), \(\sqrt{2}\), etc.) est Symbolic Ring. Cela signifie qu’on manipule bien des expressions symboliques, qui ne sont donc pas des valeurs numériques.
print(a.parent())
Symbolic Ring
Nous verrons dans une séance future les subtilités de cette distinction. Gardons néanmoins en mémoire la particularité suivante. Grâce à ces expessions symboliques (et donc, contrairement à la bibliothèque standard de python), Sagemath sait que certaines fonctions ne sont pas définies en des points singuliers. Par exemple :
tan(pi/2)
Infinity
Pour finir, voici une liste de fonctions courantes en mathématiques (il en manque certainement, n’hésitez pas à chercher ou demander !).
Tableau récapitulatif de fonctions ou objets symboliques dans Sagemath.
Fonction ou objet |
Description |
|---|---|
|
Exponentielle et logarithme de \(x\) en base \(b\). |
|
Exponentielle et logarithme de \(x\) en base \(e\). |
|
Sinus, cosinus et tangente de \(t\). |
|
Arcsinus, arccosinus et arctangente de \(y\). |
|
Racine carrée et puissance rationnelle \((p/q)\)-ème de \(x\). |
|
Nombres \(\pi\), \(e\) et \(i\). |