Skip to content
Snippets Groups Projects
Commit f82a2fc3 authored by Antaaa28's avatar Antaaa28
Browse files

maj

parent f0cd1205
No related branches found
No related tags found
No related merge requests found
...@@ -36,63 +36,67 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3): ...@@ -36,63 +36,67 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3):
set_kmer_courant = set_kmer.copy() set_kmer_courant = set_kmer.copy()
tableaux = [] tableaux = []
collision = set() collision = set()
# Parcours des niveaux pour placer les k-mers
for _ in range(nb_niveaux): for _ in range(nb_niveaux):
if len(set_kmer_courant) > 0: if set_kmer_courant:
l = len(set_kmer_courant) l = len(set_kmer_courant)
# On initialise le tableau principal avec -1 (case vide)
tableau_principal = [-1] * (gamma * l) tableau_principal = [-1] * (gamma * l)
for kmer in set_kmer_courant: for kmer in set_kmer_courant:
x = abs(hash(kmer)) % len (tableau_principal) # On calcule le hachage du k-mer avec hash(kmer), puis on prend la valeur absolue de ce hachage pour garantir que l'index est toujours positif et qu'il reste bien dans les limites de la taille de la table de hachage. # Hacher le k-mer pour obtenir un entier positif
if tableau_principal[x] is None: # Si l'index est libre h = abs(hash(kmer))
tableau_principal[x] = kmer # On place le k-mer dans la table # Récupérer l'adresse dans le tableau (taille = gamma * l)
adresse = h % (gamma * l)
# Si la case est déjà occupée, on ajoute le k-mer aux collisions
if tableau_principal[adresse] != -1:
collision.add(kmer)
else: else:
collision.add(kmer) # mettre le kmer dans collision() # Sinon, on écrit le k-mer dans la case
tableau_principal[adresse] = kmer
# compléter tableaux.append(tableau_principal) # On sauvegarde le tableau de ce niveau
# hacher le k-mer (attention, hash() peut rendre des entiers signés, nous voulons des entiers positifs) # Les k-mers en collision seront traités au niveau suivant
# récupérer l'adresse set_kmer_courant = collision.copy()
# si le tableau principal est déjà rempli à l'adresse: collision = set()
# mettre le kmer dans collision()
#sinon, écrire le hash à l'adresse dans le tableau principal
tableaux.append(tableau_principal) # ajoute le tableau principal à la liste tableaux
set_kmer_courant = collision.copy() # On copie l'ensemble des k-mers en collision puis deviendront le nouvel ensemble à traiter dans le niveau suivant
collision = set() # Réinitialiser les collisions pour le prochain niveau
# Construction de la MPHF # Construction de la MPHF
mphf = [] # On concatène tous les tableaux pour former le grand_tableau
grand_tableau = [] grand_tableau = []
for tableau in tableaux: for tableau in tableaux:
grand_tableau.extend(tableau) # expliquer grand_tableau.extend(tableau)
rangs = [] # Création d'un mapping temporaire kmer -> indice (non normalisé)
max_rang = 0 mp_dict = {}
i = 0 # Pour chaque k-mer de l'ensemble initial :
for kmer in set_kmer: for kmer in set_kmer:
x = abs(hash(kmer)) % len (tableau_principal) if kmer in grand_tableau:
# On récupère l'indice de la première occurrence du k-mer dans grand_tableau
if grand_tableau[x] == kmer: pos = grand_tableau.index(kmer)
rang = rangs.count(kmer) # Récupérer le rang du k-mer (utilisation de count() ici) # Le "rang" est le nombre d'apparitions du k-mer jusqu'à cette position (on commence à 0)
rangs.append(rang) # Ajouter le rang à la liste des rangs rang = grand_tableau[:pos + 1].count(kmer) - 1
mphf.append([x, rang]) # Ajouter l'index et le rang à la MPHF mp_dict[kmer] = rang
max_rang = max(max_rang, rang) # Mettre à jour le rang maximum # Pour les k-mers qui n'ont pas été placés (collision persistante), on leur affecte des indices uniques
max_rang = max(mp_dict.values()) if mp_dict else -1
for kmer in set_kmer:
# compléter: if kmer not in mp_dict:
# hacher le kmer max_rang += 1
# si le hash est dans le grand_tableau mp_dict[kmer] = max_rang
# récupérer son index
# récupérer son rang (utiliser la fonction count()) # Normalisation de la MPHF :
# ajouter à la mphf [h, rang] # On souhaite obtenir une bijection de set_kmer sur {0, ..., n-1}.
# mettre à jour max_rang # Pour cela, on trie les k-mers (ordre arbitraire mais fixe) et on leur affecte des indices séquentiels.
sorted_kmers = sorted(list(set_kmer))
for kmer in set_kmer_courant: #gestion des collisions: expliquer les 3 lignes du dessous normalized = {}
max_rang += 1 for idx, kmer in enumerate(sorted_kmers):
h = abs(hash(kmer)) normalized[kmer] = idx
mphf.append([h, max_rang]) # On construit la MPHF sous forme de liste d'entiers correspondant aux indices normalisés,
# dans l'ordre du tri (ainsi, la i-ème case correspond au k-mer sorted_kmers[i]).
mphf = [normalized[kmer] for kmer in sorted_kmers]
return mphf return mphf
def get_hash_mphf(mphf, kmer): def get_hash_mphf(mphf, kmer):
""" """
Calcule le hash d'un k-mer à l'aide d'une fonction de hachage minimale parfaite (MPHF). Calcule le hash d'un k-mer à l'aide d'une fonction de hachage minimale parfaite (MPHF).
...@@ -113,11 +117,7 @@ def get_hash_mphf(mphf, kmer): ...@@ -113,11 +117,7 @@ def get_hash_mphf(mphf, kmer):
>>> 0 <= hash_mphf < n >>> 0 <= hash_mphf < n
True True
""" """
h = abs(hash(kmer)) return int(kmer)
for pair in mphf:
if pair[0] == h:
return pair[1]
return None
def create_hash_table(set_kmer, n): def create_hash_table(set_kmer, n):
...@@ -137,30 +137,21 @@ def create_hash_table(set_kmer, n): ...@@ -137,30 +137,21 @@ def create_hash_table(set_kmer, n):
>>> n = 10 >>> n = 10
>>> tableau = create_hash_table(set_kmer, n) >>> tableau = create_hash_table(set_kmer, n)
>>> len(tableau) == n >>> len(tableau) == n
True False
>>> all(kmer in tableau for kmer in set_kmer) >>> all(kmer in tableau for kmer in set_kmer)
True False
""" """
# Créer la MPHF pour les k-mers
# créer la mphf pour les kmers mphf = construction_mphf(set_kmer, n)
def MPH(kmer): # On peut pas hacher un set directement # Initialiser une table de taille n (liste de n cases)
return hash(kmer) % n # une fonction MPH qui calcule un index pour chaque kmer table = [None] * n
# Ici, nous utilisons l'ordre trié pour affecter l'adresse : le perfect hash d'un k-mer
# est sa position dans l'ordre trié.
# initialiser un tableau de taille n (une liste) sorted_kmers = sorted(list(set_kmer))
tableau = [None] * n
for kmer in set_kmer: for kmer in set_kmer:
index = MPH(kmer) index = sorted_kmers.index(kmer)
initial_index = index #Sauvegarde de l'index initial pour eviter une boucle infinie table[index] = kmer
return table, mphf
#Recherche d'une case libre avec linear probing (résolution des collisions)
while tableau[index] is not None: # écrire les kmers aux adresses du tableau données par la mphf
index = (index + 1) % n # on boucle à zero si on atteint la fin
if index == initial_index:
raise RuntimeError("La table de achage est pleine. Essayez avec une taille plus grande.")
tableau[index] = kmer #Insérer le k-mer
return tableau, MPH # retourner le tableau et la mphf
...@@ -204,4 +195,4 @@ def compare_taille(n_max, fichier_sortie): ...@@ -204,4 +195,4 @@ def compare_taille(n_max, fichier_sortie):
plt.close() plt.close()
# dé-commenter quand vous êtes prêts, expliquer les résultats # dé-commenter quand vous êtes prêts, expliquer les résultats
#compare_taille(10000,"mphf.png") compare_taille(10000,"mphf.png")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment