Presque. La méthode
croisement_deux est sensée renvoyer quelque chose. Si un croisement à effectivement lieu elle renvoi un individu, sinon quoi? Telle qu'écrite en ce moment, la méthode ne renvoi rien. Ce n'est pas correct.
La condition de croisement est vérifiée à chaque croisement. Si la population totale fait 1000 individus, grosso modo 70 croisements auront lieux (en fait il faudrait plutôt dire, 70 enfants verront le jour). La "nouvelle population" ne pourra pas (et ne devrait pas) contenir
seulement les parents. Je pense que vous voulez que la taille de la nouvelle population reste inchangée, et donc compléter avec des parents. Correct?
Dans ce cas, on peut envisager de demander à la méthode croisement_deux de fournir aléatoirement un des deux parents s'il n'y a pas de croisement. Mais je ne trouve pas ça terrible. Dans un algo génétique, il doit y avoir les phases suivantes:
- Evaluation de la population (on attribut une note à chaque individu en fonction de sa performance)
- Sélection d'une fraction des meilleurs individus. On les place d'office dans la prochaine population.
- Croisement aléatoire des individus avec ou sans mutations.
- Génération éventuel de nouveaux individus aléatoires, histoire de donner du sang neuf à la population (et éviter de rester bloquer dans la convergence vers le "meilleur" individu)
On s'assure que la taille de la population ne varie pas, sinon on risque quelques problèmes.
Moi, je ferais une boucle
while comme ceci (pseudo-code) à modifier et à placer dans la méthode appropriée:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| # Liste des individus de la nouvelle population/génération
# Initialement vide, elle contient désormais les individus issus de la sélection
new_population = ...
# La population précédente
old_population = ...
# On va générer autant d'enfants que nécessaire pour compléter la population
while len(new_population) != len(old_population):
# Tirage aléatoire des individus à croiser parmi la population précédente
parent_1 = old_population[random.randint(0, len(old_population))]
parent_2 = old_population[random.randint(0, len(old_population))]
# Croisement
child = self.croisement_deux(parent_1 , parent_2)
# On gère le cas où rien ne se passe
if child:
new_population.append(child) |
La modification a apporter à
croisement_deux serait minime (attention à utiliser des variables comme a, l, i1, i2... ici le code est court mais sinon un lecteur, vous éventuellement plus tard, sera bien en mal de comprendre ce veulent dire ces variables. Préférez des noms explicites comme child, parent, gene, etc...) :
1 2 3 4 5 6 7 8 9 10 11 12 13
| def croisement_deux (self , i1 , i2, Pc=0.7):
if random.random() < Pc:
child = individu(self.nombre_genes)
l = len(i1.genes)
a = l / 2
for i in range(0, int(a)):
child.genes[i]=i1.genes[i]
for i in range( int(a), l):
child.genes[i]=i2.genes[i]
return child
return None |
J'ai pris la liberté de placer la variable Pc en argument. Cela pourrait aussi être un attribut de la classe. Il est préférable de définir les constantes ailleurs que dans la fonction/méthode elle-même. J'ai choisi de renvoyer None si aucun croisement n'a lieu. Dans votre code vous renvoyiez un nouvel individu généré aléatoirement... rien a voir avec un "croisement" .
J
Partager