Documente Academic
Documente Profesional
Documente Cultură
Dans cette théorie, une population d'individus évolue grâce au mécanisme de la reproduction sexuée. Les individus les plus adaptés à leur milieu se
reproduisent plus que les autres, favorisant les caractères les plus adaptés. Ainsi une girafe avec un cou plus long que les autres aura accès à plus de
nourriture, et aura donc plus de chances de survivre et de se reproduire. Ses descendants auront un cou plus long, et en moyenne la population de girafe aura
un cou plus long.
Au niveau de l'ADN, la recombinaison de l'ADN des deux parents (lors de la reproduction) permet de générer différentes combinaisons de gènes. Il y a des
chances qu'en recombinant l'ADN de deux parents bien adaptés, l'individu généré soit encore mieux adapté.
Exemple :
Parent 1 Parent 2
• au hasard
• toujours choisir le meilleur individu comme premier parent et un autre individu au hasard comme deuxième parent (variante de la stratégie élitiste)
• sélectionner les deux parents selon un critère de proximité dans la liste des individus
Il semble qu'une stratégie élitiste soit plus efficace au démarrage de l'algorithme, puis au fur et à mesure que l'on se rapproche de l'optimum, chaque individu a
à peu près autant de chances d'être précurseur d'une meilleure solution.
Pour tspgen 0.32 j'ai utilisé une stratégie élitiste inspirée de la "roulette wheel" : On considère la sélection d'un individu comme le lancement d'une bille sur une
roulette. Chaque individu possède plusieurs cases dans la roulette. Les meilleurs individus possèdent plus de cases et sont donc sélectionnés plus souvent.
Pour cela les individus sont classés selon leur adaptation (premier individu = longueur de trajet la plus courte). Je crée un tableau d'entiers, qui comporte autant d'éléments
que d'individus dans le groupe. Chaque entier du tableau prend une valeur croissante entre 1 et RAND_MAX. L'intervalle entre les chiffres du tableau est plus grand au début
et plus petit à la fin. Comme la fonction rand () renvoie un entier au hasard entre 1 et RAND_MAX il suffit de tirer un chiffre au hasard et de le comparer au chiffre du tableau
pour connaitre l'index de l'individu sélectionné.
Pour que chaque individu ait la même probabilité d'être séléctionné, il suffirait de positionner les chiffres du tableau à un intervalle de RAND_MAX / Nb_individus.
Voir le code source des fonctions Group::InitSelectionArray () et Group::GetRandSelectionArrayIndex ()
Recombinaison :
C'est la fonction principale de l'algorithme génétique. La recombinaison (ou reproduction ou crossover) consiste à créer un individu à partir de deux individus
parents.
Il existe presque autant d'algorithmes de recombinaison que d'implémentations d'algorithmes génétiques...
Un exemple de crossover réussi (à comparer avec l'exemple des girafes) :
Parent Parent
1 2
Fils 1
Je vais décrire ici un des plus simples, le crossover à 1 point (c'est loin d'être le plus efficace mais il a le mérite d'être assez simple à coder).
Il s'agit de recopier dans le fils une partie du parent 1, jusqu'à une "cassure", puis ensuite la partie correspondante du parent 2. La difficulté réside dans le fait
que les villes ne doivent pas être répétées. Si la ville a déjà été prise, on passe à la ville suivante dans l'ordre du parent 2.
Exemple :
Parent 1 :
1-2-3-4-5-6-7-8-9-10
Parent 2:
2-7-1-4-10-6-9-8-3-5
Fils :
1-2-3-4-10-6-9-8-5-7
Une variante de ce crossover est le crossover à 2 points (un peu plus efficace) : on introduit une deuxième cassure et le parent 2 n'est recopié qu'entre ces
deux cassures.
Ces deux algorithmes ont un défaut pour le PVC, c'est qu'ils ne respectent pas toujours la règle suivante :
- si une arête (chemin entre 2 villes) se trouve dans les deux trajets parents, il faut qu'elle se trouve dans le trajet fils
Ce problème a été en partie résolu par le crossover OX (entres autres) [que je présenterai ici prochainement].
Les crossovers peuvent aussi utiliser des informations heuristiques, comme le crossover KFP dans tspgen 0.32 (qui utilise les villes les plus proches). Cet algo a
été décrit par Karoly F. Pal dans un papier de 1993 (je n'en ai qu'un exemplaire papier, il n'est pas dispo sur le net à ma connaissance).
Dans les sources de tspgen voir les fonctions Individual::CrossoverKFP, Individual::CrossoverPMX, Individual::CrossoverOX, Individual::CrossoverCX,
Individual::CrossoverAA
Mutation :
Il s'agit d'une modification (plus ou moins aléatoire) du code génétique d'un individu. Cela permet de sortir des minimums locaux, grâce à une perturbation, un
peu à la manière du recuit simulé.
Exemples de mutations pour le PVC :
• Renversement de parcours entre deux villes (assez efficace en particulier s'il est appliqué parfois deux ou trois fois à la suite)
• Remplacement d'une liaison entre deux villes par une liaison entre la première ville et la ville la plus proche
• "Double bridge" ou 4-change non séquentiel : le parcours : 0 ... i i+1 ... j j+1 ... k k+1 ... l l+1 ... est modifié en : 0...i k+1 ... l j+1 ... k i+1 ... j
l+1 ...
i et k ainsi que j et l peuvent être proche pour plus d'efficacité (assez efficace)
Optimisation :
Cette phase est à mon avis très importante et pas assez mise en valeur dans les différentes docs sur les algos génétiques.
L'optimisation est l'utilisation d'une méthode de recherche locale (par exemple 2-opt ou 3-opt), appliquée à chaque individu lors de sa création. Chaque individu
est un minimum local, on ne risque donc pas de passer à côté d'une bonne solution.
Il faut savoir que la plupart du temps de calcul est passée dans ces optimisations locales (au moins dans tspgen, mais je pense que c'est la même chose dans
tous les algorithmes génétiques ou les autres métaheuristiques comme le recuit simulé ou la méthode de la colonie de fourmis). Sans cette optimisation, le
résultat serait assez médiocre. Mais on ne peut pas dire que c'est l'optimisation qui fait tout le travail ! Le grand avantage des algorthmes génétiques est qu'ils
fonctionnent quand même EN PLUS de l'optimisation locale. L'algorithme génétique est donc responsable de la partie la plus difficile du calcul.
Pour tspgen 0.32 j'utilise pour l'optimisation l'algo 2-opt.
Dans les sources voir les fonctions Individual::Optimize2ChangeCompl ()
Réinsertion :
Comment réinsérer le fils dans le groupe ? Les solutions sont :
• La nouvelle génération remplace l'ancienne génération (sauf le meilleur individu de l'ancienne génération)
Ce qui est certain est qu'il ne faut pas supprimer le meilleur individu du groupe, sous peine de voir l'adaptation globale diminuer !
Paramétrages divers :
• Quelle est la taille d'un groupe (nombre d'individus) ?
• Faut il utiliser une heuristique pour initialiser la population (exemple : meilleurs voisins + 2opt)
• Le paramétrage doit il changer en fonction de la phase de calcul (par exemple, plus de mutations à la fin...)
• Certaines fonctions sont elles plus efficaces avec un nombre de villes faibles ou élévé ?
• Dans le crossover ou les optimisations, faut il préférer la rapidité (afin de faire plus d'itérations) ou des opérateurs plus ophistiqués mais plus
longs ?