From 788e5fdf5f54bf123428393bd3a731f364790bfb Mon Sep 17 00:00:00 2001 From: Lukian Date: Mon, 18 Nov 2024 13:00:20 +0100 Subject: [PATCH] Saataa andagii ! --- lib/ultra_mastermind_obj.py | 70 ++++++++++++++++++++++++++++++++++--- main.py | 8 +++-- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/lib/ultra_mastermind_obj.py b/lib/ultra_mastermind_obj.py index 99d82e1..6979883 100644 --- a/lib/ultra_mastermind_obj.py +++ b/lib/ultra_mastermind_obj.py @@ -1,6 +1,7 @@ # Librairie du projet en version orientée objet import random +import Levenshtein def min_i(array: list[int]) -> int: min_val = array[0] @@ -24,7 +25,7 @@ class Population: """ Classe qui représente notre population d'individuts """ - def __init__(self, pm, ng, n, ts, tm): + def __init__(self, pm, ng, n, ts, tm, alpha, fm): self.individuals = [Individual() for _ in range(n)] for individual in self.individuals: individual.randomize(len(pm)) @@ -34,17 +35,33 @@ class Population: self.n = n self.ts = ts self.tm = tm + self.alpha = alpha + self.fitness_method = fm def select(self) -> None: + """ + Methode qui sélectionne les meilleurs individus + """ fitness_list = [] for individual in self.individuals: - fitness_list.append(individual.fitness(self.pm)) + match self.fitness_method: + case 1: + fitness_list.append(individual.fitness1(self.pm)) + case 2: + fitness_list.append(individual.fitness2(self.pm, self.alpha)) + case 3: + fitness_list.append(individual.fitness3(self.pm)) + case _: + fitness_list.append(individual.fitness1(self.pm)) for i in range(int((1 - self.ts) * self.n)): least = min_i(fitness_list) fitness_list.pop(least) self.individuals.pop(least) def reproduct(self) -> None: + """ + Methode qui reproduit les individus entre eux jusqu'à obtenir une population de taille N + """ new = [] while len(self.individuals) + len(new) != self.n: cut = random.randint(int(self.l / 3), int(2 * self.l / 3)) @@ -59,6 +76,9 @@ class Population: self.individuals += new def mutate(self) -> None: + """ + Methode qui mute une partie de la population selon le taut de mutation + """ mutated = [] for i in range(int(self.tm * self.n)): to_mutate = random.randint(0, self.n - 1) @@ -68,12 +88,26 @@ class Population: mutated.append(to_mutate) def print_best(self) -> None: + """ + Methode qui affiche le meilleur individu de la population + """ fitness_list = [] for individual in self.individuals: - fitness_list.append(individual.fitness(self.pm)) + match self.fitness_method: + case 1: + fitness_list.append(individual.fitness1(self.pm)) + case 2: + fitness_list.append(individual.fitness2(self.pm, self.alpha)) + case 3: + fitness_list.append(individual.fitness3(self.pm)) + case _: + fitness_list.append(individual.fitness1(self.pm)) print(self.individuals[max_i(fitness_list)].getChromozome()) def run(self) -> None: + """ + Boucle principale + """ for i in range(self.ng): self.select() self.reproduct() @@ -94,18 +128,46 @@ class Individual: return self.chromozome def randomize(self, l) -> None: + """ + Methode qui change la valeur d'un chromozome pour une valeur aléatoire + """ new = "" for i in range(l): new += chr(random.randint(0, 255)) self.chromozome = new - def fitness(self, pm) -> int: + def fitness1(self, pm) -> int: + """ + Première methode de fitness, fait la somme des différences entre les codages des caractères des deux chaînes. + """ sum = 0 for i in range(len(self.chromozome)): sum += abs(ord(self.chromozome[i]) - ord(pm[i])) return -sum + def fitness2(self, pm, alpha) -> int: + """ + Deuxième methode de fitness qui compte les caractères bien placés et mal placés et qui renvoie un int pondéré par alpha + """ + match = 0 + missed_placed = 0 + for i in range(len(self.chromozome)): + if self.chromozome[i] == pm[i]: + match += 1 + else: + missed_placed += 1 + return match + alpha * missed_placed + + def fitness3(self, pm) -> int: + """ + Troisième methode de fitness qui utilise la distance de Levenshtein + """ + return -Levenshtein.distance(self.chromozome, pm) + def mutate(self) -> None: + """ + Methode qui change un des caractères du chromozome + """ new = list(self.chromozome) new[random.randint(0, len(new) - 1)] = chr(random.randint(0, 255)) self.chromozome = "".join(new) diff --git a/main.py b/main.py index 1269a00..15d8142 100644 --- a/main.py +++ b/main.py @@ -5,15 +5,17 @@ import lib.ultra_mastermind_obj as libobj import lib.ultra_mastermind_imp as libomp # constants -PM = "Saataa andagii !" -NG = 2000 +PM = "Hello, world!" +NG = 1000 N = 400 TS = 0.5 TM = 0.01 +ALPHA = 0.5 +FITNESS_METHOD = 3 # main function def main() -> None: - pop = libobj.Population(pm = PM, ng = NG, n = N, ts = TS, tm = TM) + pop = libobj.Population(pm = PM, ng = NG, n = N, ts = TS, tm = TM, alpha = ALPHA, fm = FITNESS_METHOD) pop.run() if __name__ == "__main__":