TP1 - Révisions : matrices et programmation¶

In [2]:
import numpy as np
import numpy.linalg as alg
import numpy.random as rd
import scipy.special as sp

Exercice 1¶

Sans rentrer les coefficients un à un, déclarer les matrices ci-dessous : $$A = \begin{pmatrix} 5 & 3 & 3 \\ 3 & 5 & 3 \\ 3 & 3 & 5 \end{pmatrix},~~~ B = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 1 & 1 & 0 & 0 \\ 1 & 0 & 1 & 0 \\ 1 & 0 & 0 & 1 \end{pmatrix}.$$

Solution¶

In [2]:
A=3*np.ones((3,3))+2*np.eye(3)
print(A)
B=np.concatenate((np.ones((4,1)),np.concatenate((np.zeros((1,3)),np.eye(3)),axis=0)),axis=1)
print(B)
[[5. 3. 3.]
 [3. 5. 3.]
 [3. 3. 5.]]
[[1. 0. 0. 0.]
 [1. 1. 0. 0.]
 [1. 0. 1. 0.]
 [1. 0. 0. 1.]]

Exercice 2¶

Que vaut $ \begin{pmatrix} a_1 \\ \vdots \\ a_n \end{pmatrix} \begin{pmatrix} 1 & \ldots & 1 \end{pmatrix}$ ? En déduire une manière de déclarer la matrice $$\begin{pmatrix} 1 & 1 & \ldots & 1 \\ 2 & 2 & \ldots & 2 \\ \vdots & \vdots & & \vdots \\ 10 & 10 & \ldots & 10 \end{pmatrix}$$

Solution¶

In [3]:
A=np.array([np.arange(1,11)])
M=np.dot(np.transpose(A),np.ones((1,10)))
print(M)
[[ 1.  1.  1.  1.  1.  1.  1.  1.  1.  1.]
 [ 2.  2.  2.  2.  2.  2.  2.  2.  2.  2.]
 [ 3.  3.  3.  3.  3.  3.  3.  3.  3.  3.]
 [ 4.  4.  4.  4.  4.  4.  4.  4.  4.  4.]
 [ 5.  5.  5.  5.  5.  5.  5.  5.  5.  5.]
 [ 6.  6.  6.  6.  6.  6.  6.  6.  6.  6.]
 [ 7.  7.  7.  7.  7.  7.  7.  7.  7.  7.]
 [ 8.  8.  8.  8.  8.  8.  8.  8.  8.  8.]
 [ 9.  9.  9.  9.  9.  9.  9.  9.  9.  9.]
 [10. 10. 10. 10. 10. 10. 10. 10. 10. 10.]]

Exercice 3¶

On définit la matrice $A=\begin{pmatrix} 1 & 1 & 2 & 0 \\ 1 & -1 & 0 & -2 \\ 0 & 1 & 1 & 1 \\ 1 & 0 & 1 & -1\end{pmatrix}$.

  1. Déclarer la matrice $A$.
  2. Écrire une fonction $\verb|lignes(A,i,j,a)|$ qui prend entrée une matrice $\verb|A|$, les indices de lignes $\verb|i|$ et $\verb|j|$, ainsi qu'un réel $\verb|a|$, et qui retourne la matrice obtenue à partir de $A$ en soustrayant $\verb|a|$ fois la ligne $\verb|j|$ à la ligne $\verb|i|$.
  3. Écrire une fonction $\verb|echange(A,i,j)|$ qui prend en entrée une matrice $\verb|A|$, et des indices de lignes $\verb|i|$ et $\verb|j|$, et retourne la matrice obtenue en échangeant les lignes $\verb|i|$ et $\verb|j|$ de $\verb|A|$.
  4. Appliquer l'algorithme du pivot de Gauss sur la matrice $A$ à l'aide des fonctions des questions précédentes. En déduire le rang de $A$.
  5. Vérifier le résultat à l'aide de la fonction $\verb|matrix_rank|$ du module $\verb|numpy.linalg|$.
  6. Écrire une fonction $\verb|pivot(A)|$ qui prend en entrée une matrice $\verb|A|$ et retourne la matrice obtenue après avoir effectué l'algorithme du pivot de Gauss sur la matrice $\verb|A|$.
In [4]:
#1.
A=np.array([[1,1,2,0],[1,-1,0,-2],[0,1,1,1],[1,0,1,-1]])
In [5]:
#2.
def lignes(A,i,j,a):
    A[i,:]=A[i,:]-a*A[j,:]
    return(A)
In [6]:
#3.
def echange(A,i,j):
    l=np.copy(A[i,:])
    A[i,:]=A[j,:]
    A[j,:]=l
    return(A)
In [7]:
#4.
lignes(A,1,0,1)
lignes(A,3,0,1)
lignes(A,2,1,-1/2)
lignes(A,3,1,1/2)
Out[7]:
array([[ 1,  1,  2,  0],
       [ 0, -2, -2, -2],
       [ 0,  0,  0,  0],
       [ 0,  0,  0,  0]])

La matrice $A$ est de rang 2.

In [8]:
#5.
alg.matrix_rank(A)
Out[8]:
2
In [9]:
#6.
def pivot(A):
    n=len(A)
    for j in range(n-1):
        if A[j,j]==0:
            for i in range(j+1,n):
                if A[i,j]!=0:
                    echange(A,i,j)
        if A[j,j]!=0:
            for i in range(j+1,n):
                lignes(A,i,j,A[i,j]/A[j,j])
    return(A)
In [10]:
pivot(A)
Out[10]:
array([[ 1,  1,  2,  0],
       [ 0, -2, -2, -2],
       [ 0,  0,  0,  0],
       [ 0,  0,  0,  0]])

Exercice 4¶

  1. En une seule ligne de commande, créer le vecteur $x=\left(1, \frac{1}{4}, \frac{1}{9}, \frac{1}{16}, \ldots, \frac{1}{100}\right)$ sans saisir un à un les éléments.
  2. Compléter la commande précédente pour qu'elle renvoie $\displaystyle \sum_{k=1}^{10} \frac{1}{k^{2}}$.
  3. En une seule ligne de commande, calculer la somme $\displaystyle \sum_{n=0}^{10} \frac{1}{2^{n}}$.

Solution¶

In [11]:
#1.
x=1/np.arange(1,11)**2
print(x)
[1.         0.25       0.11111111 0.0625     0.04       0.02777778
 0.02040816 0.015625   0.01234568 0.01      ]
In [12]:
#2.
K=np.arange(1,11)
print("Somme des 1/k^2 entre 1 et 10 :",np.sum(1/K**2))
Somme des 1/k^2 entre 1 et 10 : 1.5497677311665408
In [13]:
#3.
K=np.arange(11)
print("Somme des 1/2^k entre 0 et 10 :",np.sum(1/(2**K)))
Somme des 1/2^k entre 0 et 10 : 1.9990234375

Exercice 5¶

  1. Écrire une commande affichant tous les multiples de 7 inférieurs ou égaux à 1000.
  2. Compléter la commande précédente pour qu'elle renvoie le plus grand multiple de 7 inférieur ou égal à 1000.
  3. Ecrire une commande renvoyant le plus petit multiple de 7 supérieur strictement à 1000 .
In [14]:
#1.
A=np.arange(0,1001,7)
print(A)
[  0   7  14  21  28  35  42  49  56  63  70  77  84  91  98 105 112 119
 126 133 140 147 154 161 168 175 182 189 196 203 210 217 224 231 238 245
 252 259 266 273 280 287 294 301 308 315 322 329 336 343 350 357 364 371
 378 385 392 399 406 413 420 427 434 441 448 455 462 469 476 483 490 497
 504 511 518 525 532 539 546 553 560 567 574 581 588 595 602 609 616 623
 630 637 644 651 658 665 672 679 686 693 700 707 714 721 728 735 742 749
 756 763 770 777 784 791 798 805 812 819 826 833 840 847 854 861 868 875
 882 889 896 903 910 917 924 931 938 945 952 959 966 973 980 987 994]
In [15]:
#2.
print("Plus grand multiple de 7 inférieur à 1000 :",A[-1])
Plus grand multiple de 7 inférieur à 1000 : 994
In [16]:
#3.
print("Plus petit multiple de 7 supérieur à 1000 :",A[-1]+7)
Plus petit multiple de 7 supérieur à 1000 : 1001

Exercice 6¶

On modélise le nombre de véhicules passant sur une petite route de campagne en une journée par une variable aléatoire $X$ qui suit une loi de Poisson $\mathscr{P}(5)$.

  1. Introduire une matrice $\verb|A|$ de taille $52\times 7$ qui simule une année de circulation, chaque ligne contenant le trafic de chaque jour d'une semaine. La matrice A contient alors $52 \times 7$ nombres tirés suivant la loi $\mathscr{P}(5)$.

  2. Déterminer le nombre maximal de véhicules circulant sur la route en une journée durant l'année, puis le nombre maximal de véhicules un mercredi durant l'année.

  3. Déterminer les numéros des semaines où la route a connu son maximum de fréquentation.

  4. Déterminer le nombre de jours où la route a connu son minimum de fréquentation.

  5. En une seule ligne de commande, calculer le nombre moyen de véhicules par jour durant ces 364 jours. Recommencez plusieurs fois en recréant la matrice A. Que constate-t-on ? Était-ce prévisible ?

  6. En une seule ligne de commande, évaluer la probabilité qu'une journée voie passer 8 véhicules ou plus. Calculer la valeur exacte de cette probabilité.

In [17]:
#1.
A=rd.poisson(5,(52,7))
In [18]:
#2.
print("Nombre max de voitures en une journée :",np.max(A))
print("Nombre max de voitures le mercredi :",np.max(A[:,2]))
Nombre max de voitures en une journée : 11
Nombre max de voitures le mercredi : 9
In [19]:
#3. Tableau des fréquentations par semaine :
F=np.sum(A,axis=1)
print("Numéro des semaines réalisant le maximum de trafic :", np.where(F==max(F))[0]+1)
Numéro des semaines réalisant le maximum de trafic : [29]
In [20]:
#4.
print("Nombre de jours ou le trafic est minimal :",np.sum(A==np.min(A)))
Nombre de jours ou le trafic est minimal : 6
In [21]:
#5.
print("Moyenne de fréquentation par jour :",np.mean(A))
Moyenne de fréquentation par jour : 4.873626373626373
In [22]:
for i in range(10):
    A=rd.poisson(5,(52,7))
    print(np.mean(A))
4.983516483516484
5.008241758241758
5.164835164835165
4.917582417582418
5.162087912087912
5.181318681318682
4.826923076923077
4.887362637362638
5.035714285714286
4.934065934065934

La moyenne est toujous très proche de 5, ce qu'on attendait car l'espréance d'une variable aléatoire qui suit la loi $\mathcal{P}(5)$ est 5.

In [23]:
#6.
A=rd.poisson(5,10**6)
print("Estimation de la probabilité de 8 véhicules ou plus :",np.mean(A>7))
Estimation de la probabilité de 8 véhicules ou plus : 0.133245
In [24]:
#Calcul de la probabilité
K=np.arange(0,8)
print("Probabilité d'avoir 8 véhicules ou plus :",1-sum(np.exp(-5)*5**K/sp.factorial(K)))
Probabilité d'avoir 8 véhicules ou plus : 0.13337167407000727

Exercice 7¶

  1. Écrire un programme permettant de calculer $\sum_{k=1}^{n} \frac{(-1)^{k-1}}{k}$ pour une valeur de $n$ entrée par l'utilisateur. On proposera pour cela deux méthodes, l'une utilisant la fonction $\verb|sum|$, l'autre à l'aide d'une boucle $\verb|for|$.

  2. On peut montrer que la série $\sum \frac{(-1)^{n-1}}{n}$ converge et que sa somme vaut $\ln (2)$. Écrire un programme permettant de déterminer le plus petit entier naturel $n$ pour lequel $\left|S_{n}-\ln (2)\right| \leq$ $10^{-3}$, où $\left(S_{n}\right)$ désigne la suite des sommes partielles de cette série.

Solution¶

In [25]:
#1.
print("Entrer n :")
n=int(input())
K=np.arange(1,n+1,1)
print("Somme des (-1)^(k-1)/k de 1 à",n,":",sum((-1)**(K-1)*(1/K)))
Entrer n :
10
Somme des (-1)^(k-1)/k de 1 à 10 : 0.6456349206349207
In [26]:
S=0
for k in range(1,n+1):
    S+=(-1)**(k-1)/k
print("Somme des (-1)^(k-1)/k de 1 à n :",S)
Somme des (-1)^(k-1)/k de 1 à n : 0.6456349206349207
In [27]:
#2.
eps=1e-3; S=0; n=0
while (abs(S-np.log(2))>eps):
    n+=1
    S+=(-1)**(n-1)/n
print("Plus petit rang tel que |S_n-ln(2)|<=eps :",n)
Plus petit rang tel que |S_n-ln(2)|<=eps : 500

Exercice 8¶

Soient $\left(u_{n}\right)_{n \in \mathbb{N}^{*}}$ et $\left(v_{n}\right)_{n \in \mathbb{N}^{*}}$ les suites définies par $\displaystyle u_{n}=\sum_{k=1}^{n} \frac{1}{k^{2}}$ et $v_{n}=u_{n}+\frac{1}{n}$, pour tout $n \in \mathbb{N}^{*}$.

  1. Montrer que les suites $\left(u_{n}\right)_{n \in \mathbb{N}^{*}}$ et $\left(v_{n}\right)_{n \in \mathbb{N}^{*}}$ sont adjacentes.

  2. Écrire un programme qui donne une approximation de $\displaystyle \sum_{k=1}^{+\infty} \frac{1}{k^{2}}$ à $\varepsilon$ près pour $\varepsilon>0$ donné.

Solution¶

2.¶

On sait que la somme $S=\sum_{k=1}^{+\infty} \frac 1 {k^2}$ est dans l'intervalle $[u_n,v_n]$ pour tout $n\in \mathbb{N}$. On cherche alors un entier $n$ tel que l'intervalle $[u_n,v_n]$ soit de longueur inférieure à $\varepsilon$. On aura alors assuré que $|u_n-S|\leq \varepsilon$.

Comme $v_n-u_n = \frac 1 n$, il suffit de s'assurer que $\frac 1 n \leq \varepsilon$, c'est-à-dire que $n\geq \frac 1 \varepsilon$.

In [28]:
eps=1e-5
n=np.ceil(1/eps) #calcul de n pour avoir n >= 1/eps
U=np.sum(1/np.arange(1,n+1)**2) #calcul de S_n pour le n trouvé
print("Estimation de la somme à ",eps," près :",U)
print("Erreur :",abs(np.pi**2/6-U)) #vérification : on sait que S=pi^2/6
Estimation de la somme à  1e-05  près : 1.644924066898227
Erreur : 9.999949999395241e-06

Exercice 9¶

Ecrire une fonction $\verb|trace(A)|$ prenant en entrée une matrice $\verb|A|$, et retournant la trace de $A$ si $A$ est carrée, et retournant un message d'erreur si $A$ n'est pas carrée.

Solution¶

In [29]:
def trace(A):
    s=np.shape(A)
    if s[0]!=s[1]:
        print("La matrice n'est pas carrée.")
    else:
        T=0
        for i in range(s[0]):
            T+=A[i,i]
        return(T)
In [30]:
#plus rapide :
def trace(A):
    s=np.shape(A)
    if s[0]!=s[1]:
        print("La matrice n'est pas carrée.")
    else:
        return(sum([A[i,i] for i in range(s[0])]))
In [31]:
A=np.ones((2,3))
trace(A)
La matrice n'est pas carrée.
In [32]:
B=np.ones((3,3))
trace(B)
Out[32]:
3.0

Exercice 10¶

  1. Pour $k$ et $n$ des entiers, écrire $\binom{n}{k}$ sous la forme d'un quotient de deux produits, et en déduire une fonction $\verb|binomial(k,n)|$ qui prend en entrée des entiers $\verb|k|$ et $\verb|n|$ et retourne $\binom{n}{k}$, en ayant recours aux fonctions $\verb|prod|$ et $\verb|arange|$ de la bibliothèque $\verb|numpy|$.
  2. À l'aide de la fonction de la question précédente, créer la matrice carrée de taille $n$ suivante : $$C = \begin{pmatrix} \binom{0}{0} & \binom{0}{1} & \ldots & \binom{0}{n} \[1mm]
                     \binom{1}{0} & \binom{1}{1} & \ldots & \binom{1}{n} \\
                     \vdots & \vdots & \vdots & \vdots \\
                     \binom{n-1}{0} & \binom{n-1}{1} & \ldots & \binom{n-1}{n-1}
                     \end{pmatrix}.$$
  3. Proposer un autre moyen de construire la matrice $C$, en utilisant la formule de Pascal.

Solution¶

1.¶

On a $\displaystyle \binom{n}{k} = \frac{\displaystyle \prod_{i=n-k+1}^n i}{\displaystyle \prod_{i=1}^k i}.$

In [33]:
def binomial(k,n):
    return np.prod(np.arange(n-k+1,n+1))/np.prod(np.arange(1,k+1))
In [34]:
#2.
n=5
C=np.zeros((n,n))
for i in range(n):
    for j in range(n):
        C[i,j]=binomial(j,i)
print(C)
[[1. 0. 0. 0. 0.]
 [1. 1. 0. 0. 0.]
 [1. 2. 1. 0. 0.]
 [1. 3. 3. 1. 0.]
 [1. 4. 6. 4. 1.]]
In [35]:
#3.
n=5
C=np.concatenate((np.ones((n,1)),np.zeros((n,n-1))),axis=1)
for i in range(1,n):
    for j in range(1,i+1):
        C[i,j]=C[i-1,j-1]+C[i-1,j]
print(C)
[[1. 0. 0. 0. 0.]
 [1. 1. 0. 0. 0.]
 [1. 2. 1. 0. 0.]
 [1. 3. 3. 1. 0.]
 [1. 4. 6. 4. 1.]]

Exercice 11¶

Écrire une fonction $\verb|Prod(A,B)|$ qui prend en entrée deux matrices $\verb|A|$ et $\verb|B|$, et qui renvoie leur produit matriciel $AB$ lorsqu'il est bien défini (sans utiliser la fonction $\verb|np.dot|$), et renvoie un message d'erreur lorsqu'il n'est pas défini.

In [6]:
def Prod(A,B):
    (n,p)=np.shape(A)
    (m,q)=np.shape(B)
    if p!=m:
        print("Mauvaises dimensions")
    else:
        C=np.zeros((n,q))
        for i in range(n):
            for j in range(q):
                for k in range(p):
                    C[i,j]+=A[i,k]*B[k,j]
        return(C)

Exercice 12¶

  1. On dit qu'une matrice carrée est stochastique si tous ses coefficients sont positifs, et la somme de chacune de ses lignes vaut 1. Écrire une fonction $\verb|stoch(A)|$ qui prend en entrée une matrice $\verb|A|$ et renvoie $\verb|True|$ si la matrice est stochastique, et $\verb|False|$ sinon.
  2. On dit qu'une matrice carrée est bistochastique si elle est stochastique et que la somme de chacune de ses colonnes vaut 1. Écrire une fonction $\verb|bistoch(A)|$ qui prend en entrée une matrice $\verb|A|$ et renvoie $\verb|True|$ si la matrice est bistochastique, et $\verb|False|$ sinon.
In [1]:
#1
def stoch(A):
    if np.min(A)<0:
        return False
    n=np.shape(A)[0]
    for i in range(n):
        if np.sum(A[i,:])!=1:
            return False
    return True
In [18]:
#2
def bistoch(A):
    return stoch(A) & stoch(np.transpose(A))

Exercice 13¶

On dit qu'une matrice carrée $A\in \mathscr M_n(\mathbb R)$ est à diagonale strictement dominante si pour tout $i\in [| 1,n |]$, on a $|a_{i,i}| > \sum\limits_{j\not=i} |a_{i,j}|$.

Écrire une fonction $\verb|Diagdom(A)|$ qui prend en entrée une matrice $\verb|A|$ et qui renvoie $\verb|True|$ si $\verb|A|$ est à diagonale strictement dominante, et $\verb|False|$ sinon.

In [23]:
def Diagdom(A):
    n=np.shape(A)[0]
    for i in range(n):
        if 2*abs(A[i,i])-np.sum(A[i,:])<=0:
            return False
    return True