Un bref tutoriel pour SageMath

  • L'objectif de ce tutoriel est de donner un bref aperçu du fonctionnement du logiciel SageMath. On y présente principalement les points suivants

Pour plus de détails on pourra consulter les liens présents dans ce tutoriel, consulter le tutoriel officiel (https://doc.sagemath.org/html/fr/tutorial/index.html) ou le livre très complet de Calculs mathématiques avec Sage(http://dl.lateralis.org/public/sagebook/sagebook-web-20130530.pdf). Pour accéder à la documentation d'une fonction spécifique on peut directement utiliser la commande $\mathtt{help}$

In [1]:
help(max)
Help on built-in function max in module __builtin__:

max(...)
    max(iterable[, key=func]) -> value
    max(a, b, c, ...[, key=func]) -> value
    
    With a single iterable argument, return its largest item.
    With two or more arguments, return the largest argument.

  • Pour utiliser SageMath il y a principalement deux options. La première est d'utiliser la version en ligne (https://cloud.sagemath.com) qui nécessite simplement la création d'un compte avec une adresse mail. Sinon, SageMath est installé sur les machines du département sur la partition Linux. Dans un terminal, taper la commande $\mathtt{sage}$. L'utilisation du terminal étant peu pratique, on recommandera alors d'utiliser la commande $\mathtt{notebook()}$ qui permet d'ouvrir un éditeur en local.
  • SageMath fonctionne avec le langage Python. Il est donc nécessaire de respecter l'indentation !

Affectations et calculs élémentaires

  • On affecte un objet directement avec le symbole $=$ mais l'affectation ne réalise aucun affichage. Pour cela on peut simplement entrer le nom de l'objet ou utiliser la commande $\mathtt{show}$
In [2]:
a = 2
a+1
Out[2]:
3
In [3]:
show(a+1)

La commande $\mathtt{show}$ peut être utilisé pour des éléments de types différents.

In [4]:
show('a+1 = ', a+1)
  • Les opérations élémentaires sont implémentés avec les symboles usuels $+$, $-$, $*$, $/$. Le calcul de puissances (de nombres ou de matrices) se fait avec le symbole $^$ ou $**$.
In [5]:
2^10
Out[5]:
1024
  • La structure de liste est définie par des crochets, les éléments étant séparés par des virgules. Le premier élément est celui d'indice $0$.
In [6]:
A = [0,1,2]
show('Le deuxième élément est : ', A[1])

On peut utiliser le symbole $\mathtt{..}$ pour définir une liste.

In [7]:
B = [1..4]
B
Out[7]:
[1, 2, 3, 4]

Pour concaténer deux listes on en fait la somme.

In [8]:
B+[5]
Out[8]:
[1, 2, 3, 4, 5]

Pour plus d'informations sur la création, la manipulation et les opérations possibles pour une liste on pourra consulter la page http://sagemath.wikispaces.com/Lists

  • Pour obtenir une approximation numérique d'un nombre on utilise la commande suivante
In [9]:
x=2534/4518
show(x)
x.n()
Out[9]:
0.560867640548915

ou celle-ci si l'on veut préciser le nombre de chiffres à afficher

In [10]:
pi.n(digits=3)
Out[10]:
3.14

Procédures

  • En plus de l'indentation il faut terminer une instruction par le symbole $\mathtt{:}$
    Ceci est valable pour la définition de procédures, pour les tests, pour les boucles etc...


Le constructeur pour définir une procédure est $\mathtt{def}$ suivi du nom de la procédure puis des arguments entre parenthèses (si la procédure ne prend pas d'argument en entrée on indique $\mathtt{(}$ $\mathtt{)}$). On n'oubliera pas non plus de terminer l'instruction par $\mathtt{:}$.

In [11]:
def f(x):
    return 2*x+1

f(0)
Out[11]:
1

Pour appliquer une fonction à une liste on peut utiliser l'une des deux écritures ci-dessous

In [12]:
A = [0,1,2,3]

def carre(x):
    return x^2

B = [carre(w) for w in A]    # Le fonctionnement de l'instruction for est détaillé au paragraphe suivant
show('B=',B)
C = map(carre,A)
show('C=',C)

Un exemple plus complet de procédure est donné dans le paragraphe 'Tests et boucles'.

Tests et boucles

Tests

  • Les connecteurs logiques s'écrivent en toutes lettres : $\mathtt{and}$, $\mathtt{or}$ etc...
In [13]:
True and False
Out[13]:
False
In [14]:
True or False
Out[14]:
True
In [15]:
if True:
    print('le test est verifie')
le test est verifie
  • Le test d'égalité s'effectue avec le symbole $\mathtt{==}$ et le test de différence avec le symbole $\mathtt{!=}$.
In [16]:
a = 2
a != 3
Out[16]:
True

On peut tester des doubles inégalités sans utiliser directement le constructeur $\mathtt{and}$.

In [17]:
i = 4
1 < i < 10
Out[17]:
True
  • Pour les tests les différents constructeurs sont $\mathtt{if}$, $\mathtt{else}$ et $\mathtt{elif}$ pour tester une autre condition. Dans l'exemple ci-dessous on construit une fonction qui renvoit True si l'argument est $1$, False si l'argument est $0$ et un message d'erreur sinon.
In [18]:
def Booleen (b):
    if b==0:
        return False
    elif b==1:
        return True
    else:
        print('argument non admissible')
        
Booleen(0) or Booleen(1)
Out[18]:
True

Boucles

  • Les boucles sont bien évidemment implémentées avec les constructeurs $\mathtt{while}$ et $\mathtt{for}$.
In [19]:
i=0
while i<= 2:
    i=i+1
i
Out[19]:
3
  • Pour la boucle $\mathtt{for}$ on peut utiliser l'instruction $\mathtt{range(n)}$ qui renvoit la liste des $n$ premiers entiers (indexé à partir de $0$). On a donc $\mathtt{range(n) = [0..n-1]}$.
In [20]:
n = 3
show(range(n))
for i in range(n):
    print(i)
0
1
2

Pour l'instruction $\mathtt{range}$ on peut spécifier un autre indice de départ, un autre indice de fin ainsi que le pas. De même, pour l'instruction $\mathtt{..}$.

In [21]:
show(range(0,11,2))
show(range(5,1,-1))
show([0..11,step=2])
show([5..1,step=-1])

Cependant on peut faire parcourir à l'indice n'importe quelle liste donnée dans l'instruction (sans que cette liste soit spécifiquement à valeurs entières ni même tous du même type).

In [22]:
TableauTest = ['t','e','s','t', 2+2]
for i in TableauTest:
    print(i)
t
e
s
t
4

L'utilisation de boucles $\mathtt{for}$ est très utile pour travailler avec les listes.

In [23]:
# Création d'une liste de 0 de taille 5
L = [0 for j in range(5)]
show(L)
# Parcours d'une liste de couples et récupération de la liste des premières composantes de chaque couple
L2 = [(0,1),(2,3),(4,5),(6,7)]
show('Liste complète ' , L2)
L2extrait = [l[0] for l in L2]
show('Liste des premières composantes ', L2extrait)

Algèbre linéaire

Vecteurs

  • Pour définir un vecteur et accéder (ou modifier un élément) on utilise les commandes suivantes
In [24]:
A = vector([0,1,2])
A[1]=3
A
Out[24]:
(0, 3, 2)

On notera qu'un vecteur est affiché avec des parenthèses et non des crochets comme pour une liste. Ce ne sont donc pas les mêmes objets.

In [25]:
B= [0,3,2]
show(A)
show(B)
A == B
Out[25]:
False

Lorsqu'un vecteur est principalement composé de zéros on peut utiliserpar exemple la commande $\mathtt{vector({3:1,5:10})}$ qui crée un vecteur composé uniquement de zéros sauf un $3$ dans la case numéro $1$ et un $5$ dans la case numéro $10$. La taille du vecteur est donnée par la position du dernier élément non nul spécifié.

In [26]:
vector({1:3,10:5})
Out[26]:
(0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 5)
  • Il faut faire attention au fait qu'un vecteur contient des éléments qui sont tous du même type (entiers, rationnels, réels). On ne peut pas changer le type d'éléments dans un vecteur. Le type est celui déclaré initialement. Par exemple, le vecteur $\mathtt{vector([0,1,2])}$ est un vecteur d'entiers : on ne peut donc pas remplacer une valeur par autre chose que des entiers.
In [27]:
A = vector([0,1,2])
A[1] = 3
show(A)
A[1] = 1/4
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-27-d00b82252a56> in <module>()
      2 A[Integer(1)] = Integer(3)
      3 show(A)
----> 4 A[Integer(1)] = Integer(1)/Integer(4)

/projects/sage/sage-7.5/src/sage/modules/free_module_element.pyx in sage.modules.free_module_element.FreeModuleElement.__setitem__ (/projects/sage/sage-7.5/src/build/cythonized/sage/modules/free_module_element.c:13792)()
   1826             if n < 0 or n >= d:
   1827                 raise IndexError("vector index out of range")
-> 1828             self.set_unsafe(n, R(value))
   1829 
   1830     cdef int set_unsafe(self, Py_ssize_t i, value) except -1:

/projects/sage/sage-7.5/src/sage/structure/parent.pyx in sage.structure.parent.Parent.__call__ (/projects/sage/sage-7.5/src/build/cythonized/sage/structure/parent.c:9852)()
    953         if mor is not None:
    954             if no_extra_args:
--> 955                 return mor._call_(x)
    956             else:
    957                 return mor._call_with_args(x, args, kwds)

/projects/sage/sage-7.5/src/sage/rings/rational.pyx in sage.rings.rational.Q_to_Z._call_ (/projects/sage/sage-7.5/src/build/cythonized/sage/rings/rational.c:33031)()
   3911         """
   3912         if not mpz_cmp_si(mpq_denref((<Rational>x).value), 1) == 0:
-> 3913             raise TypeError("no conversion of this rational to integer")
   3914         cdef integer.Integer n
   3915         n = <integer.Integer>PY_NEW(integer.Integer)

TypeError: no conversion of this rational to integer

On peut par contre spécifier au départ le type. La commande $\mathtt{vector(ZZ,[0,1,2])}$ permet d'indiquer que ce vecteur pourra contenir des entiers (non nécessairement positifs). La commande $\mathtt{vector(QQ,[0,1,2])}$ permet d'indiquer que ce vecteur pourra contenir des rationnels. La commande $\mathtt{vector(RR,[0,1,2])}$ permet d'indiquer que ce vecteur pourra contenir des réels.

In [28]:
show(vector([0,1,2]))
show(vector(RR,[0,1,2]))

A = vector(QQ,[0,1,2])
A[1] = 1/4
A
Out[28]:
(0, 1/4, 2)

Matrices

  • Pour définir une matrice on peut utiliser l'une des implémentations suivantes
In [29]:
A = matrix([[1,0],[0,1]])
A
Out[29]:
[1 0]
[0 1]
In [30]:
B = matrix(2,2,[1,0,0,1])  # les deux premiers arguments sont le nombre de lignes et le nombre de colonnes
B
Out[30]:
[1 0]
[0 1]
  • Les opérations sur les matrices et les vecteurs sont implémentées avec les symboles usuels $+$, $-$, $*$, $/$, $^$.
In [31]:
M = matrix([[1,2],[3,4]])
b = vector([2,1])
M*b
Out[31]:
(4, 10)
  • Pour calculer l'inverse d'une matrice on peut utiliser la puissance $-1$
In [32]:
show(M^(-1))
show(M*M^(-1))
  • Accéder à un élément d'une matrice se fait comme pour une liste : $M[i]$ correspond à la ligne numéro $i$. On accède au coefficient de la ligne $i$ et de la colonne $j$ par la commande $M[i,j]$ (on peut aussi y accéder par la commande $M[i][j]$ mais elle ne permet pas ensuite de modifier cet élément, on préférera donc $M[i,j]$).
In [33]:
show(M[0])
show(M[0][1])
  • De même que pour les vecteurs il faut faire attention au type des éléments d'une matrice.
In [34]:
show(matrix(QQ,[[1/2,1/4],[2,1/10]]))
show(matrix(RR,[[1/2,1/4],[2,1/10]]))

Un certain nombre de fonctions sont implémentées dans $\mathtt{Sage}$ pour calculer les valeurs propres, vecteurs propres, déterminant etc... On pourra par exemple se reporter au document https://perso.univ-rennes1.fr/gwezheneg.robert/sage-long.pdf

Systèmes linéaires

Pour résoudre un système linéaire on peut utiliser deux méthodes : implémenter directement le système linéaire ou utiliser la matrice associée. On présente ici les deux méthodes de résolution sur le système \begin{equation} \left{ \begin{aligned} & 2x + y = 0 \ & x - y = 1 \end{aligned} \right. \end{equation}

  • Pour résoudre un système linéaire il faut déclarer les variables, déclarer les équations et enfin résoudre le système.
In [35]:
x = var('x')                # ainsi la variable x est connue et l'on peut donc l'utiliser dans la suite
y = var('y')
eq1 = 2*x + y == 0
eq2 = x - y == 1
solve([eq1, eq2],x,y)       # on spécifie d'abord les équations puis les variables
Out[35]:
[[x == (1/3), y == (-2/3)]]
  • Pour la deuxième méthode, on commence par définir la matrice associée au système ainsi que le vecteur correspondant au second membre. On utilise la commande $\mathtt{\backslash}$ pour résoudre l'équation.
In [36]:
M = matrix([[2,1],[1,-1]])
b = vector([0,1])
M\b                         # M\b est la solution x de M*x=b soit x = M^(-1)*b
Out[36]:
(1/3, -2/3)

Tracer des graphiques

  • Pour tracer la courbe d'une fonction donnée, la commande est $\mathtt{plot}$. On donne le nom de la fonction et les valeurs minimales et maximales des abscisses à tracer.
In [37]:
x = var('x')
f(x) = x^2
plot(f,-3,3)
Out[37]:

Pour connaitre les différences entre les différentes définitions possibles des fonctions on pourra consulter http://doc.sagemath.org/html/fr/tutorial/tour_functions.html

In [38]:
pc = plot(cos,0,pi,rgbcolor=(1,0,0),legend_label='un morceau de la courbe de $\cos$')
pc += plot(cos,pi,2*pi,linestyle='--',rgbcolor=(1,0,1))
ps = plot(sin, 0,2*pi, rgbcolor='blue',legend_label='La fonction $x \mapsto \sin(x)$')

pc+ps
Out[38]:
  • L'autre grande famille de tracés est celle où l'on ne trace plus les valeurs d'une fonction connue en tout points mais seulement en un certain nombre de points. Par exemple, si l'on souhaite tracer une courbe passant par les points de coordonnées $(0,0)$, $(1,2)$ et $(2,0)$ on utilise la fonction $\mathtt{line}$.
In [39]:
line([(0,0),(1,2),(2,0)])
Out[39]:

Si l'on souhaite afficher uniquement les points sans les relier, on préférera la commande $\mathtt{point}$.

In [40]:
point([(0,0),(1,2),(2,0)])
Out[40]:

Si l'on connait d'une part la liste des abscisses et d'autre part la liste des ordonnées alors la fonction $\mathtt{zip}$ permet de créer la liste des couples adéquate.

In [41]:
x = [0,1,2]
y = [0,2,0]
show(zip(x,y))
line(zip(x,y))+point(zip(x,y),rgbcolor= 'red')
Out[41]: