From fc408a90ea6003cf707faa66d356981d1a64429e Mon Sep 17 00:00:00 2001
From: Simon Lecocq <simon.lecocq2.etu@univ-lille.fr>
Date: Thu, 13 Feb 2025 09:56:44 +0100
Subject: [PATCH] Upload New File

---
 tp_2_miso_mphf.py | 169 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)
 create mode 100644 tp_2_miso_mphf.py

diff --git a/tp_2_miso_mphf.py b/tp_2_miso_mphf.py
new file mode 100644
index 0000000..ebc3d33
--- /dev/null
+++ b/tp_2_miso_mphf.py
@@ -0,0 +1,169 @@
+import matplotlib.pyplot as plt
+import numpy as np
+import time
+import sys
+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
+	set_kmer_courant = set_kmer.copy()
+	tableaux = []
+	collision = set()
+	for _ in range(nb_niveaux):
+		if len(set_kmer_courant) > 0:
+			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)
+				# 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) # expliquer
+			set_kmer_courant = collision.copy() # expliquer
+			collision = set() # expliquer
+
+	# Construction de la MPHF
+	mphf = [] 
+	grand_tableau = []
+	for tableau in tableaux:
+		grand_tableau.extend(tableau) # expliquer
+
+	rangs = []
+	max_rang = 0
+	i = 0
+	for kmer in set_kmer:
+		pass # 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
+
+	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])
+	
+	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
+
+def create_hash_table(set_kmer, n):
+    """
+    Crée une table de hachage à partir d'un ensemble de k-mers et d'une mphf
+
+    Parameters:
+    set_kmer (set): Ensemble de k-mers.
+    n (int): Taille de la table de hachage.
+
+    Returns:
+    list: Table de hachage créée à partir des k-mers
+    mphf: la mphf
+
+    Examples:
+    >>> set_kmer = {'ATCG', 'TGCA', 'GCTA'}
+    >>> n = 10
+    >>> tableau = create_hash_table(set_kmer, n)
+    >>> len(tableau) == n
+    True
+    >>> all(kmer in tableau for kmer in set_kmer)
+    True
+    """
+    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
+
+
+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")
-- 
GitLab