-
- 1.1. Exo 1 - Affichage des matrices
- 1.1.1. Solution de l'exo1
- 1.1.1.1. 1) Affichage simple
- 1.1.1.2. 2) Affichage en tableau
- 1.1.1.3. 3) Liste de print
- 1.1.1.4. 4) Affichage avec join()
- 1.1.1.5. 5) Affichage par éléments formatés
- 1.1.1.6. 6) Double join()
- 1.1.1. Solution de l'exo1
- 1.2. Exo2 : Somme et différence
- 1.3. Exo 3 : Transposé
- 1.3.1. Solution
- 1.4. Exo 4 : Produit matriciel
- 1.4.1. Solution
- 1.4.1.1. Boucles imbriquées
- 1.4.2. Calcul avec Compréhensions de listes
- 1.4.2.1. Calcul $A.B^T$
- 1.4.1. Solution
- 1.5. Exo 5 : Calcul de trace
- 1.5.1. Solution
- 1.1. Exo 1 - Affichage des matrices
-
- 2.1. Exo 6 : Operations indicielles avec $\delta$
- 2.1.1. Solution
- 2.1.1.1. delta_ij
- 2.1.1.2. Operations avec delta
- 2.1.1. Solution
- 2.2. Exo 7 : Symbole de permutation
- 2.2.1. Solution
- 2.2.1.1. Symbole de permutation
- 2.2.1.2. Determinant
- 2.2.1. Solution
- 2.1. Exo 6 : Operations indicielles avec $\delta$
1.1. Exo 1 - Affichage des matrices¶
On considère les trois matrices d'ordre 3 suivantes:
# Les trois matrices
n = 3
A = [[2, 3, 5],
[4, 1, 6],
[3, 2, 1]
]
B = [[4 , 2, -1],
[2 , 5, -2],
[-1, 4, 2]
]
C = [[5, -2, 3],
[3, 6, 4],
[1, 2, 2]
]
L'affichage le plus simple de l'une des 3 matrices, par exemple matrice A est :
print('A =', A )
Afficher les 3 matrices avec cette commande, puis noter les séparations par des des virgules
Afficher la matrice A en utilisant une seule boucle
forsous forme d'un tableau qui se présente comme suit:A = [2, 3, 5] [4, 1, 6] [3, 2, 1]
Écrire la boucle for de deux manières : (a) avec parcours par lignes (sous-listes) et (b) avec parcours par indices
Taper la commande suivante :
[print(ligne) for ligne in A].- Noter et expliquer ce qu'elle affiche comme résultats
- Modifier la commande en utilisant un indice au lieu de l'élément
ligne
Taper la commande suivante :
print('\n'.join(str(A[i]) for i in range(n)))- Comparer cette commande à celle de la question 3 et commenter.
- Expliquer le transtypage en chaîne de caractère :
str(A[i]) - Écrire la commande équivalente qui utilise un parcours de la matrice par éléments
- Écrire pour les deux cas, la boucle for équivalente qui permet de produire le même affichage.
Le code à double boucles suivant permet d'afficher
Asous forme de tableau avec formatage des éléments en.2ffor ligne in A: print('[', end='') for elem in ligne: print(f'{elem :.2f}', end=' ') print(']')
- Expliquer pourquoi on a ajouter :
print('[', end='')etprint(']')en début et en fin de la boucle interne. - A quoi sert le
end=' 'dans les commandesprint - Modifier ce code pour faire un parcourt des éléments de
Apar indices
- Expliquer pourquoi on a ajouter :
La commande suivante permet est équivalente à le double boucle précédente mais n'affiche pas les crochets []. Modifier la pour y remédier.
print('\n'.join(' '.join(f'{elem :.2f}' for elem in ligne) for ligne in A))
1.1.1. Solution de l'exo1¶
1.1.1.1. 1) Affichage simple¶
Note:
- Les sous-listes et les éléments des sous listes sont séparés par des virgules
- chaque sous-liste (ligne de la matrice) est délimitée par des crochets []
# Réponse - commandes des affichages
print('Affichage simple :')
print('A =', A )
print('B =', B )
print('C =', C)
Affichage simple : A = [[2, 3, 5], [4, 1, 6], [3, 2, 1]] B = [[4, 2, -1], [2, 5, -2], [-1, 4, 2]] C = [[5, -2, 3], [3, 6, 4], [1, 2, 2]]
1.1.1.2. 2) Affichage en tableau¶
La boucle for permet de parcourir les éléments d'une liste quelque soient leurs types .
Dans notre cas, chaque élément de la liste A est aussi une liste qui contient les composantes (nombres réels) de la matrice. Les sous-listes constituent les lignes de A, on affiche donc chacune d'elles en les extrayant une à une de A avec for soit avec un parcours par éléments ou avec leurs indices.
# boucle for avec parcours par lignes
print('Affichage avec for - parcours par lignes ')
print('A =')
for ligne in A:
print(ligne)
# boucle for avec parcours d'indice
print('\nAffichage avec for - parcours par indices')
print('A =')
for i in range(n):
print(A[i])
Affichage avec for - parcours par lignes A = [2, 3, 5] [4, 1, 6] [3, 2, 1] Affichage avec for - parcours par indices A = [2, 3, 5] [4, 1, 6] [3, 2, 1]
1.1.1.3. 3) Liste de print¶
La commande : [print(ligne) for ligne in A] affiche la matrice A sous la même forme (de tableau) que les commandes précédentes.
Remarque : En mode interactif, ou sous un environnement jupyter notebook (comme google colab ou vscode, ou autre) l'expression de compréhension de liste affiche en plus de A, une ligne [None, None, None] puisque print() renvoie None
Réécriture de la commande avec indice dans le code suivant:
# liste de print de chaque ligne
# la commande peut afficher aussi [None, None, None]
# en plus de A si elle est la dernière commande de
# la cellule de code en mode interactif
print('Affichage avec liste [] - parcours par lignes :')
print('A =')
[print(ligne) for ligne in A]
# avec indices
print('\nAffichage avec liste [] - parcours par indices :')
[print(A[i]) for i in range(n)]
Affichage avec liste [] - parcours par lignes : A = [2, 3, 5] [4, 1, 6] [3, 2, 1] Affichage avec liste [] - parcours par indices : [2, 3, 5] [4, 1, 6] [3, 2, 1]
[None, None, None]
1.1.1.4. 4) Affichage avec join()¶
On rappelle que la fonction join() de str permet de joindre les élément d'une liste de str en une chaîne de caractère.
ELle peut donc être utilisée pour afficher lignes de A en les joignant avec des '\n' (retour de ligne ).
Pour cela il faut d'abord transformer avec str, chaque ligne (qui est une liste) en chaîne de caractères avant d'appliquer join().
Comparativement à la commande de la question 3, print affiche ici une chaîne de caractère construite avec join() appliquée à la liste A. La chaîne produite est : [2, 3, 5]\n[4, 1, 6]\n[3, 2, 1]
La transtypage en strest nécessaire pour la fonction join(). Il permet de transformer chaque ligne de A qui est de type list en une chaîne de caractère (de type str).
Par exemple la commande : ch = str(A[1]) contient tous les caractères qui permettent d'afficher la deuxième sous-liste de A (donc la ligne 2), y compris les crochets.
print(f'{ch = }')produit : ch = '[4, 1, 6]' et print(f'{ch[0] = }') produit ch[0] = '['
Commande équivalente avec parcours par éléments et les boucles for équivalentes dans le code suivant:
print('Affichage par indices avec join():')
print('\n'.join(str(A[i]) for i in range(n)))
print('\nAffichage par lignes avec join():')
print('A =')
print('\n'.join(str(ligne) for ligne in A))
Affichage par indices avec join(): [2, 3, 5] [4, 1, 6] [3, 2, 1] Affichage par lignes avec join(): A = [2, 3, 5] [4, 1, 6] [3, 2, 1]
1.1.1.5. 5) Affichage par éléments formatés¶
La première boucle fais un parcours sur les lignes de A et la seconde sur les éléments.
print('[', end='') en début de boucle ajoute un crochet ouvrant [ en début de chaque ligne avant de parcourir ces éléments avec la deuxième boucle. L'ajout de end='' permet de rester sur la même ligne d'affichage et d'éviter un saut de ligne à la sortie avant d'ajouter l'affichage des éléments.
Le dernier print(']') en fin de seconde boucle fait aussi partie de la boucle externe, il permet de fermer la ligne avec un crochet fermant ] tout en provoquant un saut de ligne.
Le end=' ' dans print(f'{elem :.2f}', end=' ') permet d'afficher tous les éléments sur la même ligne tout en les séparant avec un seul caractère espace.
Modification du code pour faire un parcourt des éléments de A par indices
print('Affichage par composantes formatées avec for:')
print('A =')
for ligne in A:
print('[', end='') # On ouvre avec crochet de la ligne
for elem in ligne: # noter end=' ' pour rester sur la même ligne
print(f'{elem :.2f}', end=' ') # impression des éléments sur la même ligne
print(']') # On ferme le crochet de la ligne
# parcours par indices:
print('\nParcours par indices :')
print('A =')
for i in range(n):
print('[', end='')
for j in range(n):
print(f'{A[i][j] :.2f}', end=' ')
print(']')
Affichage par composantes formatées avec for: A = [2.00 3.00 5.00 ] [4.00 1.00 6.00 ] [3.00 2.00 1.00 ] Parcours par indices : A = [2.00 3.00 5.00 ] [4.00 1.00 6.00 ] [3.00 2.00 1.00 ]
1.1.1.6. 6) Double join()¶
On modifie la commande en ajoutant les crochets:
# Le 1er join permet de sauter les lignes avec '\n'
# Le 2em join permet de joindre les éléments avec un espace ' '
# Le formatage est réalisé ici avec un f-string.
print('Affichage par composantes formatées avec join():')
print('A =')
print('\n'.join(' '.join(f'{elem :.2f}' for elem in ligne) for ligne in A))
# Avec cette commande on ajoute les crochet en début et en fin de chaque ligne
# On utilise pour cela la concaténation de str : l'opérateur plus (+)
print('Affichage par composantes formatées avec join() et crochets []:')
print('A =')
print('['+'\n['.join(' '.join(f'{elem :.2f}' for elem in ligne)+']' for ligne in A))
Affichage par composantes formatées avec join(): A = 2.00 3.00 5.00 4.00 1.00 6.00 3.00 2.00 1.00 Affichage par composantes formatées avec join() et crochets []: A = [2.00 3.00 5.00] [4.00 1.00 6.00] [3.00 2.00 1.00]
1.2. Exo2 : Somme et différence¶
Ecrire un code qui permet de calculer la somme $P = A+B$ et la différence $M = A-B$. Réaliser trois versions:
- une première se base sur des boucles
forimbriquées avec parcours sur les indices - une seconde se base sur des boucles
forimbriquées avec parcours sur des éléments - une troisième, plus compacte que les précédentes, se base sur les comprehensions de listes
1.2.1. Solution¶
1.2.1.1. Version 1¶
Dans ce cas une seule boucle suffit pour réaliser les deux operations en même temps.
Comme les matrices $P$ et $M$ sont représentées avec des variables de type list,
il faut donc les initialiser avec des crochet [] vides avant de les remplir avec la méthode append.
Les elements transmis à append doivent être des listes pour avoir au finale une liste de listes, où chaque sous-liste est une ligne de la matrice considérée.
On désigne par ligneP les sous listes de P et par ligneM celles de M. Il faut aussi initialiser ces deux sous listes pour chaque indice i de la boucle for sur les lignes. Ensuite, on les met à jour avec append pour tout indice j sur les colonnes.
# Version 1 : Boucle for avec parcours sur les indices
P = [] # initialisation de P
M = [] # initialisation de M
for i in range(n): # boucle sur les lignes
ligneP = [] # initialisation de la ligne_i de P
ligneM = [] # initialisation de la ligne_i de M
for j in range(n): # boucle sur les colonnes
ligneP.append(A[i][j] + B[i][j]) # somme
ligneM.append(A[i][j] - B[i][j]) # différence
P.append(ligneP) # ajout de la ligne à P
M.append(ligneM) # ajout de la ligne à M
print('P = \n ' , '\n '.join(str(elem) for elem in P))
print('M = \n ' , '\n '.join(str(elem) for elem in M))
P = [6, 5, 4] [6, 6, 4] [2, 6, 3] M = [-2, 1, 6] [2, -4, 8] [4, -2, -1]
1.2.1.2. Version 2¶
Dans ce cas le parcours par éléments est un peut compliqué car il faut extraire en même temps, ligne par ligne, une ligne de A et une ligne de B qui lui correspond.
On utilise pour cela zip(A,B) qui permet de construire objet contenant des tuples à partir des éléments des listes A et B. Le code ci-dessous donne un rappel sur l'utilisation de l'objet zip.
On utilisera la dernière commande de boucle for avec déballage des éléments de zip, pour écrire la 2ème version du code demandé.
# Rappel sur la méthode zip
print('Objet zip :')
print(zip(A,B)) # affiche l'objet zip
print('\nTranstypage en liste:') # Transtypage en list
print(list(zip(A,B)))
print('\nEléments du zip') # parcours des éléments
print([z for z in zip(A,B)])
print('\nDéballage du zip') # déballage (dépaquetage) des éléments
print([z1+z2 for z1,z2 in zip(A,B)]) # attention à: liste + liste
print('\nBoucle for avec dépaquetage du zip')
for z1,z2 in zip(A,B):
print(z1, z2)
Objet zip : <zip object at 0x000001FF17045D00> Transtypage en liste: [([2, 3, 5], [4, 2, -1]), ([4, 1, 6], [2, 5, -2]), ([3, 2, 1], [-1, 4, 2])] Eléments du zip [([2, 3, 5], [4, 2, -1]), ([4, 1, 6], [2, 5, -2]), ([3, 2, 1], [-1, 4, 2])] Déballage du zip [[2, 3, 5, 4, 2, -1], [4, 1, 6, 2, 5, -2], [3, 2, 1, -1, 4, 2]] Boucle for avec dépaquetage du zip [2, 3, 5] [4, 2, -1] [4, 1, 6] [2, 5, -2] [3, 2, 1] [-1, 4, 2]
# Version 2 : Boucle for avec parcours sur les éléments
P, M = [],[] # initialisation de P et M
for ligneA,ligneB in zip(A,B): # boucle sur les lignes de A et de B
ligneP, ligneM = [], [] # initialisation des lignes de P et de M
for a,b in zip(ligneA,ligneB): # le contenu des deux lignes
ligneP.append(a + b)
ligneM.append(a - b)
P.append(ligneP) # ajout de ligneP à P
M.append(ligneM) # ajout de ligneM à M
print('P = \n ' , '\n '.join(str(elem) for elem in P))
print('M = \n ' , '\n '.join(str(elem) for elem in M))
P = [6, 5, 4] [6, 6, 4] [2, 6, 3] M = [-2, 1, 6] [2, -4, 8] [4, -2, -1]
# Version 3: Compréhension de listes (avec parcours par indices)
print('Parcours par indices:')
P = [[A[i][j] + B[i][j] for j in range(n)] for i in range(n)]
M = [[A[i][j] - B[i][j] for j in range(n)] for i in range(n)]
print('P =', P)
print('M =', M)
Parcours par indices: P = [[6, 5, 4], [6, 6, 4], [2, 6, 3]] M = [[-2, 1, 6], [2, -4, 8], [4, -2, -1]]
# Version 3: Compréhension de listes (avec parcours par éléments)
print('\nParcours par éléments :')
P = [[a + b for a,b in zip(ligneA,ligneB)] for ligneA,ligneB in zip(A,B)]
M = [[a - b for a,b in zip(ligneA,ligneB)] for ligneA,ligneB in zip(A,B)]
print('P =', P)
print('M =', M)
Parcours par éléments : P = [[6, 5, 4], [6, 6, 4], [2, 6, 3]] M = [[-2, 1, 6], [2, -4, 8], [4, -2, -1]]
Remarque
Du point de vue performances, les deux versions de parcours par indices ou par éléments avec zip sont équivalents pour les petites matrices. Par contre pour les matrices de grande tailles, parcours par éléments utilisant zip est plus ride. Par exemple pour une matrice 10000x10000, on obtient un gain de 56% par rapport aux indices.
De plus la version avec zip est idiomatique (pythonic) et efficace si on ne veut pas verifier les dimensions des listes, mais elle crée des tuples pour chaque ligne à construire.
La version avec des indices : A[i][j] + B[i][j] correspond au formalisme mathématique Aij+Bij. Elle est plus naturelle pour les initiés aux calcul numérique et l'écriture indicielle.
1.3. Exo 3 : Transposé¶
Ecrire un code qui permet de calculer les transposés ($A^T$, $B^T$ et $C^T$) des matrices ($A$,$B$,$C$) en utilisant :
- des compréhensions de listes.
- des boucles
forimbriquées
Nommer les transposées avec les variables AT, BT et CT
# Transposée des matrices avec compréhensions de listes
AT = [[A[j][i] for j in range(n)] for i in range(n)]
BT = [[B[j][i] for j in range(n)] for i in range(n)]
CT = [[C[j][i] for j in range(n)] for i in range(n)]
print('AT = \n ' , '\n '.join(str(elem) for elem in AT))
print('BT = \n ' , '\n '.join(str(elem) for elem in BT))
print('CT = \n ' , '\n '.join(str(elem) for elem in CT))
AT = [2, 4, 3] [3, 1, 2] [5, 6, 1] BT = [4, 2, -1] [2, 5, 4] [-1, -2, 2] CT = [5, 3, 1] [-2, 6, 2] [3, 4, 2]
# Transposée des matrices avec boucle de listes
AT, BT, CT = [], [], [] #initialisation des listes
for i in range(n):
#initialisation des sous-listes
ligneAT, ligneBT, ligneCT = [], [],[]
for j in range(n):
ligneAT.append(A[j][i])
ligneBT.append(B[j][i])
ligneCT.append(C[j][i])
AT.append(ligneAT)
BT.append(ligneBT)
CT.append(ligneCT)
print('AT = \n ' , '\n '.join(str(elem) for elem in AT))
print('BT = \n ' , '\n '.join(str(elem) for elem in BT))
print('CT = \n ' , '\n '.join(str(elem) for elem in CT))
AT = [2, 4, 3] [3, 1, 2] [5, 6, 1] BT = [4, 2, -1] [2, 5, 4] [-1, -2, 2] CT = [5, 3, 1] [-2, 6, 2] [3, 4, 2]
1.4. Exo 4 : Produit matriciel¶
Ecrire un code qui permet de calculer avec des boucles imbriquées les produits matriciels : $D = A \cdot B$ et $E = A \cdot B \cdot C$
Réécrire le code en plus compacte avec des compréhensions de listes et des générateurs
Ecrire de de deux façons les produits suivants : $F = A \cdot B^T$
- en utilisant les matrices les transposées calculées à l'exo 2
- en utilisant les matrices originale A,B et C
1.4.1.1. Boucles imbriquées¶
# 1. Calcul avec boucles
# Matrice D = A.B avec boucles
# D_ij = somme_k (A_ik B_kj)
print('Calcul avec des boucles')
D = []
for i in range(n):
ligne = []
for j in range(n):
s = 0
for k in range(n):
s+= A[i][k]*B[k][j]
ligne.append(s)
D.append(ligne)
print('D = A.B =', D)
# matrice E = A.B.C avec boucles
# E_ij = somme_k somme_l (A_ik B_kl C_lj)
E = []
for i in range(n):
ligne = []
for j in range(n):
s = 0
for k in range(n):
for l in range(n):
s+= A[i][k]*B[k][l]*C[l][j]
ligne.append(s)
E.append(ligne)
print('E = A.B.C =', E)
Calcul avec des boucles D = A.B = [[9, 39, 2], [12, 37, 6], [15, 20, -5]] E = A.B.C = [[164, 220, 187], [177, 210, 196], [130, 80, 115]]
# 2. Calcul avec générateurs et comprehensions de listes
print('\nCalcul avec générateurs et de compréhension de liste')
# matrice D = A.B
D = [[sum( A[i][k]*B[k][j] for k in range(n) ) for j in range(n)] for i in range(n)]
print('D = A.B =', D)
# matrice E = A.B.C
# E_ij = somme_k somme_l (A_ik B_kl C_lj)
E = [[sum( A[i][k]*B[k][l]*C[l][j] for k in range(n) for l in range(n)) for j in range(n)] for i in range(n)]
print('E = A.B.C =', E)
Calcul avec générateurs et de compréhension de liste D = A.B = [[9, 39, 2], [12, 37, 6], [15, 20, -5]] E = A.B.C = [[164, 220, 187], [177, 210, 196], [130, 80, 115]]
1.4.2.1. Calcul $A.B^T$¶
#3. Calcul de F = A . B_Transposée, et G = A_Transposée.B
# On préfère les versions compactes puisque
# la question n'impose pas les boucles
# Calcul avec A et BT (on utilise BT de l'exo 2)
# F_ij = somme_k (A_ik BT_kj)
F = [[sum( A[i][k]*BT[k][j] for k in range(n) ) for j in range(n)] for i in range(n)]
print(F)
# Calcul avec A et B (on transpose B à l'intérieur de l'expression)
# F_ij = somme_k (A_ik B_jk)
F = [[sum( A[i][k]*B[j][k] for k in range(n) ) for j in range(n)] for i in range(n)]
print(F)
[[9, 9, 20], [12, 1, 12], [15, 14, 7]] [[9, 9, 20], [12, 1, 12], [15, 14, 7]]
1.5. Exo 5 : Calcul de trace¶
Ecire un code qui permet de calculer les traces des produits :
Trace(A.B), Trace(A.B_transposée) et comparer les résultats aux traces : Tr(D) et Tr(F)
# Trace du produit A.B
# trace(AB) = somme_i somme_k (A_ik) B_ki
trace_AB = sum(A[i][k]*B[k][i] for i in range(n) for k in range(n))
print(f'somme_k somme_i : {trace_AB = }')
# Remarque :
# l'ordre de indices dans le générateur aplatit n'est pas important
trace_AB = sum(A[i][k]*B[k][i] for k in range(n) for i in range(n))
print(f'somme_i somme_k : {trace_AB = }')
# Comparaison avec trace(E) : F = A.B
# trace(F) = somme_i F_ii
trace_D = sum(D[i][i] for i in range(n))
print(f'somme_i : {trace_D = }')
# Comparaison avec trace(A.BT)
trace_ABT = sum(A[i][k]*BT[k][i] for k in range(n) for i in range(n))
somme_k somme_i : trace_AB = 41 somme_i somme_k : trace_AB = 41 somme_i : trace_D = 41
# Trace du produit A.B_transposée
# trace(A.B_transposé) = somme_i somme_k (A_ik) B_ik
trace_AB_transpose = sum(A[i][k]*B[i][k] for i in range(n) for k in range(n))
print(f'{trace_AB_transpose = }')
# Comparaison avec trace(E) : E = A.BT
# trace(E) = somme_i E_ii
trace_F = sum(F[i][i] for i in range(n))
print(f'{trace_F = }')
trace_AB_transpose = 17 trace_F = 17
2.1. Exo 6 : Operations indicielles avec $\delta$¶
Dans cet exercice, on construit la matrice identité ($\delta$ de Kronecker) puis on l'utilise pour réaliser de opérations matricielles.
Tous les codes seront réalisés de préférence avec des expressions de compréhensions de listes et de générateurs
- Ecrire un code qui permet de construire delta
- Ecrire un code qui permet de réaliser les opération suivantes (au sense de l'écriture indicielle),
et commenter le résultat de chacune d'elles.- $\delta_{ij} A_{jk}$ : ---> somme sur j
- $\delta_{ij} \delta_{ji}$ : ---> somme sur i et sur j
- $\delta_{ij} \delta_{ij}$ : ---> somme sur i et sur j
- $\delta_{ij} A_{ij}$ : ---> somme sur i et sur j
# Matrice delta_ij version 1
# construction ligne par ligne
# chaque ligne par éléments
n = 3
delta = []
for i in range(n):
ligne = []
for j in range(n):
ligne.append(int(i==j)) # liste pour la ligne i
delta.append(ligne) # ajout de la sous-liste
print(delta)
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
# Matrice delta_ij version 2
# construction ligne par ligne
# chaque ligne par une compréhension de liste
n = 3
delta = []
for i in range(n):
delta.append([int(i==j) for j in range(n)])
print(delta)
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
# Matrice delta_ij version 3
# construction avec des compréhension de listes imbriquées
n = 3
delta = [ [int(i==j) for j in range(n)] for i in range(n) ]
print(delta)
2.1.1.2. Operations avec delta¶
# 1. delta_ij A_ji
# Le résultat donne la matrice A
M = [ [ sum(delta[i][j] * A[j][k] for j in range(n)) for k in range(n)] for i in range(n) ]
print('delta_ij A_ji =', M)
print('matrice A =', A)
delta_ij A_ji = [[2, 3, 5], [4, 1, 6], [3, 2, 1]] matrice A = [[2, 3, 5], [4, 1, 6], [3, 2, 1]]
#2 et 3. même chose puisque delta est symétrique :
# delta_{ij} delta_{ji} = delta_{ij} delta_{ij}
# on a une double somme sur i et sur j
# Le résultat : trace(delta) = 3
# on utilise un générateur à 2 indices aplatit
s = sum(delta[i][j] * delta[j][i] for j in range(n) for i in range(n))
print('delta_{ij} delta_{ji} = ', s)
delta_{ij} delta_{ji} = 3
# 4.\delta_{ij} A_{ij}$ : ---> somme sur i et sur j
# résultat : trace(A) = 4
# on utilise dans ce cas aussi un générateur à 2 indices aplatit
t = sum(delta[i][j] * A[j][i] for j in range(n) for i in range(n))
print('delta_{ij} A_{ij} = ', t)
delta_{ij} A_{ij} = 4
2.2. Exo 7 : Symbole de permutation¶
Dans cet exercice, on construit le symbole de permutation $\varepsilon$ de Levi-Civita puis on l'utilise pour calculer le determinant d'une matrice.
Dans cet exercice aussi, tous les codes seront réalisés de préférence avec des expressions de compréhensions de listes et de générateurs.
Ecrire un code qui permet de construire epsilon et de l'afficher comme trois matrices selon la valeur de k, puis de l'utiliser pour calculer le determinant de A.
Ajouter un test qui permet de s'assurer que $n=3$. Si ce n'est pas le cas les opérations ne sont plus valables
On rappelle qu'en 3D ($=3$) : $$ \varepsilon_{ijk} = \frac{1}{2}(i-j)(j-k)(k-i) $$ $$ \mathrm{det}(A)= \varepsilon_{ijk}\, A_{1i}\, A_{2j}\,A_{3k} $$ Attention : (i,j,k) = (1,2,3) en permutation d'indices, mais en python ces (0,1,2). Vérifier qu'il n'y a aucun impact sur la définition de epsilon
Prendre la matrice suivante
A = [[2 , -1 , 3 ],
[4 , 2 , -1 ],
[5 , 1 , 6 ]]
2.2.1. Solution¶
2.2.1.1. Symbole de permutation¶
Comme on a vu dans les exercices précédents, le plus simple est d'utiliser une expression de compréhension de liste
# Construction de epsilon
# on utilise range(3) pour imposer la 3D
#
eps = [[[(i-j)*(j-k)*(k-i)//2 for k in range(3) ] for j in range(3)] for i in range(3)]
# affichage
for k in range(3):
print('k = ', k)
print('\n'.join(' '.join(f'{val :>2d}' for val in ligne) for ligne in eps[k]) )
# on peut utiliser l'un des affichages suivants (cf exo1)
#print('\n'.join(str(ligne) for ligne in eps[k]) )
#print('k = ',k,[matrice for matrice in eps[k]])
k = 0 0 0 0 0 0 1 0 -1 0 k = 1 0 0 -1 0 0 0 1 0 0 k = 2 0 1 0 -1 0 0 0 0 0
2.2.1.2. Determinant¶
On utilise la fonction sum sur un générateur plat à 4 indices
# Calcul du determinant
A = [[2 , -1 , 3 ],
[4 , 2 , -1 ],
[5 , 1 , 6 ]]
n = len(A)
if n != 3:
raise ValueError('n doit être égale à 3')
det = sum(eps[i][j][k] * A[0][i] * A[1][j] * A[2][k]
for k in range(n) for j in range(n) for i in range(n))
print('det(A) = ', det)
det(A) = 37
Aucun commentaire:
Enregistrer un commentaire