Saataa andagii !
This commit is contained in:
parent
026033e6ad
commit
303063b78e
1 changed files with 33 additions and 0 deletions
|
@ -4,6 +4,9 @@ import random
|
|||
import Levenshtein
|
||||
|
||||
def min_i(array: list[int]) -> int:
|
||||
"""
|
||||
Fonction renvoyant l'indexe du minimum d'une liste d'entiers
|
||||
"""
|
||||
min_val = array[0]
|
||||
min_i = 0
|
||||
for i in range(len(array)):
|
||||
|
@ -13,6 +16,9 @@ def min_i(array: list[int]) -> int:
|
|||
return min_i
|
||||
|
||||
def max_i(array: list[int]) -> int:
|
||||
"""
|
||||
Fonction renvoyant l'indexe du maximum d'une liste d'entiers
|
||||
"""
|
||||
max_val = array[0]
|
||||
max_i = 0
|
||||
for i in range(len(array)):
|
||||
|
@ -37,6 +43,7 @@ def new_population(pm, ng, n, ts, tm, alpha, fm):
|
|||
"fm": fm
|
||||
}
|
||||
|
||||
# On rend aléatoire les chromozomes des individus
|
||||
for individual in population["individuals"]:
|
||||
randomize(individual, 4, 30)
|
||||
|
||||
|
@ -76,6 +83,7 @@ def fitness2(individual, pm, alpha) -> int:
|
|||
match = 0
|
||||
missed_placed = 0
|
||||
for i in range(len(individual["chromozome"])):
|
||||
# Si la chaîne est plus grande que la phrase alors on rajoute des caractères mal placés
|
||||
if i >= len(pm):
|
||||
missed_placed += len(individual["chromozome"]) - len(pm)
|
||||
break
|
||||
|
@ -83,6 +91,7 @@ def fitness2(individual, pm, alpha) -> int:
|
|||
match += 1
|
||||
else:
|
||||
missed_placed += 1
|
||||
# Si la phrase est trop longue on rajoute autant de caractères mal placés que de caractères en trop
|
||||
if len(pm) > len(individual["chromozome"]):
|
||||
missed_placed += len(pm) - len(individual["chromozome"])
|
||||
return match + alpha * missed_placed
|
||||
|
@ -94,6 +103,9 @@ def fitness3(individual, pm) -> int:
|
|||
return -Levenshtein.distance(individual["chromozome"], pm)
|
||||
|
||||
def get_fitness(population, individual) -> int:
|
||||
"""
|
||||
Fonction qui renvoie la fitness d'un individu en utilisant la fonction choisie en paramètre de la population
|
||||
"""
|
||||
match population["fm"]:
|
||||
case 1:
|
||||
return fitness1(individual, population["pm"])
|
||||
|
@ -105,6 +117,9 @@ def get_fitness(population, individual) -> int:
|
|||
return fitness1(individual, population["pm"])
|
||||
|
||||
def get_fitness_list(population):
|
||||
"""
|
||||
Fonction renvoyant une liste des fitness de touts les individus d'une population
|
||||
"""
|
||||
fitness_list = []
|
||||
for individual in population["individuals"]:
|
||||
fitness_list.append(get_fitness(population, individual))
|
||||
|
@ -129,11 +144,16 @@ def select(population) -> None:
|
|||
"""
|
||||
fitness_list = get_fitness_list(population)
|
||||
for i in range(int((1 - population["ts"]) * population["n"])):
|
||||
# On détermine quel est le moins bon individu
|
||||
least = min_i(fitness_list)
|
||||
# On le supprime des deux listes
|
||||
fitness_list.pop(least)
|
||||
population["individuals"].pop(least)
|
||||
|
||||
def get_two_random_individuals(population):
|
||||
"""
|
||||
Fonction renvoyant deux individus choisis aléatoirement
|
||||
"""
|
||||
i = random.randint(0, len(population["individuals"]) - 1)
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
while i == j:
|
||||
|
@ -145,14 +165,19 @@ def reproduct(population) -> None:
|
|||
Methode qui reproduit les individus entre eux jusqu'à obtenir une population de taille N
|
||||
"""
|
||||
new = []
|
||||
# On créé de nouveaux individus jusqu'à avoir atteint la taille de population demandée
|
||||
while len(population["individuals"]) + len(new) != population["n"]:
|
||||
# On prend deux individus aléatoires
|
||||
indivi_1, indivi_2 = get_two_random_individuals(population)
|
||||
|
||||
# On calcule le cut en fonction de la moyenne des tailles des deux individus
|
||||
avg = (len(indivi_1) + len(indivi_2)) // 2
|
||||
cut = random.randint(avg // 3, 2 * avg // 3)
|
||||
# On fait en sorte que le cut reste dans les valeurs possibles
|
||||
while cut > len(indivi_1) or cut > len(indivi_2):
|
||||
cut = random.randint(avg // 3, 2 * avg // 3)
|
||||
|
||||
# On créé le nouvel individu et on l'ajoute à la population
|
||||
new_chromozome = indivi_1["chromozome"][:cut] + indivi_2["chromozome"][cut:]
|
||||
child = new_individual()
|
||||
child["chromozome"] = new_chromozome
|
||||
|
@ -165,11 +190,15 @@ def mutate(individual) -> None:
|
|||
Methode qui change un des caractères du chromozome
|
||||
"""
|
||||
new = list(individual["chromozome"])
|
||||
# On jette un dé 6 pour déterminer l'effet qu'aura la mutation
|
||||
dice = random.randint(1, 6)
|
||||
# Sur un 1 on ajoute un caractère aléatoire
|
||||
if dice == 1 and len(new) < 30:
|
||||
new.insert(random.randint(0, len(new) - 1), chr(random.randint(0, 255)))
|
||||
# Sur un 2 on retire un caractère aléatoire
|
||||
elif dice == 2 and len(new) > 4:
|
||||
new.pop(random.randint(0, len(new) - 1))
|
||||
# Sinon on modifie un caractère déjà existant
|
||||
else :
|
||||
new[random.randint(0, len(new) - 1)] = chr(random.randint(0, 255))
|
||||
individual["chromozome"] = "".join(new)
|
||||
|
@ -180,9 +209,11 @@ def mutate_pop(population) -> None:
|
|||
"""
|
||||
mutated = []
|
||||
for i in range(int(population["tm"] * population["n"])):
|
||||
# Sélectionne un individu aléatoire qui n'a pas encore été muté à cette génération
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
while to_mutate in mutated:
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
# Mutation de l'individu choisi
|
||||
mutate(population["individuals"][to_mutate])
|
||||
mutated.append(to_mutate)
|
||||
|
||||
|
@ -190,7 +221,9 @@ def run(population) -> int:
|
|||
"""
|
||||
Boucle principale
|
||||
"""
|
||||
# On fait autant de générations que demandé
|
||||
for i in range(population["ng"]):
|
||||
# On arrête le programme une fois la phrase retrouvée et on renvoie le nombre de générations utilisées
|
||||
if get_best(population)["chromozome"] == population["pm"]:
|
||||
return i
|
||||
select(population)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue