diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..26d33521af10bcc7fd8cea344038eaaeb78d0ef5 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce446ff06cc76d892eea70fc183431982ac675fd --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,12 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true"> + <option name="ignoredIdentifiers"> + <list> + <option value="list.*" /> + </list> + </option> + </inspection_tool> + </profile> +</component> \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..105ce2da2d6447d11dfe32bfb846c3d5b199fc99 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ +<component name="InspectionProjectProfileManager"> + <settings> + <option name="USE_PROJECT_PROFILE" value="false" /> + <version value="1.0" /> + </settings> +</component> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..686ec174e6a2dc91a95520d1e09690655cb0a852 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (notebook4)" project-jdk-type="Python SDK" /> +</project> \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..28dfc9aca66065bbcd92236e0c464b1349c2d91a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/tp2-hachage.iml" filepath="$PROJECT_DIR$/.idea/tp2-hachage.iml" /> + </modules> + </component> +</project> \ No newline at end of file diff --git a/.idea/tp2-hachage.iml b/.idea/tp2-hachage.iml new file mode 100644 index 0000000000000000000000000000000000000000..8b8c395472a5a6b3598af42086e590417ace9933 --- /dev/null +++ b/.idea/tp2-hachage.iml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> + <component name="PyDocumentationSettings"> + <option name="format" value="PLAIN" /> + <option name="myDocStringFormat" value="Plain" /> + </component> +</module> \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/tp_2_miso_mphf.py b/tp_2_miso_mphf.py index dfef9902cf6c133853cf9eba5c81812351bbb76e..1d8802c0cd4efa811ebf325a18d3e6756ed9e7e2 100644 --- a/tp_2_miso_mphf.py +++ b/tp_2_miso_mphf.py @@ -8,116 +8,116 @@ 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: - 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. - if tableau_principal[x] is None: # Si l'index est libre - tableau_principal[x] = kmer # On place le k-mer dans la table - 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 - - # 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: - x = abs(hash(kmer)) % len (tableau_principal) - - if grand_tableau[h] == kmer: + + """ + 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: + 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. + if tableau_principal[x] is None: # Si l'index est libre + tableau_principal[x] = kmer # On place le k-mer dans la table + 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 + + # 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: + x = abs(hash(kmer)) % len (tableau_principal) + + if grand_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([h, rang]) # Ajouter l'index et le rang à la MPHF + 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 - - 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 + # 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 - """ - h = abs(hash(kmer)) - for pair in mphf: - if pair[0] == h: - return pair[1] - return None + """ + 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 + """ + h = abs(hash(kmer)) + for pair in mphf: + if pair[0] == h: + return pair[1] + return None def create_hash_table(set_kmer, n): @@ -151,39 +151,39 @@ def create_hash_table(set_kmer, n): 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() + 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")