PSI *
Année 2021-2022
PSI*
Exercice maison : utiliser les idées du programme précédent pour calculer le déterminant d’un matrice carrée. Complexité exigée cubique ! !
Solution disponible :
'
&
$
%
def det(A):
det=1
Ac = copy(A) n = len(A)
for i in range(n-1):#indice de colonne j = chercher_pivotN(Ac, i)
if j!=i:
det=-1*det
echange_lignesNN(Ac, i, j)
for k in range(i+1, n):#ne changent pas le det car on remplace une...
mu = Ac[k][i]/float(Ac[i][i])
transvection_ligneNN(Ac, k, i, -mu)#lk<---Lk-mu*Li for s in range(n):# triangulaire
det = det*Ac[s][s]
Exercice de cours : Décomposition Q-R
Relire le cours à ce sujet est une bonne idée pour mieux comprendre.
Voilà les éléments de cours (maths) à ce sujet :
Algorithme d’orthonormalisation de Gram-Schmidt
1
Def : Soit E un espace préhilbertien réel.
Soit (ei)16i6p une famille libre de E.
Pour tout i de{1, . . . , p}, on pose εi = 1
kuikui, où ui =ei−
i−1
X
j=1
(εj |ei)εj
La première étape de l’algorithme consiste bien sûr à poser ε1 = 1 ke1ke1
Prop : Avec les notations précédentes, l’algorithme de Gram-Schmidt se termine.
Pour tout i de{1, . . . , p}, on a Vect {ε1, . . . , εi}
= Vect {e1, . . . , ei}
, et (εi |ei)>0.
La famille (εi)16i6p ainsi construite est une base orthonormale deVect {e1, . . . , ep} . Mais aussi :
Prop : (Décomposition Q-R).
Soit A∈Gln(R), alors il existe un unique couple Q, R où Q∈On(R) etR ∈Tn++(R).
Preuve : Unicité ( si... ) A=Q1R1 =Q2R2 alors Q−12 Q1 =R2R−11 ∈ On(R).
Donc, on a un produit de triangulaires supérieures et orthogonales, cf exo avant c’est une symétrie, mais les éléments diagonaux sont strictement positifs.
Bref c’estIn. R1 =R2.
Existence : A étant inversible, les colonnes forment une base :(ci)n1. A=M at(Id,(ci)n1,(ei)n1) avec(ei)n1 base canonique et orthonormale.
On fait un schéma en cascade : , on compose deux identités , base de départ (ci)n1, base du milieu (ui)n1, base finale(ei)n1. Avec la base (ui)n1 obtenue par G-S à partir de ci)n1.
AlorsP((ei)n1,(ui)n1) est orthogonale car bon vers bon.
Et P((ui)n1,(ci)n1) est triangulaire supérieure
avec une diagonale de termes strictement positifs. (Voir G-S)...
Le code python Q-R.py
'
&
$
%
import numpy as np
np.set_printoptions(precision = 5) #pour un affichage raisonnable from math import sqrt
def ps(u, v):#bon...
n = len(u) s = 0
for k in range(n):
s += u[k]*v[k]
return s def norme(u):
return sqrt(ps(u, u))
def QR(A): #A est une matrice carrée inversible n = len(A)
e = np.transpose(A);(sss) R = np.zeros((n, n)) orth = np.zeros((n, n))
for j in range(n):#le i du cours
v = e[j]# les vecteurs colonnes de A
for k in range(j):#attention aux indices 0 R[k, j] = ps(orth[k], e[j])
v = v - R[k, j]*orth[k] # vous avez reconnu ? R[j, j] = norme(v)
orth[j] = v/R[j, j]# on remplit au fur et à mesure...
return np.transpose(orth), R# et oui, orth[j]est une ligne, on veut en colonne(sss) L = [[1, 2, 3], [4, 5, 6], [8, 9, 7]]
A = np.array(L) Q, R = QR(A)
Bien sûr, vous aurez vu que la matrice R triangulaire supérieure est la matrice de G-S.
Q∈ On(R) et est la matrice de passage de la base C à l’orthonormalisée de Schmidt.
Les vecteurs colonnes sont donc ...
Calcul du poly caractéristique d’une matrice par la méthode de Le Verrier
La méthode originale (Le Verrier, 1840)
Soit A∈ Mn(C), et (λ1, ..., λn) ses valeurs propres dans C (distinctes ou non).
On sait que le polynôme caractéristique de A s’écrit :
χ
A=Xn−σ1Xn−1+σ2Xn−2− · · ·+ (−1)n−1σn−1X+ (−1)nσn,où les σi sont les fonctions symétriques élémentaires des racines.
De plus, en trigonalisantA, on montre facilement que :∀k ∈N, tr(Ak) =
n
X
i=1
λki
Notons alors sk =
n
X
i=1
λki. On a :
(1) s1 =σ1 (2) s2 =
n
X
i=1
λ2i =
n
X
i=1
λi
!2
−2X
i<j
λiλj =σ12−2σ2.
(3) Cela se complique ensuite, mais l’on peut montrer les formules suivantes (de New- ton) :
∀k6n, sk−σ1sk−1+· · ·+ (−1)k−1σk−1s1+ (−1)kkσk= 0.
Ces formules permettent donc de calculer par récurrence les σi connaissant les sk, donc de calculer les coefficients du polynôme caractéristique deA connaissant les tr(Ak).
1er programme
(1) Quelle est la complexité de cet algorithme pour calculer
χ
A? (2) Écrire le programme Python correspondant, en utilisantnumpy.Solution :
Le nombre d’opérations élémentaires pour calculer un produit matriciel à l’aide des formules vues en cours :
ci,k =
n
X
j=1
ai,jbj,k
est de n2(2n−1) (n2 termes, et à chaque fois n multiplications et n−1additions).
Dans l’algorithme de Le Verrier, il faut calculer A2, A3, . . . , An−1 puis seulement les termes diagonaux de An, ce qui va donner
(n−2)n2(2n−1) +n(2n−1) opérations arithmétiques.
Ensuite il faut calculer les traces de n matrices, soit n(n−1) additions.
Enfin, la résolution de la récurrence exige 2
n
X
k=1
(k−1) =n(n−1)opérations.
En conclusion, la complexité de l’algorithme est en O(n4).
Rq : testez ce programme avec une matrice compagnon.
Ca marche bien et c’est très visuel.
import numpy as np def leverrier(A):
n = A.shape[0]
Ak = A.copy() # puissances de A s = [] # liste des sk
P = [1] # coeff dominant for k in range(1,n+1):
s.append(np.trace(Ak)) Ak = np.dot(Ak, A) somme = 0
for i in range(len(P)):
somme -= P[i]*s[-1-i]
P.append(somme/k) return P
Une amélioration : l’algorithme de Faddeev-Souriau (1948)
Thm : Soit A∈ Mn(K); on pose A1 =A puis :
∀k ∈J2, nK, Ak =A
Ak−1− 1
k−1tr(Ak−1)In
. Alors :
χ
A(X) =Xn−n
X
k=1
1
ktr(Ak)Xn−k Preuve : On démontre par récurrence sur k∈J1, nK que
Ak =Ak−σ1Ak−1+· · ·+ (−1)k−1σk−1A et tr(Ak) = (−1)kkσk en utilisant les formules de Newton données ci-dessus.
2ème programme
(1) Quelle est la complexité de cet algorithme pour calculer
χ
A?(2) Écrire le programme Python correspondant, en utilisantnumpy.
Comparer avec le programme précédent.
def souriau(A):
n = A.shape[0]
Ak = A.copy() # puissances de A I = np.identity(n)
P = [1] # coeff dominant for k in range(1,n+1):
c = -np.trace(Ak)/k P.append(c)
Ak = np.dot(A, Ak + c*I ) return P
Exemple de programme adapté à un objet spécifique.
Résolution d’un système tridiagonale : Le problème se pose classiquement par :
Algorithme de Thomas (1949) pour la résolution d’un système tridiagonal :
Soit à résoudre un systèmeM X =D écrit sous la forme
b1 c1 0 0
a2 b2 c2 0 0 0 a3 b3 c3
. ..
. .. bn−1 cn−1
0 an bn
x1 x2 x3 ... xn−1
xn
=
d1 d2 d3 ... dn−1
dn
Dans une première phase, on rend le système triangulaire supérieur : pour k variant de 2 à n faire
m = ak bk−1 bk =bk−mck−1
dk=dk−mdk−1
puis on résout le système obtenu en commençant par la dernière équation : xn= dn
bn
pour k variant de n-1 à 1 faire xk = dk−ckxk+1
bk
Evaluer la complexité de cet algorithme et comparer à l’algorithme naif.
Merci Odin ! Complexité linéaire ( c’est mieux !).
Conseil personnel , écrire ce programme ( qui marche ! !) sans le cours.
Les décalages d’indices sont omniprésents...
Puis testez sur une matrice de votre choix, comparer le résultat avec pivot de gauss ( vu avant dans ce cours d’informatique ).
'
&
$
%
def TriDiag(a, b, c, d):
n = len(b)
for k in range(0,n-1):
m = a[k] / b[k]
b[k+1] = b[k+1] - m * c[k]
d[k+1] = d[k+1] - m * d[k]
x = n * [0]
x[n-1] = d[n-1] / b[n-1]
for k in range(n-2, -1, -1):
x[k] = (d[k] - c[k] * x[k+1])/b[k]
return(x)
Autre exemple la décomposition LU
Pour toute matrice A possédant des propriétés requises... Au tableau.
Par exemple tous les éléments de la diagonale non nuls (CS). Sinon on inverse des lignes...
Il existe une unique décompositionA =LU avecL de type "Lower" et U de type "Up- per".
La diagonale de L étant composée de1, "preuve" au tableau...Coeff par coeff...
Nous avons dans ce cours, deux façons de voir le problème :
• On devine l’algorithme et après on le programme.
• Je vous donne le programme et on explique l’algorithme, car on manque de temps...
'
&
$
%
import numpy as np from copy import copy
def transvectionbis(A,i,j,coef,jj):
for k in range (jj,len(A)):
A[i,k]+=coef*A[j,k]
def transvectioncolbis(A,i,j,coef,jj):
for k in range(jj,len(A)):
A[k,i]+=coef*A[k,j]
def LU(A):
n=len(A) U=np.copy(A) L=np.identity(n) for j in range(n):
for k in range(j+1,n):
coef=-1*U[k,j]/U[j,j]
transvectionbis(U,k,j,coef,j)
transvectioncolbis(L,j,k,-1*coef,0) return (L,U)
Première partie de notre travail : comprendre les sous programmes.
Bis : Li <−Li+coef ∗Lj mais après Cjj...
Colbis :Ci <−Ci+coef ∗Cj mais après Ljj...
Difficile à vectoriser.
Puis le programme final, on fait apparaitre des 0sur la première colonne de U (ligne par ligne) mais en maintenant le produit LU constant ègal àA,
puis la deuxième colonne...etc
Remarque j est un indice de colonne etk de ligne.
Les questions importantes :
Correction : l’invariant de boucle peut être à chaque tour de boucle :
Le produit des variables locales L etU est égal à A (initialisation et sortie).
Mais aussi ( c’est le problème de tout mettre dans l’invariant ), typiquement
au concours on vous demanderait de le citer correctement mais pas de le prouver.
La matrice L reste triangulaire inférieure à diagonale de 1.
Et la matriceU possède des 0sur les colonnes déjà traitées, ainsi que le morceau de colonne en cours de traitement.
La complexité : attention à d’abord évaluer celle des sous programmes...
Bien sûr, elle est vérifiable avec "time".
Elle est cubique, car ...Les sous-programmes sont de complexité linéaire en moyenne.
Puis deux boucles imbriquées, avec un coeur de boucle à coût linéaire ( en moyenne).
n−1
X
j=0 n−1
X
k=j+1
2 +
n−1
X
j
3 +
n−1
X
0
3
! .
L’utilité : si on doit résoudre plusieurs systèmes de même matrice,
mais avec des seconds membres qui changent, alors la mettre sous ce format nous ramène à des résolutions de systèmes triangulaires ( voir remontée ).
Recherche des éléments propres
Il est souvent nécessaire de savoir calculer numériquement les valeurs et les vecteurs propres dans des situations concrètes impliquant des grands systèmes où les méthodes théoriques sont pratiquement inutilisables.
La stratégie générale pour déterminer les valeurs propres et les vecteurs propres consiste à construire une suite de transformations en des matrices semblables jusqu’à l’obtention d’une matrice diagonale, ou plus simplement jusqu’à l’obtention d’une matrice triangulaire, à partir de laquelle il est possible de déterminer assez facilement les vecteurs propres.
Pour réaliser ces transformations, deux grandes classes de méthodes sont disponibles : les méthodes directes et les méthodes itératives.
Les premières consistent à effectuer une suite de transformations conservant la simili- tude ; elles ne s’appliquent que sur des matrices de taille modeste, car le temps de calcul
croît comme le cube de la taille de la matrice.
Pour les matrices de grande taille et généralement creuses, les méthodes itératives sont plus adaptées.
De plus, il existe des méthodes spécifiques pour certaines catégories de matrices (les matrices symétriques, tridiagonales etc...).
Méthode de la puissance itérée
Ceci donne une très bonne approximation de la plus grande valeur propre en module.
La suite est disponible pour élèves très motivés, elle est très crescendo...
Informatique, evn , fonctions de plusieurs variables ...