diff --git a/tp_2_miso_mphf.py b/tp_2_miso_mphf.py index 64403803f46b7aecfff4e4a4c82cd7dc6c12cb42..5503f71f46d2a1f91e4756fe8b80df558d7d1dc4 100644 --- a/tp_2_miso_mphf.py +++ b/tp_2_miso_mphf.py @@ -8,31 +8,31 @@ import random ###### PARTIE 1 ###### def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3): - - """ - Construit une fonction de hachage minimale parfaite (MPHF) pour un ensemble de k-mers. - - Parameters: - set_kmer (set): Ensemble de k-mers. - n (int): Taille de l'ensemble de k-mers. - gamma (int): Facteur de réduction de la taille de la table de hachage. Default: 2. - nb_niveaux (int): Nombre de niveaux de réduction de la taille de la table de hachage. Default: 3. - - Returns: - mphf (list): Table de hachage minimale parfaite. - - Examples: - >>> set_kmer = {str(i) for i in range(10)} - >>> n = 10 - >>> mphf = construction_mphf(set_kmer, n) - >>> len(mphf) == n - True - >>> all(0 <= mphf[i] < n for i in range(n)) - True - >>> len(mphf) == n - True - """ - # Initialisation + """ + Construit une fonction de hachage minimale parfaite (MPHF) pour un ensemble de k-mers. + + Parameters: + set_kmer (set): Ensemble de k-mers. + n (int): Taille de l'ensemble de k-mers. + gamma (int): Facteur de réduction de la taille de la table de hachage. Default: 2. + nb_niveaux (int): Nombre de niveaux de réduction de la taille de la table de hachage. Default: 3. + + Returns: + mphf (list): Table de hachage minimale parfaite. + + Examples: + >>> set_kmer = {str(i) for i in range(10)} + >>> n = 10 + >>> mphf = construction_mphf(set_kmer, n) + >>> len(mphf) == n + True + >>> all(0 <= mphf[i] < n for i in range(n)) + True + >>> len(mphf) == n + True + """ + # Initialisation + set_kmer_courant = set_kmer.copy() tableaux = [] collision = set() @@ -41,25 +41,23 @@ 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: - hachage = abs(hash(kmer)) # positif - print(hachage) + hachage = abs(hash(kmer))# positif adresse = hachage % len(tableau_principal) - if tableau_principal[adresse] != -1: # Collision collision.add(kmer) else: tableau_principal[adresse] = hachage # Stocker le hachage + tableaux.append(tableau_principal) # on conserve les positions sans collision dans notre table finale - tableaux.append(tableau_principal) # expliquer - set_kmer_courant = collision.copy() # expliquer - collision = set() # expliquer + set_kmer_courant = collision.copy() # on prépare les positions en collision dans le set + # courant pour un nouveau hachage + collision = set() # on replace les positions non-hachées en tant que set pour le hachage # Construction de la MPHF mphf = [] grand_tableau = [] for tableau in tableaux: - grand_tableau.extend(tableau) # expliquer - + grand_tableau.extend(tableau) # on ajoute tous les éléments de tous les tabeaux dans le tableau final, sans renvoyer de valeur rangs = [] max_rang = 0 count = 0 @@ -68,24 +66,21 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3): h_tab = grand_tableau[pos] if h_tab != -1: count += 1 - list_h_pos.append((h_tab, count)) - #tester et approuver par les autorité competente, fait une liste sous forme : - # [(2052854839243325982, 1), (4957333478667127183, 2), (937960722055874324, 3), (5781457990790611126, 4), (639567318783299370, 5), (8946549155908438712, 6), (2965694465669227395, 7), (2528361345495398196, 8), (4425804304571150798, 9), (8833577342042152210, 10)] + list_h_pos.append((h_tab, count)) # fonction de hashage minimale parfaite ! - - col_h = [] + mphf = list_h_pos + + '''col_h = [] col_kmer = [] for k in kmer: h = abs(hash(k)) ok = 0 for e in range(len(list_h_pos)): if list_h_pos[e][0] == h: - ok +=1 - if ok ==0: - col_h.append(h) #si besoin d'une liste de h qui sont pas dans tableau et qu'il faut rajouter apres - col_kmer.append(k) #pareil mais avec les kmer, jsp ce qu'on aura besoin ensuite - - + ok += 1 + if ok == 0: + col_h.append(h) # si besoin d'une liste de h qui sont pas dans tableau et qu'il faut rajouter apres + col_kmer.append(k) # pareil mais avec les kmer, jsp ce qu'on aura besoin ensuite # compléter # hacher le kmer # si le hash est dans le grand_tableau @@ -94,35 +89,42 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3): # ajouter à la mphf [h, rang] # mettre à jour max_rang - for kmer in set_kmer_courant: # gestion des collisions: expliquer les 3 lignes du dessous + for kmer in set_kmer_courant: # permet de récupérer la dernière collision si elle existe max_rang += 1 h = abs(hash(kmer)) mphf.append([h, max_rang]) +''' return mphf def get_hash_mphf(mphf, kmer): - """ - Calcule le hash d'un k-mer à l'aide d'une fonction de hachage minimale parfaite (MPHF). - - Parameters: - mphf (list): Table de hachage minimale parfaite. - kmer (str): K-mer à hasher. - - Returns: - int: Hash du k-mer. - - Examples: - >>> set_kmer = {str(i) for i in range(10)} - >>> n = 10 - >>> mphf = construction_mphf(set_kmer, n) - >>> kmer = "5" - >>> hash_mphf = get_hash_mphf(mphf, kmer) - >>> 0 <= hash_mphf < n - True - """ - pass # TODO modifier + """ + Calcule le hash d'un k-mer à l'aide d'une fonction de hachage minimale parfaite (MPHF). + + Parameters: + mphf (list): Table de hachage minimale parfaite. + kmer (str): K-mer à hasher. + + Returns: + int: Hash du k-mer. + + Examples: + >>> set_kmer = {str(i) for i in range(10)} + >>> n = 10 + >>> mphf = construction_mphf(set_kmer, n) + >>> kmer = "5" + >>> hash_mphf = get_hash_mphf(mphf, kmer) + >>> 0 <= hash_mphf < n + True + """ + hashkmer = abs(hash(kmer)) + for hach in mphf: + if hach[0] == hashkmer: + return hach[0] + else: + return "ça existe pô" + def create_hash_table(set_kmer, n): """ @@ -145,49 +147,57 @@ def create_hash_table(set_kmer, n): >>> all(kmer in tableau for kmer in set_kmer) True """ - pass # TODO modifier + 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 - - def generer_kmers(n, k): - ''' - genere un set de n k-mers - ''' - kmers = set() - while len(kmers) < n: - kmer = ''.join(random.choice('ATCG') for _ in range(k)) - kmers.add(kmer) - return kmers + ''' + genere un set de n k-mers + ''' + kmers = set() + while len(kmers) < n: + kmer = ''.join(random.choice('ATCG') for _ in range(k)) + kmers.add(kmer) + return kmers def compare_taille(n_max, fichier_sortie): - n_values = [] - table_size = [] - dict_size = [] - k = 21 - - for n in range(100, n_max, 1000): - set_kmer = generer_kmers(n, k) - 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 ? - dict_size.append(sys.getsizeof(set_kmer)) - - plt.plot(n_values, table_size, label='Table avec MPHF') - plt.plot(n_values, dict_size, label='Dict') - plt.xlabel('n') - plt.xticks(n_values, [str(x) for x in n_values], rotation=45) - plt.ylabel('Taille (octets)') - plt.title('Évolution de la taille de la table de hachage avec MPHF et du dict') - plt.legend() - plt.savefig(fichier_sortie) - plt.close() - -# dé-commenter quand vous êtes prêts, expliquer les résultats -#compare_taille(10000,"mphf.png") + n_values = [] + table_size = [] + dict_size = [] + k = 21 + + for n in range(100, n_max, 1000): + set_kmer = generer_kmers(n, k) + 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 ? + dict_size.append(sys.getsizeof(set_kmer)) + + plt.plot(n_values, table_size, label='Table avec MPHF') + plt.plot(n_values, dict_size, label='Dict') + plt.xlabel('n') + plt.xticks(n_values, [str(x) for x in n_values], rotation=45) + plt.ylabel('Taille (octets)') + plt.title('Évolution de la taille de la table de hachage avec MPHF et du dict') + plt.legend() + plt.savefig(fichier_sortie) + plt.close() + +if __name__ == "__main__": + import doctest + doctest.testmod() + kmers = generer_kmers(10, 10) + set_kmer = set(kmers) + n = 10 + mphf = construction_mphf(set_kmer, n) + print('mpfh') + print(mphf) + print('get') + print(get_hash_mphf(mphf, "prout")) \ No newline at end of file