Skip to content
Snippets Groups Projects
Commit 85338186 authored by Nguyen Samuel's avatar Nguyen Samuel
Browse files

Partie 1 finie. Partie 2 commencée jusqu'à la question 2

parent 3ec7c773
Branches
No related tags found
No related merge requests found
mphf.png 0 → 100644
mphf.png

33.5 KiB

......@@ -7,10 +7,26 @@ import sys
###### PARTIE 2 ######
def experiment_load_factor(load_factors):
def experiment_load_factor(load_factors : list):
"""
Étude du facteur de charge
Parameters
----------
load_factors : list
Une liste de facteurs de charge
Returns
-------
lists
Les temps d'insertion de clefs
Les nombres de réallocations de mémoire
Les tailles de mémoire occupée par le dictionnaire pour chaque facteur de charge
"""
insertion_times = []
num_resizes = []
sizes = []
for factor in load_factors :
dictio = {}
# num_elements = .......... QUESTION 2 PARTIE 2
return [],[],[]
def experiment_longest():
......
......@@ -39,42 +39,64 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3):
for _ in range(nb_niveaux):
if len(set_kmer_courant) > 0:
l = len(set_kmer_courant)
if l==0 :
break #Evite une division par 0
tableau_principal = [-1] * (gamma * l)
for kmer in set_kmer_courant:
pass # compléter
# hacher le k-mer (attention, hash() peut rendre des entiers signés, nous voulons des entiers positifs)
hachage = abs(hash(kmer))
# récupérer l'adresse
# si le tableau principal est déjà rempli à l'adresse:
# mettre le kmer dans collision()
#sinon, écrire le hash à l'adresse dans le tableau principal
# sinon, écrire le hash à l'adresse dans le tableau principal
adresse = hachage % (gamma * l)
if tableau_principal[adresse] != -1:
collision.add(kmer)
else:
tableau_principal[adresse] = hachage
tableaux.append(tableau_principal) # expliquer
# Chaque niveau de hachage produit un nouveau tableau de hachage.
# Donc on enregistre le tableau dans tableaux pour garder une trace des niveaux.
set_kmer_courant = collision.copy() # expliquer
# On hache à nouveau les k-mers qui ont causé des collisions.
collision = set() # expliquer
# On réinitialise collision pour le prochain niveau de hachage, pour pas que les valeurs dont on n'a plus besoin s'accumulent.
if not set_kmer_courant: # Arrête la boucle si plus de collisions
break
# Construction de la MPHF
mphf = []
grand_tableau = []
for tableau in tableaux:
grand_tableau.extend(tableau) # expliquer
# Après avoir fait tous les hachages, on regroupe les tableaux finaux de hachage dans un seul tableau.
grand_tableau_dict = {val: i for i, val in enumerate(grand_tableau)}
rangs = []
max_rang = 0
i = 0
for kmer in set_kmer:
pass # compléter:
# hacher le kmer
hache = abs(hash(kmer))
# si le hash est dans le grand_tableau
# récupérer son index
# récupérer son rang (utiliser la fonction count())
# ajouter à la mphf [h, rang]
# mettre à jour max_rang
if hache in grand_tableau_dict :
index = grand_tableau_dict[hache]
rang = grand_tableau[:index].count(hache)
mphf.append([hache, rang])
max_rang = max(max_rang, rang)
for kmer in set_kmer_courant: #gestion des collisions: expliquer les 3 lignes du dessous
max_rang += 1
h = abs(hash(kmer))
mphf.append([h, max_rang])
max_rang += 1 # On attribue un nouveau rang unique à chaque élément en collision.
h = abs(hash(kmer)) # Recalcul du hash, on veut uniquement des entiers positifs.
mphf.append([h, max_rang]) # On ajoute le k-mer à mphf
# On fait ces étapes car les collisions n'ont pas pu être placées avant,
# on leur attribue un rang plus grand pour ne pas perturber l'ordre précédent
if not mphf:
print("⚠️ Attention : MPHF vide, vérifiez les données en entrée.")
return mphf
......@@ -98,36 +120,46 @@ def get_hash_mphf(mphf, kmer):
>>> 0 <= hash_mphf < n
True
"""
pass # TODO modifier
def create_hash_table(set_kmer, n):
"""
Crée une table de hachage à partir d'un ensemble de k-mers et d'une mphf
hache = abs(hash(kmer))
for h, rang in mphf :
if h == hache :
return rang
return -1
Parameters:
set_kmer (set): Ensemble de k-mers.
n (int): Taille de la table de hachage.
Returns:
list: Table de hachage créée à partir des k-mers
mphf: la mphf
def create_hash_table(set_kmer, n):
"""
Crée une table de hachage à partir d'un ensemble de k-mers et d'une mphf
Examples:
>>> set_kmer = {'ATCG', 'TGCA', 'GCTA'}
>>> n = 10
>>> tableau = create_hash_table(set_kmer, n)
>>> len(tableau) == n
True
>>> all(kmer in tableau for kmer in set_kmer)
True
"""
pass # TODO modifier
# créer la mphf pour les kmers
# initialiser un tableau de taille n (une liste)
# écrire les kmers aux adresses du tableau données par la mphf
# retourner le tableau et la mphf
Parameters:
set_kmer (set): Ensemble de k-mers.
n (int): Taille de la table de hachage.
Returns:
list: Table de hachage créée à partir des k-mers
mphf: la mphf
Examples:
>>> set_kmer = {'ATCG', 'TGCA', 'GCTA'}
>>> n = 10
>>> tableau = create_hash_table(set_kmer, n)
>>> len(tableau) == n
True
>>> all(kmer in tableau for kmer in set_kmer)
True
"""
mphf = construction_mphf(set_kmer, n) # créer la mphf pour les kmers
# initialiser un tableau de taille n (une liste)
tableau = [None]*n
# écrire les kmers aux adresses du tableau données par la mphf
for kmer in set_kmer :
adresse = get_hash_mphf(mphf, kmer)
if adresse == -1:
print(f"Erreur : Impossible de trouver l'adresse pour {kmer} (MPHF renvoie -1)")
continue
if 0 <= adresse < n:
tableau[adresse]=kmer
return tableau, mphf # retourner le tableau et la mphf
def generer_kmers(n, k):
......@@ -149,10 +181,12 @@ def compare_taille(n_max, fichier_sortie):
for n in range(100, n_max, 1000):
set_kmer = generer_kmers(n, k)
tableau, mphf = create_hash_table(set_kmer,n)
tableau, mphf = create_hash_table(set_kmer, n)
n_values.append(n)
table_size.append(sys.getsizeof(tableau)+sys.getsizeof(mphf)) # pourquoi ici on ne mesure pas juste la taille en mémoire du tableau ?
table_size.append(sys.getsizeof(tableau)+sys.getsizeof(mphf)) # pourquoi ici on ne mesure pas juste la taille en mémoire du tableau ?
#Car sys.getsizeof(tableau) ne mesure que la liste elle-même, pas les objets stockés dedans.
# On veut mesurer la mémoire totale du système de hachage, pas seulement la liste.
dict_size.append(sys.getsizeof(set_kmer))
plt.plot(n_values, table_size, label='Table avec MPHF')
......@@ -166,4 +200,10 @@ def compare_taille(n_max, fichier_sortie):
plt.close()
# dé-commenter quand vous êtes prêts, expliquer les résultats
#compare_taille(10000,"mphf.png")
compare_taille(10000,"mphf.png")
# Sur le graphe obtenu, on observe que la taille de la table de hachage du dictionnaire augmente par paliers,
# alors que celle de la MPHF augmente de manière linéaire, et beaucoup plus progressivement.
# Cela est cohérent, en effet le dictionnaire va allouer plus d'espace dès que le nombre d'éléments atteint un seuil.
# Quant à la MPHF, elle minimise la mémoire en évitant les collisions.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment