Les matrices sont un élément primordial du calcul scientifique sur ordinateur pour deux raisons :
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
Rappels et complément sur le tranchage.
Soit une liste L composée de "n" éléments.
Ainsi, codice_6 va extraire le premier élément, codice_7 va extraire tous les éléments sauf le premier et le dernier.
NumPy fournit des fonctions permettant de manipuler les matrices :
Définir un tenseur.
Un tenseur est similaire à une liste mais il est défini par la fonction codice_17. La définition et l'extraction de composante utilise la méthode du découpage en tranches "()".
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 codice_18 est similaire à la fonction codice_19 pour les liste ; elle génère un vecteur de réels. La fonction codice_20 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é à codice_18 est le premier nombre qui ne "figure pas" dans le vecteur.). La fonction codice_22 génère une matrice nulle, codice_23 une matrice nulle ayant les dimensions d'une matrice fournie comme modèle. De même, codice_24 et codice_25 crée des matrices, dont toutes les composantes sont à 1. La fonction codice_26 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 nombres 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 codice_27 permet de forcer le type. Par exemple
a = np.array([1, 2, 3], dtype="complex")
k = np.ones_like(a, dtype="int")
La commande codice_20 peut créer des matrices colonne : on donne la première et la dernière ligne ; par exemple : :
np.linspace([1, -1], [10, -10], 4)
Les commandes codice_29 et codice_29 fonctionnent comme codice_20, mais avec une progression logarithmique. La commande codice_32 crée un vecteur (ou une matrice colonne) allant de "a" à "b" alors que codice_33 crée un vecteur (ou une matrice colonne) allant de 10"a" à 10"b".
La méthode codice_34 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)
c = np.arange(1, 10).reshape(3, 3) 
Avec la méthode codice_34, on peut utiliser la valeur –1 pour une des dimensions ; sa valeur est alors automatiquement calculée en fonction du nombre d'éléments et de l'autre dimension. On peut aussi utiliser une dimension vide ; cela crée alors un vecteur. Par exemple, pour une matrice M quelconque :
M.reshape(-1, 1) # crée une matrice colonne
M.reshape(1, -1) # crée une matrice ligne
M.reshape(-1,) # crée un vecteur
La méthode codice_36 remplit la matrice avec un scalaire :
b.fill(5) # remplace les valeurs de b par la valeur 5
Extraction matricielle.
Si l'on veut extraire les colonnes 1 et 3 pour toutes les lignes d'une matrice M, on utilise :
M[:, [0, 2]]
Assemblage de matrices.
Si l'on veut regrouper deux matrices, on utilise la commande codice_37. On utilise le paramètre "axis" pour indiquer si l'on empile les matrices l'une au-dessus de l'autre (codice_38) ou bien l'une derrière l'autre (codice_39). Par exemple :
A = np.matrix(1 ,2], [3, 4)
B = np.matrix(5 ,6], [7, 8)
np.concatenate((A, B), axis = 0)
np.concatenate((A, B), axis = 1)
Si l'on veut transformer deux vecteurs en une matrice de deux colonnes, chaque vecteur occupant une colonne :
A = np.matrix([1 ,2])
B = np.matrix([3 ,4])
np.concatenate((A.reshape(-1, 1), B.reshape(-1, 1)), axis = 1)
Opérations matricielles.
Les quatre opérations classiques codice_40, codice_41, codice_42 et codice_43 ne fonctionnent qu'entre tenseurs de mêmes dimensions et sont des opérations élément par élément "()" :
De même, les fonctions codice_52, codice_53, codice_54 et codice_55 effectuent des opérations élément par élément sur des tenseurs de mêmes dimensions :
La multiplication matricielle, au sens de l'algèbre linéaire, se fait avec les fonctions codice_64 ou codice_65, ou bien avec l'opérateur codice_66.
a = np.matrix(1, 2], [3, 4)
b = np.matrix(5, 6], [7, 8)
print(a @ b) # np.matmul(a, b)
Notez que :
L'opérateur codice_75 fait un produit matriciel en modifiant la variable elle-même (à l'image de codice_76 pour les nombres).
Calcul vectorisé.
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 codice_77 est un vecteur de 50 valeurs et il est traité en une seule passe par la fonction sinus codice_78.
Outre le tranchage "()", on peut utiliser deux autres méthodes pour extraire certaines valeurs d'une matrice :
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])
Si l'on veut inverser tous les éléments d'une matrice de bolléens, il faut utiliser la fonction codice_80
Exercice
Écrire un programme Python mettant en œuvre le crible d'Érathostène pour trouver les nombres premiers inférieurs à une valeur donnée.
import numpy as np
import matplotlib.pyplot as plt
def eratosthene(limite):
 # Détermine la liste des nombres premiers entre 1 et N
 # par le crible d'Ératosthène
 # Entrées : limite : nombre entier, N
 # Sorties : liste : vecteur d'entiers,liste des nombres premiers
 indices = (np.ones(limite) == 1) # vecteur de booléens tous à True
 # à la fin, indice(i-1) est True si i est premier, False sinon
 indices[0]=False # 1 n'est pas premier
 imax = int(limite)
 i = 2 # initialisation
 repete = (i <= imax)
 while repete:
 if indices[i-1]:
 jmax = int(limite/i)
 j = np.arange(1, jmax)+1
 indices[i*j-1]=False # élimination des multiples de i
 test = (i*jmax == imax)
 i = i + 1
 repete = i*i < limite # condition d'arrêt
 liste0 = np.arange(limite)
 liste = liste0[indices]+1
 return liste
print("***** Recherche de nombres premiers par le crible d'Ératosthène *****\n")
nmax = eval(input("Entrez la valeur maximale : "))
resultat = eratosthene(nmax)
print("\n", resultat.shape[0], "nombres premiers entre 1 et", nmax, ":\n")
print(resultat)
plt.plot(resultat, np.zeros_like(resultat), "|")
L'extraction par un vecteur d'indice intervient dans l'instruction :
indices[i*j-1]=False
qui élimine en une seule passe tous les multiples de "i". L'extraction par un vecteur booléen intervient dans l'instruction :
liste = liste0[indices]+1
qui permet d'extraire toutes la valeurs conservées en une seule passe.
Attributs.
La classe codice_81, qui définit les matrices, possède un certain nombre d'attributs :
a = np.linspace(1, 9, 9)
print("a", a, "\n",
 " ; shape :", a.shape,
 " ; dim : ", a.ndim,
 " ; size : ", a.size,
 " ; dtype : ", a.dtype, "\n")
a = np.arange(0, 9).reshape(3, 3)
print(a)
print(a.T)
print(a.flat[:])
Fonctions et méthodes de base.
La classe codice_81 possède un certain nombre de méthodes :
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 :
Extraction de données :
a.tofile("matriceA.txt", sep=" ; ")
a = a.astype(float) # pour avoir une matrice de réels en virgule flottante
a = a.astype(str) # pour avoir une matrice de chaînes de caractères
Tri :
Pour trier les lignes selon la deuxième colonne d'une matrice, on peut faire comme suit :
M = np.array(1, 5, 7, 5], [2, 9, 4, 3], [9, 1, 7, 5)
ind = np.argsort(M[:, 1]) # indices de tri selon la 2e colonne
N = M[ind, :] # réarrangement des lignes
Pour faire un tri lexicographique, on utilise la fonction codice_113 en indiquant les différentes colonnes :
M = np.array(1, 5, 7, 5], [2, 9, 4, 3], [9, 1, 7, 5], [2, 9, 8, 5)
ind = np.lexsort((M[:, 3], M[:, 2], M[:, 1], M[:, 0])) # indices de tri selon la 1re, puis la 2e, puis la 3e, puis la 4e colonne
N = M[ind, :] # réarrangement des lignes
Algèbre linéaire :
Matrices de booléens :
Autre méthodes :
Propagation.
Le terme « propagation » "()" 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 "m"1 × "n"1 et "m"2 × "n"2 différentes. Alors :
Par exemple :
A = np.array(1, 2], [3, 4)
print(5 + A)
print(np.array(5, 4) + A)
print(np.array(5], [4) + A)
Fonctions « universelles ».
Les fonctions universelles "()" sont les fonctions s'appliquant aux matrices, des fonctions vectorisées.
Notes et références.
Graphiques < ↑ > Polynômes