VaultBy ENSAMIENParrainage
Notebook

Vectorisation:

correction.ipynb

TDP 05
Vectorisation, Matrices, Fichiers

Répondez aux questions et envoyez à votre classe room le fichier
ayant comme nom le format suivant

  • TDP_05_Python_NOM_PRENOM.ipynb

    </ul>
    

Nom Prénom : CHOUBIK Houssam

Technique efficace qui permet d’appliquer des opérations à des ensembles de données (comme des tableaux) sans utiliser de boucles explicites.

  • Générer deux tableaux a et b via np.random.rand() chacun de taille 10_000_000
  • calculer manuellement (via une boucle for) le produit scalaire de a et b, en calculant le temps d'execution
  • comparer avec le temps d'execution du calcul du produit scalaire en utilisant:
    • np.dot()
    • np.inner()
    • a@b
  • conclusion ?
import numpy as np
import random
import time

nbf = 1_000_000
a = np.array([random.randint(0,10) for i in range(nbf)])
b = np.array([random.randint(0,10) for i in range(nbf)])
# Calcul du Produit scalaire via une boucle for

start = time.time()
dot_for = 0
dot_for1 = 0
for i in range(nbf):
    dot_for += a[i] * b[i]
end = time.time()
t_for = end - start
print(f"Produit scalaire (for): {dot_for} - Temps: {t_for:.10f} s")

# Calcul du Produit scalaire via np.dot()
start_np = time.time()
dot_np = np.dot(a, b)
end_np = time.time()
t_np = end_np - start_np
print(f"np.dot: {dot_np} - Temps: {t_np:.10f} s")

# Calcul du Produit scalaire via np.inner()

start = time.time()
dot_inner = np.inner(a, b)
end = time.time()
t_inner = end - start
print(f"np.inner: {dot_inner} - Temps: {t_inner:.10f} s")

# Calcul du Produit scalaire via a@b

start = time.time()
dot_at = a @ b
end = time.time()
t_at = end - start
print(f"a @ b: {dot_at} - Temps: {t_at:.10f} s")

# Afficher les temps d'execution respectifs

print(f"for loop : {t_for:.10f} s")
print(f"np.dot():  {t_np:.10f} s")
print(f"np.inner():{t_inner:.10f} s")
print(f"a @ b:     {t_at:.10f} s")
Produit scalaire (for): 24976387 - Temps: 0.7201502323 s
np.dot: 24976387 - Temps: 0.0020172596 s
np.inner: 24976387 - Temps: 0.0020222664 s
a @ b: 24976387 - Temps: 0.0040330887 s
for loop : 0.7201502323 s
np.dot():  0.0020172596 s
np.inner():0.0020222664 s
a @ b:     0.0040330887 s
  • Refaire un travail similaire, mais cette fois ci pour des matrices :
    • A de taille (100, 100)
    • B de taille (100, 100)
import numpy as np
import random
import time


dim = 100
plg=99

A = np.random.randint(plg, size=(dim, dim))
B = np.random.randint(plg, size=(dim, dim))
D = np.zeros((dim,dim))
#Produit matriciel via trois boucles for
start = time.time()
for i in range(dim):
    for j in range(dim):
        s = 0
        for k in range(dim):
            s += A[i, k] * B[k, j]
        D[i, j] = s
end = time.time()
t_for = end - start
print(f"Produit matriciel (3 boucles for) terminé - Temps: {t_for:.4f} s")

#Produit matriciel via np.dot()
start = time.time()
D_dot = np.dot(A, B)
end = time.time()
t_dot = end - start
print(f"np.dot terminé - Temps: {t_dot:.6f} s")

#Produit matriciel via np.matmul()
start = time.time()
D_matmul = np.matmul(A, B)
end = time.time()
t_matmul = end - start
print(f"np.matmul terminé - Temps: {t_matmul:.6f} s")

# Calcul du Produit scalaire via a@b
start = time.time()
D_at = A @ B
end = time.time()
t_at = end - start
print(f"A @ B terminé - Temps: {t_at:.6f} s")

# Afficher les temps d'execution respectifs
print(f"Manuel (for loops): {t_for:.4f} s")
print(f"np.dot():           {t_dot:.6f} s")
print(f"np.matmul():        {t_matmul:.6f} s")
print(f"A @ B:              {t_at:.6f} s")
Produit matriciel (3 boucles for) terminé - Temps: 0.7567 s
np.dot terminé - Temps: 0.002025 s
np.matmul terminé - Temps: 0.004032 s
A @ B terminé - Temps: 0.002014 s
Manuel (for loops): 0.7567 s
np.dot():           0.002025 s
np.matmul():        0.004032 s
A @ B:              0.002014 s

Matrice Unitaire:

  • Une matrice U est unitaire si la Matrice U* Transposée conjuguée de U vérifie :
    • U x U = U x U = I
  • Définir une fonction matUnit qui prend en paramètre une matrice carrée et return si la matrice est Unitaire (True) ou pas (False)
import numpy as np
# mat conjuguée : np.conj(u)
# mat Transposée : u.T
# matrice identité : np.eye(n)

def matUnit(A):
    # ecrire votre soluiton ici 
    n, m = A.shape
    if n != m:
        return False
    A_star = np.conj(A.T)
    prod = A @ A_star
    I = np.eye(n, dtype=A.dtype)
    return np.allclose(prod, I)

- Tester matUnit sur les 3 matrices suivantes : vérifier si chacune est Unitaire ou pas

import numpy as np

MA = np.array([[0, 1],[1, 0]])

MB = np.array([[ 0, -3.j],
                  [1.j, 0  ]])
MC = np.array([[ 0, -1.j],
                  [1.j, 0  ]])
print("MA unitaire ? ", matUnit(MA))
print("MB unitaire ? ", matUnit(MB))
print("MC unitaire ? ", matUnit(MC))
MA unitaire ?  True
MB unitaire ?  False
MC unitaire ?  True

Exercice Matrices :

- Matrice Triangulaire Supérieure
- Matrice Triangulaire Inférieure
- Matrice Diagonale
  • Une matrice carrée M est triangulaire supérieure si tous les éléments situés en dessous de la diagonale principale sont nuls.
 Écrire une fonction EstTriangSup(M) qui retourne True si la matrice M est triangulaire supérieure, et False sinon.
  Exemple :
  M = [
    [1, 2, 3],
    [0, 5, 6],
    [0, 0, 9]
  ]
import numpy as np

def EstTriangSup(M):
    M = np.array(M)
    n, m = M.shape
    if n != m:
        raise ValueError("La matrice doit être carrée")
    for i in range(1, n):
        for j in range(0, i):
            if M[i, j] != 0:
                return False
    return True
M = np.array([
  [1, 2, 3],
  [0, 5, 6],
  [0, 0, 9]
])
print("M est triangulaire supérieure ?", EstTriangSup(M))
M est triangulaire supérieure ? True
  • Une matrice carrée M est triangulaire Inférieure si tous les éléments situés au dessus de la diagonale principale sont nuls.
 Écrire une fonction EstTriangInf(M) qui retourne True si la matrice M est triangulaire supérieure, et False sinon.
  Exemple :
  M = [
    [1, 2, 3],
    [0, 5, 6],
    [0, 0, 9]
  ]
def EstTriangInf(M):
    M = np.array(M)
    n, m = M.shape
    if n != m:
        raise ValueError("La matrice doit être carrée")
    for i in range(n):
        for j in range(i + 1, n):
            if M[i, j] != 0:
                return False
    return True
    
M = np.array([
  [1, 0, 0],
  [4, 5, 0],
  [7, 8, 9]
])
print("M est triangulaire inférieure ?", EstTriangInf(M))
M est triangulaire inférieure ? True
  • Une matrice carrée M est diagonale si tous les éléments situés en dehors de la diagonale principale sont nuls.
 Écrire une fonction EstDiagonale(M) qui retourne True si la matrice M est diagonale, et False sinon. 
    Exemple : 
    M = [ 
         [4, 0, 0], 
         [0, 7, 0], 
         [0, 0, 2] 
    ] 
import numpy as np

def EstDiag(M):
    M = np.array(M)
    n, m = M.shape
    if n != m:
        raise ValueError("La matrice doit être carrée")
    for i in range(n):
        for j in range(n):
            if i != j and M[i, j] != 0:
                return False
    return True
M = np.array([
  [4, 0, 0],
  [0, 7, 0],
  [0, 0, 2]
])
print("M est diagonale ?", EstDiag(M))
M est diagonale ? True

Matrice de Hankel

Une matrice de Hankel est une matrice dans laquelle les éléments sont identiques sur chaque anti-diagonale,

# Exemple 3×3 :

import numpy as np
H = np.array([[1, 2, 3],
     [2, 3, 4],
     [3, 4, 5]])
print(H)
[[1 2 3]
 [2 3 4]
 [3 4 5]]
# Exemple 3×5 :
MatHankel = np.array([
  [1, 2, 3, 4, 5],
  [2, 3, 4, 5, 6],
  [3, 4, 5, 6, 7]
])
print(MatHankel)
[[1 2 3 4 5]
 [2 3 4 5 6]
 [3 4 5 6 7]]
  • écrire une fonction qui prend en paramètre une matrice et qui return 1 si elle est de Hankel et 0 sinon
import numpy as np

def MatHankel(A):
    A = np.array(A)
    n, m = A.shape
    for i in range(n):
        for j in range(m):
            if i > 0 and j < m - 1:
                if A[i, j] != A[i - 1, j + 1]:
                    return 0
    return 1
print(MatHankel(H), MatHankel([[1, 2], [3, 4]]))
1 0
  • Somme diagonale
MD = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])

print(MD)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
- écrire une fonction qui retourne la somme des élements de la diagonale d'une matrice carrée
    - Exemple pour MD : 1+5+9
def SommeDiag(M):
    M = np.array(M)
    if M.shape[0] != M.shape[1]:
        raise ValueError("La matrice doit être carrée")
    return np.trace(M)
- écrire une fonction qui retourne la somme des elements de la diagonale secondaire d'une matrice carrée
    - Exemple pour MD : 7+5+3
def SommeDiagSec(M):
    M = np.array(M)
    if M.shape[0] != M.shape[1]:
        raise ValueError("La matrice doit être carrée")
    return np.trace(np.fliplr(M))
print(SommeDiag(MD), SommeDiagSec(MD))
15 15

Traitement du Fichier "personnes.txt"

- Créer un fichier texte nommé "personnes.txt" qui contient plusieurs lignes, telles que chacune contient les champs suivants relatifs à une personne ( séparés par le caractère ':' )
    - Nom
    - Prenom
    - age
    - Genre
    - Email
    - Telephone

Exemple : 
Nabil:Benahmed:21:M:n.ben@gmail.com:0666656565

N.B : Vous pouvez créer le fichier manuellement
with open("personnes.txt", "w", encoding="utf-8") as f:
    f.write("Nabil:Benahmed:21:M:n.ben@gmail.com:0666656565\n")

print("Fichier 'personnes.txt' créé avec succès !")
Fichier 'personnes.txt' créé avec succès !
 - Afficher le fichier "personnes.txt" 
with open("personnes.txt", "r", encoding="utf-8") as f:
    contenu = f.read()
print(contenu)
Nabil:Benahmed:21:M:n.ben@gmail.com:0666656565

 - Ajouter un enregistrement au fichier 'personnes.txt', puis afficher
le résultat
with open("personnes.txt", "a", encoding="utf-8") as f:
    f.write("Imane:test:24:F:imane.test@gmail.com:0688997744\n")

print("Nouvelle personne ajoutée avec succès !")

with open("personnes.txt", "r", encoding="utf-8") as f:
    print("\nContenu du fichier 'personnes.txt' après ajout :\n")
    for ligne in f:
        print(ligne.strip())
Nouvelle personne ajoutée avec succès !

Contenu du fichier 'personnes.txt' après ajout :

Nabil:Benahmed:21:M:n.ben@gmail.com:0666656565
Imane:test:24:F:imane.test@gmail.com:0688997744
 
- Faire une recherche / email suite à une saisie au clavier  
- puis afficher les détails du contact s'il existe, sinon afficher un 
message adéquat
emailR = "n.ben@gmail.com"

trouve = False

with open("personnes.txt", "r", encoding="utf-8") as f:
    for ligne in f:
        nom, prenom, age, genre, email, telephone = ligne.strip().split(":")
        
        if email.lower() == emailR.lower():
            print(f"Nom       : {nom}")
            print(f"Prénom    : {prenom}")
            print(f"Âge       : {age}")
            print(f"Genre     : {genre}")
            print(f"Email     : {email}")
            print(f"Téléphone : {telephone}")
            trouve = True
            break

if not trouve:
    print("\n Aucun contact trouvé avec cet email.")
Nom       : Nabil
Prénom    : Benahmed
Âge       : 21
Genre     : M
Email     : n.ben@gmail.com
Téléphone : 0666656565
- mettre à jour le fichier en incrémentant de 1 l'age de toutes les personnes 
- Pour vérifier, faire un affichage du fichier avant et après màj
import numpy as np

with open("personnes.txt", "r", encoding="utf-8") as f:
    lignes = f.readlines()
    for ligne in lignes:
        print(ligne.strip())

nouvelles_lignes = []

for ligne in lignes:
    nom, prenom, age, genre, email, telephone = ligne.strip().split(":")
    age = str(int(age) + 1)
    nouvelles_lignes.append(f"{nom}:{prenom}:{age}:{genre}:{email}:{telephone}\n")
    
with open("personnes.txt", "w", encoding="utf-8") as f:
    f.writelines(nouvelles_lignes)
    
with open("personnes.txt", "r", encoding="utf-8") as f:
    for ligne in f:
        print(ligne.strip())
Nabil:Benahmed:21:M:n.ben@gmail.com:0666656565
Imane:test:24:F:imane.test@gmail.com:0688997744
Nabil:Benahmed:22:M:n.ben@gmail.com:0666656565
Imane:test:25:F:imane.test@gmail.com:0688997744
- Faire une recherche / email d'un élément saisi au clavier
- Supprimer l'élément s'il existe, sinon afficher un message d'erreur
- Pour vérifier, faire un affichage avant et après supression
with open("personnes.txt", "r", encoding="utf-8") as f:
    lignes = f.readlines()
    for ligne in lignes:
        print(ligne.strip())

email_supprimer = "inconnu@test.com"

nouvelles_lignes = []
trouve = False

for ligne in lignes:
    nom, prenom, age, genre, email, telephone = ligne.strip().split(":")
    if email.lower() == email_supprimer.lower():
        trouve = True
    else:
        nouvelles_lignes.append(ligne)

with open("personnes.txt", "w", encoding="utf-8") as f:
    f.writelines(nouvelles_lignes)

if trouve:
    print(f"\nLa personne avec l'email '{email_supprimer}' a été supprimée.")
else:
    print(f"\nAucun contact trouvé avec l'email '{email_supprimer}'.")

with open("personnes.txt", "r", encoding="utf-8") as f:
    for ligne in f:
        print(ligne.strip())
Nabil:Benahmed:22:M:n.ben@gmail.com:0666656565
Imane:test:25:F:imane.test@gmail.com:0688997744

Aucun contact trouvé avec l'email 'inconnu@test.com'.
Nabil:Benahmed:22:M:n.ben@gmail.com:0666656565
Imane:test:25:F:imane.test@gmail.com:0688997744
- Décomposer le fichiers "personnes.txt" en deux fichiers : "hommes.txt" et "femmes.txt"
- aficher le résultat
with open("personnes.txt", "r", encoding="utf-8") as f:
    lignes = f.readlines()

hommes = []
femmes = []

for ligne in lignes:
    champs = ligne.strip().split(":")
    if len(champs) != 6:
        continue
    nom, prenom, age, genre, email, telephone = champs
    if genre.upper() == "M":
        hommes.append(ligne)
    elif genre.upper() == "F":
        femmes.append(ligne)

with open("hommes.txt", "w", encoding="utf-8") as f:
    f.writelines(hommes)

with open("femmes.txt", "w", encoding="utf-8") as f:
    f.writelines(femmes)

print("Contenu du fichier hommes.txt :\n")
with open("hommes.txt", "r", encoding="utf-8") as f:
    for ligne in f:
        print(ligne.strip())

print("\nContenu du fichier femmes.txt :\n")
with open("femmes.txt", "r", encoding="utf-8") as f:
    for ligne in f:
        print(ligne.strip())
Contenu du fichier hommes.txt :

Nabil:Benahmed:22:M:n.ben@gmail.com:0666656565

Contenu du fichier femmes.txt :

Imane:test:25:F:imane.test@gmail.com:0688997744

Retour aux Matrices

  • Matrice en spirale
- Écrire une fonction GenMatSpirale(n) qui crée une matrice n × n dont les éléments sont remplis de 1 à n² dans un ordre spiralé dans le sens des aiguilles d'une montre.
Exemples :
- GenMatSpirale(3)
    [1, 2, 3]
    [8, 9, 4]
    [7, 6, 5]
- GenMatSpirale(4)
    [ 1,  2,  3, 4]
    [12, 13, 14, 5]
    [11, 16, 15, 6]
    [10,  9,  8, 7]
import numpy as np

def GenMatSpirale(n):
    # écrire votre solution ici
    mat = np.zeros((n, n), dtype=int)
    num = 1 
    top, bottom = 0, n - 1
    left, right = 0, n - 1

    while top <= bottom and left <= right:
        for j in range(left, right + 1):
            mat[top, j] = num
            num += 1
        top += 1

        for i in range(top, bottom + 1):
            mat[i, right] = num
            num += 1
        right -= 1

        if top <= bottom:
            for j in range(right, left - 1, -1):
                mat[bottom, j] = num
                num += 1
            bottom -= 1

        if left <= right:
            for i in range(bottom, top - 1, -1):
                mat[i, left] = num
                num += 1
            left += 1

    return mat
for row in GenMatSpirale(3):
    print(row)
#    [1, 2, 3]
#    [8, 9, 4]
#    [7, 6, 5]

for row in GenMatSpirale(4):
    print(row)
#    [1, 2, 3, 4]
#    [12,13,14,5]
#    [11,16,15,6]
#    [10,9, 8, 7]
[1 2 3]
[8 9 4]
[7 6 5]
[1 2 3 4]
[12 13 14  5]
[11 16 15  6]
[10  9  8  7]

    Type at least 2 letters. ↑ ↓ to move, Enter to open.