La recherche locale
Ce que ce chapitre apporte7 points
- Définir un mouvement, un voisin, un voisinage, et compter les voisins d'une solution.
- Écrire les voisinages par échange, par insertion et par 2-opt sur une permutation, et dire ce que chacun garantit.
- Expliquer pourquoi le 2-opt défait un croisement, et calculer son effet avec quatre distances au lieu de tout recalculer.
- Écrire une descente, en distinguant le premier voisin qui améliore du meilleur voisin.
- Reconnaître un optimum local, et dire pourquoi il dépend du voisinage et du point de départ.
- Lancer plusieurs descentes depuis des départs différents et lire ce que la dispersion des résultats apprend.
- Écrire le squelette chercher(initiale, voisin, cout, accepter, iterations) et l'appliquer à trois problèmes de Valdrome en ne changeant que la représentation, le voisin et le coût.
Partir d'une solution et la retoucher
Le chapitre sur les heuristiques constructives a construit des solutions d'un seul jet : le plus proche voisin pour la plaque, le rangement par longueur décroissante pour les barres, une règle de priorité pour la machine. Chaque règle décide vite et ne revient jamais sur une décision. La recherche locale fait l'inverse : elle prend une solution déjà complète, quelle qu'en soit l'origine, et la modifie par de petits changements.
Sur la plaque P-217, le plus proche voisin donne l'ordre T1, T7, T10, T11, T5, T6, T12, T8, T3, T2, T9, T4. Les dernières étapes traversent la plaque pour aller chercher T2, puis reviennent vers T9 et T4 qu'on avait laissés derrière soi : la règle, qui ne regarde que le trou le plus proche, s'est acculée. Une retouche possible : retourner le passage T8, T3, T2, ce qui donne T1, T7, T10, T11, T5, T6, T12, T2, T3, T8, T9, T4.
Ce que change une retouche
- 1.
La retouche remplace deux trajets, T12 vers T8 (25 mm) et T2 vers T9, par T12 vers T2 et T8 vers T9. T12 est en (150 ; 60), T8 en (130 ; 45), T2 en (180 ; 105), T9 en (70 ; 60). Quelle est la longueur de T2 vers T9, en mm ?
- 2.
Quelle est la longueur de T12 vers T2, en mm ?
- 3.
Quelle est la longueur de T8 vers T9, en mm ?
- 4.
De combien la longueur de la tournée varie-t-elle, en mm (un nombre négatif est un gain) ?
Presque 28 mm de gagnés, en ne touchant que deux trajets. L'idée tient dans cette phrase : pour juger une retouche, il suffit de regarder ce qu'elle change.
Une solution courante est la solution qu'on est en train de retoucher. Un mouvement est une modification élémentaire d'une solution : permuter deux trous, retourner un segment de la tournée. Un voisin de la solution courante est le résultat d'un mouvement. Le voisinage est l'ensemble de tous les voisins, et on parle de sa taille pour le nombre de ses éléments.
Une descente part d'une solution, prend un voisin qui est meilleur, s'y installe, et recommence, jusqu'à ce qu'aucun voisin ne soit meilleur. La solution où elle s'arrête est un optimum local : aucun de ses voisins ne fait mieux.
Un mouvement ne se définit pas sur « la solution » en général : il se définit sur sa représentation, celle qu'a posée le premier chapitre. Permuter deux éléments d'une permutation donne encore une permutation, donc encore une tournée valide. Changer un bit d'une sélection de commandes donne encore une sélection, mais pas toujours une sélection qui tient dans la capacité. Le voisinage est donc la moitié de la représentation : deux voisinages sur la même représentation donnent deux recherches différentes.
Le voisinage : trois façons de retoucher un ordre
Pour un ordre de perçage, trois mouvements reviennent partout.
L'échange permute deux éléments d'un ordre : les trous aux positions et se font mutuellement place.
L'insertion retire un élément et le replace ailleurs : le trou en position est sorti de l'ordre, puis réinséré pour finir en position .
Le 2-opt choisit deux positions et retourne le segment qui les sépare : les éléments de la position à la position sont lus à l'envers. Dans la tournée, cela remplace deux trajets par deux autres.
Un exemple sur cinq trous, l'ordre 1, 2, 3, 4, 5 :
| Mouvement | Résultat |
|---|---|
| échange des positions 1 et 4 (les trous 2 et 5, positions numérotées à partir de 0) | 1, 5, 3, 4, 2 |
| insertion du trou en position 1 pour qu'il finisse en position 3 | 1, 3, 4, 2, 5 |
| 2-opt sur les positions 1 à 3 (le segment 2, 3, 4) | 1, 4, 3, 2, 5 |
Les trois mouvements ne se valent pas. L'échange change jusqu'à quatre trajets, l'insertion trois, le 2-opt deux seulement. Un mouvement qui change peu de trajets change peu la longueur : c'est ce qu'on attend d'un « petit » changement, et ce qui rend le 2-opt bien adapté aux tournées.
Chaque voisinage a une taille, et elle se compte. Pour trous, il y a paires de positions, donc échanges. L'insertion offre mouvements, car déplacer un trou d'une position vers la suivante revient à déplacer le suivant d'une position vers la précédente, et on ne le compte qu'une fois. Le 2-opt offre mouvements : retourner tout l'ordre redonne la même tournée parcourue à l'envers, ce n'est pas un voisin. Le code les énumère et les compte.
Pour les douze trous de P-217, 66 échanges, 121 insertions et 65 mouvements 2-opt : quelques centaines de voisins au plus, qu'on examine en un clin d'œil. Pour une plaque de soixante trous, il y en a 1 770, 3 481 et 1 769. Le voisinage grossit comme le carré du nombre de trous, alors que l'espace des solutions grossit comme sa factorielle : on explore toujours une infime partie de l'espace, mais on l'explore là où la solution courante a des chances d'être améliorée.
Les autres problèmes de Valdrome ont les leurs, et le tableau suivant les met côte à côte. Dans chaque cas, le voisinage se lit sur la représentation posée au premier chapitre.
| Problème | Représentation | Un mouvement | Nombre de voisins |
|---|---|---|---|
| Tournée de 12 trous | un ordre des 12 trous | retourner un segment (2-opt) | 65 |
| Machine, 10 ordres de fabrication | un ordre de passage | permuter deux ordres | 45 |
| Affectation, 8 opérateurs | poste_de[i], une permutation | échanger les postes de deux opérateurs | 28 |
| Commandes, 10 commandes | dix zéros et uns | changer un bit | 10 |
Le 2-opt : défaire un croisement
Le mouvement de la tournée, c'est le 2-opt. Il a une propriété géométrique qui fait son succès.
Prenons deux trajets d'une tournée qui se croisent, l'un de à , l'autre de à . Retirer ces deux trajets sépare la tournée en deux morceaux ; on peut les recoller de deux manières, et une seule redonne une tournée d'un seul tenant : vers et vers , ce qui retourne le segment entre et . Dans le plan, en distance euclidienne, la somme des deux nouveaux trajets est strictement plus courte que celle des deux anciens, par l'inégalité triangulaire : les deux trajets qui se croisent sont les diagonales d'un quadrilatère convexe, et la somme des diagonales dépasse celle de deux côtés opposés. Une tournée où deux trajets se croisent n'est jamais optimale, et le 2-opt sait la raccourcir.
La réciproque est fausse : une tournée peut n'avoir aucun croisement et se laisser encore améliorer, ou l'être par un mouvement qui ne défait aucun croisement. Le 2-opt est un voisinage, pas seulement une chasse aux croisements.
Le calcul de la longueur du voisin est plus économique qu'il n'y paraît. Retourner le segment de la position à la position ne change que deux trajets, de à et de à , où est le point avant la position , celui en position , celui en position et celui qui suit. Le reste de la tournée est lu à l'envers ou non, la distance est la même dans les deux sens : rien d'autre ne bouge. La variation de longueur vaut
où est la distance entre deux points (le dist du code qui suit) : une tournée de soixante trous se juge ainsi en quatre distances au lieu de soixante et une. Le code vérifie que les deux calculs concordent sur le mouvement retouché plus haut.
Le voisin est évalué en quatre distances, alors que le recalcul complet en demande treize. Sur une grande plaque l'écart devient considérable, et c'est ce qui rend le 2-opt praticable : une descente évalue des dizaines de milliers de voisins.
La figure suivante fait retoucher la tournée à la main. Elle part du plus proche voisin. Choisir deux arêtes de la tournée, en cliquant dessus, fait apparaître ce que le mouvement retirerait, ce qu'il ajouterait, et sa variation de longueur ; il ne s'applique que sur demande. On peut aussi changer de voisinage, ou lancer la descente entière.
- Longueur
- 692,1 mm
- Mouvements faits
- 0
- Voisins (2-opt)
- 65
- Qui raccourcissent
- 5
Trait rouge pointillé : arête retirée. Trait noir en pointillés serrés : arête ajoutée. Trait orangé épais : arête qui en croise une autre. Départ : le losange.
- T1
- T7
- T10
- T11
- T5
- T6
- T12
- T8
- T3
- T2
- T9
- T4
La descente
Une descente répète un même geste : examiner les voisins de la solution courante, se déplacer vers un voisin meilleur, recommencer ; elle s'arrête quand aucun voisin n'est meilleur. Deux variantes se distinguent par la façon de choisir le voisin.
La descente au premier voisin qui améliore parcourt le voisinage dans un ordre fixé et s'installe dès qu'elle en trouve un meilleur, sans regarder les suivants.
La descente au meilleur voisin parcourt tout le voisinage, puis s'installe sur le meilleur voisin trouvé.
La première fait des pas peu coûteux et souvent nombreux ; la seconde, des pas plus coûteux et moins nombreux. Aucune n'est plus juste que l'autre : elles s'arrêtent parfois sur des solutions différentes, et le code suivant les compare sur la plaque, depuis deux points de départ. Ses deux dernières parties servent aux deux sections suivantes.
Le premier tableau qui s'affiche est riche, et il faut le lire avec méthode. Depuis le plus proche voisin, le 2-opt descend de 692,06 à 633,23 mm en trois pas au meilleur voisin (692,06, puis 664,14, puis 635,83, puis 633,23) et en cinq au premier voisin : les deux arrivent au même endroit. L'échange, lui, s'arrête à 661,53 mm, en deux pas. Depuis l'ordre d'écriture, tout change : le 2-opt s'arrête à 647,35 mm, l'échange à 724,18 mm au premier voisin et à 688,22 mm au meilleur, et l'insertion, selon la variante, à 633,23 ou à 647,35 mm. Le résultat d'une descente dépend de trois choses : le point de départ, le voisinage, et la variante.
La dernière colonne, « voisins évalués », compte le travail total, et elle ne donne pas toujours raison à la première variante : par pas, le premier voisin coûte moins, mais il faut plus de pas. Depuis l'ordre d'écriture, le 2-opt évalue 574 voisins au premier voisin contre 455 au meilleur, alors que l'insertion en évalue 524 contre 1 089 : au total, le premier voisin n'est pas toujours le moins cher.
L'optimum local
Une descente s'arrête quand aucun voisin n'est meilleur. Ce n'est pas la même chose que « la solution est la meilleure ».
Une solution est un optimum local pour un voisinage quand aucun de ses voisins n'a un meilleur coût. Un optimum global est meilleur que toute autre solution de l'espace. Tout optimum global est un optimum local, pour n'importe quel voisinage ; la réciproque est fausse.
Le bloc de code de la section précédente le montre sur P-217, dans sa seconde partie, sous le titre « optimums locaux » : il fait descendre par le 2-opt depuis l'ordre d'écriture, puis compte, pour chacun des trois voisinages, les voisins qui raccourcissent encore la tournée obtenue. Rien à recopier : le préambule (plaque, voisinages, descente) est le même.
Deux constats. D'abord, la tournée T1, T7, T9, T11, T10, T8, T3, T12, T2, T6, T5, T4 mesure 647,35 mm : aucun voisin ne la raccourcit, quel que soit le voisinage, et pourtant la meilleure tournée de P-217 mesure 633,23 mm, deux pour cent de moins. On est piégé : pour la sortir de là, il faudrait passer par des tournées plus longues, ce qu'une descente refuse par construction. Ensuite, la tournée à 661,53 mm, optimum local pour l'échange, ne l'est pas pour le 2-opt : un seul mouvement de plus la ramène à 633,23 mm. Un optimum local n'est pas une propriété de la tournée, c'est une propriété de la tournée et du voisinage.
1.Une descente 2-opt s'arrête sur une tournée : aucun des 65 voisins ne la raccourcit. Que peut-on affirmer ?
2.Deux descentes 2-opt partent de deux ordres différents et s'arrêtent à 633,23 mm et à 647,35 mm. Que peut-on en conclure ?
Sur une grande plaque
Douze trous se retouchent à la main. Pour éprouver la méthode, Valdrome a une plaque plus grande, P-600 : soixante trous sur une plaque de 600 par 400 mm, l'outil partant de l'origine et y revenant, à 30 mm par seconde comme sur P-217. Ses coordonnées, entières en millimètres, sont engendrées par une formule reproductible, un générateur congruentiel de graine 598 : chacun peut la regénérer, elle ne change jamais. La graine 598 est la première en dessous de 600 pour laquelle aucun trou n'a deux voisins exactement à la même distance, ce qui rendrait le plus proche voisin ambigu. La figure suivante fait retoucher cette plaque. Le nombre de voisins y est grand, et le compteur « Qui raccourcissent » montre l'état de la descente. Aucune référence n'est donnée avant l'essai.
- Longueur
- 3588,9 mm
- Mouvements faits
- 0
- Voisins (2-opt)
- 1769
- Qui raccourcissent
- 51
Trait rouge pointillé : arête retirée. Trait noir en pointillés serrés : arête ajoutée. Trait orangé épais : arête qui en croise une autre. Départ : le losange.
Le code suivant engendre la plaque, applique le plus proche voisin, puis le 2-opt au meilleur voisin avec la variation en quatre distances, et enfin cinquante descentes depuis des ordres tirés au hasard (graine 598). Sa dernière partie calcule deux bornes, commentées plus bas.
Le plus proche voisin mesure 3 588,87 mm, le 2-opt le ramène à 2 944,01 mm en treize pas, soit 18 % de moins. Ce n'est plus une affaire de coup d'œil. Quelle est la distance à l'optimum ? Pour soixante trous, la force brute est hors de question, mais un solveur exact y parvient : milp, celui du chapitre 3, alimenté par une formulation de la tournée que ce parcours ne détaille pas (une variable 0 ou 1 par arête, exactement deux arêtes en chaque point, puis des coupes qui interdisent les tournées en plusieurs boucles, ajoutées au fur et à mesure tant que la solution en comporte plusieurs), démontre que la meilleure tournée de P-600 mesure 2 788,70 mm. Il faut quelques tours de résolution, de moins d'une seconde chacun : cela tient à la taille de cette instance, et le chapitre 3 a montré que l'exact explose quand elle grossit. Ce n'est pas une « meilleure connue » : c'est l'optimum, prouvé. Le plus proche voisin est donc à 28,7 % de l'optimum, le plus proche voisin suivi du 2-opt à 5,6 %, et la meilleure des cinquante descentes (graine 598) à 0,8 %.
Deux bornes simples, que la dernière partie du bloc précédent calcule avec networkx, encadrent l'optimum par en dessous sans rien résoudre. Une tournée privée d'une arête est un arbre couvrant, donc l'arbre couvrant minimal de la plaque, départ compris, est une borne inférieure. Le 1-arbre la resserre : l'arbre couvrant minimal des trous seuls, plus les deux plus courts trajets du départ, car la tournée arrive au départ et en repart.
L'arbre couvrant minimal vaut 2 286,36 mm et le 1-arbre 2 439,15 mm, soit 87,5 % de l'optimum. Ce sont des bornes lâches, comme celles du chapitre 3 avant la relaxation, mais elles s'obtiennent en une fraction de seconde et sans connaître l'optimum. Avec le 1-arbre pour seule référence, le 2-opt depuis le plus proche voisin (2 944,01 mm) est garanti à au plus 20,7 % de l'optimum, et la meilleure des cinquante descentes (2 810,44 mm) à au plus 15,2 % : l'écart garanti du chapitre 3, sans avoir résolu le problème.
Les redémarrages
Une descente s'arrête dans le premier creux qu'elle rencontre, et le creux dépend du point de départ. Il y en a plusieurs, plus ou moins profonds. L'idée des redémarrages multiples est de ne pas parier sur un seul départ : on lance plusieurs descentes, chacune depuis une solution de départ différente (typiquement tirée au hasard), et on garde le meilleur optimum local rencontré. C'est la plus simple des stratégies pour sortir d'un creux, et elle est étonnamment efficace quand la descente est rapide.
Le code de ces essais est déjà écrit : c'est la dernière partie du bloc de la section « La descente », sous le titre # ---- Suite : les redemarrages. Rien à recopier : la plaque, les trois voisinages et la descente sont ceux de plus haut. Pour chacun des trois voisinages, il lance cent descentes au meilleur voisin depuis cent ordres tirés au hasard, compte les optimums locaux distincts, puis détaille les plus fréquents pour le 2-opt.
Sur P-217, cent descentes 2-opt depuis cent ordres tirés au hasard (graine 217) se répartissent en sept optimums locaux différents, du meilleur (633,23 mm, atteint 38 fois) au pire (679,32 mm). Le voisinage compte autant que le nombre d'essais, et ce n'est pas sa taille qui décide : l'échange (66 voisins) est plus grand que le 2-opt (65), et pourtant ses descentes ne trouvent la meilleure tournée que 6 fois sur 100 et se dispersent sur 49 optimums locaux, jusqu'à 779,42 mm, parce qu'un échange de deux trous éloignés change quatre trajets d'un coup. L'insertion (121 voisins, trois trajets changés) la trouve 62 fois. Dans tous les cas, le meilleur des essais est meilleur que la moyenne des essais : c'est ce que les redémarrages achètent, en temps de calcul.
La figure suivante le fait sentir sur P-600, où les creux sont nombreux. Chaque descente est lancée depuis un ordre tiré au hasard, et son optimum local est rangé dans un histogramme.
- Descentes
- 0
- Meilleure vue
- aucune
- Moyenne
- aucune
- Optimums distincts
- 0
Départs tirés au hasard : la série est choisie au premier lancement, et chaque lecteur a la sienne.
Chaque barre compte les descentes dont l'optimum local tombe dans son intervalle. Contour épais : la classe de la meilleure.
La meilleure tournée vue jusqu'ici. Départ : le losange.
Les chiffres du texte (meilleure, médiane et pire des cinquante descentes de P-600, plus haut) sont ceux d'une graine fixée, 598 : ils se rejouent en Python à l'identique, mais ceux de la figure varient d'un lecteur à l'autre, et d'une série à l'autre.
Les redémarrages ont un défaut : chaque descente repart de zéro, et ne profite pas de ce que les précédentes ont trouvé. Les chapitres suivants reprennent l'idée par un autre bout : ne plus s'arrêter dans un creux, mais se donner le moyen d'en sortir.
Le squelette commun
Presque toutes les méthodes de ce parcours ont la même charpente : une solution courante, un voisin tiré, un coût mesuré, une décision de s'y déplacer ou non, et le souvenir de la meilleure solution vue. Le tabou en garde l'esprit mais examine tout le voisinage à chaque pas (une seconde forme, au chapitre 7), et les algorithmes génétiques et les fourmis en sortent tout à fait. Écrire cette charpente une fois évite de la réécrire à chaque chapitre.
chercher fait quatre choses, dans cet ordre, autant de fois que demandé : tirer un voisin de la solution courante, le mesurer, décider de l'accepter, et retenir la meilleure solution rencontrée. Rien d'autre. Trois pièces changent d'un problème à l'autre, et ce sont celles qu'on a apprises à poser :
| Pièce | Tournée | Machine | Postes |
|---|---|---|---|
représentation (initiale) | ordre des 12 trous | ordre des 10 ordres | poste_de, permutation de 0 à 7 |
| voisin | retourner un segment | permuter deux ordres | permuter deux postes |
| coût | longueur | somme des retards | temps total |
La quatrième pièce, accepter, est ici la plus simple qui soit : la descente est le cas où l'on n'accepte un voisin que s'il est strictement meilleur. C'est elle qui, avec un nombre suffisant d'itérations, s'arrête dans un optimum local. Le squelette tire un voisin au hasard plutôt que de parcourir tout le voisinage : la descente devient ainsi une suite de tirages en nombre fixé, et non une boucle qui s'arrête d'elle-même. Avec assez d'itérations, elle a essayé presque tous les voisins de la solution où elle s'est arrêtée, et la longue série de tirages sans progrès en est la signature.
Lire la dernière ligne du tableau affiché : la même charpente, sans y toucher, retouche une tournée, un planning de machine et une affectation. Les résultats varient d'une graine à l'autre, parce que chaque graine tire des voisins dans un autre ordre, et donc s'arrête dans un autre optimum local. Sur l'affectation, ils s'étalent de 99 à 112 minutes alors que la meilleure affectation en vaut 95 : la descente n'y trouve l'optimum sur aucune des cinq graines, ce qui rappelle à quoi servent les redémarrages.
chercher restent celles de tout le parcours. Le recuit simulé (chapitre 6) ne changera que accepter : au lieu de refuser tout voisin moins bon, il l'accepte parfois, avec une probabilité qui décroît, pour sortir des optimums locaux. La recherche tabou (chapitre 7) ajoutera une mémoire : elle examinera les voisins, prendra le meilleur même s'il est moins bon, et s'interdira de revenir en arrière. Les algorithmes génétiques et les fourmis (chapitres 8 et 9) sortent de ce moule : ils ne retouchent pas une solution, ils en manient tout un ensemble, ou construisent des solutions nouvelles à partir de traces.
random.Random(graine) rend la recherche reproductible : la même graine donne le même résultat, et l'on peut comparer deux réglages sans que le hasard décide à leur place. Une seule graine ne suffit pourtant pas à comparer deux méthodes : la comparaison honnête, sur plusieurs graines, est posée au chapitre 6.
Les erreurs d'un débutant
voisin = ordre puis échanger deux éléments modifie la solution courante elle-même, et le voisin qu'on refuse reste appliqué. La recherche rend alors une solution qui n'est plus celle dont elle annonce le coût. Un voisin se construit toujours sur une copie (list(ordre), une tranche ordre[:], une nouvelle liste), et la solution courante n'est touchée que quand on accepte.
nouveau <= actuel fait accepter les voisins de même coût. La solution se promène alors sur un palier, sans progrès : une descente qui boucle jusqu'à ne plus rien trouver ne s'arrête plus, et le squelette dépense ses iterations sur ce palier. Sur les nombres à virgule, une comparaison stricte pose un problème voisin : deux longueurs égales au millième d'unité se départagent par des erreurs d'arrondi. Comparer avec un petit écart (c < actuel - 1e-9) rend la descente robuste.
chemin qui n'inclut pas le départ aux deux bouts donne des variations fausses sur les bords, et la descente « améliore » des tournées qu'elle rallonge. Comparer toujours la variation à un recalcul complet sur quelques mouvements, comme le fait le code plus haut.
Exercices type
Pourquoi le 2-opt évalue-t-il un voisin en quatre distances, alors que l'échange de deux trous éloignés en demande davantage ?
Retourner un segment ne change que deux trajets de la tournée : celui qui y entre et celui qui en sort. Les trajets à l'intérieur du segment sont parcourus à l'envers, et la distance est la même dans les deux sens. Un échange de deux trous éloignés change quatre trajets (les deux trajets voisins de chacun des deux trous), donc huit distances, et une insertion en change trois. Le 2-opt est le voisinage qui change le moins de trajets pour un ordre de perçage, ce qui explique son succès.
Combien de voisins un ordre de 40 trous a-t-il pour l'échange, l'insertion et le 2-opt ?
L'échange : . L'insertion : . Le 2-opt : , car retourner tout l'ordre ne change pas la tournée. Passer de 12 à 40 trous multiplie par 12 le nombre d'échanges, alors que le nombre de tournées est multiplié par un nombre à quarante chiffres (environ ).
Une descente s'arrête après avoir examiné tous les voisins sans en trouver de meilleur. La solution est-elle optimale ?
Non. Elle est un optimum local pour ce voisinage, et rien de plus. Pour dire si elle est proche de l'optimum, il faut une borne : avec le 1-arbre de P-600, l'écart garanti d'une tournée à 2 944,01 mm est de 20,7 %, ce qui ne dit pas si elle est à cinq pour cent de l'optimum ou à vingt. Un optimum local peut aussi être excellent : c'est la mesure qui décide, pas la méthode.
Pourquoi lancer cent descentes depuis cent départs différents plutôt qu'une seule descente cent fois plus longue ?
Une descente ne peut pas être « plus longue » : elle s'arrête d'elle-même dès qu'aucun voisin n'est meilleur, et laisser tourner davantage ne change rien. Le seul moyen de faire fructifier plus de temps de calcul est de repartir ailleurs, ce qui explore d'autres creux. Sur P-217, cent départs au hasard donnent sept optimums locaux différents en 2-opt, dont le meilleur est trouvé 38 fois sur 100.
Que change-t-on dans chercher pour passer de la tournée à l'affectation des opérateurs ?
Trois pièces, pas une ligne du squelette : la solution initiale (une permutation de 0 à 7 au lieu d'un ordre des trous), le voisin (permuter les postes de deux opérateurs) et le coût (le temps total de l'affectation au lieu de la longueur). La règle accepter, elle, ne bouge pas. Séparer ces quatre pièces rend la recherche réutilisable, et c'est le sens du squelette.
La méthode
- Choisir la représentation et vérifier qu'un mouvement lui reste fidèle : une permutation reste une permutation.
- Choisir un voisinage et compter ses voisins. Trop petit, la descente se bloque ; trop grand, chaque pas coûte trop.
- Écrire le coût du voisin par la variation seule quand c'est possible (quatre distances pour un 2-opt), et la vérifier contre un recalcul complet.
- Construire une solution de départ par une règle simple : plus proche voisin, rangement par longueur décroissante, priorité.
- Descendre : premier voisin ou meilleur voisin, jusqu'à l'optimum local. Compter les pas et les voisins évalués.
- Redémarrer depuis plusieurs départs, et rendre le meilleur, la moyenne et le pire.
- Juger le résultat par une borne ou par un optimum connu, et annoncer l'écart.
- Passer par le squelette
chercherquand on veut changer la règle d'acceptation : la descente est le casaccepter = seulement si meilleur.
Synthèse
- La recherche locale part d'une solution complète et la retouche par de petits mouvements ; les solutions obtenues sont ses voisins, et leur ensemble est le voisinage.
- Un mouvement se définit sur la représentation. Sur une permutation : l'échange ( voisins), l'insertion () et le 2-opt ().
- Le 2-opt retourne un segment et ne remplace que deux trajets : sa variation se calcule en quatre distances, et il défait tout croisement, car en distance euclidienne une tournée qui se croise n'est jamais optimale.
- Une descente s'installe sur un voisin meilleur jusqu'à n'en plus trouver : au premier voisin qui améliore, ou au meilleur voisin.
- Elle s'arrête sur un optimum local, qui n'est en général pas l'optimum : sur P-217, 647,35 mm contre 633,23 mm.
- L'optimum local dépend du voisinage (un optimum d'échange n'en est pas un pour le 2-opt) et du point de départ.
- Les redémarrages lancent plusieurs descentes depuis des départs différents et gardent le meilleur : sur P-600, la meilleure de cinquante est à 0,8 % de l'optimum démontré, 2 788,70 mm, alors que la médiane est à 5,3 %.
- Le squelette
chercher(initiale, voisin, cout, accepter, iterations)sert à tout problème : seuls la représentation, le voisin et le coût changent, et la descente est le casaccepter = seulement si meilleur. - Le recuit simulé ne changera que
accepter; le tabou ajoutera une mémoire ; le génétique et les fourmis sortiront du moule.
Et ensuite
La descente est rapide et se bloque. Le chapitre suivant garde le squelette et n'y change que la règle d'acceptation : accepter parfois un voisin moins bon, avec une probabilité qui décroît, c'est le recuit simulé. Pour situer ce que vaut une tournée sans connaître l'optimum, les bornes du chapitre 3 servent de règle ; pour la représentation et le coût, le chapitre 1.
Mettre en pratique
Écrire un voisinage, chiffrer le coût d'un balayage, et attraper une descente qui garde ce qu'elle a refusé.
- Les voisins d'un chemin ouvert par retournementNiveau 2
- Compter les voisins et les distances d'un balayageNiveau 2
- Débogage : la descente qui garde ce qu'elle refuseNiveau 3