Python pour le calcul scientifique/Manipulation de matrices

Un livre de Wikilivres.
Sauter à la navigation Sauter à la recherche

Les matrices sont un élément primordial du calcul scientifique sur ordinateur pour deux raisons :

  1. L'algèbre linéaire est au cœur de nombreux calculs.
  2. Les matrices sont l'élément de base du calcul vectorisé qui permet un gain de temps appréciable.

Pour pouvoir expliter les matrices, il faut charger le module NumPy ; nous utilisons également Matplotlib pour les graphiques. Ainsi, les programmes contiennent tous au début :

import numpy as np
import matplotlib.pyplot as plt

Définir un tenseur[modifier | modifier le wikicode]

Un tenseur est similaire à une liste mais il est défini par la fonction np.array(). La définition et l'extraction de composante utilise la méthode du découpage en tranches (slicing).

Exemples

a = np.array([1, 3, 5, 7]) # vecteur
bc = np.array([[1], [2], [3], [4]]) # matrice 4 × 1 (matrice colonne)
bl = np.array([[1, 2, 3, 4]]) # matrice 1 × 4 (matrice ligne)
c = np.array([[1, 2, 3],
              [2, 3, 4],
              [3, 4, 5]]) # matrice 3 × 3
d = np.array([[[1,  2, 3],
               [2,  3, 4]],
              [[10, 9, 8],
               [ 7, 6, 5]]]) # tenseur d'ordre 3, de dimension 3 × 2 × 2

Notez que dans NumPy, un vecteur n'est pas la même chose qu'une matrice ligne ou colonne. Un vecteur de dimension n est un tenseur d'ordre 1 et de dimension n ; une matrice ligne ou colonne est un tenseur d'ordre 2 et de dimension 1 × n ou n × 1.

a = np.array([1, 2, 3])
b = np.array([[1, 2, 3]])
c = np.array([[1], [2], [3]])
print(a.size, b.size, c.size) # 3 3 3
print(a.ndim, b.ndim, c.ndim) # 1 2 2
print(a.shape, b.shape, c.shape) # (3,) (1, 3) (3, 1)

La fonction np.arange() est similaire à la fonction range() pour les liste ; elle génère un vecteur de réels. La fonction np.linspace() permet également de créer un vecteur de même type mais on indique le dernier nombre alors que la règle du découpage en tranches fait que le nombre maximal indiqué à np.arange() est le premier nombre qui ne figure pas dans le vecteur.). La fonction np.zeros() génère une matrice nulle, np.zeros_like() une matrice nulle ayant les dimensions d'une matrice fournie comme modèle. De même, np.ones() et np.ones_like() crée des matrice dont toutes les composantes sont à 1. La fonction np.eye() crée une matrice unité.

Exemples

e = np.arange(0, 2, 0.1) # vecteur [0, 0.1, 0.2…, 1.8, 1.9]
f = np.linspace(0, 2, 5) # 5 nombre entre 0 et 2 soit le vecteur [0, 0.5, 1, 1.5, 2]
g = np.zeros(3) # vecteur nul de dimension 3
h = np.zeros((3, 3)) # matrice nulle 3 × 3
k = np.ones_like(a) # matrice de 1 de même dimension que a 
u = np.eye(3) # matrice unité 3 × 3

Le paramètre dtype permet de forcer le type. Par exemple

a = np.array([1, 2, 3], dtype="complex")
k = np.ones_like(a, dtype="int")

La méthode .reshape() remet en forme une matrice. Par exemple, pour transformer un vecteur de dimension 9 en une matrice 3 × 3 :

a = np.arange(1, 10)
b = a.reshape(3, 3)
# ou bien directement
c = np.arange(1, 10).reshape(3, 3)

La méthode .fill() remplit la matrice avec un scalaire :

b.fill(5) # remplace les valeurs de b par la valeur 5

Calcul vectorisé[modifier | modifier le wikicode]

Les fonctions de NumPy traitent en général les matrices en entier. Ainsi, il n'est pas nécessaire de créer une boucle pour faire défiler les indices un par un. Il en résulte un code clair et compact et surtout un plus grande rapidité d'exécution. Par exemple :

x = np.linspace(0, 2*np.pi, 50) # 50 points entre 0 et 2π
y = np.sin(x)
plt.plot(x, y)

La variable x est un vecteur de 50 valeurs et il est traité en une seule passe par la fonction sinus np.sin().

Outre le tranchage (slicing), on peut utiliser deux autres méthodes pour extraire certaines valeurs d'une matrice :

  • utiliser un vecteur ou une matrice d'indices, Python extrait alors les valeurs correspondant aux indices ;
  • utiliser un vecteur ou une matrice de booléens de même dimension que a matrice ; Python extrait alors les valeurs correspondant aux True, la matrice booléenne est un « masque » pour la matrice d'origine. Par exemple :
a = np.arange(0, 10)
b = np.array([1, 3, 5, 7, 9])
c = np.array([True, True, False, False, True, False, True, False, False, True])
print(a[b], "\n", a[c])

Exercice

Écrire un programme Python mettant en œuvre le crible d'Érathostène pour trouver les nombres premiers inférieurs à une valeur donnée.

Attributs[modifier | modifier le wikicode]

La classe ndarray, qui définit les matrices, possède un certain nombre d'attributs :

  • .shape : dimensions de la matrice ;
  • .ndim : ordre du tenseur ;
  • .size : nombre d'éléments ;
  • .dtype : type des éléments.
a = np.linspace(1, 9, 9)
print("a", a, "\n",
    " ; shape :", a.shape,
    " ; dim : ", a.ndim,
    " ; size : ", a.size,
    " ; dtype : ", a.dtype, "\n")
  • .real, .imag : parties réelle et imaginaire de la matrice ;
  • .flat : liste des éléments de la matrice ; les éléments sont réorganisés en une liste ;
  • .T : transposée.
a = np.arange(0, 9).reshape(3, 3)
print(a)
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]] 
print(a.T)
# [[0 3 6]
#  [1 4 7]
#  [2 5 8]] 
print(a.flat[:])
# array([0, 1, 2, 3, 4, 5, 6, 7, 8])
Ressources
Section « Attribute », numpy.ndarray sur Numpy and Scipy Documentation. Consulté le 2019-03-16

Fonctions et méthodes de base[modifier | modifier le wikicode]

La classe ndarray possède un certain nombre de méthodes :

  • .min() et max() : valeurs respectivement minimale et maximale ;
  • .ptp() : amplitude « max – min » (peak to peak) ;
  • .argmin() et argmax() : indice où se trouvent les valeurs respectivement minimale et maximale ;
  • .sum(), prod() : somme et produit de tous les éléments de la matrice ;
  • .cumsum(), cumprod() : somme et produit cumulés.
a = np.linspace(1, 9, 9)
print("min : ", a.min(),
    "; max : ", a.max(), "\n",
    "sum : ", a.sum(),
    "; cumsum : ", a.cumsum(), "\n",
    "prod : ", a.prod(),
    "; cumprod : ", a.cumprod(), "\n")

Méthodes statistiques :

  • .mean() : moyenne ;
  • .std() : écart type (standard deviation).

Extraction de données :

  • .diagonal() : vecteur contenant les éléments de la diagonale ;
  • .flatten() : vecteur contenant les éléments réorganisés en liste ; par rapport à l'attribut .flat, on peut choisir le sens de linéarisation (par lignes, .flatten(C), ou par colonnes, .flatten(F)) mais cela crée une copie, on ne peut pas par exemple s'en servir pour modifier la matrice ;
  • .tofile() : crée un fichier texte contenant les valeurs de la matrice ; par exemple, pour une matrice a et pour séparer les valeurs par un point-virgule :
a.tofile("matriceA.txt", sep=" ; ")

Algèbre linéaire :

  • a.dot(b) : produit matriciel ab ; on peut aussi écrire a@b ;
  • .trace() : trace de la matrice (somme des éléménts diagonaux) ;
  • .transpose() : transpose la matrice, résultat similaire à l'attribut .T.

Matrices de booléens :

  • .all() : applique un « et » logique à toutes les valeurs de la matrice ;
  • .any() : applique un « ou » logique à toutes les valeurs de la matrice.

Autre méthodes :

  • .conj() : conjugué des valeurs complexes ;
  • .nonzero() : n-uplet contenant les indices des valeurs non-nulles ;
  • .round(n) : arrondit les valeurs à la n-ième décimale.
Ressources
Section « Method », numpy.ndarray sur Numpy and Scipy Documentation. Consulté le 2019-03-16

Propagation[modifier | modifier le wikicode]

Le terme « propagation » (broadcasting) désigne la manière dont Python complète les matrice lorsque des dimensions manquent.

Supposons que l'on veuille additionner deux matrices M1 et M2 de dimensions m1 × n1 et m2 × n2 différentes. Alors :

  • le résultat a pour dimension max(m1, m2) × max(n1, n2) ;
  • si une des dimensions vaut 1, alors les valeurs de l'autre dimension sont dupliquées ;
  • sinon, les dimensions manquantes pour chaque matrice sont complétées par des 1.

Par exemples :

La matrice (5) est de dimension 1 × 1, la valeur « 5 » est donc répétée dans les deux dimensions
A = np.array([[1, 2], [3, 4]])
print(5 + A)
# [[6 7]
#  [7 8]]
print(np.array([[5, 4]]) + A)
# [[6 6]
#  [6 8]]
print(np.array([[5], [4]]) + A)
# [[6 7]
#  [7 8]]

Fonctions « universelles »[modifier | modifier le wikicode]

Les fonctions universelles (ufunc) sont les fonctions s'appliquant aux matrices, des fonctions vectorisées.

Ressource
Available ufuncs sur SciPy documentation. Consulté le 2019-03-21

Notes et références[modifier | modifier le wikicode]


Graphiques < > Polynômes