Saataa andagii !

This commit is contained in:
Lukian 2024-11-25 09:09:21 +01:00
parent 788e5fdf5f
commit da4d3dca5f
2 changed files with 182 additions and 3 deletions

View file

@ -0,0 +1,176 @@
# Librairie du projet en version impératif
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
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
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
}
for individual in population["individuals"]:
randomize(individual, len(pm))
return population
def new_individual(): # -> set(str)
"""
fonction qui renvoie un nouvel individu
"""
return {
"chromozome": ""
}
def select(population) -> None:
"""
Methode qui sélectionne les meilleurs individus
"""
fitness_list = []
for individual in population["individuals"]:
match population["fm"]:
case 1:
fitness_list.append(fitness1(individual, population["pm"]))
case 2:
fitness_list.append(fitness2(individual, population["pm"], population["alpha"]))
case 3:
fitness_list.append(fitness3(individual, population["pm"]))
case _:
fitness_list.append(fitness1(individual, population["pm"]))
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
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)
def print_best(population) -> None:
"""
Methode qui affiche le meilleur individu de la population
"""
fitness_list = []
for individual in population["individuals"]:
match population["fm"]:
case 1:
fitness_list.append(fitness1(individual, population["pm"]))
case 2:
fitness_list.append(fitness2(individual, population["pm"], population["alpha"]))
case 3:
fitness_list.append(fitness3(individual, population["pm"]))
case _:
fitness_list.append(fitness1(individual, population["pm"]))
print(population["individuals"][max_i(fitness_list)]["chromozome"])
def run(population) -> None:
"""
Boucle principale
"""
for i in range(population["ng"]):
select(population)
reproduct(population)
mutate_pop(population)
print_best(population)
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
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
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
def fitness3(individual, pm) -> int:
"""
Troisième methode de fitness qui utilise la distance de Levenshtein
"""
return -Levenshtein.distance(individual["chromozome"], pm)
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)

View file

@ -2,21 +2,24 @@
# project libs importations
import lib.ultra_mastermind_obj as libobj
import lib.ultra_mastermind_imp as libomp
import lib.ultra_mastermind_imp as libimp
# constants
PM = "Hello, world!"
NG = 1000
NG = 2000
N = 400
TS = 0.5
TM = 0.01
ALPHA = 0.5
FITNESS_METHOD = 3
FITNESS_METHOD = 1
# main function
def main() -> None:
pop = libobj.Population(pm = PM, ng = NG, n = N, ts = TS, tm = TM, alpha = ALPHA, fm = FITNESS_METHOD)
pop.run()
pop = libimp.new_population(PM, NG, N, TS, TM, ALPHA, FITNESS_METHOD)
libimp.run(pop)
if __name__ == "__main__":
main()