diff --git a/tp_2_miso_mphf.py b/tp_2_miso_mphf.py index ebc3d3328dd4c33b1c29a5692f95b319518eb291..ccb73c1df5e29624caf1e1c6b97370d4a156be5f 100644 --- a/tp_2_miso_mphf.py +++ b/tp_2_miso_mphf.py @@ -41,39 +41,59 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3): l = len(set_kmer_courant) 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 = hash(kmer) + if hachage < 0: + hachage = -1 * hachage # 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. + # 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. rangs = [] max_rang = 0 i = 0 for kmer in set_kmer: - pass # compléter: # hacher le kmer + hache = 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 : + index = grand_tableau.index(hache) + rang = grand_tableau[:index].count(hache) + mphf.append([hache, rang]) + if rang > max_rang : + 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 return mphf @@ -98,7 +118,11 @@ def get_hash_mphf(mphf, kmer): >>> 0 <= hash_mphf < n True """ - pass # TODO modifier + hache = abs(hash(kmer)) + for h, rang in mphf : + if h == hache : + return rang + def create_hash_table(set_kmer, n): """ @@ -121,13 +145,15 @@ def create_hash_table(set_kmer, n): >>> all(kmer in tableau for kmer in set_kmer) True """ - pass # TODO modifier - # créer la mphf pour les kmers + 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 - # retourner le tableau et la mphf - - + for kmer in set_kmer : + adresse = get_hash_mphf(mphf, kmer) + if 0 <= adresse < n: + tableau[adresse]=kmer + return tableau, mphf # retourner le tableau et la mphf def generer_kmers(n, k): @@ -149,7 +175,7 @@ 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 ? @@ -166,4 +192,4 @@ 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")