TP 3 : Matrice de population#

Rappels sur les matrices#

Définition#

Une matrice est représentée en Python par une liste de listes (ou : un tableau de tableaux), chaque sous-liste correspondant à une ligne de la matrice.

Par exemple, la matrice

\[\begin{split} M = \begin{pmatrix} 1 & 0 & 3\\ 2 & 2 & 1 \end{pmatrix} \end{split}\]

est représentée par :

M = [[1, 0, 3], [2, 2, 1]]

Ainsi, la première sous-liste [1, 0, 3] correspond à la première ligne de la matrice et [2, 2, 1] correspond à la deuxième ligne.

Accéder et modifier un élément#

On accède à l’élément sur la ligne i, colonne j de la matrice avec M[i][j]. Par exemple :

M[0][2] # élément ligne 0, colonne 2
3

Remarque : Les lignes et colonnes commencent à \(0\) (au lieu de \(1\) en mathématiques).

On peut modifier l’élément ligne i, colonne j avec M[i][j] = .... Par exemple :

M[1][0] = 42
M # M a bien été modifiée
[[1, 0, 3], [42, 2, 1]]

Taille d’une matrice#

Le nombre de lignes de la matrice est le nombre de sous-listes, qui peut être obtenue avec len(M) :

len(M) # nombre de lignes de M
2

Le nombre de colonnes est égal au nombre d’éléments sur une ligne, c’est-à-dire la taille d’une sous-liste. On eut l’obtenir avec len(M[0]) (nombre d’éléments sur la première ligne de M) :

len(M[0]) # la 1ère ligne contient 3 éléments, donc il y a 3 colonnes
3

Création d’une matrice de taille \(n \times p\)#

Pour créer une matrice de taille \(n \times p\) remplie de \(0\), on a deux possibilités :

  • Utiliser np.zeros((n, p)) du module numpy (import numpy as np). Ceci donne un tableau (np.darray), qui ressemble beaucoup aux listes avec quelques petites différences (pas de append, opérations terme à terme…).

  • Définir une liste contenant \(n\) listes de \(p\) zéros ;

M = []
for i in range(3):
    L = [] # la ième ligne
    for j in range(5):
        L.append(0)
    M.append(L)
M # matrice 3x5 remplie de 0
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]

Parcourir une matrice#

Pour parcourir une matrice, on utilise deux indices (un pour la ligne, un pour la colonne), dans deux boucles for. Par exemple, mettons des \(2\) partout dans \(M\) :

for i in range(3): # i est le numéro de ligne
    for j in range(5): # j est le numéro de colonne
        M[i][j] = 2
M
[[2, 2, 2, 2, 2], [2, 2, 2, 2, 2], [2, 2, 2, 2, 2]]

Exercices sur les matrices#

Exercice

Écrire une fonction somme(M) renvoyant la somme des éléments d’une matrice M.

M = [[1, 2], [3, 4]]
somme(M) # 10
10

Exercice

Écrire une fonction nulle déterminat si une matrice est nulle (ne contient que des \(0\)). nulle(M) doit renvoyer True si M est nulle, False sinon.

print(nulle([[1, 2], [3, 4]]))
nulle([[0, 0], [0, 0]])
False
True

Exercice

Écrire une fonction identite(n) renvoyant la matrice identité de taille \(n\).

identite(3)
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]

Exercice

Écrire une fonction transpose(M) renvoyant la transposée d’une matrice M.

transpose([[1, 2], [3, 4]])
array([[1., 3.],
       [2., 4.]])

Exercice

Écrire une fonction produit(A, B) renvoyant le produit matriciel de A et B. On rappelle que \(AB = (c_{i, j})\)\(c_{i, j} = \sum_{k = 0}^p a_{i, k} b_{k, j}\), où \(p\) est le nombre de colonnes de \(A\) (qui doit être égal au nombre de lignes de \(B\), ce qu’on suppose être le cas).
On pourra compléter le code suivant :

def produit(A, B):
    n = ... # nombre de lignes de A
    p = ... # nombre de colonnes de A
    q = ... # nombre de colonnes de B
    # définir une matrice C de taille n*q remplie de 0
    for i in range(n):
        for j in range(q):
            # ici on va calculer C[i][j] (c'est-à-dire une somme)
            for k in range(p):
                C[i][j] += ...
    return C
produit([[1, 2], [3, 4]], [[5, 6], [7, 8]])
[[19, 22], [43, 50]]

Matrice de population#

On souhaite étudier l’évolution d’une population de rongeurs à des stades d’âges différents. On ne s’intéresse qu’à la population d’individus femelles. On suppose qu’aucun rongeur vit au plus \(3\) ans et on note \(a_n\), \(b_n\), \(c_n\) le nombre de femelles âgées de \(0\), \(1\), \(2\) ans à l’année \(n\) (initialement \(n = 0\)).
Chaque femelle donne en moyenne naissance à \(6\) femelles lors de sa 2ème année et \(10\) femelles lors de sa \(3\)ème année.
Cependant, seul un rongeur sur deux survit au dela de sa première année et seul 40% de ceux qui survivent la deuxième année survivront jusqu’à la troisième année.

Exercice

(Sans programmation) Exprimer \(a_{n+1}\), \(b_{n+1}\), \(c_{n+1}\) en fonction de \(a_{n}\), \(b_{n}\), \(c_{n}\).

On définit maintenant le vecteur \(X_n = \begin{pmatrix} a_n\\ b_n\\ c_n \end{pmatrix}\), que l’on représentera sous forme de liste en Python.

Exercice

On prend initalement \(a_0 = 10\), \(b_0 = 0\), \(c_0 = 0\). Définir \(X_0\) en Python, sous forme d’une matrice colonne.

Exercice

Définir (sur papier puis en Python) une matrice \(A\) telle que \(X_{n + 1} = AX_n\).

\(A\) est appelée une matrice de Leslie.
On remarque que, par récurrence évidente : \(X_n = A^n X_0\).

Exercice

Écrire une fonction puissance(A, n) renvoyant \(A^n\).

puissance(A, 3)
[[2.0, 18.0, 30.0], [1.5, 2.0, 0.0], [0.0, 1.2000000000000002, 2.0]]

Exercice

Écrire une fonction population(n) renvoyant \(X_n\).

population(10)
[4590.0, 1120.0, 234.00000000000003]

Exercice

Que vaut \(X_1\), \(X_2\), \(X_3\), \(X_4\) ?

Exercice

Utiliser la fonction suivante pour afficher les \(n\) premières valeurs de \(a_k\), \(b_k\), \(c_k\). On appelera par exemple plot_population(10).

import matplotlib.pyplot as plt

def plot_population(n):
    x = list(range(n))
    y = [population(i) for i in x]
    a, b, c = zip(*y)
    plt.plot(x, a, label="$a_n$")
    plt.plot(x, b, label="$b_n$")
    plt.plot(x, c, label="$c_n$")
    plt.legend()
    plt.show()

Exercice

Utiliser la fonction suivante pour afficher le taux d’accroissement, c’est-à-dire \(\frac{a_{n+1}}{a_n}\), par exemple. On pourra appeler plot_accroissement(20), par exemple.

import matplotlib.pyplot as plt

def plot_accroissement(n):
    x = list(range(n))
    x_ = list(range(1, n - 1))
    y = [population(i) for i in x]
    X = list(zip(*y))
    X_ = [[]]*3
    for i in range(3):
        X_[i] = [0 if X[i][j] == 0 else X[i][j+1]/X[i][j] for j in x_]
    plt.plot(x_, X_[0], label=r"$\frac{a_{n+1}}{a_n}$")
    plt.plot(x_, X_[1], label=r"$\frac{b_{n+1}}{b_n}$")
    plt.plot(x_, X_[2], label=r"$\frac{c_{n+1}}{c_n}$")
    plt.legend()
    plt.show()

Exercice

D’après le théorème de Perron-Frobenius, le taux d’accroissement est censé tendre, quand \(n \longrightarrow \infty\), vers la plus grande valeur propre de \(A\).

  1. Calculer les valeurs propres de \(A\) (si vous avez déjà vu la définition de valeur propre en mathématiques…).

  2. Vérifier avec np.linalg.eig(A), qui renvoie deux tableaux, le premier contenant les valeurs propres et le deuxième les vecteurs propres.