Aller au contenu principal

Les algorithmes génétiques

Ce que ce chapitre apporte7 points
  • Expliquer ce qui distingue une population qui évolue d'une solution qu'on retouche, et pourquoi le squelette chercher n'y suffit plus.
  • Choisir un chromosome, et vérifier qu'un croisement et une mutation le laissent valide.
  • Montrer sur un exemple que le croisement à un point casse une permutation, et écrire l'order crossover (OX), qui la préserve.
  • Régler la sélection par tournoi, l'élitisme et le taux de mutation, et lire la pression de sélection.
  • Mesurer la diversité d'une population et reconnaître une convergence prématurée.
  • Représenter la découpe de barres par un ordre de pièces décodé par First Fit, de sorte que toute solution soit réalisable.
  • Comparer honnêtement un algorithme génétique, seul puis hybridé avec la recherche locale, aux redémarrages, au recuit et au tabou.
Sur la plaque P-600 de Valdrome Mécanique, la descente, le recuit et le tabou ont un point commun : ils n'ont jamais qu'une tournée entre les mains, qu'ils retouchent pas à pas. Un atelier a une autre habitude. Quand l'équipe de jour et l'équipe de nuit ont chacune écrit un programme de perçage, on ne choisit pas l'un des deux : on lit les deux, et on reprend de chacun ce qui marche, un tronçon de l'un, l'ordre des trous restants de l'autre. Les algorithmes génétiques font de cette habitude une méthode. Ils gardent toute une population de tournées, en fabriquent de nouvelles en croisant les anciennes, et laissent les plus courtes se reproduire. Ce chapitre montre que ce geste, en apparence anodin, casse une tournée dès qu'on le fait naïvement (un trou percé deux fois, un trou oublié), donne le croisement qui la préserve, règle la sélection, la mutation et la taille de la population, puis compare honnêtement le résultat aux méthodes précédentes : sur la grande plaque, l'algorithme génétique seul est battu, et il ne devient compétitif qu'en s'alliant à la recherche locale.

Une population plutôt qu'une solution

Le squelette chercher(initiale, voisin, cout, accepter, iterations) du chapitre sur la recherche locale tient quatre choses : une solution courante, un voisin tiré à partir d'elle, une règle qui décide de s'y déplacer ou non, et le souvenir de la meilleure solution vue. Le recuit simulé a changé la règle, la recherche tabou a ajouté une mémoire et pris le voisinage entier. Toutes ces méthodes ont gardé la même charpente : elles partent d'une solution et la font bouger.

Un algorithme génétique n'en garde qu'une seule pièce, la meilleure solution vue. Il n'y a plus une solution courante, il y en a cent. Il n'y a plus de voisin : un enfant a deux parents, il n'est le voisin d'aucun des deux au sens du chapitre 5. Il n'y a plus de règle d'acceptation : chaque génération remplace la précédente. À la place, quatre gestes, répétés génération après génération.

Ce que faisait chercherCe que fait un algorithme génétique
une solution couranteune population de solutions, de taille fixe
un voisin tiré au hasardun enfant : deux parents, un croisement, parfois une mutation
accepter ou refuser le voisinla sélection des parents, puis le remplacement de la génération
garder la meilleure solution vueinchangé : on la garde, comme au recuit
un voisinage à définirun croisement et une mutation à définir
Le vocabulaire, emprunté à la biologie

Un individu est une solution telle que la représentation la range. Son chromosome est cette représentation : pour la tournée, l'ordre des trous. Un gène est un élément du chromosome, ici un trou. La population est l'ensemble des individus d'une même génération. Le croisement fabrique un enfant à partir de deux parents, la mutation modifie un peu un enfant, la sélection choisit les parents, et le remplacement décide qui passe à la génération suivante. Ce qu'on appelle en biologie l'adaptation d'un individu est ici son coût : la longueur de la tournée.

Pourquoi croiser ? Une bonne tournée est faite de morceaux bien enchaînés : un groupe de trous voisins percés à la suite, un passage qui longe un bord sans zigzaguer. Deux tournées différentes ont chacune ses bons morceaux, que l'autre n'a pas. Le croisement essaie de les réunir dans un même enfant, la sélection fait que les tournées porteuses de bons morceaux se reproduisent plus souvent, et la mutation apporte de temps en temps quelque chose qu'aucun parent n'avait. Le croisement n'a rien de magique : le chapitre le montre, sur deux bonnes tournées différentes il donne presque toujours un enfant plus long que le plus court de ses parents. C'est la répétition, avec une sélection qui garde les meilleurs, qui fait avancer.

Le chromosome : la représentation d'abord

Tout ce que fait un algorithme génétique se définit sur le chromosome, comme un voisinage se définit sur une représentation. Pour la tournée, c'est l'ordre des trous, une permutation : le choix du premier chapitre. Ici, ce choix devient plus exigeant. Il ne suffit plus qu'un objet soit valide : le mélange de deux objets valides doit l'être aussi. Une représentation qui survit à la retouche d'un voisin peut très bien ne pas survivre au croisement.

Le croisement le plus simple casse la tournée

Le croisement des chaînes de zéros et de uns est celui qu'on imagine d'abord, le croisement à un point : couper les deux parents au même endroit, prendre le début de l'un et la fin de l'autre. Sur dix zéros et uns, il donne toujours dix zéros et uns. Sur une permutation, voyons ce qu'il donne. Le bloc suivant ouvre sur un exemple à huit gènes, A à H, puis prend deux tournées de la plaque P-217 (deux optimums locaux de descentes 2-opt, comme au chapitre 5). La fonction valider_ordre est l'équivalent Python du validerOrdre du moteur des figures : chaque gène exactement une fois, aucun de trop, aucun de moins.

main.py
Sortie
>_ Prêt à exécuter…

Le petit exemple montre l'essentiel. Coupés après le troisième gène, les parents ABCDEFGH et CGEAFHBD donnent ABCAFHBD : A et B y sont deux fois, E et G ont disparu. Sur la plaque, le résultat est le même : le début du parent A jusqu'à la troisième position et la fin du parent B donnent une tournée où T11 est percé deux fois et T9 jamais. Ce n'est pas un malheur de cet exemple : sur les onze coupes possibles, trois seulement donnent une tournée, et ce sont celles où les deux parents commencent (ou finissent) par les mêmes trous. La raison est simple : une coupe après cc gènes donne une permutation seulement si les cc premiers gènes des deux parents forment le même ensemble, ce qui arrive avec la probabilité 1/(nc)1 / \binom{n}{c} pour des parents tirés au hasard. Avec des parents tirés au hasard, 2,1 % des enfants sont des tournées valides (le calcul exact donne 1,94 %), et 0,06 % sur soixante trous : à peu près aucun.

Réparer ou jeter un enfant invalide
Deux réflexes viennent avant de changer de croisement. Jeter l'enfant invalide et recommencer : avec 2 % de réussite, l'algorithme dépense presque tout son temps à fabriquer des rebuts. Réparer l'enfant, en remplaçant chaque trou en double par un trou oublié : le choix de quel double remplacer par quel oubli est arbitraire, et l'enfant réparé ressemble de moins en moins à ses parents, alors que c'est tout l'intérêt du croisement. La bonne réponse est celle du premier chapitre : choisir un opérateur fait pour la représentation, qui ne produit jamais d'objet impossible.

L'order crossover

L'order crossover, ou OX, est un croisement écrit pour les permutations. Il garde intact un morceau du premier parent et complète avec les autres gènes dans l'ordre où le second parent les rencontre.

Order crossover (OX)

Deux parents A et B, deux coupes i<ji < j tirées entre les positions 00 et nn :

  1. le segment A[i..j[A[i..j[ est recopié dans l'enfant, à la même place ;
  2. on lit B à partir de la position jj, en revenant au début quand on arrive au bout, et on saute les gènes que le segment contient déjà ;
  3. les gènes restants, dans cet ordre, remplissent les places libres à partir de la position jj, en revenant au début.

Sur l'exemple à huit gènes, avec les coupes 3 et 6, le segment de A est DEF.

01234567
Parent AABCDEFGH
Parent BCGEAFHBD
1. le segment de A, à sa place...DEF..
3. les gènes restants, à leur placeGAHDEFBC

L'étape 2 se lit sur B, à partir de la position 6 : B, D, C, G, E, A, F, H. Le segment contient D, E et F, qu'on saute ; il reste B, C, G, A, H. À l'étape 3, B et C prennent les places 6 et 7, puis, en revenant au début, G, A et H prennent les places 0, 1 et 2.

L'enfant est GAHDEFBC : une permutation, quels que soient les parents et les coupes. En Python, la lecture de B à partir de la position jj tient en b[j:] + b[:j], et la dernière ligne de croisement_ox place les gènes restants : les n - j premiers occupent les places après le segment, les suivants les places du début.

Sur la plaque P-217, le bloc de la section précédente fait l'essai. Avec les coupes 3 et 8, l'enfant OX mesure 645,65 mm, plus court que ses deux parents (659,78 et 667,03 mm) : deux tournées médiocres ont donné une meilleure tournée. Sur les 78 coupes possibles, aucun enfant n'est invalide, mais deux seulement sont plus courts que les deux parents. Enfin, croisement_ox(parent_a, parent_a, 3, 8) redonne parent_a : croiser deux copies ne produit rien de neuf, ce qui servira quand la population aura perdu sa diversité.

La figure suivante fait faire ces essais. Le lecteur choisit deux parents et deux coupes, et voit le croisement à un point et l'OX produire chacun un enfant, avec ses défauts et sa longueur.

Atelier de croisement12 trous, deux parents, deux coupes
Parent A, 659,8 mmParent B, 667,0 mmEnfant à un point : pas une tournéeEnfant OX, 772,6 mmT4T5T11T6T2T12T3T8T10T9T7T1T4T9T5T2T3T8T12T6T11T10T7T1T4T5T11T6T3T8T12T6T11T10T7T1T9T5T6T11T2T12T3T8T10T7T1T412

Case pleine : trou hérité de A. Case cernée : hérité de B. Case barrée en pointillés : trou de B déjà pris par le segment de A, sauté par l'OX. Case hachurée : trou percé deux fois. Les coupes 1 (tirets) et 2 (points) sont marquées sur chaque rangée.

  • En double : T6, T11
  • Oubliés : T2, T9
Parent A
659,8 mm
Parent B
667,0 mm
Enfant à un point
pas une tournée
Enfant OX
772,6 mm
Dessiner
T1T2T3T4T5T6T7T8T9T10T11T12

La tournée dessinée part du losange et y revient.

0 croisement regardé, ces deux boutons se débloquent à 3
Choisir deux parents, déplacer les coupes, et comparer les deux enfants. Un croisement tiré au hasard rallonge presque toujours la tournée : à essayer.
La plaque P-217, deux parents, deux coupes : ce que donnent le croisement à un point et l'order crossover. Le losange est le départ de l'outil.
À manipuler
Garder d'abord les parents proposés et déplacer la première coupe : le croisement à un point échoue presque partout, les trous en double sont hachurés et cerclés, les trous oubliés listés, et le bouton « Enfant à un point » de la carte dessine un tracé que la perceuse ne pourrait pas suivre. Regarder ensuite l'enfant OX, qui reste une tournée, et sa longueur : elle dépasse presque toujours celle des parents. Chercher deux coupes pour lesquelles l'enfant OX est plus court que ses deux parents, puis changer de parents et recommencer. Les deux boutons du bas se débloquent après trois croisements regardés : le premier passe en revue toutes les coupes et dit combien d'enfants sont valides, le second compare le meilleur enfant regardé à la meilleure tournée connue. « Coupes au hasard » tire deux coupes, et « Un ordre tiré au hasard » remplace un parent : ces tirages sont différents pour chaque lecteur.
Il y a d'autres croisements de permutations
L'OX n'est pas le seul : d'autres opérateurs (PMX, croisement cyclique, recombinaison d'arêtes) sont écrits pour les permutations, avec des compromis différents. L'OX conserve bien l'ordre relatif des gènes du second parent et la position du segment du premier ; la recombinaison d'arêtes conserve mieux les voisinages entre trous, ce qui compte pour une tournée. Ici, l'OX a été retenu pour sa simplicité : quatre lignes de Python, et la leçon est la même quel que soit l'opérateur retenu.

La représentation décide de l'opérateur, et pas seulement pour la tournée. Le tableau reprend les problèmes de Valdrome.

ProblèmeChromosomeCroisement possible
Commandes à lancerdix zéros et unsà un point : le résultat est toujours une sélection, mais la capacité de cent heures peut être violée (pénalité, comme au premier chapitre)
Tournée de la perceusel'ordre des trousOX : le résultat est toujours une tournée
Ordre de passage de la machinel'ordre des dix ordres de fabricationOX
Postes des opérateursposte_de, une permutation de 0 à 7OX : le résultat est encore une affectation
Découpe de barresun ordre des pièces, décodé par First FitOX, et toute solution est réalisable : voir plus bas

La mutation

Le croisement ne fabrique que des combinaisons de ce que la population contient déjà. Si aucun individu n'a l'arête entre T5 et T11, aucun croisement ne la créera : un enfant ne reçoit que des arêtes de ses deux parents, à part celles qui se forment aux jointures. La mutation apporte ce qui manque : elle modifie un enfant au hasard, un peu.

Deux mutations d'une permutation

La mutation par échange permute deux gènes tirés au hasard : jusqu'à quatre trajets changent. La mutation par inversion retourne un segment tiré au hasard : deux trajets seulement changent. C'est exactement le mouvement 2-opt du chapitre 5, tiré au hasard plutôt que choisi. Les deux laissent une permutation.

Le taux de mutation est la probabilité qu'un enfant en subisse une, entre 0 (jamais) et 1 (toujours).

L'inversion est le plus souvent préférable pour une tournée, pour la raison qui a fait le succès du 2-opt : elle change peu de trajets, donc peu la longueur. Une mutation trop brutale défait ce que le croisement a construit, comme un recuit trop chaud. Un taux nul prive la population de tout ce qu'elle n'a pas déjà. Le bon taux se mesure, ce que la section « La boucle complète » fait.

La sélection : qui a le droit de se reproduire

Si les parents étaient tirés au hasard, la population ne s'améliorerait guère : rien ne favoriserait les courtes tournées. La sélection donne plus d'enfants aux meilleurs. La plus simple à écrire et à comprendre est le tournoi.

Sélection par tournoi

Pour choisir un parent, on tire au hasard kk individus de la population (avec remise), et le plus court gagne. On recommence pour le second parent. Le nombre kk est la taille du tournoi.

Le tournoi ne compare que des coûts deux à deux : il ne dépend pas de leur échelle. La sélection « à la roulette », où l'on tire un individu avec une probabilité proportionnelle à sa qualité, en dépend : une constante ajoutée à tous les coûts en change les probabilités. La taille kk règle la pression de sélection, c'est-à-dire à quel point la reproduction est réservée aux meilleurs. Avec k=1k = 1, il n'y a aucune pression : c'est un tirage au hasard. Avec kk grand, presque tous les parents viennent du haut du classement.

Dans une population de NN individus classés du meilleur au pire, l'individu de rang rr (le meilleur a le rang 0) gagne un tournoi de kk candidats avec la probabilité

pr=(N−r)k−(N−r−1)kNkp_r = \frac{(N - r)^k - (N - r - 1)^k}{N^k}

car il gagne quand le plus petit rang tiré est rr : tous les candidats ont un rang au moins rr, et l'un d'eux exactement. Le bloc suivant la calcule pour cent individus, la vérifie par tirage, et donne aussi la part des parents pris parmi les dix meilleurs.

main.py
Sortie
>_ Prêt à exécuter…

Un tournoi de trois candidats désigne le meilleur individu pour 2,97 % des parents, soit trois fois plus qu'un tirage au hasard, et un individu parmi les dix meilleurs pour 27,1 % des parents, contre 10 % au hasard. Avec dix candidats, deux parents sur trois viennent des dix meilleurs. Le dernier de la population, lui, ne gagne pratiquement jamais dès que k≥3k \ge 3 : sa chance est (1/N)k(1/N)^k.

La pression d'un tournoi

  • 1.

    Dans une population de 100 individus, avec quelle probabilité, en pourcentage, le meilleur gagne-t-il un tournoi de 3 candidats tirés avec remise ?

  • 2.

    Avec quelle probabilité, en pourcentage, aucun des 3 candidats d'un tournoi n'appartient-il aux 10 meilleurs ?

  • 3.

    Quelle part des parents, en pourcentage, un tournoi de 3 prend-il donc parmi les 10 meilleurs ?

La taille du tournoi est un curseur de pression
Un tournoi de un candidat : aucune sélection, la population ne s'améliore pas. Un tournoi de deux ou trois candidats : une pression douce, que la mutation et le croisement ont le temps de compenser. Un tournoi de dix candidats : la reproduction est réservée à une petite élite, la population converge vite, et peut converger au mauvais endroit. C'est un compromis à mesurer, comme la durée tabou ou la température.

La boucle complète

Il reste à assembler les pièces. L'algorithme est générationnel : à chaque génération, toute la population est remplacée, sauf une petite élite de meilleurs individus qui passe telle quelle, c'est l'élitisme. Il garantit que la meilleure tournée de la génération ne peut pas être perdue par malchance.

Une génération
  1. Classer la population par coût, recopier les elite meilleurs dans la génération suivante.
  2. Remplir les places restantes : choisir deux parents par tournoi, les croiser, muter l'enfant avec la probabilité p_mutation, l'évaluer.
  3. Remplacer l'ancienne population par la nouvelle, et noter au passage la meilleure tournée vue.

Le budget se compte en évaluations, comme aux chapitres 6 et 7 : la population de départ coûte taille évaluations, chaque génération taille - elite. Le bloc suivant contient toute la boucle, avec les pièces de la section précédente pour la plaque P-217, et deux premières mesures. La première fait évoluer cinquante individus sur cinq graines. La seconde compare l'absence de mutation, l'échange et l'inversion à plusieurs taux, sur cinq graines, trente individus et 3 000 évaluations : c'est la mesure annoncée à la section précédente. Les tableaux de ce chapitre se lisent avec cinq graines seulement, pour que chaque bloc tourne en quelques secondes : ils montrent des tendances, pas des écarts établis.

main.py
Sortie
>_ Prêt à exécuter…

Avec 10 000 évaluations, soit environ deux cents générations de cinquante individus, quatre graines sur cinq trouvent 633,23 mm, l'optimum de P-217, et la cinquième s'arrête à 645,65 mm : l'algorithme fonctionne, sur une plaque de douze trous. Le tableau des mutations se lit de haut en bas.

  • Sans mutation, aucune graine ne trouve l'optimum : la médiane est à 754,79 mm, loin des 633,23 mm de l'optimum, et la pire des cinq à 787,21.
  • L'inversion est meilleure que l'échange à taux égal : à 30 %, trois graines sur cinq trouvent l'optimum contre aucune, et la médiane est de 633,23 mm contre 673,26.
  • Un taux trop haut ne vaut pas mieux : à 100 %, l'inversion ne trouve plus l'optimum sur aucune graine, avec une médiane de 647,35 mm. Sur cinq graines, l'écart avec 30 % est plausible, il n'est pas établi, et ce chapitre y reviendra.

Ce que coûte une génération

  • 1.

    Une population de 100 individus, dont 2 d'élite, évolue pendant 305 générations. Combien d'évaluations a-t-elle dépensées, population de départ comprise ?

  • 2.

    Avec un budget de 100 000 évaluations, combien de générations complètes cette population peut-elle mener ?

  • 3.

    Avec 300 individus et une élite de 2, combien de générations tiennent dans 5 000 évaluations ?

Cette dernière question annonce la section suivante : à budget égal, plus la population est grande, moins elle a le temps d'évoluer.

L'élitisme garde le meilleur, il n'invente rien
Sans élitisme, la meilleure tournée d'une génération peut disparaître si aucun enfant ne la reproduit : la courbe du meilleur coût remonte. Le code garde donc toujours la meilleure solution vue, comme le recuit, et c'est elle qu'il rend. L'élitisme évite en plus de perdre du temps à la retrouver. Une élite trop large, en revanche, remplit la population de copies du même individu, et prépare la perte de diversité de la section suivante.

Taille de la population, diversité et convergence prématurée

Il reste trois réglages à comprendre : la taille de la population, ce qu'il advient quand tous les individus se ressemblent, et comment le voir. Pour le voir, il faut une mesure.

Distance entre deux tournées, diversité d'une population

La distance entre deux tournées est la part des arêtes de l'une qui ne sont pas dans l'autre (les arêtes sont non orientées, le départ compris) : 0 pour deux tournées identiques, à l'endroit ou à l'envers, et près de 1 pour deux ordres tirés au hasard. La diversité d'une population est la distance moyenne entre deux individus.

Une tournée et son inverse sont à distance zéro : c'est la même tournée, comme l'a noté le premier chapitre (un ordre et son inverse mesurent la même chose). Le bloc suivant reprend les pièces de la boucle complète, mesure d'abord la taille de la population, puis suit la diversité génération après génération dans trois réglages.

main.py
Sortie
>_ Prêt à exécuter…

La taille de la population se lit dans le premier tableau : cinq graines, 3 000 évaluations pour toutes. À budget fixé, plus la population est grande, moins elle a de générations, et plus les résultats se dégradent : avec 10 individus (373 générations), trois graines sur cinq trouvent l'optimum et la médiane est de 633,23 mm ; avec 100 (29 générations), une seule, à 645,65 mm de médiane ; avec 300, neuf générations seulement, aucune graine et 698,34 mm ; avec 1 000, deux générations, ce qui ne laisse presque rien à la sélection, et 751,10 mm. Sur douze trous, une petite population suffit. À budget fixé, une population trop grande n'a pas le temps d'évoluer.

La convergence prématurée se lit dans les trois réglages suivants. Sans mutation, la diversité tombe à zéro en une vingtaine de générations, avec un tournoi de 7 comme avec un tournoi de 3 : sur la graine 0, tous les individus sont devenus des copies d'une même tournée, à 756,6 mm dans le premier cas, 879,2 mm dans le second, loin des 633,23 mm de l'optimum. Croiser deux copies redonne la copie, et sans mutation plus rien ne peut apparaître : la population est morte, sur une tournée médiocre. Aucune des cinq graines n'atteint l'optimum, dans aucun des deux réglages (médianes de 776,97 et 806,54 mm). Avec une mutation de 30 %, la diversité baisse aussi (79 %, 17 % puis 10 % aux générations 1, 20 et 100) mais ne s'éteint pas : la mutation en réinjecte, elle remonte à 15 % à la génération 149, et trois graines sur cinq trouvent l'optimum.

Convergence prématurée

Une population converge prématurément quand ses individus deviennent presque identiques avant d'avoir trouvé une bonne solution. Le croisement de deux quasi-copies ne produit plus rien de neuf, et il ne reste que la mutation pour s'échapper. Les causes se lisent dans les réglages : une pression de sélection trop forte (tournoi de 7, élite large), une population trop petite, une mutation trop faible.

La diversité est pour l'algorithme génétique ce que la température est pour le recuit : la réserve de hasard qui permet de s'échapper. Elle baisse toujours, c'est le principe de la sélection. Le réglage consiste à ce qu'elle baisse assez lentement pour que la population ait trouvé de bonnes tournées avant d'être devenue uniforme.

Vérification rapideon peut se reprendre

1.Une population de 50 tournées a une diversité de 3 % et son meilleur coût ne baisse plus depuis trente générations. Que faire ?

2.Croiser un parent avec lui-même par l'order crossover donne…

La découpe de barres : une représentation indirecte

Le deuxième problème de Valdrome, la découpe de vingt pièces dans des barres de 6 000 mm, semble se prêter mal à un croisement. Représenter la solution par « pour chaque pièce, sa barre » donne des enfants qui posent les pièces de 2 920, 2 820 et 2 600 mm dans la même barre. Le remède est une représentation indirecte : le chromosome n'est pas le rangement, c'est un ordre des pièces, et un décodeur en fait un rangement. Ici, le décodeur est la règle du chapitre 4 : First Fit, qui met chaque pièce, dans l'ordre donné, dans la première barre où elle tient encore.

Un ordre de pièces est une permutation, comme un ordre de perçage. Le même OX et les mêmes mutations s'appliquent, et toute permutation se décode en un rangement réalisable : aucune barre ne déborde, aucune pièce n'est oubliée. Le décodeur porte la contrainte, comme la troisième représentation du premier chapitre, celle qui lançait chaque commande « si elle tient encore ». Le coût est le nombre de barres du rangement décodé.

Deux vérifications s'imposent avant de chercher. La représentation n'oublie-t-elle aucune solution ? Il existe des ordres qui se décodent en un rangement optimal (lister les pièces barre après barre d'un rangement quelconque : First Fit n'utilise alors jamais plus de barres que lui) : l'algorithme peut donc atteindre les 5 barres de l'optimum. Et l'ordre choisi par le chapitre 4, la longueur décroissante, n'est qu'un ordre parmi 20! : il donne 6 barres. Le bloc suivant applique le même algorithme génétique, avec un coût qui compte les barres.

main.py
Sortie
>_ Prêt à exécuter…

First Fit Decreasing, un seul ordre, fait 6 barres. Sur 10 000 ordres tirés au hasard, 97,1 % donnent aussi 6 barres, et 288 (2,9 %) en donnent 5, la borne et l'optimum du chapitre 3. L'algorithme génétique trouve 5 barres sur les cinq graines, avec 1 000 évaluations, et un ordre qui se décode en 5 barres laisse seulement 500 mm libres au total (110, 10, 60, 150 et 170) : c'est un rangement optimal.

Mais lire le dernier résultat honnêtement : le meilleur de 1 000 ordres tirés au hasard trouve aussi 5 barres sur les cinq graines. Un ordre sur 35 environ se décode en 5 barres, donc 1 000 tirages n'y manquent presque jamais. Sur cette instance de vingt pièces, la recherche est facile, et le génétique n'a rien apporté que le hasard n'aurait trouvé. Ce que la découpe apprend est ailleurs : la représentation indirecte rend le croisement inoffensif, et tout problème dont une solution se décode depuis un ordre (ordonnancement, découpe, tournées de véhicules) en profite. Une instance plus grande départagerait le hasard et l'algorithme, mais elle n'est pas celle de Valdrome.

Un coût en escalier n'oriente pas la sélection
Le nombre de barres est un entier, et 97 % des ordres tirés au hasard valent 6 : la sélection n'a presque rien à comparer. Sur une grande instance, on ajoute d'ordinaire un critère de départage au nombre de barres, par exemple le remplissage de la barre la moins pleine (une barre presque vide est une barre qu'on peut peut-être supprimer). Un coût qui ne distingue pas les individus ne peut pas guider un algorithme génétique.

Sur la grande plaque, honnêtement

Douze trous se résolvent sans effort : l'algorithme génétique y trouve l'optimum. La vraie question se pose sur la plaque P-600, soixante trous, dont l'optimum, 2 788,70 mm, est démontré. La figure suivante fait régler la population et lancer l'évolution. Elle part de tournées tirées au hasard, environ cinq fois plus longues que la meilleure, et montre la meilleure tournée, la courbe du meilleur coût et du coût moyen par génération, et la diversité. Aucune référence n'est donnée avant l'essai.

Une population qui évolue, réglée et regardée60 trous, départ : tournées tirées au hasard
Mutation
Recherche locale par enfant (tirages 2-opt)
Budget (évaluations : un individu créé, ou un tirage de recherche locale)
Génération
0 / 1 019
Évaluations
0 / 100 000
Meilleure vue
aucune
Meilleure de la génération
aucune
Moyenne de la population
aucune
Diversité
aucune

Trait épais : la meilleure tournée vue. Pointillés : la meilleure de la génération, qui peut être moins bonne sans élitisme. Départ : le losange.

Les coûts se tracent ici.

Coût en mm selon la génération, échelle logarithmique. Trait épais : le meilleur de la génération. Tirets : la moyenne de la population.

Diversité : part des arêtes qui diffèrent d'un individu à l'autre

100 %0
Un point par tirage terminé.

Le trait vertical marque la médiane de chaque rangée. Les résultats plus courts sont à gauche.

Régler la population, la mutation, le tournoi et l'élitisme, puis lancer un tirage. Chaque lancer tire une graine neuve : deux tirages ne se ressemblent pas.
La plaque P-600 : une population de tournées qui évolue. Chaque lancer tire une graine neuve.
À manipuler
Lancer un tirage avec les réglages du départ et regarder trois choses : la meilleure tournée, qui se démêle peu à peu, la courbe du meilleur coût, qui plonge puis s'aplatit, et la diversité, qui s'effondre. Réduire la taille de la population à quelques dizaines, ou monter le tournoi à dix : la diversité s'effondre plus vite, et la courbe s'arrête plus haut. Mettre le taux de mutation à zéro : la courbe se fige sur une tournée médiocre. Couper l'élitisme : le meilleur de la génération remonte parfois, alors que la meilleure tournée vue, elle, ne remonte jamais. Monter la population à 500 : à budget fixé, très peu de générations, et la courbe n'a pas le temps de descendre. Essayer enfin la recherche locale par enfant, avec une population de six individus : chaque enfant reçoit quelques milliers de tirages 2-opt, et la courbe change de nature. Cliquer « Relancer dix tirages » pour voir la dispersion, et « Dix séries de redémarrages à budget égal » pour la comparer à celle du chapitre 5. Quand un réglage paraît satisfaisant, cliquer « Comparer à la meilleure connue ».

Le génétique seul, puis le mémétique

Le budget se mesure comme au chapitre 6, en évaluations, avec les budgets des deux chapitres précédents : 100 000 sur dix graines (0 à 9) pour le recuit et les redémarrages du chapitre 6, 353 800 sur cinq graines (0 à 4) pour les redémarrages et le tabou du chapitre 7. Le bloc suivant reprend toutes les pièces pour la plaque P-600 : le génétique seul, avec le réglage de départ de la figure (cent individus, un tournoi de trois, une élite de deux, une mutation par inversion à 30 %), puis le même algorithme avec une recherche locale sur chaque individu, expliquée plus bas.

Une limite du navigateur. Un bloc Python y est interrompu au bout de huit secondes, et le génétique seul, qui évalue une tournée entière à chaque enfant, ne tient pas dans ce délai aux budgets des chapitres 6 et 7 : dix graines à 100 000 évaluations, ou cinq à 353 800, demandent de l'ordre de la minute en Python ordinaire, et davantage dans le navigateur. Le bloc ne lance donc le génétique seul qu'à 10 000 évaluations, sur trois graines. Les lignes du tableau qui donnent le génétique seul aux budgets du chapitre, et le mémétique à 100 000 évaluations, sont précalculées, avec ce même code lancé à part (budget=100_000 sur dix graines, budget=353_800 sur cinq), et le tableau les marque comme telles.

main.py
Sortie
>_ Prêt à exécuter…

Sur ses 10 000 évaluations, cent générations de cent individus, le génétique seul est à plus de deux fois l'optimum : 6 397,9 mm de médiane (129,4 % au-dessus de 2 788,70 mm), de 5 609,4 à 6 867,8 mm selon la graine. Les soixante trous sont trop nombreux pour que le croisement et la mutation, seuls, en tirent vite de bonnes tournées. Un budget plus grand aide beaucoup, sans suffire : le calcul fait à part à 100 000 évaluations donne une médiane à 17,1 % de l'optimum, et à 353 800 évaluations, le budget des chapitres 5 et 7, une médiane à 6,4 % sur cinq graines. Il reste derrière le recuit, les redémarrages et le tabou.

Le génétique seul est mauvais pour une raison que le chapitre a déjà donnée : le croisement OX conserve des morceaux de tournée, mais ne raccourcit rien de façon systématique (sur les 78 coupes de P-217, deux enfants seulement battent leurs parents). Les enfants sont des tournées où des trajets se coupent, et il faut des générations pour les démêler un à un. La recherche locale du chapitre 5 sait faire cela très bien, en quelques milliers de tirages. L'idée est de réunir les deux : le génétique fabrique des points de départ diversifiés, la recherche locale les affine. On parle d'algorithme mémétique.

Concrètement, chaque individu créé, initial ou enfant, reçoit essais tirages de la descente du squelette chercher : un voisin 2-opt est tiré, gardé s'il raccourcit, jamais sinon. Ces tirages comptent dans le budget, une évaluation chacun : c'est le paramètre essais de evoluer, avec la fonction ameliorer : la boucle ne change presque pas. Avec une population de six individus, la recherche locale change ce que cherche la population : 2 000 tirages par individu sous un budget de 100 000, 5 000 sous un budget de 353 800. Ce réglage a été fait à part, sur d'autres graines (100 à 114), pour ne pas juger sur les graines de réglage : en balayant 6, 10 et 20 individus et 500 à 5 000 tirages, les médianes vont de 2,9 % à 12,3 % à 100 000 évaluations, et de 1,2 % à 5,1 % à 353 800. Le réglage compte autant que la méthode, et les valeurs retenues ici sont proches des meilleures de ce balayage.

La dernière ligne du bloc donne le résultat au budget du chapitre 7, sur ses cinq graines : le mémétique arrive à 0,5 % de médiane (1,1 % sur dix graines, calcul à part). À 100 000 évaluations, calcul à part lui aussi, il arrive à 3,7 % de médiane, contre 17,1 % pour le génétique seul : il remonte de plus de treize points, mais reste derrière le recuit (2,2 %), qui est ici la méthode la mieux adaptée à ce budget. Le tableau réunit les résultats.

BudgetMéthodeMeilleureMédianePire
100 000recuit (chapitre 6, dix graines)2 804,9 (0,6 %)2 850,8 (2,2 %)2 929,2 (5,0 %)
100 000redémarrages, meilleur voisin (chapitre 6, dix graines)2 845,7 (2,0 %)3 019,6 (8,3 %)3 104,0 (11,3 %)
100 000génétique seul, dix graines (précalculé)2 997,3 (7,5 %)3 266,9 (17,1 %)4 087,8 (46,6 %)
100 000génétique et recherche locale, dix graines (précalculé)2 841,8 (1,9 %)2 891,5 (3,7 %)2 992,7 (7,3 %)
353 800redémarrages (chapitre 7, cinq graines)2 821,6 (1,2 %)2 880,5 (3,3 %)2 949,9 (5,8 %)
353 800tabou, durée 30 (chapitre 7, cinq graines)2 788,7 (0 %)2 841,7 (1,9 %)2 931,0 (5,1 %)
353 800génétique seul, cinq graines (précalculé)2 943,0 (5,5 %)2 968,3 (6,4 %)3 063,8 (9,9 %)
353 800génétique et recherche locale, cinq graines (bloc)2 790,4 (0,1 %)2 803,1 (0,5 %)2 861,2 (2,6 %)
353 800génétique et recherche locale, dix graines (précalculé)2 790,4 (0,1 %)2 818,1 (1,1 %)2 867,5 (2,8 %)

Les pourcentages sont les écarts à l'optimum démontré, 2 788,70 mm. Ce qu'on en tire, avec son cadre.

  • Le génétique seul perd sur cette plaque : de très loin à 100 000 évaluations (17,1 % de médiane, contre 2,2 % pour le recuit), et encore à 353 800 (6,4 %, contre 3,3 % pour les redémarrages et 1,9 % pour le tabou). Il n'est pas adapté à une tournée de soixante trous, et le dire est la première conclusion honnête de ce chapitre.
  • Hybridé, il remonte : à 353 800 évaluations sa médiane (0,5 % sur cinq graines, 1,1 % sur dix) passe devant le tabou (1,9 %) et les redémarrages (3,3 %) du chapitre 7, et se place au niveau du recuit à 300 000 évaluations du chapitre 6 (1,5 %). À 100 000 évaluations, en revanche, il reste derrière le recuit. Aucune méthode ne gagne à tout budget.
  • Ce que le tableau ne démontre pas. Cinq graines pour les lignes à 353 800 évaluations donnent une médiane fragile (le mémétique passe de 0,5 % à 1,1 % de médiane en passant de cinq à dix graines), et dix pour les lignes à 100 000. Un seul voisinage (le 2-opt), une seule plaque, un réglage choisi à part sur d'autres graines pour le mémétique, et des réglages plus sommaires pour les autres méthodes : rien n'autorise à dire que le mémétique bat le tabou, seulement qu'il l'égale ou le dépasse dans ces conditions.
  • Une évaluation n'est pas une évaluation. Le budget compte pareil une évaluation d'une tournée entière du génétique (soixante et une distances) et une évaluation d'un voisin 2-opt (quatre distances). À évaluations égales, le génétique seul dépense en fait beaucoup plus de calcul que les autres méthodes, et perd quand même : le temps de calcul, que les blocs ne mesurent pas ici mais que le délai du navigateur suffit à rendre sensible (le génétique seul ne tient pas dans huit secondes, le mémétique oui), le montre. Mesurer aussi un budget en temps donnerait une comparaison plus proche de celle d'un atelier.
Ce qui marche en pratique sur une tournée
Un algorithme génétique seul est rarement compétitif sur une tournée : le croisement recombine bien, il raccourcit mal. Les meilleurs résultats viennent de l'hybridation avec une recherche locale, qui fait le travail fin de raccourcir chaque enfant, pendant que la population fournit la diversité. Le génétique est une manière d'organiser des points de départ, pas un substitut à la descente.

Les erreurs d'un débutant

Un croisement qui produit des objets invalides
Le croisement à un point est le premier auquel on pense, et sur une permutation il casse presque toutes les tournées. Avant d'écrire une seule ligne de sélection, vérifier qu'un croisement et une mutation, appliqués à des objets valides, en rendent un valide : valider_ordre sur cent enfants, avant tout le reste. Un test d'invalidité ne remplace pas un opérateur adapté.
Modifier un parent en construisant l'enfant
Construire l'enfant par échange sur la liste du parent (enfant = a, puis permuter deux éléments) modifie le parent lui-même, qui est aussi présent dans la population et dans l'élite. Un enfant se construit toujours sur une copie, comme le voisin du chapitre 5 : une tranche, une nouvelle liste, jamais l'objet reçu.
Rendre la dernière génération plutôt que la meilleure tournée vue
Sans élitisme, ou avec un tournoi dur, la meilleure tournée peut ne plus être dans la dernière population. Le code garde la meilleure solution vue, comme le recuit et le tabou, et rend celle-là.
Juger un algorithme génétique sur une seule graine
Le génétique tire au hasard à chaque étape : la population de départ, les parents, les coupes, les mutations. Sur la grande plaque, au budget réduit du bloc, les trois graines vont de 5 609 à 6 868 mm. Comparer avec plusieurs graines, à budget égal, en donnant la meilleure, la médiane et la pire, c'est la méthode posée au chapitre 6.
Régler à l'œil et sur les graines qui jugent
Taille de population, tournoi, mutation, élite, recherche locale : cinq réglages, et le résultat en dépend autant que de la méthode. On les règle sur d'autres graines que celles du tableau final, et avec autant de soin pour toutes les méthodes comparées.
Croire que plus de population, c'est mieux
À budget fixé, la population et le nombre de générations se partagent les mêmes évaluations. Trois cents individus pour 3 000 évaluations font neuf générations : l'algorithme n'a pas le temps d'évoluer. Compter les générations que le budget permet avant de choisir la taille.

Exercices type

Pourquoi le croisement à un point ne convient-il pas à une tournée ?

Parce que l'enfant reçoit le début d'un parent et la fin de l'autre, et que ces deux morceaux n'ont aucune raison de contenir des ensembles de trous complémentaires. Ce que le premier parent a déjà donné, le second peut le redonner : un trou est percé deux fois, un autre n'est pas percé du tout. Sur deux tournées de douze trous prises au hasard, 2,1 % des enfants seulement sont des tournées. Il faut un croisement écrit pour les permutations, comme l'OX, qui recopie un segment du premier parent et complète avec les trous restants dans l'ordre du second.

Combien de coupes l'order crossover a-t-il pour une tournée de vingt trous ?

Une coupe est une paire de positions i<ji < j parmi les positions de 0 à 20, soit 21 positions : (212)=21×20/2=210\binom{21}{2} = 21 \times 20 / 2 = 210 coupes, contre 78 pour douze trous. Le segment n'est jamais vide, et croisement_ox(a, b, 0, n) recopie tout le parent A, ce qui est un cas dégénéré mais valide.

Une population sans mutation dont tous les individus sont identiques peut-elle encore s'améliorer ?

Non. Le croisement de deux copies redonne la copie, et la sélection ne peut choisir qu'entre des individus égaux. Sans mutation, rien de nouveau ne peut apparaître : c'est la convergence prématurée. Sur P-217, vingt individus sans mutation perdent toute diversité en une vingtaine de générations, et aucune des cinq graines n'atteint l'optimum. La parade est de la diversité : une mutation, une population plus grande, une pression de sélection plus douce.

Pourquoi comparer un algorithme génétique à un recuit « à évaluations égales » est-il imparfait ?

Parce qu'une évaluation n'a pas le même prix : le génétique évalue une tournée entière, soixante et une distances, alors que le recuit et la recherche locale évaluent une variation en quatre distances. À évaluations égales, le génétique dépense beaucoup plus de calcul. Le budget en évaluations est indépendant de la machine et du langage, ce qui le rend reproductible, mais un budget en secondes est plus proche de ce qui intéresse l'atelier. Le plus honnête est de rapporter les deux et de dire lequel a servi à égaliser.

Pourquoi représenter la découpe par un ordre de pièces plutôt que par « pour chaque pièce, sa barre » ?

Parce que la seconde représentation laisse passer l'impossible : un croisement peut mettre les pièces de 2 920, 2 820 et 2 600 mm dans la même barre, et il faudrait réparer ou rejeter. L'ordre des pièces est une permutation, l'OX et la mutation s'y appliquent sans rien casser, et le décodeur First Fit fait de tout ordre un rangement réalisable. On paie un décodage à chaque évaluation, et beaucoup d'ordres donnent le même rangement, mais la contrainte est portée par la représentation.

La méthode

  1. Choisir le chromosome, et lister ce qu'il peut contenir d'impossible : c'est la représentation du premier chapitre.
  2. Choisir un croisement et une mutation écrits pour ce chromosome, et vérifier qu'ils rendent un objet valide (valider_ordre sur des centaines d'enfants).
  3. Écrire la sélection (un tournoi de deux ou trois candidats pour commencer) et l'élitisme (quelques individus).
  4. Régler le budget en évaluations, compter les générations qu'il permet, et en déduire la taille de la population.
  5. Mesurer la diversité génération après génération, et se méfier d'une population qui devient uniforme avant d'avoir trouvé de bonnes tournées.
  6. Garder et rendre la meilleure solution vue, pas la dernière génération.
  7. Hybrider avec la recherche locale quand le voisinage est bon marché : quelques milliers de tirages par enfant, et une population petite.
  8. Comparer honnêtement : plusieurs graines, meilleure, médiane et pire, à budget égal, avec l'écart à l'optimum ou à la borne, et des réglages faits sur d'autres graines.

Synthèse

  • Un algorithme génétique garde une population de solutions et la fait évoluer par sélection, croisement, mutation et remplacement : il sort du moule du squelette chercher, qui n'a ni population ni croisement.
  • Le chromosome est la représentation. Le croisement à un point casse une permutation : sur P-217, 2,1 % des enfants de parents au hasard sont des tournées. L'order crossover recopie un segment du premier parent et complète dans l'ordre du second : toujours une permutation.
  • Croiser deux tournées prises au hasard donne presque toujours un enfant plus long : sur 78 coupes, deux enfants seulement sont plus courts que leurs deux parents. La sélection et la répétition font avancer.
  • La mutation apporte ce que la population n'a pas : l'inversion, qui est un 2-opt tiré au hasard, vaut mieux que l'échange ; sans mutation, aucune graine n'atteint l'optimum de P-217.
  • La sélection par tournoi règle la pression : un tournoi de trois donne trois fois plus de parents aux meilleurs qu'un tirage au hasard, un tournoi de dix presque toute la reproduction aux dix meilleurs. L'élitisme garde le meilleur, mais la meilleure solution vue est toujours gardée.
  • Le budget se compte en évaluations : à budget fixé, une population trop grande n'a pas le temps d'évoluer (300 individus, 9 générations pour 3 000 évaluations).
  • La diversité est la distance moyenne entre individus. Quand elle tombe à zéro trop tôt, c'est la convergence prématurée : sans mutation, elle atteint zéro en une vingtaine de générations sur une tournée médiocre.
  • Une représentation indirecte (un ordre de pièces décodé par First Fit) rend toute solution réalisable : sur la découpe, l'algorithme trouve 5 barres, ce que le hasard trouve aussi, la recherche étant facile sur vingt pièces.
  • Sur P-600, à 100 000 évaluations, le génétique seul est à 17,1 % de l'optimum démontré (médiane de dix graines, calcul fait à part), très loin du recuit (2,2 %). Hybridé avec la recherche locale (algorithme mémétique), il tombe à 3,7 %, et à 0,5 % à 353 800 évaluations (cinq graines, 1,1 % sur dix), devant le tabou du chapitre 7 (1,9 %). Aucune méthode ne gagne à tout budget, et le génétique seul n'est pas ce qui marche.

Et ensuite

Le recuit, le tabou et le génétique, qui ont chacun leur idée, se mesurent maintenant sur le même terrain : les chapitres suivants ajoutent les fourmis, qui construisent des solutions à partir de traces, puis comparent l'ensemble des méthodes, entre elles et avec un solveur. Pour la représentation, le chapitre 1 ; pour le squelette dont le génétique sort et la recherche locale qu'il emploie, le chapitre 5 ; pour la méthode de comparaison honnête, le chapitre 6.

Mettre en pratique

Écrire l'order crossover de deux tournées, chiffrer le budget et la pression de sélection d'une population, et débusquer une diversité qui distingue une tournée de son inverse.

Tous les exercices sur les algorithmes génétiques