Académique Documents
Professionnel Documents
Culture Documents
February 3, 2020
1.2 Rappel
On considère le SEL
a11 x1 + a12 x2 + . . . + a1n xn = b1
a21 x1 + a22 x2 + . . . + a2n xn = b2
(S) : ..
.
an1 x1 + an2 x2 + . . . + ann xn = bn
L’écriture matricielle de (S) est donnée par AX = b, avec :
a11 a12 a13 · · · a1n x1 b1
a21 a22 a23 · · · a2n x2 b2
A = a31 a32 a33 · · · a3n , X = x3 , et b = b3 .
.. .. .. .. .. .. ..
. . . . . . .
an1 an2 an3 · · · ann xn bn
Il existe deux catégories de méthodes pour la résolution du système (S) :
• les méthodes directes : la solution X est exacte, et donnée après un nombre d’opérations
algorithmiques fixé en fonction de n, la taille de la matrice A.
• les méthodes itératives (ou indirectes) : la solution X est approchée et donnée une fois qu’une
condition d’arrêt, imposée à l’algorithme, est satisfaite.
1
2 Méthodes directes
2.1 Description de l’algorithme du pivot de Gauss
On suppose que le système linéaire AX = b, avec A = ( aij )1≤i,j≤n , X = ( xi )1≤i≤n et b = (bi )1≤i≤n ,
est de Cramer, c’est-à-dire il admet une unique solution. La matrice A est donc inversible.
L’algorithme du pivot de Gauss, consiste à triangulariser la matrice A à l’aide d’opérations élé-
mentaires.
En notant Li la ime ligne de A, 1 ≤ i ≤ n, on appelle opération élémentaire sur A toute opération
de l’un des types suivants:
Li ←− Li + λL j , λ ∈ R∗ ,
Li ←− λLi ,
Li ←→ L j .
• Etape 1 : on construit la matrice élargie ( A|b) de type (n, n + 1), en concaténant la matrice
A et le second membre b comme suit :
a11 · · · a1n b1
..
( A|b) = ... ..
. .
an1 · · · ann bn
• Etape 2 : on effectue des opérations élementaires sur les lignes de ( A|b) jusqu’à arriver à un
système triangulaire.
• Etape 3 : on remonte par substitutions pour obtenir la solution X du système.
2
:
[2]: A=5*np.eye(4)-np.ones((4,4))
[A[0,3],A[1,2],A[2,1],A[3,0]]=np.zeros(4)
b=np.array([[50,30,70,50]]).transpose()
print(b)
concatener(A,b)
[[50]
[30]
[70]
[50]]
3
Li ←− Li + αL j
c- Recherche d’un pivot non nul Ecrire une fonction choix_pivot(A,j) qui, si le pivot de l’étape
j est nul, 1 ≤ j ≤ n − 1, cherche le premier élément non nul de a j+1,j , a j+2,j ,. . . ,an,j et renvoie l’indice
de la ligne correspondante. Sinon, elle retourne j. Compléter le code ci-dessous en utilisant la
fonction np.where. Utiliser le help de python pour se documenter sur l’utilité de cette fonction.
[8]: def choix_pivot(A,j):
n=A.shape[0]
if A[j,j]!=0:
Ind_max=j
else:
Ind=np.where(A[j+1:n,j]!=0)
Ind_max=Ind[0][0]+j+1
return Ind_max
Tester la fonction choix_pivot(A,j) sur B=A.copy() avec B[1,1]=0 et pour j=1.
[9]: B=A.copy()
B[1,1]=0
choix_pivot(B,1)
[9]: 3
d- Triangularisation du système Ecrire une fonction triangulariser qui triangularise une ma-
trice A par la méthode du pivot de Gauss. Compléter le code suivant :
[10]: def triangulariser(A):
n=A.shape[0]
T=A.copy()
for j in np.arange(0,n-1):
ind_pivot=choix_pivot(T,j)
if ind_pivot>j:
T=permuter(T,j,ind_pivot)
for i in np.arange(j+1,n):
4
T=ajouter(T,i,j,-T[i,j]/T[j,j])
return T
Tester la fonction triangulariser(A) sur A.
[11]: triangulariser(A)
[11]: array([[ 4. , -1. , -1. , 0. ],
[ 0. , 3.75 , -0.25 , -1. ],
[ 0. , 0. , 3.73333333, -1.06666667],
[ 0. , 0. , 0. , 3.42857143]])
Ecrire une fonction remonter()qui résout un SEL AX = b par remotée, avec A une matrice
triangulaire supérieure.
[12]: def remonter(A):
n=A.shape[0]
x=np.zeros((n,1))
x[n-1]=A[n-1,n]/A[n-1,n-1]
for i in np.arange(n-2,-1,-1):
S=A[i,i+1:n].dot(x[i+1:n])
x[i]=(A[i,n]-S)/A[i,i]
return x
2.2.4 Synthèse
Ecrire une fonction PivotDeGauss(A,b)qui résout un SEL AX = b par la méthode du pivot de
Gauss. Completer le code suivant :
[13]: def PivotDeGauss(A,b):
if np.linalg.det(A)==0:
print('A n est pas inversible')
else :
Ab=concatener(A,b)
T=triangulariser(Ab)
X=remonter(T)
return X
Appliquer la fonction PivotDeGauss(A,b) pour résoudre le SEL (S0 ).
[14]: PivotDeGauss(A,b)
5
[14]: array([[25.],
[20.],
[30.],
[25.]])
100 ţs ś 1.08 ţs per loop (mean ś std. dev. of 7 runs, 10000 loops each)
10.6 ţs ś 1.09 ţs per loop (mean ś std. dev. of 7 runs, 100000 loops each)
3 Remarque
Les méthodes directes sont très efficaces : elles donnent la solution exacte (aux erreurs d’arrondi
près) du système linéaire considéré mais elles ont l’inconvénient de nécessiter une assez grande
place mémoire car elles nécessitent le stockage de toute la matrice en mémoire vive.
4 Méthodes itératives
Contrairement aux méthodes directes (pivot de Gauss, LU,..) qui consistent à un gros calcul exacte,
les méthodes itératives ( Jacobi, Gauss-Seidel,. . . ) consistent en une succession de petit calcul
approché de la solution.
4.0.1 Principe
On considère le système linéaire AX = b de Cramer. Les méthodes itératives se basent sur une dé-
composition de A sous la forme A = M − N où M est une matrice inversible. Une suite récurrente
de solutions X (k) , k ≥ 0, est ensuite génére comme suit :
• Pour un choix de M = D, où D est une matrice diagonale dont les éléments diagonaux
correspondent à ceux de A, et N = D − A on se trouve avec la méthode de Jacobi.
• Pour un choix de M = L, où L est une matrice triangulaire inférieure dont les éléments sont :
lij = aij si i ≥ j et lij = 0 sinon, et N = L − A on se trouve avec la méthode de Gauss-Seidel.
4.0.2 Convergence
Théorème: Si la matrice A est à diagonale strictement dominante alors les méthodes de Jacobi et
de Gauss_Seidel convergent quelque soit le choix du vecteur initial X (0) .
Ecrire une fonction qui vérifie si une matrice est à diagonale strictement dominante (etat 0) ou
non (etat 1).
6
[16]: def Matrice_diag_dominante(A):
for i in np.arange(0,A.shape[0]):
if np.abs(A[i,i])<=np.sum(np.abs(A[i,:]))-np.abs(A[i,i]):
#print('A n\'est pas à diagonale strictement dominante')
etat=0
break
else:
#print('A est à diagonale strictement dominante')
etat=1
return etat
Tester la fonction Matrice_diag_dominante(A) sur A.
[17]: Matrice_diag_dominante(B)
[17]: 0
> > > > Fin pour > > Fin Tant que
Exercie
Ecrire une fonction jacobi(A, b, X0, epsilon) qui résout le SEL AX = b par la méthode de
Jacobi avec une précision ε et un vecteur initial X0. Proposer deux façons pour le faire.
[18]: # Méthode 1
def jacobi(A, b, X0, epsilon):
etat=int(Matrice_diag_dominante(A))
if etat==0:
print('A n\'est pas à diagonale strictement dominante')
return
else:
D = np.diagflat(np.diag(A))
N = D-A
X1=np.linalg.inv(D).dot(N.dot(X0)+b)
k=1
while np.linalg.norm(X1-X0,1)>epsilon:
X0=X1
X1=np.linalg.inv(D).dot(N.dot(X0)+b)
k+=1
return X0,k
1
1
Tester la méthode de Jacobi pour X (0) = −6
1 et ε = 10 . Interpréter le résultat.
1
7
[19]: X0=np.ones((4,1))
epsilon=10**(-6)
jacobi(A, b, X0, epsilon)
[19]: (array([[24.99999964],
[19.99999964],
[29.99999964],
[24.99999964]]), 27)
Pour des raisons de stockage dans les cases mémoires, il est recommendé d’utilser l’algorithme
de Jacobi qui consiste à calculer directement le vecteur x (k) au cours des itérations.
(k)
En effait, pour calculer ∑nj=1 aij x j on peut utilser les commandes suivantes:
j ̸ =i
1 ( n
(k) )
b1 − ∑ a1j x j
( k +1)
x1 =
a11 j =2
8
D = np.tril(A)
N = D-A
X1=np.linalg.inv(D).dot(N.dot(X0)+b)
k=1
while np.linalg.norm(X1-X0,1)>epsilon:
X0=X1
X1=np.linalg.inv(D).dot(N.dot(X0)+b)
k+=1
return X0,k
1
1
Tester la méthode de Gauss_Seidel pour X (0) = −6
1 et ε = 10 . Interpréter le résultat.
1
[22]: X0=np.ones((4,1))
epsilon=10**(-6)
Gauss_Seidel(A, b, X0, epsilon)
[22]: (array([[24.99999973],
[19.99999987],
[29.99999987],
[24.99999993]]), 15)
Comparer le temps de calcul de chacune des méthodes de résolution de SEL appliquées sur
( S0 ) .
[23]: %timeit jacobi(A,b,X0,epsilon)
%timeit Gauss_Seidel(A,b,X0,epsilon)
%timeit np.linalg.solve(A,b)
%timeit PivotDeGauss(A,b)
831 ţs ś 25.2 ţs per loop (mean ś std. dev. of 7 runs, 1000 loops each)
550 ţs ś 38.5 ţs per loop (mean ś std. dev. of 7 runs, 1000 loops each)
12 ţs ś 1.7 ţs per loop (mean ś std. dev. of 7 runs, 100000 loops each)
108 ţs ś 7.98 ţs per loop (mean ś std. dev. of 7 runs, 10000 loops each)
Exercice
On considère le SEL (Sn ) :AX = b, avec
8 −1 −1 0 0 ··· 0 x1
6
−1 8 −1 −1 0 ··· 0 x2
x3 5
−1 −1 8 −1 −1 ··· 0
. 4
A=
..
.
..
.
..
. ,X = . .
. , b = .. , et n ≥ 4.
.. .. .. .
.. 4
. . .
.. 5
−1 −1 8 −1 .
0 ··· ··· 0 −1 −1 8 xn
6
1- Pour ε = 10−6 , représenter sur un même graphe, le nombre d’itérations effectuées pour
atteindre la convergence par les deux méthodes itératives : Jacobi et Gauss-Seidel, en fonction de
n la taille de la matrice. On considère n ∈ {5, 10, 15, 20, 25, 30}.
9
2- Pour n = 20, représenter sur un même graphe, le nombre d’itérations effectuées pour at-
teindre la convergence par les deux méthodes itératives : Jacobi et Gauss-Seidel, en fonction de la
précision ε. On considère ε ∈ {10−3 , 10−6 , 10−9 , 10−12 }.
On considère le vecteur nul comme vecteur initial.
Interpréter les résultats.
[24]: def S_n(n):
A=8*np.eye(n)+np.diagflat(-np.ones(n-1),1)+np.diagflat(-np.ones(n-2),2)+np.
,→diagflat(-np.ones(n-1),-1)+np.diagflat(-np.ones(n-2),-2)
b=4*np.ones((n,1))
[b[0,0], b[-1,0]]=[6,6]
[b[1,0], b[n-2,0]]=[5,5]
return A,b
[25]: # question 1
epsilon=10**(-6)
N=np.arange(5,31,5)
Iter_J=[]
Iter_GS=[]
for n in N:
S=S_n(n)
X0=np.zeros((n,1))
J=jacobi(S[0],S[1],X0,epsilon)
GS=Gauss_Seidel(S[0],S[1],X0,epsilon)
Iter_J.append(J[1])
Iter_GS.append(GS[1])
[26]: import matplotlib.pyplot as plt
plt.figure(figsize=(20,10))
plt.plot(N,Iter_J,'ro--',N,Iter_GS,'b^--', linewidth=3,markersize=12)
plt.xlabel('Taille de la matrice',fontsize=30)
plt.ylabel('Nombre d\'itérations',fontsize=30)
plt.legend(('Méthode de Jacobi','Méthode de Gauss-Seidel'),fontsize=20, loc = 0)
plt.grid(True)
plt.savefig('Comparaison_n.png',format='png')
[27]: # question 2
n=20
epsilon=[10**-3,10**-6,10**-9,10**-12]
S=S_n(n)
X0=np.zeros((n,1))
Iter_J=[]
Iter_GS=[]
for eps in epsilon:
J=jacobi(S[0],S[1],X0,eps)
GS=Gauss_Seidel(S[0],S[1],X0,eps)
Iter_J.append(J[1])
Iter_GS.append(GS[1])
10
[28]: plt.figure(figsize=(20,10))
plt.plot(epsilon,Iter_J,'ro--',epsilon,Iter_GS,'b^--',␣
,→linewidth=3,markersize=12)
plt.xscale('log')
plt.xlabel('La précision',fontsize=30)
plt.ylabel('Nombre d\'itérations',fontsize=30)
plt.legend(('Méthode de Jacobi','Méthode de Gauss-Seidel'),fontsize=20, loc = 0)
plt.grid(True)
plt.savefig('Comparaison_n.png',format='png')
5 Application
On considère le circuit, donné ci-dessous, pour lequel on donne :
U1 = 110V, U2 = 105V, U3 = 90V, R1 = 0.5W, R2 = 0.25W, et R3 = 0.5W.
V et W désignent respectivement Volt et Watt.
[29]: plt.figure(figsize=(20,10))
plt.imshow(plt.imread('circuit.png'))
[29]: <matplotlib.image.AxesImage at 0x25798f13fd0>
11
i1
Soit I = i2 , on souhaite résoudre un système de la forme RI = U, où R est une matrice
i3
dont les éléments se définissent avec R1 , R2 , et R3 et U est un vecteur dont les éléments se
définissent avec U1 , U2 , et U3 .
A l’aide des lois des nuds, des mailles et d’Ohm, on va déterminer R et U.
Pour calculer les courants i1 , i2 et i3 , on leur choisit un sens, ce qui permet de flécher les tensions
aux bornes des résistances. Le circuit ayant deux noeuds, il n’y a q’une équation de noeuds, en A
par exemple:
i1 + i2 = i3
Il y a 3 mailles, donc on choisit 2 mailles indépendantes afin de compléter le système à résoudre :
Maille 1 : A, R1 , U1 , B, U2 , R2 , A, avec le sens de parcours indiqué :
R1 .i1 − U1 + U2 − R2 .i2 = 0
R2 .i2 U2 + U3 + R3 .i3 = 0
12
[[15.]
[10.]
[25.]]
[[15.]
[10.]
[25.]]
Références [1] Kiusalaas, J. (2013). Numerical methods in engineering with Python 3. Cam-
bridge university press.
[2] Numpy Package
[3] Mathplotlib Package
[4] Jupyter markdowns
13