Saataa andagii !
This commit is contained in:
parent
b858033964
commit
788e5fdf5f
2 changed files with 71 additions and 7 deletions
|
@ -1,6 +1,7 @@
|
||||||
# Librairie du projet en version orientée objet
|
# Librairie du projet en version orientée objet
|
||||||
|
|
||||||
import random
|
import random
|
||||||
|
import Levenshtein
|
||||||
|
|
||||||
def min_i(array: list[int]) -> int:
|
def min_i(array: list[int]) -> int:
|
||||||
min_val = array[0]
|
min_val = array[0]
|
||||||
|
@ -24,7 +25,7 @@ class Population:
|
||||||
"""
|
"""
|
||||||
Classe qui représente notre population d'individuts
|
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)]
|
self.individuals = [Individual() for _ in range(n)]
|
||||||
for individual in self.individuals:
|
for individual in self.individuals:
|
||||||
individual.randomize(len(pm))
|
individual.randomize(len(pm))
|
||||||
|
@ -34,17 +35,33 @@ class Population:
|
||||||
self.n = n
|
self.n = n
|
||||||
self.ts = ts
|
self.ts = ts
|
||||||
self.tm = tm
|
self.tm = tm
|
||||||
|
self.alpha = alpha
|
||||||
|
self.fitness_method = fm
|
||||||
|
|
||||||
def select(self) -> None:
|
def select(self) -> None:
|
||||||
|
"""
|
||||||
|
Methode qui sélectionne les meilleurs individus
|
||||||
|
"""
|
||||||
fitness_list = []
|
fitness_list = []
|
||||||
for individual in self.individuals:
|
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)):
|
for i in range(int((1 - self.ts) * self.n)):
|
||||||
least = min_i(fitness_list)
|
least = min_i(fitness_list)
|
||||||
fitness_list.pop(least)
|
fitness_list.pop(least)
|
||||||
self.individuals.pop(least)
|
self.individuals.pop(least)
|
||||||
|
|
||||||
def reproduct(self) -> None:
|
def reproduct(self) -> None:
|
||||||
|
"""
|
||||||
|
Methode qui reproduit les individus entre eux jusqu'à obtenir une population de taille N
|
||||||
|
"""
|
||||||
new = []
|
new = []
|
||||||
while len(self.individuals) + len(new) != self.n:
|
while len(self.individuals) + len(new) != self.n:
|
||||||
cut = random.randint(int(self.l / 3), int(2 * self.l / 3))
|
cut = random.randint(int(self.l / 3), int(2 * self.l / 3))
|
||||||
|
@ -59,6 +76,9 @@ class Population:
|
||||||
self.individuals += new
|
self.individuals += new
|
||||||
|
|
||||||
def mutate(self) -> None:
|
def mutate(self) -> None:
|
||||||
|
"""
|
||||||
|
Methode qui mute une partie de la population selon le taut de mutation
|
||||||
|
"""
|
||||||
mutated = []
|
mutated = []
|
||||||
for i in range(int(self.tm * self.n)):
|
for i in range(int(self.tm * self.n)):
|
||||||
to_mutate = random.randint(0, self.n - 1)
|
to_mutate = random.randint(0, self.n - 1)
|
||||||
|
@ -68,12 +88,26 @@ class Population:
|
||||||
mutated.append(to_mutate)
|
mutated.append(to_mutate)
|
||||||
|
|
||||||
def print_best(self) -> None:
|
def print_best(self) -> None:
|
||||||
|
"""
|
||||||
|
Methode qui affiche le meilleur individu de la population
|
||||||
|
"""
|
||||||
fitness_list = []
|
fitness_list = []
|
||||||
for individual in self.individuals:
|
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())
|
print(self.individuals[max_i(fitness_list)].getChromozome())
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
|
"""
|
||||||
|
Boucle principale
|
||||||
|
"""
|
||||||
for i in range(self.ng):
|
for i in range(self.ng):
|
||||||
self.select()
|
self.select()
|
||||||
self.reproduct()
|
self.reproduct()
|
||||||
|
@ -94,18 +128,46 @@ class Individual:
|
||||||
return self.chromozome
|
return self.chromozome
|
||||||
|
|
||||||
def randomize(self, l) -> None:
|
def randomize(self, l) -> None:
|
||||||
|
"""
|
||||||
|
Methode qui change la valeur d'un chromozome pour une valeur aléatoire
|
||||||
|
"""
|
||||||
new = ""
|
new = ""
|
||||||
for i in range(l):
|
for i in range(l):
|
||||||
new += chr(random.randint(0, 255))
|
new += chr(random.randint(0, 255))
|
||||||
self.chromozome = new
|
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
|
sum = 0
|
||||||
for i in range(len(self.chromozome)):
|
for i in range(len(self.chromozome)):
|
||||||
sum += abs(ord(self.chromozome[i]) - ord(pm[i]))
|
sum += abs(ord(self.chromozome[i]) - ord(pm[i]))
|
||||||
return -sum
|
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:
|
def mutate(self) -> None:
|
||||||
|
"""
|
||||||
|
Methode qui change un des caractères du chromozome
|
||||||
|
"""
|
||||||
new = list(self.chromozome)
|
new = list(self.chromozome)
|
||||||
new[random.randint(0, len(new) - 1)] = chr(random.randint(0, 255))
|
new[random.randint(0, len(new) - 1)] = chr(random.randint(0, 255))
|
||||||
self.chromozome = "".join(new)
|
self.chromozome = "".join(new)
|
||||||
|
|
8
main.py
8
main.py
|
@ -5,15 +5,17 @@ import lib.ultra_mastermind_obj as libobj
|
||||||
import lib.ultra_mastermind_imp as libomp
|
import lib.ultra_mastermind_imp as libomp
|
||||||
|
|
||||||
# constants
|
# constants
|
||||||
PM = "Saataa andagii !"
|
PM = "Hello, world!"
|
||||||
NG = 2000
|
NG = 1000
|
||||||
N = 400
|
N = 400
|
||||||
TS = 0.5
|
TS = 0.5
|
||||||
TM = 0.01
|
TM = 0.01
|
||||||
|
ALPHA = 0.5
|
||||||
|
FITNESS_METHOD = 3
|
||||||
|
|
||||||
# main function
|
# main function
|
||||||
def main() -> None:
|
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()
|
pop.run()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue