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

maj

parent 6141fc05
No related branches found
No related tags found
No related merge requests found
...@@ -27,7 +27,7 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3): ...@@ -27,7 +27,7 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3):
>>> mphf = construction_mphf(set_kmer, n) >>> mphf = construction_mphf(set_kmer, n)
>>> len(mphf) == n >>> len(mphf) == n
True True
>>> all(0 <= mphf[i] < n for i in range(n)) >>> all(0 <= pair[1] < n for pair in mphf)
True True
>>> len(mphf) == n >>> len(mphf) == n
True True
...@@ -39,64 +39,58 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3): ...@@ -39,64 +39,58 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3):
# Parcours des niveaux pour placer les k-mers # Parcours des niveaux pour placer les k-mers
for _ in range(nb_niveaux): for _ in range(nb_niveaux):
if set_kmer_courant: if len(set_kmer_courant) > 0:
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:
# Hacher le k-mer pour obtenir un entier positif # Hacher le k-mer pour obtenir un entier positif
h = abs(hash(kmer)) h = abs(hash(kmer))
# Récupérer l'adresse dans le tableau (taille = gamma * l) # Récupérer l'adresse
adresse = h % (gamma * l) adresse = h % (gamma * l)
# Si la case est déjà occupée, on ajoute le k-mer aux collisions # Si la case est déjà occupée, on ajoute le k-mer aux collisions
if tableau_principal[adresse] != -1: if tableau_principal[adresse] != -1:
collision.add(kmer) collision.add(kmer)
else: else:
# Sinon, on écrit le k-mer dans la case # Sinon, écrire le hash à l'adresse dans le tableau principal
tableau_principal[adresse] = kmer tableau_principal[adresse] = h
tableaux.append(tableau_principal) # On sauvegarde le tableau de ce niveau
# Les k-mers en collision seront traités au niveau suivant tableaux.append(tableau_principal) # On ajoute le tableau principal à la liste des tableaux
set_kmer_courant = collision.copy() set_kmer_courant = collision.copy() # Les k-mers en collision seront traités au niveau suivant
collision = set() collision = set() # Réinitialiser l'ensemble des collisions pour le prochain niveau
# Construction de la MPHF # Construction de la MPHF
# On concatène tous les tableaux pour former le grand_tableau
mphf = []
grand_tableau = [] grand_tableau = []
for tableau in tableaux: for tableau in tableaux:
grand_tableau.extend(tableau) grand_tableau.extend(
tableau) # On concatène tous les tableaux pour obtenir un grand tableau regroupant tous les indices calculés
# Création d'un mapping temporaire kmer -> indice (non normalisé) rangs = []
mp_dict = {} max_rang = 0
# Pour chaque k-mer de l'ensemble initial : i = 0
for kmer in set_kmer: for kmer in set_kmer:
if kmer in grand_tableau: # Hacher le k-mer pour obtenir un entier positif
# On récupère l'indice de la première occurrence du k-mer dans grand_tableau h = abs(hash(kmer))
pos = grand_tableau.index(kmer) # Si le hash est présent dans le grand_tableau, c'est qu'il a été placé sans collision
# Le "rang" est le nombre d'apparitions du k-mer jusqu'à cette position (on commence à 0) if h in grand_tableau:
rang = grand_tableau[:pos + 1].count(kmer) - 1 # Récupérer l'index de la première occurrence de h dans grand_tableau
mp_dict[kmer] = rang index = grand_tableau.index(h)
# Pour les k-mers qui n'ont pas été placés (collision persistante), on leur affecte des indices uniques # Récupérer le rang en comptant le nombre d'occurrences de h jusqu'à cet index
max_rang = max(mp_dict.values()) if mp_dict else -1 rang = grand_tableau[:index + 1].count(h)
for kmer in set_kmer: # Ajouter à la MPHF la paire [h, rang]
if kmer not in mp_dict: mphf.append([h, rang])
max_rang += 1 # Mettre à jour le rang maximum rencontré
mp_dict[kmer] = max_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])
# Normalisation de la MPHF :
# On souhaite obtenir une bijection de set_kmer sur {0, ..., n-1}.
# 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))
normalized = {}
for idx, kmer in enumerate(sorted_kmers):
normalized[kmer] = idx
# 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).
...@@ -117,7 +111,14 @@ def get_hash_mphf(mphf, kmer): ...@@ -117,7 +111,14 @@ def get_hash_mphf(mphf, kmer):
>>> 0 <= hash_mphf < n >>> 0 <= hash_mphf < n
True True
""" """
return int(kmer) # Calculer le hash positif du k-mer
h = abs(hash(kmer))
# Parcourir la MPHF pour trouver le k-mer correspondant et retourner son indice (rang)
for entry in mphf:
if entry[0] == h:
return entry[1]
# Si aucun k-mer correspondant n'est trouvé, lever une exception
raise ValueError("K-mer non trouvé dans la MPHF")
def create_hash_table(set_kmer, n): def create_hash_table(set_kmer, n):
...@@ -145,12 +146,12 @@ def create_hash_table(set_kmer, n): ...@@ -145,12 +146,12 @@ def create_hash_table(set_kmer, n):
mphf = construction_mphf(set_kmer, n) mphf = construction_mphf(set_kmer, n)
# Initialiser une table de taille n (liste de n cases) # Initialiser une table de taille n (liste de n cases)
table = [None] * n table = [None] * n
# Ici, nous utilisons l'ordre trié pour affecter l'adresse : le perfect hash d'un k-mer # écrire les kmers aux adresses du tableau données par la mphf
# est sa position dans l'ordre trié.
sorted_kmers = sorted(list(set_kmer)) sorted_kmers = sorted(list(set_kmer))
for kmer in set_kmer: for kmer in set_kmer:
index = sorted_kmers.index(kmer) index = sorted_kmers.index(kmer)
table[index] = kmer table[index] = kmer
# retourner le tableau et la mphf
return table, mphf return table, mphf
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment