@@ -36,63 +36,67 @@ def construction_mphf(set_kmer, n, gamma=2, nb_niveaux=3):
set_kmer_courant=set_kmer.copy()
tableaux=[]
collision=set()
# Parcours des niveaux pour placer les k-mers
for_inrange(nb_niveaux):
iflen(set_kmer_courant)>0:
ifset_kmer_courant:
l=len(set_kmer_courant)
# On initialise le tableau principal avec -1 (case vide)
tableau_principal=[-1]*(gamma*l)
forkmerinset_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.
iftableau_principal[x]isNone:# Si l'index est libre
tableau_principal[x]=kmer# On place le k-mer dans la table
# Hacher le k-mer pour obtenir un entier positif
h=abs(hash(kmer))
# 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
iftableau_principal[adresse]!=-1:
collision.add(kmer)
else:
collision.add(kmer)# mettre le kmer dans collision()
# compléter
# hacher le k-mer (attention, hash() peut rendre des entiers signés, nous voulons des entiers positifs)
# 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
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
# Sinon, on écrit le k-mer dans la case
tableau_principal[adresse]=kmer
tableaux.append(tableau_principal)# On sauvegarde le tableau de ce niveau
# Les k-mers en collision seront traités au niveau suivant
set_kmer_courant=collision.copy()
collision=set()
# Construction de la MPHF
mphf=[]
# On concatène tous les tableaux pour former le grand_tableau
grand_tableau=[]
fortableauintableaux:
grand_tableau.extend(tableau)# expliquer
grand_tableau.extend(tableau)
rangs=[]
max_rang=0
i=0
# Création d'un mapping temporaire kmer -> indice (non normalisé)
mp_dict={}
# Pour chaque k-mer de l'ensemble initial :
forkmerinset_kmer:
x=abs(hash(kmer))%len (tableau_principal)
ifgrand_tableau[x]==kmer:
rang=rangs.count(kmer)# Récupérer le rang du k-mer (utilisation de count() ici)
rangs.append(rang)# Ajouter le rang à la liste des rangs
mphf.append([x,rang])# Ajouter l'index et le rang à la MPHF
max_rang=max(max_rang,rang)# Mettre à jour le rang maximum
# compléter:
# hacher le 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
forkmerinset_kmer_courant:#gestion des collisions: expliquer les 3 lignes du dessous
max_rang+=1
h=abs(hash(kmer))
mphf.append([h,max_rang])
ifkmeringrand_tableau:
# On récupère l'indice de la première occurrence du k-mer dans grand_tableau
pos=grand_tableau.index(kmer)
# Le "rang" est le nombre d'apparitions du k-mer jusqu'à cette position (on commence à 0)
rang=grand_tableau[:pos+1].count(kmer)-1
mp_dict[kmer]=rang
# 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())ifmp_dictelse-1
forkmerinset_kmer:
ifkmernotinmp_dict:
max_rang+=1
mp_dict[kmer]=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={}
foridx,kmerinenumerate(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]forkmerinsorted_kmers]
returnmphf
defget_hash_mphf(mphf,kmer):
"""
Calcule le hash d'un k-mer à l'aide d'une fonction de hachage minimale parfaite (MPHF).