Saataa andagii !

This commit is contained in:
Lukian 2025-01-07 23:05:40 +01:00
parent d99a556d3d
commit 757ea77cc5
8 changed files with 549 additions and 500 deletions

View file

@ -5,6 +5,7 @@
### Linux
- `git clone https://git.leizour.fr/lucien/ultra-mastermind-implementation`
- `cd ultra-mastermind-implementation`
- `python -m venv .venv`
- `source .venv/bin/activate`
- `pip install -r requirements.txt`
@ -20,8 +21,9 @@
#### Second method
- `git clone https://git.leizour.fr/lucien/ultra-mastermind-implementation`
- `cd ultra-mastermind-implementation`
- `python -m venv .venv`
- `./.venv/bin/activate`
- `.venv/bin/activate`
- `pip install -r requirements.txt`
- `python main.py`

103
analyse.py Normal file
View file

@ -0,0 +1,103 @@
# fichier de tests du projet
import matplotlib.pyplot as plt
import random
# project libs importations
import lib.ultra_mastermind_obj as libobj
import lib.ultra_mastermind_imp as libimp
import lib.ultra_mastermind_pp_imp as libppimp
PM = "Hello, world!"
NG = 4000
N = 400
TS = 0.7
TM = 0.25
ALPHA = 0.5
FITNESS_METHOD = 3
# Variation de la taille de la phrase
length_ng = []
length = []
for i in range(5, 26, 3):
print(f"Step {i}:")
length.append(i)
vals = []
for j in range(5):
print(f" Part {j}")
PM = "".join([chr(random.randint(0, 255)) for _ in range(i)])
pop = libppimp.new_population(PM, NG, N, TS, TM, ALPHA, FITNESS_METHOD)
ng = libppimp.run(pop)
vals.append(ng)
length_ng.append(sum(vals) / len(vals))
plt.plot(length, length_ng)
plt.title("Nombre de générations nécéssaires en fonction de la taille de la phrase.")
plt.xlabel("Taille de la phrase")
plt.ylabel("Nombre de générations")
plt.show()
# Variation de la taille de la population
n_ng = []
n = []
for i in range(50, 1000, 100):
print(f"Step {i}:")
n.append(i)
vals = []
for j in range(5):
print(f" Part {j}")
pop = libppimp.new_population(PM, NG, i, TS, TM, ALPHA, FITNESS_METHOD)
ng = libppimp.run(pop)
vals.append(ng)
n_ng.append(sum(vals) / len(vals))
plt.plot(n, n_ng)
plt.title("Nombre de générations nécéssaires en fonction de la taille de la population.")
plt.xlabel("Taille de la population")
plt.ylabel("Nombre de générations")
plt.show()
# Variation du taut de sélection
ts_ng = []
ts = []
for i in range(1, 9, 1):
print(f"Step {i / 10}:")
ts.append(i / 10)
vals = []
for j in range(5):
print(f" Part {j}")
pop = libppimp.new_population(PM, NG, N, i / 10, TM, ALPHA, FITNESS_METHOD)
ng = libppimp.run(pop)
vals.append(ng)
ts_ng.append(sum(vals) / len(vals))
plt.plot(ts, ts_ng)
plt.title("Nombre de générations nécéssaires en fonction du taut de sélection.")
plt.xlabel("Taut de sélection")
plt.ylabel("Nombre de générations")
plt.show()
# Variation du taut de mutation
tm_ng = []
tm = []
for i in range(10, 40, 5):
print(f"Step {i / 100}:")
tm.append(i / 100)
vals = []
for j in range(5):
print(f" Part {j}")
pop = libppimp.new_population(PM, NG, N, TS, i / 100, ALPHA, FITNESS_METHOD)
ng = libppimp.run(pop)
vals.append(ng)
tm_ng.append(sum(vals) / len(vals))
plt.plot(tm, tm_ng)
plt.title("Nombre de générations nécéssaires en fonction du taut de mutation.")
plt.xlabel("Taut de mutation")
plt.ylabel("Nombre de générations")
plt.show()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View file

@ -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)

View file

@ -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 setChromozome(self, c: str) -> None:
self.chromozome = c
def getChromozome(self) -> str:
return self.chromozome
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)

View file

@ -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"]

View file

@ -31,6 +31,7 @@ def main() -> None:
# imperative version ++
pop = libppimp.new_population(PM, NG, N, TS, TM, ALPHA, FITNESS_METHOD)
libppimp.run(pop)
print(libppimp.get_best(pop)["chromozome"])
if __name__ == "__main__":
main()

View file

@ -1,59 +0,0 @@
# fichier de tests du projet
import matplotlib.pyplot as plt
# project libs importations
import lib.ultra_mastermind_obj as libobj
import lib.ultra_mastermind_imp as libimp
import lib.ultra_mastermind_pp_imp as libppimp
# Variation du nombre de générations
PM = "Hello, world!"
# NG = 2000
N = 400
TS = 0.5
TM = 0.25
ALPHA = 0.5
FITNESS_METHOD = 3
fitness_ng = []
all_ng = []
for i in range(1, 11):
NG = i * 200
all_ng.append(NG)
pop = libppimp.new_population(PM, NG, N, TS, TM, ALPHA, FITNESS_METHOD)
libppimp.run(pop)
fitness_ng.append(libppimp.get_fitness(pop, libppimp.get_best(pop)))
plt.plot(all_ng, fitness_ng)
plt.title("Fitness du meilleur individu en fonction du nombre de générations")
plt.xlabel("Nombre de générations")
plt.ylabel("Fitness du meilleur individu")
plt.show()
# Variation du nombre de générations
PM = "Hello, world!"
NG = 500
# N = 400
TS = 0.5
TM = 0.25
ALPHA = 0.5
FITNESS_METHOD = 3
fitness_n = []
all_n = []
for i in range(1, 11):
N = i * 100
all_n.append(N)
pop = libppimp.new_population(PM, NG, N, TS, TM, ALPHA, FITNESS_METHOD)
libppimp.run(pop)
fitness_n.append(libppimp.get_fitness(pop, libppimp.get_best(pop)))
plt.plot(all_n, fitness_n)
plt.title("Fitness du meilleur individu en fonction de la taille de population")
plt.xlabel("Taille de population")
plt.ylabel("Fitness du meilleur individu")
plt.show()