Saataa andagii !
This commit is contained in:
parent
d99a556d3d
commit
757ea77cc5
8 changed files with 549 additions and 500 deletions
|
@ -4,174 +4,174 @@ import random
|
|||
import Levenshtein
|
||||
|
||||
def min_i(array: list[int]) -> int:
|
||||
min_val = array[0]
|
||||
min_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] < min_val:
|
||||
min_val = array[i]
|
||||
min_i = i
|
||||
return min_i
|
||||
min_val = array[0]
|
||||
min_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] < min_val:
|
||||
min_val = array[i]
|
||||
min_i = i
|
||||
return min_i
|
||||
|
||||
def max_i(array: list[int]) -> int:
|
||||
max_val = array[0]
|
||||
max_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] > max_val:
|
||||
max_val = array[i]
|
||||
max_i = i
|
||||
return max_i
|
||||
max_val = array[0]
|
||||
max_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] > max_val:
|
||||
max_val = array[i]
|
||||
max_i = i
|
||||
return max_i
|
||||
|
||||
|
||||
def new_population(pm, ng, n, ts, tm, alpha, fm): # -> set(list(set(str)), str, int, int, int, float, float, float, int)
|
||||
"""
|
||||
fonction qui renvoie une nouvelle population
|
||||
"""
|
||||
population = {
|
||||
"individuals": [new_individual() for i in range(n)],
|
||||
"pm": pm,
|
||||
"ng": ng,
|
||||
"l": len(pm),
|
||||
"n": n,
|
||||
"ts": ts,
|
||||
"tm": tm,
|
||||
"alpha": alpha,
|
||||
"fm": fm
|
||||
}
|
||||
"""
|
||||
fonction qui renvoie une nouvelle population
|
||||
"""
|
||||
population = {
|
||||
"individuals": [new_individual() for i in range(n)],
|
||||
"pm": pm,
|
||||
"ng": ng,
|
||||
"l": len(pm),
|
||||
"n": n,
|
||||
"ts": ts,
|
||||
"tm": tm,
|
||||
"alpha": alpha,
|
||||
"fm": fm
|
||||
}
|
||||
|
||||
for individual in population["individuals"]:
|
||||
randomize(individual, len(pm))
|
||||
for individual in population["individuals"]:
|
||||
randomize(individual, len(pm))
|
||||
|
||||
return population
|
||||
return population
|
||||
|
||||
def new_individual(): # -> set(str)
|
||||
"""
|
||||
fonction qui renvoie un nouvel individu
|
||||
"""
|
||||
return {
|
||||
"chromozome": ""
|
||||
}
|
||||
"""
|
||||
fonction qui renvoie un nouvel individu
|
||||
"""
|
||||
return {
|
||||
"chromozome": ""
|
||||
}
|
||||
|
||||
def randomize(individual, l) -> str:
|
||||
"""
|
||||
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))
|
||||
individual["chromozome"] = new
|
||||
"""
|
||||
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))
|
||||
individual["chromozome"] = new
|
||||
|
||||
def fitness1(individual, 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(individual["chromozome"])):
|
||||
sum += abs(ord(individual["chromozome"][i]) - ord(pm[i]))
|
||||
return -sum
|
||||
"""
|
||||
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(individual["chromozome"])):
|
||||
sum += abs(ord(individual["chromozome"][i]) - ord(pm[i]))
|
||||
return -sum
|
||||
|
||||
def fitness2(individual, 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(individual["chromozome"])):
|
||||
if individual["chromozome"][i] == pm[i]:
|
||||
match += 1
|
||||
else:
|
||||
missed_placed += 1
|
||||
return match + alpha * missed_placed
|
||||
"""
|
||||
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(individual["chromozome"])):
|
||||
if individual["chromozome"][i] == pm[i]:
|
||||
match += 1
|
||||
else:
|
||||
missed_placed += 1
|
||||
return match + alpha * missed_placed
|
||||
|
||||
def fitness3(individual, pm) -> int:
|
||||
"""
|
||||
Troisième methode de fitness qui utilise la distance de Levenshtein
|
||||
"""
|
||||
return -Levenshtein.distance(individual["chromozome"], pm)
|
||||
"""
|
||||
Troisième methode de fitness qui utilise la distance de Levenshtein
|
||||
"""
|
||||
return -Levenshtein.distance(individual["chromozome"], pm)
|
||||
|
||||
def get_fitness(population, individual) -> int:
|
||||
match population["fm"]:
|
||||
case 1:
|
||||
return fitness1(individual, population["pm"])
|
||||
case 2:
|
||||
return fitness2(individual, population["pm"], population["alpha"])
|
||||
case 3:
|
||||
return fitness3(individual, population["pm"])
|
||||
case _:
|
||||
return fitness1(individual, population["pm"])
|
||||
match population["fm"]:
|
||||
case 1:
|
||||
return fitness1(individual, population["pm"])
|
||||
case 2:
|
||||
return fitness2(individual, population["pm"], population["alpha"])
|
||||
case 3:
|
||||
return fitness3(individual, population["pm"])
|
||||
case _:
|
||||
return fitness1(individual, population["pm"])
|
||||
|
||||
def get_best(population):
|
||||
"""
|
||||
Methode qui renvoie le meilleur individu de la population
|
||||
"""
|
||||
fitness_list = []
|
||||
for individual in population["individuals"]:
|
||||
fitness_list.append(get_fitness(population, individual))
|
||||
return population["individuals"][max_i(fitness_list)]
|
||||
"""
|
||||
Methode qui renvoie le meilleur individu de la population
|
||||
"""
|
||||
fitness_list = []
|
||||
for individual in population["individuals"]:
|
||||
fitness_list.append(get_fitness(population, individual))
|
||||
return population["individuals"][max_i(fitness_list)]
|
||||
|
||||
def print_best(population) -> None:
|
||||
"""
|
||||
Methode qui affiche le meilleur individu de la population
|
||||
"""
|
||||
print(get_best(population)["chromozome"])
|
||||
"""
|
||||
Methode qui affiche le meilleur individu de la population
|
||||
"""
|
||||
print(get_best(population)["chromozome"])
|
||||
|
||||
def mutate(individual) -> None:
|
||||
"""
|
||||
Methode qui change un des caractères du chromozome
|
||||
"""
|
||||
new = list(individual["chromozome"])
|
||||
new[random.randint(0, len(new) - 1)] = chr(random.randint(0, 255))
|
||||
individual["chromozome"] = "".join(new)
|
||||
"""
|
||||
Methode qui change un des caractères du chromozome
|
||||
"""
|
||||
new = list(individual["chromozome"])
|
||||
new[random.randint(0, len(new) - 1)] = chr(random.randint(0, 255))
|
||||
individual["chromozome"] = "".join(new)
|
||||
|
||||
def select(population) -> None:
|
||||
"""
|
||||
Methode qui sélectionne les meilleurs individus
|
||||
"""
|
||||
fitness_list = []
|
||||
for individual in population["individuals"]:
|
||||
fitness_list.append(get_fitness(population, individual))
|
||||
"""
|
||||
Methode qui sélectionne les meilleurs individus
|
||||
"""
|
||||
fitness_list = []
|
||||
for individual in population["individuals"]:
|
||||
fitness_list.append(get_fitness(population, individual))
|
||||
|
||||
for i in range(int((1 - population["ts"]) * population["n"])):
|
||||
least = min_i(fitness_list)
|
||||
fitness_list.pop(least)
|
||||
population["individuals"].pop(least)
|
||||
for i in range(int((1 - population["ts"]) * population["n"])):
|
||||
least = min_i(fitness_list)
|
||||
fitness_list.pop(least)
|
||||
population["individuals"].pop(least)
|
||||
|
||||
def reproduct(population) -> None:
|
||||
"""
|
||||
Methode qui reproduit les individus entre eux jusqu'à obtenir une population de taille N
|
||||
"""
|
||||
new = []
|
||||
while len(population["individuals"]) + len(new) != population["n"]:
|
||||
cut = random.randint(int(population["l"] / 3), int(2 * population["l"] / 3))
|
||||
i = random.randint(0, len(population["individuals"]) - 1)
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
while i == j:
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
indivi_1 = population["individuals"][i]
|
||||
indivi_2 = population['individuals'][j]
|
||||
new_chromozome = indivi_1["chromozome"][:cut] + indivi_2["chromozome"][cut:]
|
||||
child = new_individual()
|
||||
child["chromozome"] = new_chromozome
|
||||
new.append(child)
|
||||
population["individuals"] += new
|
||||
"""
|
||||
Methode qui reproduit les individus entre eux jusqu'à obtenir une population de taille N
|
||||
"""
|
||||
new = []
|
||||
while len(population["individuals"]) + len(new) != population["n"]:
|
||||
cut = random.randint(int(population["l"] / 3), int(2 * population["l"] / 3))
|
||||
i = random.randint(0, len(population["individuals"]) - 1)
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
while i == j:
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
indivi_1 = population["individuals"][i]
|
||||
indivi_2 = population['individuals'][j]
|
||||
new_chromozome = indivi_1["chromozome"][:cut] + indivi_2["chromozome"][cut:]
|
||||
child = new_individual()
|
||||
child["chromozome"] = new_chromozome
|
||||
new.append(child)
|
||||
population["individuals"] += new
|
||||
|
||||
def mutate_pop(population) -> None:
|
||||
"""
|
||||
Methode qui mute une partie de la population selon le taut de mutation
|
||||
"""
|
||||
mutated = []
|
||||
for i in range(int(population["tm"] * population["n"])):
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
while to_mutate in mutated:
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
mutate(population["individuals"][to_mutate])
|
||||
mutated.append(to_mutate)
|
||||
"""
|
||||
Methode qui mute une partie de la population selon le taut de mutation
|
||||
"""
|
||||
mutated = []
|
||||
for i in range(int(population["tm"] * population["n"])):
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
while to_mutate in mutated:
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
mutate(population["individuals"][to_mutate])
|
||||
mutated.append(to_mutate)
|
||||
|
||||
def run(population) -> None:
|
||||
"""
|
||||
Boucle principale
|
||||
"""
|
||||
for i in range(population["ng"]):
|
||||
select(population)
|
||||
reproduct(population)
|
||||
mutate_pop(population)
|
||||
print_best(population)
|
||||
"""
|
||||
Boucle principale
|
||||
"""
|
||||
for i in range(population["ng"]):
|
||||
select(population)
|
||||
reproduct(population)
|
||||
mutate_pop(population)
|
||||
print_best(population)
|
||||
|
|
|
@ -4,170 +4,170 @@ import random
|
|||
import Levenshtein
|
||||
|
||||
def min_i(array: list[int]) -> int:
|
||||
min_val = array[0]
|
||||
min_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] < min_val:
|
||||
min_val = array[i]
|
||||
min_i = i
|
||||
return min_i
|
||||
min_val = array[0]
|
||||
min_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] < min_val:
|
||||
min_val = array[i]
|
||||
min_i = i
|
||||
return min_i
|
||||
|
||||
def max_i(array: list[int]) -> int:
|
||||
max_val = array[0]
|
||||
max_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] > max_val:
|
||||
max_val = array[i]
|
||||
max_i = i
|
||||
return max_i
|
||||
max_val = array[0]
|
||||
max_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] > max_val:
|
||||
max_val = array[i]
|
||||
max_i = i
|
||||
return max_i
|
||||
|
||||
class Population:
|
||||
"""
|
||||
Classe qui représente notre population d'individuts
|
||||
"""
|
||||
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))
|
||||
self.pm = pm
|
||||
self.ng = ng
|
||||
self.l = len(pm)
|
||||
self.n = n
|
||||
self.ts = ts
|
||||
self.tm = tm
|
||||
self.alpha = alpha
|
||||
self.fitness_method = fm
|
||||
"""
|
||||
Classe qui représente notre population d'individuts
|
||||
"""
|
||||
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))
|
||||
self.pm = pm
|
||||
self.ng = ng
|
||||
self.l = len(pm)
|
||||
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:
|
||||
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 select(self) -> None:
|
||||
"""
|
||||
Methode qui sélectionne les meilleurs individus
|
||||
"""
|
||||
fitness_list = []
|
||||
for individual in self.individuals:
|
||||
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))
|
||||
indivi_1 = self.individuals[random.randint(0, len(self.individuals) - 1)]
|
||||
indivi_2 = self.individuals[random.randint(0, len(self.individuals) - 1)]
|
||||
while indivi_1 == indivi_2:
|
||||
indivi_2 = self.individuals[random.randint(0, len(self.individuals) - 1)]
|
||||
new_chromozome = indivi_1.getChromozome()[:cut] + indivi_2.getChromozome()[cut:]
|
||||
child = Individual()
|
||||
child.setChromozome(new_chromozome)
|
||||
new.append(child)
|
||||
self.individuals += new
|
||||
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))
|
||||
indivi_1 = self.individuals[random.randint(0, len(self.individuals) - 1)]
|
||||
indivi_2 = self.individuals[random.randint(0, len(self.individuals) - 1)]
|
||||
while indivi_1 == indivi_2:
|
||||
indivi_2 = self.individuals[random.randint(0, len(self.individuals) - 1)]
|
||||
new_chromozome = indivi_1.getChromozome()[:cut] + indivi_2.getChromozome()[cut:]
|
||||
child = Individual()
|
||||
child.setChromozome(new_chromozome)
|
||||
new.append(child)
|
||||
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)
|
||||
while to_mutate in mutated:
|
||||
to_mutate = random.randint(0, self.n - 1)
|
||||
self.individuals[to_mutate].mutate()
|
||||
mutated.append(to_mutate)
|
||||
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)
|
||||
while to_mutate in mutated:
|
||||
to_mutate = random.randint(0, self.n - 1)
|
||||
self.individuals[to_mutate].mutate()
|
||||
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:
|
||||
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 print_best(self) -> None:
|
||||
"""
|
||||
Methode qui affiche le meilleur individu de la population
|
||||
"""
|
||||
fitness_list = []
|
||||
for individual in self.individuals:
|
||||
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()
|
||||
self.mutate()
|
||||
self.print_best()
|
||||
def run(self) -> None:
|
||||
"""
|
||||
Boucle principale
|
||||
"""
|
||||
for i in range(self.ng):
|
||||
self.select()
|
||||
self.reproduct()
|
||||
self.mutate()
|
||||
self.print_best()
|
||||
|
||||
class Individual:
|
||||
"""
|
||||
Classe qui représente les individuts de la population (les solutions potentielles)
|
||||
"""
|
||||
def __init__(self):
|
||||
self.chromozome = ""
|
||||
"""
|
||||
Classe qui représente les individuts de la population (les solutions potentielles)
|
||||
"""
|
||||
def __init__(self):
|
||||
self.chromozome = ""
|
||||
|
||||
def setChromozome(self, c: str) -> None:
|
||||
self.chromozome = c
|
||||
|
||||
def getChromozome(self) -> str:
|
||||
return self.chromozome
|
||||
def setChromozome(self, c: str) -> None:
|
||||
self.chromozome = c
|
||||
|
||||
def getChromozome(self) -> str:
|
||||
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 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 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 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 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 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)
|
||||
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)
|
||||
|
|
|
@ -4,194 +4,196 @@ import random
|
|||
import Levenshtein
|
||||
|
||||
def min_i(array: list[int]) -> int:
|
||||
min_val = array[0]
|
||||
min_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] < min_val:
|
||||
min_val = array[i]
|
||||
min_i = i
|
||||
return min_i
|
||||
min_val = array[0]
|
||||
min_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] < min_val:
|
||||
min_val = array[i]
|
||||
min_i = i
|
||||
return min_i
|
||||
|
||||
def max_i(array: list[int]) -> int:
|
||||
max_val = array[0]
|
||||
max_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] > max_val:
|
||||
max_val = array[i]
|
||||
max_i = i
|
||||
return max_i
|
||||
max_val = array[0]
|
||||
max_i = 0
|
||||
for i in range(len(array)):
|
||||
if array[i] > max_val:
|
||||
max_val = array[i]
|
||||
max_i = i
|
||||
return max_i
|
||||
|
||||
def new_population(pm, ng, n, ts, tm, alpha, fm):
|
||||
"""
|
||||
fonction qui renvoie une nouvelle population
|
||||
"""
|
||||
population = {
|
||||
"individuals": [new_individual() for i in range(n)],
|
||||
"pm": pm,
|
||||
"ng": ng,
|
||||
"l": len(pm),
|
||||
"n": n,
|
||||
"ts": ts,
|
||||
"tm": tm,
|
||||
"alpha": alpha,
|
||||
"fm": fm
|
||||
}
|
||||
"""
|
||||
fonction qui renvoie une nouvelle population
|
||||
"""
|
||||
population = {
|
||||
"individuals": [new_individual() for i in range(n)],
|
||||
"pm": pm,
|
||||
"ng": ng,
|
||||
"l": len(pm),
|
||||
"n": n,
|
||||
"ts": ts,
|
||||
"tm": tm,
|
||||
"alpha": alpha,
|
||||
"fm": fm
|
||||
}
|
||||
|
||||
for individual in population["individuals"]:
|
||||
randomize(individual, 4, 30)
|
||||
for individual in population["individuals"]:
|
||||
randomize(individual, 4, 30)
|
||||
|
||||
return population
|
||||
return population
|
||||
|
||||
def new_individual():
|
||||
"""
|
||||
fonction qui renvoie un nouvel individu
|
||||
"""
|
||||
return {
|
||||
"chromozome": ""
|
||||
}
|
||||
"""
|
||||
fonction qui renvoie un nouvel individu
|
||||
"""
|
||||
return {
|
||||
"chromozome": ""
|
||||
}
|
||||
|
||||
def randomize(individual, min_l, max_l) -> str:
|
||||
"""
|
||||
Methode qui change la valeur d'un chromozome pour une valeur aléatoire
|
||||
"""
|
||||
new = ""
|
||||
for i in range(random.randint(min_l, max_l)):
|
||||
new += chr(random.randint(0, 255))
|
||||
individual["chromozome"] = new
|
||||
"""
|
||||
Methode qui change la valeur d'un chromozome pour une valeur aléatoire
|
||||
"""
|
||||
new = ""
|
||||
for i in range(random.randint(min_l, max_l)):
|
||||
new += chr(random.randint(0, 255))
|
||||
individual["chromozome"] = new
|
||||
|
||||
def fitness1(individual, 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(individual["chromozome"])):
|
||||
if i < len(pm) and i < len(individual["chromozome"]):
|
||||
sum += abs(ord(individual["chromozome"][i]) - ord(pm[i]))
|
||||
return -sum
|
||||
"""
|
||||
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(individual["chromozome"])):
|
||||
if i < len(pm) and i < len(individual["chromozome"]):
|
||||
sum += abs(ord(individual["chromozome"][i]) - ord(pm[i]))
|
||||
return -sum
|
||||
|
||||
def fitness2(individual, 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(individual["chromozome"])):
|
||||
if i >= len(pm):
|
||||
missed_placed += len(individual["chromozome"]) - len(pm)
|
||||
break
|
||||
elif individual["chromozome"][i] == pm[i]:
|
||||
match += 1
|
||||
else:
|
||||
missed_placed += 1
|
||||
if len(pm) > len(individual["chromozome"]):
|
||||
missed_placed += len(pm) - len(individual["chromozome"])
|
||||
return match + alpha * missed_placed
|
||||
"""
|
||||
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(individual["chromozome"])):
|
||||
if i >= len(pm):
|
||||
missed_placed += len(individual["chromozome"]) - len(pm)
|
||||
break
|
||||
elif individual["chromozome"][i] == pm[i]:
|
||||
match += 1
|
||||
else:
|
||||
missed_placed += 1
|
||||
if len(pm) > len(individual["chromozome"]):
|
||||
missed_placed += len(pm) - len(individual["chromozome"])
|
||||
return match + alpha * missed_placed
|
||||
|
||||
def fitness3(individual, pm) -> int:
|
||||
"""
|
||||
Troisième methode de fitness qui utilise la distance de Levenshtein
|
||||
"""
|
||||
return -Levenshtein.distance(individual["chromozome"], pm)
|
||||
"""
|
||||
Troisième methode de fitness qui utilise la distance de Levenshtein
|
||||
"""
|
||||
return -Levenshtein.distance(individual["chromozome"], pm)
|
||||
|
||||
def get_fitness(population, individual) -> int:
|
||||
match population["fm"]:
|
||||
case 1:
|
||||
return fitness1(individual, population["pm"])
|
||||
case 2:
|
||||
return fitness2(individual, population["pm"], population["alpha"])
|
||||
case 3:
|
||||
return fitness3(individual, population["pm"])
|
||||
case _:
|
||||
return fitness1(individual, population["pm"])
|
||||
match population["fm"]:
|
||||
case 1:
|
||||
return fitness1(individual, population["pm"])
|
||||
case 2:
|
||||
return fitness2(individual, population["pm"], population["alpha"])
|
||||
case 3:
|
||||
return fitness3(individual, population["pm"])
|
||||
case _:
|
||||
return fitness1(individual, population["pm"])
|
||||
|
||||
def get_fitness_list(population):
|
||||
fitness_list = []
|
||||
for individual in population["individuals"]:
|
||||
fitness_list.append(get_fitness(population, individual))
|
||||
return fitness_list
|
||||
fitness_list = []
|
||||
for individual in population["individuals"]:
|
||||
fitness_list.append(get_fitness(population, individual))
|
||||
return fitness_list
|
||||
|
||||
def get_best(population):
|
||||
"""
|
||||
Methode qui renvoie le meilleur individu de la population
|
||||
"""
|
||||
fitness_list = get_fitness_list(population)
|
||||
return population["individuals"][max_i(fitness_list)]
|
||||
"""
|
||||
Methode qui renvoie le meilleur individu de la population
|
||||
"""
|
||||
fitness_list = get_fitness_list(population)
|
||||
return population["individuals"][max_i(fitness_list)]
|
||||
|
||||
def print_best(population) -> None:
|
||||
"""
|
||||
Methode qui affiche le meilleur individu de la population
|
||||
"""
|
||||
print(get_best(population)["chromozome"])
|
||||
"""
|
||||
Methode qui affiche le meilleur individu de la population
|
||||
"""
|
||||
print(get_best(population)["chromozome"])
|
||||
|
||||
def select(population) -> None:
|
||||
"""
|
||||
Methode qui sélectionne les meilleurs individus
|
||||
"""
|
||||
fitness_list = get_fitness_list(population)
|
||||
for i in range(int((1 - population["ts"]) * population["n"])):
|
||||
least = min_i(fitness_list)
|
||||
fitness_list.pop(least)
|
||||
population["individuals"].pop(least)
|
||||
"""
|
||||
Methode qui sélectionne les meilleurs individus
|
||||
"""
|
||||
fitness_list = get_fitness_list(population)
|
||||
for i in range(int((1 - population["ts"]) * population["n"])):
|
||||
least = min_i(fitness_list)
|
||||
fitness_list.pop(least)
|
||||
population["individuals"].pop(least)
|
||||
|
||||
def get_two_random_individuals(population):
|
||||
i = random.randint(0, len(population["individuals"]) - 1)
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
while i == j:
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
return (population["individuals"][i], population['individuals'][j])
|
||||
i = random.randint(0, len(population["individuals"]) - 1)
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
while i == j:
|
||||
j = random.randint(0, len(population["individuals"]) - 1)
|
||||
return (population["individuals"][i], population['individuals'][j])
|
||||
|
||||
def reproduct(population) -> None:
|
||||
"""
|
||||
Methode qui reproduit les individus entre eux jusqu'à obtenir une population de taille N
|
||||
"""
|
||||
new = []
|
||||
while len(population["individuals"]) + len(new) != population["n"]:
|
||||
indivi_1, indivi_2 = get_two_random_individuals(population)
|
||||
"""
|
||||
Methode qui reproduit les individus entre eux jusqu'à obtenir une population de taille N
|
||||
"""
|
||||
new = []
|
||||
while len(population["individuals"]) + len(new) != population["n"]:
|
||||
indivi_1, indivi_2 = get_two_random_individuals(population)
|
||||
|
||||
avg = (len(indivi_1) + len(indivi_2)) // 2
|
||||
cut = random.randint(avg // 3, 2 * avg // 3)
|
||||
while cut > len(indivi_1) or cut > len(indivi_2):
|
||||
cut = random.randint(avg // 3, 2 * avg // 3)
|
||||
avg = (len(indivi_1) + len(indivi_2)) // 2
|
||||
cut = random.randint(avg // 3, 2 * avg // 3)
|
||||
while cut > len(indivi_1) or cut > len(indivi_2):
|
||||
cut = random.randint(avg // 3, 2 * avg // 3)
|
||||
|
||||
new_chromozome = indivi_1["chromozome"][:cut] + indivi_2["chromozome"][cut:]
|
||||
child = new_individual()
|
||||
child["chromozome"] = new_chromozome
|
||||
new.append(child)
|
||||
new_chromozome = indivi_1["chromozome"][:cut] + indivi_2["chromozome"][cut:]
|
||||
child = new_individual()
|
||||
child["chromozome"] = new_chromozome
|
||||
new.append(child)
|
||||
|
||||
population["individuals"] += new
|
||||
population["individuals"] += new
|
||||
|
||||
def mutate(individual) -> None:
|
||||
"""
|
||||
Methode qui change un des caractères du chromozome
|
||||
"""
|
||||
new = list(individual["chromozome"])
|
||||
dice = random.randint(1,3)
|
||||
if dice == 1 and len(new) < 30:
|
||||
new.insert(random.randint(0, len(new) - 1), chr(random.randint(0, 255)))
|
||||
elif dice == 2 and len(new) > 4:
|
||||
new.pop(random.randint(0, len(new) - 1))
|
||||
else :
|
||||
new[random.randint(0, len(new) - 1)] = chr(random.randint(0, 255))
|
||||
individual["chromozome"] = "".join(new)
|
||||
"""
|
||||
Methode qui change un des caractères du chromozome
|
||||
"""
|
||||
new = list(individual["chromozome"])
|
||||
dice = random.randint(1, 6)
|
||||
if dice == 1 and len(new) < 30:
|
||||
new.insert(random.randint(0, len(new) - 1), chr(random.randint(0, 255)))
|
||||
elif dice == 2 and len(new) > 4:
|
||||
new.pop(random.randint(0, len(new) - 1))
|
||||
else :
|
||||
new[random.randint(0, len(new) - 1)] = chr(random.randint(0, 255))
|
||||
individual["chromozome"] = "".join(new)
|
||||
|
||||
def mutate_pop(population) -> None:
|
||||
"""
|
||||
Methode qui mute une partie de la population selon le taut de mutation
|
||||
"""
|
||||
mutated = []
|
||||
for i in range(int(population["tm"] * population["n"])):
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
while to_mutate in mutated:
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
mutate(population["individuals"][to_mutate])
|
||||
mutated.append(to_mutate)
|
||||
"""
|
||||
Methode qui mute une partie de la population selon le taut de mutation
|
||||
"""
|
||||
mutated = []
|
||||
for i in range(int(population["tm"] * population["n"])):
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
while to_mutate in mutated:
|
||||
to_mutate = random.randint(0, population["n"] - 1)
|
||||
mutate(population["individuals"][to_mutate])
|
||||
mutated.append(to_mutate)
|
||||
|
||||
def run(population) -> None:
|
||||
"""
|
||||
Boucle principale
|
||||
"""
|
||||
for i in range(population["ng"]):
|
||||
select(population)
|
||||
reproduct(population)
|
||||
mutate_pop(population)
|
||||
print_best(population)
|
||||
def run(population) -> int:
|
||||
"""
|
||||
Boucle principale
|
||||
"""
|
||||
for i in range(population["ng"]):
|
||||
if get_best(population)["chromozome"] == population["pm"]:
|
||||
return i
|
||||
select(population)
|
||||
reproduct(population)
|
||||
mutate_pop(population)
|
||||
return population["ng"]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue