introduction_metaheuristiques_Taillard

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 222

Introduction aux

métaheuristiques

17
20
c É.D. Taillard 25 septembre 2017

e
br
em
pt
se
25
g
Al
T_
T_ ii

Al
g
25
se
pt
em
br
e
20
17
Introduction

17
Si le lecteur sait ce qu’est une heuristique — un algorithme permettant de

20
trouver avec un effort raisonnable une solution pas forcément la meilleure à un
problème donné, algorithme se basant sur des connaissances acquises par
l’expérience — la définition d’une métaheuristique est plus discutée.
Beaucoup d’auteurs ont adopté celle d’un processus maître itératif guidant

e
et modifiant les opérations d’une heuristique subordonnée. En conséquence,
les ouvrages dans le domaine sont décomposés en chapitres présentant cha-

br
cun une métaheuristique, comme par exemple le recuit simulé, la recherche
avec tabous, les colonies de fourmi artificielles ou les algorithmes génétiques,
em
pour ne citer que les plus connues.
Le présent livre aborde les métaheuristiques sous un angle différent. Il les
présente la forme d’un ensemble de méthodes de base qui sont combinées
entre elles pour constituer une heuristique. Ces principes de base sont suf-
pt

fisamment généraux pour qu’ils puissent s’appliquer à un large ensemble de


problèmes. Nous avons identifié 5 grands principes de base dans la démarche
conduisant à l’élaboration d’un nouvel algorithme :
se

La modélisation du problème La phase la plus délicate lorsqu’on est con-


fronté à un nouveau problème est sa modélisation. En effet, si un pro-
blème est pris « par le mauvais bout », sa résolution peut en être large-
25

ment compromise.
La décomposition en sous-problèmes Lorsque l’on doit résoudre un pro-
blème de grande taille, il est nécessaire de le décomposer en sous-
g

problèmes plus petits. Ces derniers peuvent être eux-mêmes des pro-
blèmes difficiles, qu’il faut approcher par une technique appropriée, par
Al

exemple une métaheuristique.


T_

Heuristique Métaheuristique
Domaine Un problème générique Optimisation combinatoire
d’application d’optimisation
Connaissance Spécifiques au problème Méthodes heuristiques
à inclure d’optimisation
Données à Les valeurs numériques Un problème générique
fournir d’un exemple de problème d’optimisation
Résultat Solution heuristique de Un algorithme heuristique
l’exemple de problème

Tableau 1 – Contexte d’applicabilité d’une heuristique et d’une métaheuristique


2

La construction d’une solution Lorsqu’un modèle approprié est trouvé, il


devient aisé de construire une solution au problème, même si cette der-
nière n’est pas de bonne qualité, voire inapplicable en pratique. Une des
méthodes de construction les plus courantes est un algorithme glouton,
qui peut être du reste un algorithme exact pour des problèmes simples
comme la recherche d’arbre ou de chemin optimaux.
La modification d’une solution L’étape suivante tente d’améliorer une so-
lution construite de façon plus ou moins sommaire en lui faisant subir
de légères modifications. Cette approche est en quelque sorte une tra-

17
duction au monde discret des méthodes basées sur les gradients pour
l’optimisation différentiable.
Randomisation et apprentissage Finalement, la répétition de constructions

20
ou de modifications permet d’améliorer la qualité des solutions produites,
pour peu que l’on fasse intervenir une composante aléatoire et/ou un
processus d’apprentissage.

e
Les métaheuristiques sont devenues un outil incontournable lorsqu’il s’agit
de s’attaquer à la résolution de problèmes d’optimisation difficiles, même si

br
elles ont parfois été décriées, surtout dans les années 1980 par des personnes
qui opposaient méthodes « exactes » et heuristiques. Depuis, on s’est rendu
compte que bien des méthodes exactes, donc sensées fournir une solution la
em
meilleure possible, ne garantissaient l’optimalité qu’avec une précision limitée
et qu’elles utilisaient abondamment des heuristiques !
pt

Public-cible
se

Le présent ouvrage est destiné aux étudiants et informaticiens profession-


nels désirant se familiariser avec les métaheuristiques. Un accent particulier
est mis sur les exemples d’applications, afin que les principes de base énumé-
rés plus haut ne soient pas perçus comme une sculpture sur nuages, ce qui
25

est le danger lorsque l’on se situe à un certain niveau d’abstraction.


Pour cela, de nombreux exercices ont été imaginés d’une part. Il faut tou-
tefois mentionner que certains sont fortement inspirés d’autres ouvrages sur
le sujet. D’autre part, les codes sources implantant la plupart des métaheu-
g

ristiques sont présentés pour un problème emblématique, celui du voyageur


Al

de commerce, qui se prête à des représentations concrètes. Ainsi, l’informati-


cien désirant mettre au point une méthode heuristique pour un problème par-
ticulier pourra s’inspirer de ces codes. Mais surtout, ces derniers lèvent toute
T_

ambiguïté sur les inévitables interprétations qui peuvent être faites lors de la
présentation d’une trame de métaheuristique.
Comme un code source n’est utile que lorsque l’on veut connaître tous les
détails d’une méthode mais qu’il est d’une lecture peu attractive, nous avons
dépouillés les codes proposés au maximum, en essayant de les limiter à une
seule page. Certes, ces codes ne sont pas des « chevaux de course », on en
trouvera de plus complets et de plus efficaces par exemple dans la « Source
Code Library », mais ils ne contiennent que la quintessence des méthodes et
leur extrême concision devrait permettre au lecteur de les comprendre. Ainsi,
plus d’une douzaine de méthodes différentes ont été implantées tout en pre-
nant ensemble moins du dixième du nombre de lignes de code d’une des im-
3

plantations les plus rapide. Nous avons cependant dû, pour respecter cette
concision, compacter quelque peu les codes notamment en ne les commentant
que succinctement et parfois en plaçant plusieurs instructions sur une même
ligne ; nous prions donc le lecteur habitué à des codes plus aérés d’être indul-
gent.
Le choix des exercices a toujours été guidé par les solutions auxquelles on
s’attend, qui doivent être aussi univoques que possible. En effet, lorsque l’on
conçoit une nouvelle heuristique, il n’y a plus de solution juste ou fausse. Il y
a seulement des heuristiques qui fonctionnent bien pour certaines données du

17
problème considéré et d’autres qui ne produisent pas de résultats satisfaisants
— piètre qualité des solutions, temps de calcul prohibitif, etc.
Rien n’est plus déstabilisant pour un étudiant que des réponses ambiguës,

20
voire philosophiques. C’est pour cela les solutions pour l’ensemble des exer-
cices sont données en annexe.

Organisation du livre

e
br
Le présent ouvrage est découpé en 3 parties. La première (chapitres 1 et 2)
rappelle quelques bases de programmation linaire, de la théorie des graphes,
em
de théorie de la complexité et présente quelques problèmes, simples et diffi-
ciles, d’optimisation combinatoire. Le but de cette première partie est de rendre
le domaine intelligible par un lecteur ne disposant pas de connaissances parti-
culières en optimisation combinatoire.
pt

La deuxième partie (chapitres 3 à 6) traite des blocs constituant la base


des métaheuristiques : la construction et l’amélioration de solutions ainsi la
décomposition d’un problème en sous-problème. Des métaheuristiques primi-
se

tives assemblant ces ingrédients et les utilisant dans des processus itératifs
fonctionnant sans mémoire sont y sont également incorporées.
La troisième partie présente des métaheuristiques plus évoluées qui uti-
25

lisent des formes de mémoire et d’apprentissage permettant de mettre au point


des heuristiques plus élaborées.
1. Éléments de programmation linéaire, de théories des graphes et de la
complexité Ce chapitre introduit très succinctement deux techniques de
g

modélisation de problèmes d’optimisation, la programmation linéaire et la


théorie des graphes. En effet, la formulation d’un problème sous la forme
Al

d’un programme linéaire le décrit de manière formelle et sans ambiguïté


alors que de nombreux problèmes d’optimisation combinatoire peuvent
T_

être « dessinés » et par là représentés de façon intuitive et relativement


naturelle par un graphe. Quelques éléments de théorie de la complexité
sont également présentés. Très brièvement, cette branche s’occupe de
classer les problèmes selon leur difficulté. En effet, avant d’envisager
l’utilisation d’une métaheuristique pour un problème, il faut s’assurer que
ce dernier est difficile et qu’il n’existe pas un algorithme efficace pour le
résoudre exactement.
2. Exemples de problèmes combinatoire et modélisation Ce chapitre passe
en revue un certains nombre de problèmes classiques en optimisation
combinatoire. Il permet d’illustrer la frontière parfois ténue qu’il y a entre
un problème facile, pour lequel des algorithmes efficaces sont connus, et
4

un problème difficile qui ne diffère que par un petit détail pouvant paraître
anodin à première vue. Il met également en évidence le fait qu’un pro-
blème peut avoir diverses modélisations, même si sa formulation reste
très simple.
3. Méthodes constructives Ce chapitre présente des méthodes de construc-
tion de solutions, en commençant par un rappel sur les méthodes de
séparation et évaluation, largement utilisées pour la conception d’algo-
rithmes exacts. Ensuite deux méthodes élémentaires sont présentées, la
construction aléatoire et la construction gloutonne. Cette dernière sélec-

17
tionne séquentiellement les éléments à ajouter à une solution partielle, en
ne remettant jamais en cause les choix qui ont été faits. Cette méthode
peut être améliorée en évaluant plus profondément les conséquences du

20
choix d’un éléments. La recherche en faisceaux et la méthode pilote en
font partie.
4. Recherches locales Les méthodes d’amélioration d’une solution forment
l’épine dorsale de la plupart des métaheuristiques. Ces méthodes sont

e
basées sur la définition d’un ensemble de solutions voisines, pour toute

br
solution du problème. La définition de cet ensemble dépend naturelle-
ment de la modélisation du problème. Selon cette dernière, un voisinage
s’exprimant naturellement peut s’avérer trop petit pour mener à des solu-
em
tions de qualité ou au contraire trop grand, induisant des temps de calcul
prohibitifs. Diverses méthodes ont été proposées pour agrandir le voisi-
nage, comme la recherche en éventail ou les chaînes d’éjections, ou pour
le réduire, comme la recherche granulaire ou la liste de candidats.
pt

5. Méthodes de décomposition Dans le processus d’élaboration d’un nou-


vel algorithme, ce chapitre aurait logiquement dû se trouver juste après
se

celui consacré à la modélisation de problème. Néanmoins, les méthodes


de décomposition ne s’utilisent que lorsque la dimension des données
à traiter est importante. Il s’agit donc d’une phase optionnelle, que le
lecteur peut sans autre ignorer avant de passer aux méthodes stochas-
25

tiques et d’apprentissage. C’est la raison justifiant sa place à la fin de la


première partie de cet ouvrage, consacrée aux ingrédients de base des
métaheuristiques. On trouvera dans ce chapitre des méthodes comme
POPMUSIC ou plus générale comme la recherche dans de grands voisi-
g

nages.
Al

6. Méthodes stochastiques sans mémoire La second partie de cet ouvrage


est consacré aux méthodes qui répètent de façon aléatoire et sans mé-
T_

moire des constructions ou des modifications de solutions. Parmi les


techniques les plus populaires présentées dans ce chapitre, on trouvera
GRASP, le recuit simulé, l’acceptation à seuil, la méthode du grand dé-
luge, les méthodes de bruitage et la méthode à voisinage variable.
7. Apprendre à construire En suivant l’ordre dans lequel sont présentés les
ingrédients de base des métaheuristiques, on peut tout d’abord chercher
à améliorer le processus de construction de solutions. Les colonies de
fourmis artificielles en sont exemple typique.
8. Recherche avec tabous Si les recherches locales forment l’épine dor-
sale des métaheuristiques, la recherche avec tabous, qui cherche à ap-
prendre comment modifier itérativement une solution, peut être considé-
5

rée comme la reine des métaheuristiques. C’est du reste à son inventeur


que l’on doit ce terme. Ce chapitre se concentrera sur les ingrédients
que l’on peut considérer à la base de la recherche avec tabous, à sa-
voir l’utilisation de mémoires et de tactiques d’exploration des solutions.
D’autres ingrédients proposés dans le cadre de la recherche avec tabous
par son inventeur, comme les listes de candidats, les chaînes d’éjection
ou la construction de vocabulaire trouvent une place plus naturelle dans
d’autres chapitres.
9. Méthodes à population Lorsque l’on dispose d’une population de solu-

17
tions, on peut chercher à apprendre comment les combiner et comment
gérer cette population. La méthode la plus populaire dans ce domaine est
sans conteste les algorithmes génétiques. Ces derniers sont cependant

20
une métaheuristique moins évoluée que la recherche par dispersion. Fi-
nalement, parmi les dernières-nées des métaheuristiques on trouve les
méthodes à essaim particulaires, qui semblent adaptés à l’optimisation
continue.

e
br
em
pt
se
25
g
Al
T_
T_ 6

Al
g
25
se
pt
em
br
e
20
17
17
20
Première partie

e
br
Concepts de base
em
pt
se
25
g
Al
T_
T_
Al
g
25
se
pt
em
br
e
20
17
Chapitre 1

17
Éléments de théories des

20
graphes et de la complexité

e
1.1 Optimisation combinatoire
br
em
Le domaine d’application privilégié des métaheuristiques est l’optimisation
combinatoire. Pour fixer les idées, il n’est donc pas inutile de brièvement rap-
peler en quoi consiste ce domaine. Prenons un petit exemple de problème
pt

combinatoire : celui de la coloration d’une carte de géographie. On désire attri-


buer une couleur pour chaque division d’une carte de sorte que deux divisions
se

qui ont une frontière commune ne reçoivent pas la même couleur. Dans la fi-
gure 1.1 on a utilisé 5 couleurs différentes, sans se préoccuper de l’attribution
politique des îles ou enclaves.
Ce problème est combinatoire. S’il y a n divisions à colorer et que l’on désire
25

utiliser 5 couleurs, il y a 5n manières différentes de colorer la carte. Un grand


nombre de ces colorations ne sont pas admissibles car elles ne respectent pas
la contrainte que deux divisions avec frontière commune ne reçoivent pas une
couleur identique. On pourrait se poser la question de savoir s’il existe une co-
g

loration admissible n’utilisant que 4 couleurs. De façon plus générale, on peut


vouloir procéder à une coloration utilisant un nombre minimum de couleurs. On
Al

a donc affaire ici à un problème d’optimisation combinatoire.


Comment exprimer ce problème plus formellement ? Prenons tout d’abord
T_

le petit exemple suivant : peut-on colorer la Suisse (s) et les pays voisins
(Allemagne d, France f , Italie i, Autriche a et Liechtenstein l) avec 3 cou-
leurs (voir figure 1.2) ? Pour cela, on peut introduire 18 variables booléennes
bs1 , bs2 , bs3 , bd1 , bd2 , . . . , bl3 qui indiqueront pour chaque pays la couleur 1, 2 ou
3 qu’il reçoit. Il s’agit d’écrire une longue formule booléenne qui prendra la va-
leur vraie si, et seulement s’il existe une coloration admissible en 3 couleurs.
Tout d’abord, on peut imposer que la Suisse soit colorée dans au moins une
couleur : bs1 ∨ bs2 ∨ bs3 . Mais il ne faut pas qu’elle reçoive à la fois la couleur 1
et la couleur 2, ce qui peut s’écrire : bs1 ∧ bs2 , ce qui est équivalent à : bs1 ∨ bs2 .
Elle ne devra également pas prendre à la fois la couleur 1 et la couleur 3 ou la
couleur 2 et la couleur 3. Ainsi, pour imposer que la Suisse soit colorée avec
10 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

17
20
e
F IGURE 1.1 – Une ancienne carte de l’Europe colorée en 5 couleurs (en comptant celle
du fond).
br
em
exactement 1 couleur, on aura la conjonction de 4 clauses :

(bs1 ∨ bs2 ∨ bs3 ) ∧ (bs1 ∨ bs2 ) ∧ (bs1 ∨ bs3 ) ∧ (bs2 ∨ bs3 )


pt

Pour chacun des pays concernés, il faudra également écrire une conjonction de
4 clauses, mais avec les variables correspondant aux autres pays. Finalement,
se

pour chaque frontière, il faudra imposer que les couleurs de part et d’autre
soient différentes. Par exemple, pour la frontière entre la Suisse et la France,
on devra avoir :
(bs1 ∨ bf 1 ) ∧ (bs2 ∨ bf 2 ) ∧ (bs3 ∨ bf 3 )
25

De manière générale, si on désire colorer une carte avec n pays qui ont,
en tout, m frontières communes en k couleurs, on peut se poser la question
du nombre de variables que le problème aura ainsi que du nombre de clauses
qui devront être toutes vraies simultanément. Tout d’abord, il faudra introduire
g

n · k variables booléennes. Ensuite, pour chaque pays, il faudra écrire 1 +


Al

k·(k−1)
2 clauses pour s’assurer que chaque pays reçoive exactement 1 couleur.
Finalement, pour chaque frontière, il faudra écrire m·k clauses. Le problème de
la coloration d’une telle carte en k couleurs aura une solution si, et seulement
T_

s’il existe des valeurs vrai ou f aux pour chacune des variables telles que
l’ensemble de toutes ces clauses soient vraies simultanément. Ce problème
est connu comme celui de l’acceptabilité et joue un rôle central en théorie de
la complexité. Tout ce développement a permis de formaliser le problème par
une seule, longue, formule booléenne, mais ne nous dit pas encore comment
trouver une solution à ce problème !
Un algorithme, très primitif, permettant de trouver une solution est d’es-
sayer toutes les valeurs possibles pour les variables (il y a 2nk jeux de valeurs
différentes), et pour chaque jeu, de vérifier si la formule est juste.
Tel que modélisé par une formule booléenne, le problème de la coloration
d’une carte est un problème de décision, dont la réponse est vrai (on arrive à
1.1 O PTIMISATION COMBINATOIRE 11

colorer la carte en k couleurs) ou f aux (on n’y arrive pas). En supposant que
l’on dispose d’un algorithme A qui permette de trouver les valeurs à donner aux
variables booléennes pour que la formule soit vraie — ou qui dise que de telles
valeurs n’existent pas — est-il possible de résoudre le problème d’optimisation,
c’est-à-dire de trouver la valeur minimale de k telle qu’il existe une coloration
admissible ?
Une façon de répondre à cette question est de constater que l’on a be-
soin, au maximum, de n couleurs pour colorer n surfaces, en attribuant une
couleur différente à chacune. Par conséquent, on sait qu’une coloration en n

17
couleurs existe. On peut appliquer l’algorithme A en lui demandant de trouver
une coloration en n − 1 couleurs, puis n − 2, etc. jusqu’à ce qu’il réponde qu’il
n’existe pas de coloration. On saura alors que la dernière valeur pour laquelle

20
l’algorithme a trouvé une solution correspond à une coloration optimale.
Une technique plus rapide est de procéder par dichotomie : plutôt que de
diminuer d’une unité à chaque appel de A, on maintient deux valeurs kmin
et kmax pour lesquelles on sait, respectivement, qu’il n’y a pas de coloration

e
admissible et qu’il en existe une. En éliminant le cas de la carte triviale qui n’a
pas de frontière, on sait que l’on peut démarrer avec kmin = 1 et kmax = n. On

Si la réponse est oui, on modifie kmax ← b br


demande à l’algorithme s’il existe une coloration en k = b kmin +k
kmin +kmax
2 c, si la
2
max

réponse
c couleurs.
est non,
em
kmin +kmax
on modifie kmin ← b 2 c. On répète le procédé jusqu’à ce que kmax =
kmin + 1, valeur qui correspond au nombre optimum de couleurs.

1.1.1 Programme linéaire


pt

La programmation linéaire est un outil extrêmement utile pour modéliser


se

mathématiquement de nombreux problèmes d’optimisation. On appelle pro-


grammation mathématique la recherche et l’analyse de problèmes pour les-
quels on veut déterminer un meilleur élément d’un ensemble pour lequel on
peut évaluer un critère quantitatif. Lorsque l’expression de ce critère est une
25

fonction linéaire et que l’ensemble peut être décrit au moyen de fonctions li-
néaires, on parle de programmation linéaire.
Un programme linéaire sous forme canonique s’écrit mathématiquement de
la manière suivante :
g

Maximiser z = c1 x1 + c2 x2 + . . .+ cn xn (1.1)
Al

a11 x1 + a12 x2 + . . .+ a1n xn 6 b1 (1.2)


Sous a21 x1 + a22 x2 + . . .+ a2n xn 6 b2
T_

contraintes ...
am1 x1 + am2 x2 + . . .+ amn xn 6 bm
xi > 0(i = 1, . . . , n) (1.3)

Dans le cas particulier où tous les coefficients cj , aij et bi sont positifs, une
interprétation du problème consiste à chercher des quantités xj à produire,
non négatives (1.3), chaque unité du produit j rapportant un revenu cj , de
sorte à maximiser le revenu global z (1.1). La production d’une unité du produit
j consomme des quantités aij de chaque ressource i, disponible en quantité
bi (contraintes 1.2).
12 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

La forme canonique de la programmation linéaire n’est pas limitative, en ce


sens que tout programme linéaire peut se mettre sous cette forme. En effet,
si l’objectif est de minimiser la quantité z, cela revient à maximiser −z ; si une
variable x peut être de signe quelconque, on peut la substituer par x00 − x0 ,
où x00 et x0 doivent être non négatifs ; finalement, si on a une contrainte avec
égalité ai1 x1 + ai2 x2 + · · · + ain xn = bi , elle peut être remplacée par les deux
contraintes ai1 x1 +ai2 x2 +· · ·+ain xn 6 bi et −ai1 x1 −ai2 x2 −· · ·−ain xn 6 −bi .
On peut modéliser le problème de la coloration d’une carte par un pro-
gramme linéaire un peu particulier. On introduit pour cela des variables yk qui

17
indiquent si la couleur k (pour k = 1, . . . , n) est utilisée (yk = 1) ou non (yk = 0)
ainsi que des variables xik qui indiquent si la surface i reçoit la couleur k. Le
programme linéaire en nombres entiers suivant permet de formaliser le pro-

20
blème de la coloration d’une carte :

n
X
Minimiser yk (1.4)

e
k=1
Sous contraintes
Xn
xik =
k=1 br
1 i = 1, . . . , n (1.5)
em
xik − yk 6 1 i, k = 1, . . . , n (1.6)
xik + xjk 6 1 (i, j) ont une frontière commune, (1.7)
k = 1, . . . , n
pt

xik , yk ∈ {0, 1} (1.8)


L’objectif (1.4) consiste à utiliser le nombre minimum de couleurs. Le pre-
se

mier ensemble de contraintes (1.5) impose que chaque sommet reçoive une
couleur exactement ; le second ensemble (1.6) que l’on n’attribue pas à un
sommet une couleur non utilisée ; et l’ensemble (1.7) empêche de donner
la même couleur à deux surface contigües. Les contraintes d’intégrité (1.8)
25

peuvent également s’écrire en faisant ressortir des inégalités linéaires (yk >
0, yk 6 1, yk ∈ Z).
La programmation linéaire est un outil de modélisation et de formalisa-
tion de problèmes très puissant. Lorsqu’il n’y a pas de contraintes d’intégrité
g

on peut résoudre efficacement des problèmes comportant des milliers de va-


Al

riables et des milliers de contraintes. Dans ce cas, la résolution est à peine plus
complexe que la résolution d’un système d’équations linéaires. La principale li-
mitation vient essentiellement de la place mémoire nécessaire au stockage des
T_

données ainsi que d’éventuels problèmes numériques pouvant survenir si les


données sont mal conditionnées.
En revanche, les programmes linéaires en nombres entiers, comme le pro-
blème de la coloration exprimé ci-dessus, sont en général difficile à résoudre et
on doit mettre en œuvre des techniques spécifiques dont les métaheuristiques
font partie.
Si la formulation d’un problème sous la forme d’un programme linéaire per-
met une modélisation rigoureuse, elle n’aide pas beaucoup notre cerveau dans
sa résolution. En effet, la vue est le plus important de nos sens. L’adage dit
qu’un petit dessin vaut mieux qu’un long discours. Les graphes sont une ma-
nière plus appropriée pour notre esprit de schématiser un problème. Avant de
1.1 O PTIMISATION COMBINATOIRE 13

17
20
F IGURE 1.2 – La Suisse et ses pays limitrophes que l’on désire colorer. Chaque pays est
symbolisé par un disque et un frontière communes est symbolisée par un trait reliant

e
entre les pays-disques correspondants. On obtient ainsi une représentation schéma-
tique du problème de coloration sous forme d’un graphe.

br
présenter d’autres modélisations du problème de coloration (voir section 2.9),
em
nous rappellerons très brièvement quelques définitions de la théorie des gra-
phes sur lesquelles le reste de l’ouvrage s’appuiera.
pt

1.1.2 Petit lexique sur les graphes


Les graphes sont un outil très utile pour modéliser des problèmes où l’on
se

a des éléments qui présentent des relations entre eux. On représente les élé-
ments par un point et si deux éléments sont en relation, on les relie par un seg-
ment. Ainsi, le problème de coloration d’une carte vu précédemment pourra se
25

schématiser par un petit graphe, comme illustré en figure 1.2.

Graphe non orienté, sommet, arête Un graphe non orienté G est une col-
lection d’éléments V appelés également sommets (« vertex » en globish) ou
g

nœuds et d’un ensemble E d’arêtes (« edge ») associées chacune à une paire


(non ordonnée) de nœuds qui en sont les extrémités. On note un tel graphe
Al

G = (V, E). Si v et w sont deux sommets reliés par une arête, on dit qu’ils
sont adjacents ou encore que cette arête est incidente avec v et w. Lorsque
T_

plusieurs arêtes relient la même paire de sommets, on a des arêtes multiples.


Lorsque les deux extrémités d’une arêtes sont confondues, on parle de boucle.
Lorsque V = ∅ (et donc E = ∅) on a le graphe nul. Lorsque V 6= ∅ et E = ∅
on a un graphe vide. Un graphe qui n’a ni boucle, ni arêtes multiples est un
graphe simple. Le graphe de la figure 1.2 est un exemple de graphe simple.

Graphe orienté, arc Dans certains cas, les relations entre les couples d’élé-
ments sont ordonnées. On parle alors de graphe orienté et les « arêtes orien-
tées » sont appelées des arcs. Il convient dès lors de distinguer les deux extré-
mités d’un arc en une extrémité initiale et une extrémité terminale ou finale. Un
arc dont l’extrémité initiale et terminale est confondue est également appelé
14 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

boucle, comme pour le cas non-orienté, de même que deux arcs qui ont les
mêmes extrémités initiales et terminales sont des arcs parallèles ou multiples.
Deux arcs a et b dont l’extrémité initiale de l’un est l’extrémité terminale de
l’autre et vice versa sont dit tête bêche ; dans ce cas, les arcs a et b ne forment
pas des arcs multiples.

Degré Le degré d’un sommet v d’un graphe non orienté, noté deg(v) est le
nombre d’arêtes incidentes à v. Une boucle augmente le degré d’un sommet
de 2. Un sommet de degré 1 est dit pendant. Un graphe est régulier si tous

17
ses sommets ont le même degré. Pour un graphe orienté, on parle de degré
sortant ou degré extérieur, noté deg + (v) le nombre d’arcs sortant du sommet
v. Le degré entrant ou degré intérieur, noté deg − (v) est le nombre d’arcs dont

20
l’extrémité finale est v.

Chaîne, chemin, cycle, circuit Une chaîne est une suite alternée de som-
mets et d’arêtes, débutant et finissant par un sommet, telle que chaque arête

e
est encadrée par ses deux extrémités. Un cycle est une chaîne dont les deux

br
extrémités sont identiques. Pour un graphe orienté, l’équivalent d’une « chaîne
orientée » est appelé chemin. Dans ce cas, chaque arc est encadré d’abord
par son extrémité initiale puis par son extrémité terminale. Un « cycle orienté »
em
est appelé un circuit.
La longueur d’une chaîne (ou d’un chemin) est le nombre d’arêtes (d’arcs)
qui la compose. Une chaîne (ou un chemin) est simple si une arête (un arc) n’y
apparaît pas plus d’une fois. Une chaîne (ou un chemin) est élémentaire si un
pt

sommet n’y apparaît pas plus d’une fois (à l’exception des extrémités).
se

Connexité Un graphe non orienté est connexe si toute paire de sommets


est reliée par une chaîne. Une composante connexe d’un graphe est un sous-
ensemble maximal de sommets avec une chaîne entre chaque paire de ses
25

sommets. Un graphe orienté est fortement connexe s’il existe un chemin entre
tout couple de sommet (de l’un vers l’autre et vice versa).

Arbre, graphe partiel, sous-graphe Un arbre est un graphe connexe sans


g

cycle. Les sommets pendants d’un arbre sont également appelés feuilles. Un
graphe sans cycle est une forêt (qui peut donc être composée de plusieurs
Al

arbres). Un « arbre orienté » tel qu’il existe un chemin d’un sommet r à tous les
autres est une arborescence de racine r.
T_

Si G = (V, E) et G0 = (V, E 0 ) avec E 0 ⊂ E, on dit que G0 est un graphe


partiel de G. Si G = (V, E) et G0 = (V 0 , E 0 ) avec V 0 ⊂ V et que E 0 comporte
toutes les arêtes de E qui ont leurs deux extrémités dans V 0 , on dit que G0
est un sous-graphe de G induit ou engendré par V 0 . Un arbre recouvrant d’un
graphe G est un graphe partiel de G qui est un arbre.

Graphe eulérien, hamiltonien Un graphe est eulérien s’il possède une


chaîne (ou un chemin, dans le cas orienté) passant par toute ses arêtes (ou
tous ses arcs) exactement une fois. Un graphe est hamiltonien s’il possède une
chaîne passant exactement une fois par chaque sommet du graphe. Certains
auteurs limitent les graphes eulériens ou hamiltoniens au cas où il existe un
1.1 O PTIMISATION COMBINATOIRE 15

cycle qui passe par toute les arêtes ou tous les sommets exactement une fois
(à l’exception du sommet de départ et d’arrivée, qui est confondu).

Graphes particuliers Un graphe simple non orienté est complet s’il existe
une arête entre toute paire de sommet. Un graphe G = (V, E) tel que V =
V1 ∪ V2 , V1 ∩ V2 = ∅ et toute arête de E a l’une de ses extrémités dans V1 et
l’autre dans V2 est biparti. Un graphe G = (V, E) tel que V = V1 ∪ V2 ∪ · · · ∪ Vm ,
Vi ∩ Vj = ∅ ∀i, j ∈ V et que pour tout arête de E, il existe un i tel que l’arête a
l’une de ses extrémités dans Vi et l’autre dans Vi+1 est un graphe en couches.

17
Une clique est un sous-ensemble des sommets d’un graphe qui induit un sous-
graphe complet. Un ensemble stable est un sous-ensemble de sommets non
adjacents deux à deux.

20
Coloration, couplage Le problème de la coloration des sommets d’un gra-
phe qui a été utilisé comme exemple introductif à la section 1.1 sur l’optimi-

e
sation combinatoire permet de définir le nombre chromatique d’un graphe G,
parfois noté χ(G), qui est le nombre minimum de couleurs nécessaires pour

br
colorer les sommets de G sans que deux sommets adjacents ne reçoivent la
même couleur. Le nombre de stabilité d’un graphe G, parfois noté α(G) est le
em
cardinal maximum d’un ensemble stable de G. L’indice chromatique d’un gra-
phe G, parfois noté q(G) est le nombre minimum de couleurs nécessaires pour
colorer les arêtes de G de sorte que deux arêtes incidentes ne reçoivent pas
la même couleur.
pt

Un couplage dans un graphe simple non orienté est un sous-ensemble


d’arêtes qui n’ont aucune extrémité commune. Un couplage est dit parfait s’il
est incident à tous les sommet du graphe. Un sous-ensemble des sommets
se

d’un graphe est un transversal s’il recouvre toutes les arêtes du graphe, c’est-
à-dire si chaque arête est incidente à au moins un sommet du transversal.
25

Réseau

Dans bien des cas, on veut associer une valeur à chaque arête ou à chaque
arc. La valeur w(e) ou poids de l’arête ou de l’arc e représentera typiquement
g

une distance, un débit ou un coût. Un réseau, noté R = (V, E, w) est un graphe


muni d’une pondération w : E → R. La longueur d’un chemin dans un réseau
Al

est la somme du poids de ses arcs.


T_

Flots Pour résoudre des problèmes de flot, on associe une limitation de débit
aux arcs d’un réseau, ou capacité wij > 0 entre les nœuds i et j. Un flot
d’un sommet-source s à un sommets-puits t dans un réseau R = (V, E, w) est
l’attribution d’un flux, ou quantité de flot xij telle que la somme des flux sortant
d’un
P sommet soitPégale à la somme des flux entrants (loi de conservation) :
i∈Succ(j) xij = k∈P red(i) xki ∀i ∈ V, i 6= s, t. La valeur du flot de s à t est
la somme des flux qui sortent de s (qui est identique à celle qui entre en t, en
raison de la loi de conservation). Lorsque 0 6 xij 6 wij ∀(i, j) ∈ E, le flot est
dit compatible ou admissible.
La séparation des sommets d’un réseau R = (V, E, w) en A ⊂ V et son
complémentaire A ⊂ V permet de définir une coupe ⊆ E de A vers A, qui est
16 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

l’ensemble des arcs qui ont leur extrémité initiale dans A et terminale dans A.
La capacité d’une coupe est la somme des poids des arcs de la coupe.
Les flots permettent de modéliser des problèmes qui n’ont, à première vue,
rien en commun avec des débits, comme par exemple les problèmes d’affec-
tation de ressources (voir par exemple la section 2.4.2). Plus loin dans ce cha-
pitre, nous passerons en revue quelques algorithmes bien connus et efficaces
pour la résolution de problèmes, comme la recherche d’un arbre, d’un chemin
ou d’un flot optimum dans un réseau. D’autres problèmes, comme celui de la
coloration de graphes, sont difficiles, et les seuls algorithmes connus pour les

17
résoudre prennent un temps qui peut croître exponentiellement avec la taille
du graphe.
La classification en problèmes faciles et difficiles ressort de la théorie de la

20
complexité. Les métaheuristiques ont été conçues pour trouver des solutions
acceptables avec un effort de calcul limité pour des problèmes en principe
difficiles. Avant d’élaborer un nouvel algorithme sur la base des principes des
métaheuristiques, il est essentiel de s’assurer que le problème traité est bien

e
difficile et qu’il n’existe pas déjà un algorithme efficace pour le résoudre. La
suite de ce chapitre expose quelques bases théoriques dans le domaine de la

br
classification des problèmes selon leur difficulté.
em
1.2 Éléments de théorie de la complexité
La théorie de la complexité a pour but de classer les problèmes afin de
pt

pouvoir prédire s’ils seront facile ou non à résoudre. Très grossièrement, en


se limitant à des méthodes de résolutions séquentielles, on considère qu’un
problème est facile si l’on connaît un algorithme dont l’exécution se réalise
se

avec nombre d’opérations limité par une fonction polynomiale du volume de


données à traiter. On peut d’emblée se poser la question de savoir pourquoi la
frontière de la difficulté doit se situer sur la classe des polynômes et pas sur
celle des fonctions logarithmiques, trigonométriques, ou encore exponentielles.
25

La raison est très simple : on conçoit parfaitement que l’on ait besoin de
plus d’opérations pour traiter un plus gros volume de données, ce qui élimine
les fonctions non croissantes, comme les fonctions trigonométriques. Si l’on
se limite aux méthodes séquentielles, on conçoit aisément que l’on doive lire
g

chaque donnée au moins une fois, ce qui implique une croissance au moins
Al

linéaire du nombre d’opérations, et l’élimination des fonctions logarithmiques,


racine carrée, etc. Il faut se rendre compte que dans le cas du traitement en
parallèle des données par plusieurs tâches, il est tout à fait raisonnable de défi-
T_

nir une classe de problèmes (très faciles), demandant un nombre d’opérations


et une mémoire par processeur croissant au plus logarithmiquement avec le
volume des données. Un exemple de tels problèmes est l’extraction du plus
grand des nombres d’un ensemble.
Finalement, il faut considérer le fait qu’une fonction exponentielle (soit au
sens mathématique telle que 2x , mais aussi des extensions telles que xlog(x) ,
x! ou xx ) finissent toujours par croître plus rapidement que n’importe quel
polynôme, et cette croissance est réellement impressionnante. On peut citer
l’exemple d’un algorithme qui nécessiterait 350 opérations pour un problème
avec 50 données, et qui s’exécuterait sur une machine capable de réaliser
109 opérations à la seconde : dans ce cas, la machine ne finirait son travail
1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 17

qu’après 23 millions d’années. Par comparaison, la résolution d’un problème


de taille 10, donc 5 fois plus petit, avec le même algorithme ne prendrait que
60µs. Ainsi, il ne serait pas raisonnable en pratique de considérer comme facile
des problèmes nécessitant un nombre exponentiel d’opérations pour être réso-
lus. Or, les problèmes combinatoires ont un nombre exponentiel de solutions.
Par conséquent, les algorithmes d’énumération complète, parfois qualifiés de
« force brute », ne peuvent pas raisonnablement être considérés comme ac-
ceptables. Ainsi, le calcul d’un plus court chemin entre deux sommets d’un
réseau ne se résout pas en énumérant l’ensemble des chemins (il y en a un

17
nombre exponentiel) et en isolant le plus court, mais à l’aide d’algorithmes
faisant appel à des propriétés mathématiques du plus court chemin. Ces al-
gorithmes effectuent un nombre d’opérations polynomial en la taille du réseau.

20
Le problème de la recherche d’un plus court chemin est donc un problème
simple. Par contre, la recherche d’un plus long (ou d’un plus court) chemin
simple ou élémentaire (sans boucles ou sans passer deux fois par le même
sommet) entre deux sommets est un problème difficile, car on ne connaît pas

e
d’algorithme polynomial pour le résoudre.
Pour terminer, il faut mentionner que la classe des polynômes présente

br
une propriété mathématique intéressante : elle est fermée. La composition de
deux polynômes est encore un polynôme. Pratiquement, dans le contexte de
em
la programmation, cela signifie que si à l’intérieur d’un algorithme, on utilise un
nombre polynomial de fois un sous-algorithme, lui-même polynomial, le nom-
bre total d’instructions effectuées par tous les appels du sous-algorithme est
encore polynomial.
pt

1.2.1 Complexité algorithmique


se

Il ne faut pas confondre théorie de la complexité et complexité algorith-


mique. Comme déjà mentionné, la théorie de la complexité a pour objet la
classification des problèmes. La complexité algorithmique a pour but d’évaluer
25

les ressources nécessaires à l’exécution d’un algorithme donné. Il est donc


possible de mettre au point un algorithme de complexité élevée pour un pro-
blème appartenant à une classe de complexité « simple ». Pour pouvoir mettre
un problème dans une classe de complexité, on ne supposera pas que l’on
g

utilise un algorithme donné pour résoudre ce problème, mais on analysera les


Al

performances du meilleur algorithme possible — pas forcément connu — pour


ce problème et s’exécutant sur un type de machine donné.
Il ne faut pas non plus confondre la simplicité d’un algorithme (exprimé par
T_

exemple par le nombre de lignes de code nécessaires pour l’implanter) et sa


complexité. En effet, un algorithme simple peut être de complexité élevée. Par
exemple, pour tester si un nombre entier p est premier, on peut essayer de le

diviser par tous les nombres entiers entre 2 et p, si aucun de ces nombre ne
mène à une division sans reste, on peut en conclure que p est premier. Sinon,
on dispose d’un certificat (un diviseur de p) prouvant que p n’est pas premier.
Cet algorithme n’est cependant pas polynomial en la taille des données : en
effet, il suffit de n = log2 (p) bits pour représenter le nombre p. L’algorithme
nécessite donc un nombre de divisions proportionnel à 2n/2 , ce qui n’est pas
polynomial. Or, on a prouvé en 2002 qu’il existe un algorithme polynomial per-
mettant de détecter si un nombre p est premier. Comme on peut s’en douter,
18 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

cet algorithme n’est pas vraiment élémentaire ; son analyse et son élaboration
constituent même des tâches aux limites des capacités humaines. Donc, tester
si un nombre est premier est un problème simple (car il existe un algorithme
polynomial pour le résoudre), mais l’algorithme en question est toutefois dif-
ficile à implanter et requerrait un temps de calcul prohibitif pour montrer que
243112609 − 1 est premier. Inversement, il peut exister des algorithmes qui en
théorie pourraient dégénérer mais qui se comportent tout-à-fait bien en pra-
tique, comme l’algorithme du simplexe en programmation linéaire.
Les ressources utilisées pour durant l’exécution d’un algorithme sont limi-

17
tées. Elles sont de plusieurs types : nombre de processeurs, place mémoire,
temps. En se restreignant à cette dernière ressource, si l’on désire mesurer
l’efficacité d’un algorithme, on pourrait évaluer sa durée d’exécution sur une

20
machine donnée. Malheureusement, cette mesure présente de nombreuses
faiblesses. Tout d’abord, elle est relative à une machine particulière, dont la
durée de vie est limitée à quelques années. Ensuite, la manière dont l’algo-
rithme a été implanté (langage de programmation, compilateur, options, sys-

e
tème d’exploitation) peut influencer énormément son temps d’exécution. Par
conséquent, on préfère mesurer le nombre d’opérations caractéristiques qu’un

br
algorithme va effectuer. En effet, ce nombre ne dépend pas de la machine ou
du langage et peut parfaitement s’évaluer théoriquement.
em
On appelle complexité d’un algorithme une fonction f (n) qui donne le nom-
bre d’opérations caractéristiques exécutées dans le pire des cas lorsqu’il s’exé-
cute sur un problème dont le volume des données est n. Il faut mentionner que
cette complexité n’a rien à voir avec la longueur du code ou la difficulté de
pt

programmation et que l’on ne se préoccupe que rarement du nombre moyen


d’opérations, car ce nombre est en général malaisé à évaluer. En effet, il fau-
drait faire la moyenne sur tous les jeux de données possibles. De plus, l’éva-
se

luation du pire des cas est très importante dans les applications où le temps
de réponse est critique.
25

1.2.2 Notation de Bachmann-Landeau


Pour évaluer le nombre d’opérations qu’effectuera un algorithme sur un jeu
de données dont le volume est n, on se contente en pratique d’une évalua-
g

tion grossière par surestimation. Supposons que deux algorithmes, A1 et A2


effectuent, respectivement pour un même problème de taille n, f (n) = 10n2 et
Al

g(n) = 0, 2 · n3 opérations. Il est clair que pour un jeu de données avec n = 10,
A1 effectue 5 fois plus d’opérations que A2 . Par contre, dès que n > 50, c’est
T_

A2 qui en fera le plus. En réalité, quels que soient les cœfficients positifs de
n2 et n3 dans f (n) et g(n), la fonction g sera plus grande que f à partir d’un
certain n. On appelle ordre la croissance asymptotique d’une fonction.

Définition Si f et g sont deux fonctions réelles d’une variable réelle x, on dit


que f est d’ordre inférieur ou égal à g s’il existe deux réels positifs x0 et c tels
que ∀x > x0 , f (x) 6 c · g(x).
Cela signifie que g devient plus grande que f à partir d’un certain nom-
bre x0 , à un facteur constant c près. Ceci est noté à l’aide de la notation de
Bachmann-Landau ou notation grand O : f est en O(g) ou encore f ∈ O(g).
L’intérêt pratique de cette notation est qu’il est souvent aisé de trouver une
1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 19

fonction g qui majore asymptotiquement la fonction exacte f (inconnue ou dif-


ficile à évaluer) donnant le nombre d’opérations d’un algorithme. On dira que
cet algorithme est en O(g).
Parfois, on ne se préoccupe pas du pire des cas, mais du meilleur des cas.
On écrit alors f ∈ Ω(g) lorsque l’on sait que le nombre f d’opération sera d’un
ordre supérieur à g.
Mathématiquement, f ∈ Ω(g) si ∀x > x0 , f (x) > c · g(x), ce qui est équi-
valent à g ∈ O(f ). Cette notation est utile en particulier pour montrer qu’un al-
gorithme A est moins performant qu’un autre B (e.g. B effectue dans le meilleur

17
des cas au moins autant d’opérations que A n’en effectue dans le pire des cas)
ou qu’un algorithme C est optimal (e.g. C résout un problème en effectuant dans
le pire des cas un nombre d’opérations pas plus grand que le minimum qui est

20
requis par n’importe quel algorithme pour résoudre ce problème).
Si le meilleur et le pire des cas sont les mêmes, c’est-à-dire si ∃0 < c1 < c2
tel que c1 · g(n) 6 f (n) 6 c2 · g(n) alors on notef ∈ Θ(g). Il faut bien différencier
la notation Θ(·) d’une notion (souvent mal définie) de complexité moyenne : en

e
effet, si l’on prend l’algorithme de tri rapide de n éléments, on peut dire qu’il
sera en Ω(n) et en O(n2 ), mais pas en Θ(n · log(n)), même si en moyenne il
prend un temps proportionnel à n · log(n).
br
Cependant, on peut montrer que l’espérance du temps de calcul de l’algo-
em
rithme de tri rapide pour un ensemble de n éléments aléatoirement mélangés
est proportionnelle à (n · log(n)). Les notations O(·) (espérance ou moyenne
théorique) et Ô(·) (moyenne empirique) seront utilisées plus loin, tout en souli-
gnant qu’elles ne sont pas couramment utilisées car on doit spécifier sur quel
pt

ensemble de problèmes on prend la moyenne, quelle est la probabilité d’appa-


rition de chaque exemple de problème, etc.
En mathématiques, et plus rarement en informatique, on rencontre des no-
se

tations petit o et associées , qui ont pour définition :


g(x)
— f ∈ o(x) si limx→∞ f (x) >0
f (x)
25

— f ∈ ω(g) si limx→∞ g(x) >0


f (x)
— f ∼ g si limx→∞ g(x) =1
Exprimer la complexité d’un algorithme à l’ordre près présente de multiples
g

avantages :
Al

— f ∈ O(g) signifie que la fonction g est un majorant de la complexité réelle,


ce qui permet souvent de trouver, par un calcul grossier et sommaire une
fonction g, alors que la déduction de f ∈ Θ(g) aurait été beaucoup plus
T_

complexe.
— 25n3 = O(3n3 ) et 3n3 = O(25n3 ), ce qui signifie que deux fonctions
différant uniquement par un facteur sont du même ordre, ce qui permet
de s’affranchir des vitesses relatives des calculateurs. Plutôt que d’écrire
O(25n3 ), on écrira donc O(n3 ), ce qui est équivalent et plus simple.
— 3n3 + 55n = O(n3 ), ce qui implique que l’on peut négliger les termes
d’ordre inférieur et ne retenir que la puissance la plus élevée.
Il est important d’insister sur le fait que la complexité d’un algorithme est
une notion théorique, qui se dérive par réflexion et calculs qui peuvent être
faits avec une feuille et un crayon. Cette complexité s’exprime généralement
20 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

αΩ
O(n!)

O(2n )
O(n3 )
S˚ O(n2 )
O(n log n)
h O(n)

17
s
O(log n)

20
µs O(1)

e
ns 1 2 3 4 5 6 7 8 9 10 11 12 13 14
10 10 10 10 10 10 10 10 10 10 10 10 10 10 1015

br
F IGURE 1.3 – Illustration de la croissance de quelques fonctions souvent utilisées pour
em
exprimer la complexité d’un algorithme. L’axe horizontal donne la taille du problème
(avec une croissance exponentielle) et l’axe vertical donne l’ordre de grandeur du temps
de calcul (avec une croissance bi-exponentielle).
pt

au moyen de l’ordre du temps de calcul (ou d’un nombre abstrait d’opérations


se

effectuées par un processeur virtuel) en fonction de la taille du problème. Par


ordre croissant, les complexités que l’on rencontre le plus fréquemment sont :
O(1) (constante), O(log(n)) (logarithmique ; on ne spécifie pas la base du lo-
25

garithme, car O(loga (n)) = O(logb (n)) ), O(nc ) (puissance fractionnaire ; avec
0 < c < 1), O(n) (linéaire), O(n · log(n)) (log-linéaire ou quasi-linéaire), O(n2 )
(quadratique), O(n3 ) (cubique), O(nc ) (polynomial ; avec c > 1 constante),
O(nlog(n) ) (quasi-polynomial ; super-polynomial, sous-exponentiel), O(cn ) (ex-
g

ponentiel, avec c > 1 constante), O(n!) (factoriel). La figure 1.3 illustre la crois-
sance de quelques-unes de ces fonctions.
Al

1.2.3 Classes de complexité de base


T_

La théorie de la complexité est une branche qui s’est considérablement


développée depuis le début des années 70, lorsque Cook a montré qu’il exis-
tait un problème qui, si l’on était capable de le résoudre en temps polynomial,
permettrait d’en résoudre un grand nombre d’autres efficacement, comme le
voyageur de commerce, la programmation linéaire en nombres entiers, la co-
loration de graphes, etc.
Pour arriver à ce résultat, il a fallu formuler en termes mathématiques ce
qu’est un problème, comment fonctionne un ordinateur et préciser comment
le temps de calcul peut être mesuré. Pour alléger au maximum cette théorie,
on a simplifié le plus possible les concepts, à commencer par le types de pro-
1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 21

blèmes considérés. Ici, on se restreindra donc aux problèmes de décision. Un


problème de décision est formalisé par un problème générique et une ques-
tion ; la réponse à ce problème est soit « oui », soit « non ».

Exemple de problème générique : Soit C = {c1 , . . . , cn } un ensemble


de n villes et des distances dij entières entre les villes ci et cj . Soit une borne
B.
On devine ici un problème associé à celui du voyageur de commerce, qui
est certainement le problème difficile d’optimisation combinatoire le plus connu.

17
Cependant, comme on veut se restreindre à un problème de décision, la ques-
tion posée ne sera pas « quelle est la tournée de longueur minimum », mais

20
Question : Existe-t-il un tour passant par toutes les villes de C et n’ayant
pas une longueur supérieure à P B ? (i.e. trouver σ, une permutation des élé-
n−1
ments 1, 2, ?, n telle que dσn ,1 + i=1 dσi , dσi+1 6 B. )

e
br
Schéma de codage, langage et machine de Turing déterministe

Un exemple de problème (appelé parfois une « instance », suite à une mau-


em
vaise traduction) consistera en une variable de ce type, variable qui devra être
contrainte. Plus généralement, on peut représenter ce problème sous la forme
d’un fichier de texte. Il faut alors utiliser certaines conventions, par exemple
donner sur la première ligne n, le nombre de villes, la borne B sur la seconde
pt

et chacune des suivantes contiendra trois nombres, interprétés comme i, j et


dij . En d’autres termes, on utilise un schéma de codage.
se

Formellement, en prenant des notations de la théorie des langages, proches


de celles utilisées en techniques de compilation (grammaires formelles), on a
un ensemble fini de symboles ou alphabet Σ. On désignera par Σ∗ l’ensemble
des chaînes finies construites avec l’alphabet Σ. Un schéma de codage e, pour
25

un problème génériqueπ, permet de décrire tout exemple I de π par une chaîne


x de Σ∗ . Par exemple, pour le voyageur de commerce, I contient les coeffi-
cients dij ainsi que la borne B.
Relativement à un problème π et à un schéma de codage e, les chaînes de
g

Σ∗ peuvent être partitionnées en trois classes :


Al

1. Les chaînes qui ne codent pas un exemple I de π.


2. Les chaînes qui codent un exemple I de π pour lequel la réponse est
« non ».
T_

3. Les chaînes qui codent un exemple I de π pour lequel la réponse est


« oui ».
Cette dernière classe est appelée le langage associé à π et à e et est
notéL(π, e).
En informatique théorique ou plus précisément en théorie des automates,
on étudie la puissance de calcul de divers modèles de calculateurs. Parmi les
automates les plus simples, on trouve les automates à états fini, qui sont par
exemple utilisés pour mettre au point ou analyser un protocole de communica-
tion. Ils sont constitués d’états, représentés par les sommets d’un graphe et de
transitions, représentées par des arcs. Lorsqu’on lui fournit un mot en entrée,
22 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

l’automate passe d’un état à un autre selon la lettre du mot en cours de lecture
et des transitions associées. Comme un tel automate a un nombre fini d’états,
cette machine a donc une mémoire bornée.
Un modèle un peu plus complexe est un automate à pile, fonctionnant de fa-
çon semblable à une machine à états finis mais disposant d’une pile. À chaque
étape on lit une lettre du mot ainsi que le symbole en sommet de pile (si elle
n’est pas vide) et on se met dans un nouvel état, en empilant au besoin un
nouveau symbole en sommet de pile. Ce type d’automate permet de faire des
calculs un peu plus complexes, par exemple reconnaître les mots d’un langage

17
non contextuel (e.g. effectuer l’analyse syntaxique d’un programme décrit par
une grammaire de type 2). Un modèle de calculateur plus puissant qu’un auto-
mate à pile est la machine de Turing.

20
Machine de Turing déterministe Pour pouvoir représenter mathématique-
ment le fonctionnement d’un ordinateur, Allan Turing a imaginé en 1936 une

e
machine fictive (il n’existait pas d’ordinateurs à cette époque) dont le fonction-
nement peut être modélisé par une fonction de transition. Avec cette machine,

br
il est possible de mettre en œuvre tous les algorithmes usuels ou de recon-
naître en un temps fini un mot généré par une grammaire générale de type 0.
La figure 1.4 illustre une telle machine, composée d’un programme qui com-
em
mande le défilement d’une bande magnétique ainsi qu’une tête de lecture et
d’écriture.
pt

Programme δ
se

État
25

Tête de lecture-écriture
Bande infinie
··· b b b b 1 1 0 0 0 0 1 0 1 1 0 0 1 0 1 1 0 b b ···
g

-2 -1 0 1 2 3 4
Al

Cases

F IGURE 1.4 – Schéma de principe d’une machine de Turing, qui permet de modéliser et
T_

de formaliser un calculateur

Un programme pour machine de Turing déterministe est spécifiée par :


1. Un alphabet de bande Γ, qui est un ensemble de symboles pouvant être
écrits sur la bande. Γ contient en particulier Σ, l’ensemble des symboles
utilisés pour coder un problème, ainsi qu’un symbole spécial b (blanc)
n’appartenant pas à Σ et éventuellement d’autres symboles de contrôle.
2. Un ensemble d’états Q, comportant au moins trois éléments particuliers
q0 , qY et qN , représentant respectivement l’état initial de la machine et les
1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 23

états finaux correspondant à la réponse « oui » et « non » de l’exemple


de problème.
3. Une fonction de transition δ : Q \ qY , qN × Γ → Q × Γ × −1, 1.
Cette fonction représente les actions que doit effectuer la machine lors-
qu’elle se trouve dans un certain état et qu’elle lit un certain symbole. Une
machine de Turing fonctionne comme suit : Elle se trouve dans l’état initial
q0 , sa tête de lecture et d’écriture est placée sur la case 1 ; la bande contient
la chaîne x ∈ Σ∗ dans les cases 1 à |x| et b pour toutes les autres cases.

17
Soit q, l’état courant de la machine, σ le symbole lu sur la bande ainsi que
(q 0 , σ 0 , ∆) = δ(σ, q). Un pas de la machine consiste à :
— Effacer σ sur la bande et écrire σ 0 à la place.

20
— Déplacer la tête de lecture d’une case à gauche si ∆ = −1 et d’une case
à droite si ∆ = 1.
— Se mettre dans l’état q 0 .

e
La machine s’arrête lorsqu’on se trouve dans l’un des deux états qY ou qN .
C’est pour cette raison que la fonction de transition δ n’est définie que pour les
états non finaux de la machine.
br
Bien que très simple au niveau conceptuel, une machine de Turing permet
em
de représenter schématiquement tout ce qui se passe dans un ordinateur cou-
rant, contrairement à d’autres modélisations de machines plus simples, comme
les automates à états finis (qui n’ont qu’une tête de lecture se déplaçant tou-
jours dans le même sens) ou les automates à pile. Ces machines permettent
pt

tout de même d’analyser des expressions régulières ou des grammaires indé-


pendantes du contexte, ce qui est suffisant pour créer un analyseur syntaxique.
se

Exemple de programme Soit la machine M = (Γ, Σ, Q, δ) :


Γ = 0, 1, b
Σ = 0, 1
25

Q = q0 , q1 , q2 , q3 , qY , qN

Symbole σ sur la bande


g

État 0 1 b
(q1 , b, −1)
Al

q0 (q0 , 0, 1) (q0 , 1, 1)
q1 (q2 , b, −1) (q3 , b, −1) (qN , b, −1)
q2 (qY , b, −1) (qN , b, −1) (qN , b, −1)
T_

q3 (qN , b, −1) (qN , b, −1) (qN , b, −1)

Tableau 1.1 – Spécification de la fonction de transition δ d’une machine de Turing.

Classe P des langages

La classe P (pour « polynomial ») contient les problèmes que l’on considère


comme faciles, c’est-à-dire ceux dont on connaît un algorithme dont l’exécu-
tion effectuera un nombre d’opérations limité à un polynôme en la taille des
données représentant le problème. Plus formellement, cette classe est définie
24 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

de la manière suivante : On dit que la machine M accepte x ∈ Σ∗ si, et seule-


ment si M s’arrête dans l’état qY . Le langage reconnu par M est l’ensemble
des chaînes x ∈ Σ∗ telles que M accepte x. On peut vérifier dans l’exemple de
programme donné par le tableau 1.1 que le langage reconnu par la machine
sont les chaînes qui codent en binaire un nombre divisible par 4 (bits de poids
fort au début).
Un algorithme est un programme qui s’arrête pour toute chaîne x ∈ Σ∗ . Le
temps de calcul d’un algorithme est le nombre de pas effectués par la machine
avant arrêt. La complexité d’un programme M , est le temps de calcul maximum

17
TM (n) que la machine a besoin pour s’arrêter, quelle que soit la chaîne x de
longueur n écrite sur la bande initialement. On dit qu’un programme pour ma-
chine de Turing déterministe est en temps polynomial s’il existe un polynôme p

20
tel que TM (n) 6 p(n)
La classe P des langages comprend tous les langages L tels qu’il existe
un programme pour machine de Turing déterministe reconnaissant L en temps
polynomial. Par abus de langage, on dira que le problème π appartient à la

e
classe P si le langage associé à π et à un schéma de codage e (non spécifié
mais supposé raisonnable) appartient à P . Lorsque l’on utilise l’expression « il

br
existe un programme », on fait en quelque sorte l’hypothèse que l’on dispose du
meilleur programme possible pour ce problème, mais sans forcément connaître
em
ce programme. Inversement, si l’on connaît un programme — pas forcément le
meilleur — s’exécutant en temps polynomial pour ce problème, alors on peut
affirmer que le problème fait partie de la classe de complexité P .
pt

Classe N P des langages


se

La classe N P (pour « polynomial non déterministe ») des langages com-


prend tous les problèmes pour lesquels on peut vérifier en temps polynomial
qu’une solution donnée produit la réponse « oui ». Pour qu’un problème fasse
partie de cette classe, les exigences sont moins grandes que pour la classe
25

P , puisqu’on ne demande pas de pouvoir trouver une solution en temps po-


lynomial, mais seulement de pouvoir vérifier en temps polynomial l’exactitude
d’une solution donnée. Pratiquement, cette classe contient des problèmes dif-
ficiles, pour lesquels on ne connaît pas d’algorithme de résolution en temps
g

polynomial en la taille des données.


Al

Afin de formaliser cette définition, les théoriciens de l’information ont ima-


giné un nouveau type de calculateur théorique, la machine de Turing non dé-
terministe, qui n’a pas son équivalent matériel dans le monde dans lequel nous
T_

vivons. Conceptuellement, cette machine est composée d’un module qui de-
vine la solution du problème et l’écrit sur les cases de la bande d’indices né-
gatifs (voir la figure 1.5). Cet artifice permet de s’affranchir de notre ignorance
d’un algorithme efficace pour résoudre un problème : la machine le devine.
La spécification d’un programme pour machine de Turing non déterministe
est identique à celle d’une machine déterministe. Initialement la machine se
trouve dans l’état q0 , la bande contient la chaîne x codant le problème dans les
cases 1 à |x| de la bande et le programme est inactif. Suit alors une phase divi-
natoire durant laquelle le module écrit des symboles aléatoires dans les cases
négatives et s’arrête arbitrairement. Ensuite, le programme de la machine s’ac-
tive et elle fonctionne comme une machine de Turing déterministe.
1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 25

Programme δ
Module divinatoire
État

Tête d’écriture Tête de lecture-écriture

17
Bande infinie
··· b b 1 0 1 1 0 0 0 0 1 0 1 1 0 0 1 0 1 1 0 b b ···
-2 -1 0 1 2 3 4

20
Cases

F IGURE 1.5 – Schéma de principe d’une machine de Turing non déterministe, qui per-
met de de formaliser la classe N P mais n’existe pas dans la réalité

e
br
Avec une telle machine, il est clair qu’une chaîne donnée x peut engendrer
divers calculs, à cause du caractère non déterministe de la phase divinatoire.
em
Un problème ayant une solution peut engendrer des exécutions se terminant
par l’état qN de la machine, ou des exécutions de diverses durées se terminant
par l’état qY (mais la machine ne peut pas terminer dans l’état qY pour un
problème n’ayant pas de solution). Le langage LM reconnu par la machine M
pt

est par définition l’ensemble des chaînes x ∈ Σ∗ telles qu’il existe au moins un
calcul pour lequel la chaîne x est acceptée. Le temps de calcul TM (n) est le
se

nombre minimum de pas qu’effectue la machine pour accepter une chaîne x de


longueur n. Le nombre de pas de la phase divinatoire n’est pas comptabilisé.
La complexité d’un programme est définie de manière similaire à la définition
pour une machine déterministe.
25

La classe NP des langages est formellement définie comme étant l’en-


semble des langages L pour lesquels il existe un programme M pour machine
de Turing non déterministe reconnaissant L en temps polynomial. Il convient
d’insister sur le fait que la dénomination de cette classe vient de l’abréviation
g

anglophone « Non-deterministic Polynomial » et n’a nullement « non polyno-


mial » pour origine.
Al

Théorème : Si π est dans N P , il existe un polynôme p(n) tel que π peut être
T_

résolu par une machine de Turing déterministe en O(2p(n) ).


Ce théorème dit que l’on peut résoudre avec une machine ordinaire tous
les problèmes de la classe N P , mais en un temps exponentiel en la taille des
données. Sa démonstration est très simple, il suffit de considérer que le temps
de vérification d’une solution potentielle est majoré par un polynôme q(n) et de
compter le nombre de chaînes devinables. Si l’on sait qu’il existe une solution
pour laquelle la machine s’arrête en q(n) étapes au plus, cela signifie que la
longueur d’une solution est également bornée par q(n). Par conséquent, le
nombre de chaînes devinables est donné par |Γ|q(n) et le temps de calcul par
q(n) · |Γ|q(n) . Comme q(n) < |Γ|n , on peut écrire q(n) · |Γ|q(n) < |Γ|q(n)+n <
0
|Γ|q (n) pour un certain polynome q 0 (n). En choisissant q 0 (n) · log2 (|Γ|) = p(n),
26 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

∝T (n)
Problème 1 Problème 2
Codage
f (Donnees1)
Données 1 Données 2

Résolution

Résultat 1 Résultat 2

17
Reconstruction
F IGURE 1.6 – Transformation en temps T (n) d’un problème 1 vers un problème 2. Dans
la pratique seule sont réalisées les opérations marquées par les flèches pleines.

20
0 0
on a |Γ|q (n) = 2q (n)·log2 (|Γ|) , d’où le résultat.

e
br
Transformation polynomiale : La notion de transformation polynomiale d’un
premier problème en un second problème est fondamentale en théorie de la
complexité, car elle est d’une grande utilité pour la classification des problèmes.
em
En effet, si l’on sait — ou, pour les problèmes difficiles : si l’on savait — ré-
soudre efficacement le second problème et que le premier peut se mettre sous
la forme du second par une transformation peu coûteuse en ressources de
calcul, alors on peut aussi résoudre efficacement le premier problème.
pt

Formellement, on dit qu’un premier langage L1 ⊂ Σ∗1 se transforme polyno-


mialement en un second langage L2 ⊂ Σ∗2 s’il existe une fonction f : Σ∗1 → Σ∗2 ,
se

évaluable en temps polynomial par une machine de Turing déterministe, telle


que pour tout exemple de problème x ∈ Σ∗1 dont la réponse est « oui », f (x) est
un exemple du second problème avec réponse « oui ». Une telle transformation
polynomiale est notée L1 ∝ L2 ; si l’on désire spécifier le temps T (n) néces-
25

saire pour évaluer la fonction f , on peut noter la transformation L1 ∝T (n) L2 .


La figure 1.6 illustre le principe d’une transformation d’un problème vers un
autre. Dans la définition d’une transformation, on ne se préoccupe que de la
complexité de l’évaluation de la fonction f et du fait que les réponses « oui-
g

non » des deux problèmes soient les mêmes. La complexité de la résolution du


problème 2 ou celle de la reconstruction d’une solution du problème 1 à partir
Al

de celle du problème 2 n’entre pas en considération.


T_

Exemple de transformation polynomiale : On considère les deux pro-


blèmes suivants : le parcours hamiltonien dans un graphe (un cycle passant
une, et une seule fois par tous les sommets du graphe) et un problème de
voyageur de commerce de longueur bornée B dans un réseau (existe-t-il un
cycle passant une, et une seule fois par tous les sommets du réseau et de
poids ne dépassant pas B). La fonction f permettant de transformer le graphe
du parcours hamiltonien en un exemple de voyageur de commerce construit
un réseau complet sur le même ensemble de sommets que pour le graphe,
en associant un poids de 0 aux arêtes existant dans le graphe et un poids de
1 aux arêtes qui n’existent pas dans le graphe. La borne B est égale à 0. Il
n’existe une solution de longueur 0 au problème du voyageur de commerce
1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 27

que si, et seulement s’il existe un parcours hamiltonien dans le graphe initial.
On en déduit que le problème du parcours hamiltonien peut se transformer en
un problème de voyageur de commerce. Il faut noter que l’inverse n’est pas
forcément vrai.

Classe NP-Complet

On dit qu’un problème π fait partie de la classe de complexité NP-complet


si le problème appartient à la classe N P et que tout problème de la classe N P

17
peut se transformer polynomialement en π.

Théorèmes : En partant de la définition d’une transformation polynomiale et

20
en constatant que la composition de deux polynômes est encore un polynôme,
on peut énoncer quelques théorèmes dont la démonstration est évidente.
— Si π est NP-complet et si π peut être résolus en temps polynomial, alors

e
P = NP.
— Si π est NP-complet et si π n’appartient pas à la classe P , alors P 6= N P .

br
— Si π1 se transforme polynomialement en π2 et π2 se transforme polyno-
mialement en π3 , alors π1 se transforme polynomialement en π3 .
em
— Si π1 est NP-complet, π2 appartient à la classe N P et π1 se transforme
polynomialement en π2 , alors π2 est NP-complet.
On ne connaît pas de problème NP-complet qui se résolve en temps po-
pt

lynomial. On conjecture qu’il n’en existe pas. La dernière propriété énoncée


ci-dessus est très souvent utilisée pour montrer qu’un problème π2 , de com-
se

plexité a priori inconnue, est NP-complet. Pour cela, on choisit un problème π1


dont on sait qu’il est NP-complet et on montre comment on peut transformer
polynomialement n’importe quel exemple de π1 en un exemple de π2 .
25

Théorème de Cook (1971)

La définition de la classe NP-complet présentée ci-dessus est purement


théorique. Il pourrait s’avérer que l’on n’ait construit que du vent et que cette
g

classe de complexité soit vide ! Il convient donc de se poser la question : existe-


t-il au moins un problème appartenant à cette classe ? Il est en effet loin d’être
Al

évident de trouver un problème « universel » de N P tel que tous les autres


problèmes de N P puissent se transformer polynomialement en ce problème.
T_

Il n’est pas possible d’imaginer quels sont tous les problèmes de N P , et en-
core moins de trouver une transformation pour chacun d’eux vers le problème
universel. Or, un tel problème existe, et le premier pour lequel on a démontré
qu’il était N P -complet est le problème d’acceptabilité. À partir de ce résultat,
on a réussi à montrer que tout un ensemble de problèmes faisaient aussi par-
tie de la classe NP-complet, en utilisant le principe énoncé dans la remarque
ci-dessus.

Problème d’acceptabilité : Soit un ensemble u1 , . . . um de variables boo-


léennes. On appel littéral une variable ou sa négation et une clause un en-
semble de littéraux reliés entre eux par un « ou » logique. Une clause sera
28 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

fausse si, et seulement si tous ses littéraux sont faux. Un problème d’accepta-
bilité est un ensemble de clauses reliées entre elles par des « et » logiques. Un
exemple de problème d’acceptabilité aura pour réponse « oui » s’il existe une
affectation de valeurs aux variables booléennes telles que toutes les clauses
du problème soient simultanément vraies. Par exemple (u1 ∨ u2 ) ∧ (u1 ∨ u2 ) est
un exemple de problème acceptable. Par contre, (u1 ∨u3 )∧(u1 ∨u3 )∧(u1 )∧(u2 )
n’est pas un exemple acceptable.

Démonstration du théorème de Cook : Pour montrer que le problème d’ac-

17
ceptabilité est NP-complet, il faut tout d’abord vérifier que ce problème soit
dans N P , ce qui est évident. Ensuite, il faut montrer que tout problème de
N P peut se transformer polynomialement en un problème d’acceptabilité. Une

20
telle transformation ne peut se faire explicitement, car on ne peut pas prendre
individuellement tous les problèmes de N P et leur trouver une transformation
adéquate, premièrement parce que le nombre de problèmes de N P est infini et
deuxièmement parce que trouver une transformation directe pourrait être très

e
difficile. Au lieu de cela, on montre implicitement qu’une telle transformation

br
existe, cette transformation pouvant être inconnue.
Pour prouver que cette transformation existe, on part de la définition de la
classe N P . Si un problème π appartient à cette classe de complexité, c’est
em
qu’il existe un programme en temps polynomial pour machine de Turing non
déterministe reconnaissant π. Cette machine est spécifiée par son alphabet de
bande, son ensemble d’états et la fonction δ de transition. Si l’on veut montrer
que π peut se transformer polynomialement en un problème d’acceptabilité, il
pt

faut trouver une fonction f qui, appliquée à π créera un exemple de problème


d’acceptabilité qui sera acceptable si, et seulement s’il existe une exécution
se

de la machine qui se termine dans l’état qY . Dans la mesure où l’on ne fait


aucune supposition sur le problème π autre qu’il appartienne à N P , on aura
ainsi prouvé que tout problème de N P peut se transformer polynomialement
en un problème d’acceptabilité, donc, par définition, que ce problème est NP-
25

complet.
La construction de cette fonction f se fait par six groupes de clauses qui
ne seront vraies que pour une exécution du programme conforme aux spécifi-
cations de fonctionnement de la machine de Turing. Les variables booléennes
g

considérées dans le problème d’acceptabilité seront : Qtq (au temps t, la ma-


Al

chine est dans l’état q), Htj (au temps t, la tête examine la case j) et Stjσ
(au temps t, la case j de la bande contient le symbole σ). Comme le temps
de calcul est limité par un polynôme p(n) en la taille n du problème, il y a un
T_

nombre polynomial de variables booléennes. Ces six groupes assureront les


conformités suivantes :
1. En tout temps, la machine se trouve dans un et un seul état.

(Qtq0 ∨ Qtq1 ∨ · · · ∨ Qtqy ∨ QtqN ) (on se trouve au moins dans un état).

(Qtq ∧ Qtq0 ) ≡ (Qqt ∨ Qtq0 ) ∀q 6= q 0 ∈ Q (on est au plus dans un état).

2. En tout temps, la tête examine exactement une case de la bande.

Ht,−p(n)+1 ∨ Ht,−p(n)+2 ∨ · · · ∨ Ht,p(n)+1) ∀t


1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 29

(Htj ∨ Htj 0 ) ∀t, ∀j 6= j 0

3. En tout temps, chaque case de la bande contient exactement un symbole

(Stjσ0 ∨ Stjσ1 ∨ · · · ∨ Stjσ|Λ| ) ∀t, ∀j

(Stjσ ∨ Stjσ0 ) ∀t, ∀j, ∀σ 6= σ 0

17
4. Au temps 0 (début de la phase de vérification), on est dans l’état q0 ,

20
la tête est sur la case 1, la bande contient dans les cases 1 à n les
symboles codant l’exemple de problème de π et il y a le symbole blanc
dans les autres cases non négatives (par contre, on ne sait pas ce qu’il
y a dans les cases négatives qui devraient contenir une solution avec

e
réponse « oui » au problème).

br
Q0q0 ∧ H01 ∧ S00b ∧ S01x1 ∧ S02x2 ∧ · · · ∧ S0nxn ∧ S0n+1b ∧ · · · ∧ S0,p(n)+1,b
em
5. À un temps borné par un polynôme en n, la machine doit se trouver dans
l’état qY .
Qp(n)qY
pt
se

6. Pour tout temps, la configuration de la machine au temps suivant est


donnée par l’application de la fonction δ. Il faut donc écrire un ensemble
de clause disant que si au temps t, la tête de lecture est en position j, que
25

la machine est dans l’état q et qu’elle lit le symbole σ, alors, au temps t+1,
la machine doit se trouver dans l’état q 0 , le symbole s0 doit être écrit dans
la case j et la tête se trouver en position j + ∆, avec (q 0 , s0 , ∆) = δ(s, q).
g

Htj ∧ Qtq ∧ Stjσ =⇒ Ht+1,j+∆ ∧ Qt+1q0 ∧ St+1jσ0 ≡


Al

(Htj ∨Qtq ∨Stjσ ∨Ht+1,j+∆ )∧(Htj ∨Qtq ∨Stjσ ∨Qt+1q0 )∧(Htj ∨Qtq ∨Stjσ ∨St+1jσ0 )
T_

De plus, seule la case j peut être modifiée. Toutes les autres doivent
conserver le symbole qu’elles avaient au temps t.

Htj ∧ Stjσ =⇒ St+1jσ ≡ (Htj ∨ Stjσ ∨ St+1jσ )

Maintenant que l’on a démontré que le problème d’acceptabilité était NP-


complet, il est aisé de montrer que d’autres problèmes de N P le sont aussi.
On donne ci-dessous l’exemple de la transformation polynomiale du problème
d’acceptabilité vers le problème de l’ensemble stable, ce qui prouve que ce
dernier problème est NP-complet.
30 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

x̄ ∨ y ∨ z̄ x ∨ ȳ y∨z

x̄ x z

y ȳ y

17
F IGURE 1.7 – Transformation de l’exemple de problème d’acceptabilité : (x̄ ∨ y ∨ z̄) ∧
(x ∨ ȳ) ∧ (y ∨ z) en un problème de stable.

20
Problème de l’ensemble stable : Données : G = (X, E), un graphe et k,
un entier Question : Existe-t-il un sous-ensemble X 0 ⊆ X, |X 0 | = k tel que :

e
∀i, j ∈ X 0 , (i, j) ∈
/ E (sous-ensemble de k sommets sans connexion) ?

br
La transformation d’un exemple de problème d’acceptabilité vers un en-
semble stable se fait de la façon suivante :
em
— On associe un sommet à tous les littéraux de toutes les clauses
— On relie en une clique (entièrement) tous les sommets associés à une
clause
— On relie les sommets-littéraux incompatibles (une variable et sa négation)
pt

— Dans ce graphe, on cherche un ensemble stable de taille k = nombre de


clauses
se

Une telle transformation est illustrée en figure 1.7 pour un petit problème à trois
littéraux et trois clauses.
25

Exemples de problèmes non encore classés : Les problèmes suivants


n’ont pas encore pu être classés plus précisément que dans N P :
Dans un championnat de foot, chaque équipe joue une fois contre chaque
autre. L’équipe gagnante reçoit trois points, l’équipe perdante reçoit zéro points.
g

En cas d’égalité, chaque équipe reçoit un point. Étant donné une suite de
Al

scores pour chaque équipe, cette suite peut-elle être le résultat obtenu à la
fin d’un championnat ?
Remarque : si le gagnant reçoit seulement deux points, alors il existe un algo-
T_

rithme polynomial pour répondre à cette question.


Est-il possible d’orienter les arêtes d’un graphe de telle sorte qu’il soit fortement
connexe et que chaque sommet ait un degré rentrant impair ?

Classe fortement NP-complet


Certains problèmes NP-complets, comme le problème du sac de montagne,
se résolvent dans certains cas très bien au moyen d’algorithmes ad hoc (pro-
grammation dynamique). Une des conditions pour que ces problèmes puissent
se résoudre aisément est que le plus grand nombre apparaissant dans les don-
nées du problème soit limité (pour le problème du sac de montagne, ce nombre
1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 31

est le volume du sac). D’autres problèmes, au contraire, ne peuvent pas être


résolus efficacement, même si la valeur du plus grand nombre apparaissant
dans le problème est limitée. On dit que l’on a affaire à un problème sur des
nombres s’il n’existe pas de polynôme p(n) tel que le plus grand nombre M
apparaissant dans un exemple de problème de taille n soit borné par p(n).
Le problème de bipartition d’un ensemble en deux sous-ensembles de poids
égaux ou celui du voyageur de commerce sont donc des problèmes sur des
nombres car, si l’on ajoute un bit à la taille du problème, M peut être multiplié
par deux. Par conséquent, pour ces problèmes, M peut être en O(2n ), ce qui

17
n’est pas polynomial.
Par contre, les problèmes d’acceptabilité, du stable ou du cycle hamiltonien
ne sont pas des problèmes sur des nombres (car ils ne font simplement pas

20
intervenir de nombres).
On dit qu’un algorithme est pseudo-polynomial s’il s’exécute en un temps
borné par un polynôme dépendant de la taille n des données et du plus grand
nombre M intervenant dans le problème. Le problème de bipartition d’un en-

e
semble en deux sous-ensembles de poids égaux est un problème NP-complet
pour lequel il existe un algorithme pseudo-polynomial simple.

br
Exemple de problème de bipartition d’un ensemble : Est-il possible de
em
diviser l’ensemble {5, 2, 1, 6, 4} en deux sous-ensembles de poids égaux ? La
somme des poids pour cet exemple est de 18. On cherchera donc deux sous-
ensembles de poids 9. Pour résoudre ce problème, on crée un tableau de n
lignes, où n est le cardinal de l’ensemble, et M = 9 colonnes, où M est la
pt

moitié de la somme des poids des éléments. On remplit certaines cases de ce


tableau avec des × en procédant ligne par ligne : Avec le premier élément, de
se

poids 5, on arrive à créer un sous-ensemble de poids 0 (si on ne prend pas


cet élément) ou un sous-ensemble de poids 5 (en le prenant). On place donc
dans la première ligne des × dans les colonnes 0 et 5. Avec les deux premiers
éléments, il est possible de créer des sous-ensembles dont le poids est le
25

même qu’avec un seul élément (en ne prenant pas le deuxième élément). Là


où il y a des × dans une ligne, on peut donc en mettre dans la ligne suivante. En
prenant le deuxième élément, on pourra créer des sous-ensembles de poids
2 et 7, on mettra donc également des × là où on en a mis pour la première
g

ligne, mais décalé du poids du deuxième élément (ici : 2). On répète ensuite
Al

le procédé jusqu’à ce que tous les éléments aient été considérés. S’il y a un
× dans une case le la dernière colonne, c’est qu’il est possible de créer un
sous-ensemble de poids M , ce qui est le cas pour cet exemple. Une solution
T_

est : {2, 1, 6}{5, 4}. La complexité de l’algorithme est O(M · n), ce qui est bien
polynomial en n et en M .
Somme des poids
Élément 0 1 2 3 4 5 6 7 8 9
5 × ×
2 × × × ×
1 × × × × × × × ×
6 × × × × × × × × ×
4 × × × × × × × × × ×
Soit π, un problème sur des nombres et πp(n) les sous-problèmes de π res-
treints aux exemples pour lesquels M 6 p(n). L’ensemble πp(n) ne fait donc
32 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

intervenir que les problèmes de π ne contenant que des « petits » nombres.


On dit que π est fortement NP-complet si, et seulement s’il existe un polynôme
p(n) tel que πp(n) est NP-complet.
Avec cette définition, un problème fortement NP-complet ne peut être ré-
solu en temps pseudo-polynomial si la classe P est différente de la classe N P .
Ainsi, le problème du voyageur de commerce est fortement NP-complet, car le
problème du cycle hamiltonien peut se transformer polynomialement en un pro-
blème du voyageur de commerce avec une matrice de distance ne contenant
que des 0 ou des 1. Par conséquent, comme le problème du cycle hamiltonien

17
est NP-complet, les sous-problèmes de voyageur de commerce ne faisant in-
tervenir que des petits nombres sont également NP-complets.
Par contre, les problèmes que l’on peut résoudre par programmation dyna-

20
mique, comme le problème du sac de montagne ou celui de la partition d’un
ensemble ne sont pas fortement NP-complets. En effet, si pour ce dernier pro-
blème la somme des poids des n éléments est bornée par un polynôme p(n),
l’algorithme ci-dessus aura une complexité polynomiale O(n · p(n)).

e
1.2.4
br
Autres classes de complexité
D’innombrables autres classes de complexité ont été proposées. Parmi
em
celles qui sont le plus fréquemment rencontrées dans la littérature et qui peu-
vent être décrites de façon intuitive, on peut citer :
Classe NP-difficile Les problèmes considérés ci-dessus sont des problèmes
pt

de décision, et non des problèmes d’optimisation. Avec un algorithme de


dichotomie on peut facilement résoudre le problème d’optimisation asso-
cié à un problème de décision. Un problème est NP-difficile si tout pro-
se

blème de N P peut se transformer en temps polynomial en ce problème.


Contrairement à la classe NP-complet, on n’impose pas que ce dernier
fasse partie de N P . Ainsi, un problème d’optimisation, dont la version
25

décisionnelle est NP-complète, entre dans la catégorie des problèmes


NP-difficiles.
Classe P-SPACE Les problèmes que l’on peut résoudre avec une machine
dont la mémoire est limitée par un polynôme en la taille des données
g

font partie de la classe P-SPACE. On n’impose ici aucune limite sur le


temps de calcul, qui peut être exponentiel. Ainsi, tous les problèmes de
Al

N P sont dans la classe P-SPACE car il est possible de concevoir des


algorithmes d’énumération exhaustive ne nécessitant pas trop de mé-
T_

moire. Un exemple de problème de cette classe est de déterminer si un


jeu (déterministe) à deux joueurs est inéquitable : en d’autres termes, si
le joueur B perd à coup sûr si le joueur A ne fait pas d’erreurs. Ce pro-
blème a peu de chances de faire partie de la classe N P , car on imagine
mal que l’on puisse donner un certificat compact pour la solution d’un
problème de ce type.
Classe L Les problèmes que l’on peut résoudre avec une machine dont la
mémoire de travail — c’est-à-dire en faisant abstraction de la place né-
cessaire au stockage des données du problème — est bornée par un po-
lynôme en la taille des données font partie de la classe L. Rentrent dans
cette classe des problèmes de recherche d’éléments dans des bases de
1.2 É LÉMENTS DE THÉORIE DE LA COMPLEXITÉ 33

données dont la taille ne tiendrait pas dans la mémoire vive des ordina-
teurs.
Classe N C La classe N C est celle des problèmes pouvant se résoudre en
temps poly-logarithmique sur une machine disposant d’un nombre po-
lynomial de processeurs. Les problèmes de cette classe peuvent donc
résoudre en parallèle en un temps plus faible que celui dont on a be-
soin pour lire les données en séquentiel. Le tri des éléments d’un tableau
entre dans la catégorie N C.

17
Peu de résultats ont été établi en ce qui concerne les relations existantes
entre ces diverses classes de complexité. À l’exception des évidentes inclu-
sions au sens large L ⊆ P ⊆ N P ⊆ NP-complet ⊆ P-SPACE et N C ⊆ P , il
n’a été possible d’établir que L 6= P-SPACE. Il est communément conjecturé

20
que P 6= N P , mais cette conjecture fait partie des quelques problèmes du
millénaire.

e
br
em
pt
se
25
g
Al
T_
34 É LÉMENTS DE THÉORIES DES GRAPHES ET DE LA COMPLEXITÉ

Exercices
Exercice 1.1. On cherche à dessiner 5 segments sur le plan de manière à ce
que chaque segment en coupe exactement 3 autres. Formaliser ce problème
en termes de graphes.
n
Exercice 1.2. Simplifier les expressions suivantes : O(n5 + 2n ), O(5n + 22 ),
Ω(n2 · n! + (n + 2)!), Ω(nlog(log(n)) + 23n), O(nlog(n) + n5+cos(n) )
Exercice 1.3. Écrire un programme pour machine de Turing déterministe qui

17
reconnaît si la sous-chaîne ane est contenue sur la bande. L’alphabet d’entrée
est : Σ = {a, c, e, n}. Spécifier l’alphabet de bande Γ, l’ensemble Q des états
possibles de la machine et la fonction de transition δ.

20
Exercice 1.4. Démontrer que la recherche d’une clique de taille donnée dans
un graphe est un problème NP-complet.

Exercice 1.5. Montrer que l’on peut transformer un problème du voyageur de

e
commerce asymétrique en un problème symétrique en doublant le nombre de
villes.

br
em
pt
se
25
g
Al
T_
Chapitre 2

17
Exemples et modélisation de

20
problèmes combinatoires

e
Maintenant que nous avons passé en revue les principales définitions de

br
théorie des graphes et de théorie de la complexité, nous pouvons donner quel-
ques exemples de problèmes d’optimisation combinatoire. Certains de ces pro-
em
blèmes sont faciles, mais l’ajout d’une contrainte qui semble anodine peut les
rendre difficiles. Nous rappellerons également brièvement le principe de fonc-
tionnement de quelques algorithmes simples qui permettent de résoudre cer-
tains de ces problèmes.
pt

2.1 Arbres optimaux


se

La recherche d’un sous-graphe connexe de poids optimal est un problème


de base en théorie des graphes. De nombreuses applications nécessitent de
25

trouver une telle structure comme étape préalable.

2.1.1 Arbre recouvrant de poids minimal


g

Le problème de la recherche d’un arbre recouvrant de poids minimal se


Al

formule ainsi : Étant donné un réseau R = (V, E, w) sur un ensemble V de


sommets, E d’arêtes munies d’une fonction de pondération w → R, on cherche
un sous-réseau connexe, sans cycle, dont la somme des poids est minimale.
T_

Les deux algorithmes les plus connus pour résoudre ce problème sont celui de
Kruskal et celui de Prim. Ils sont basés tous deux sur une méthode gloutonne :
à chaque étape on ajoute un élément à la structure que l’on construit, sans
jamais remettre en question ultérieurement le choix de cet élément.
L’algorithme de Kruskal (2.1) démarre avec un graphe T = (V, ET = ∅) et
ajoute à ET successivement une arête de E de poids aussi faible que possible
tout en veillant à ne pas créer de cycle. L’algorithme de Prim démarre avec un
graphe T = (V 0 = {s}, ET = ∅) et ajoute successivement un sommet v à V 0 et
une arête e à ET , telle que le poids de e soit aussi faible que possible et qu’une
de ses extrémité fasse partie de V 0 et l’autre non. Autrement dit, Kruskal part
d’une forêt constituée d’autant d’arbres qu’il y a de sommets et cherche à réunir
36 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

Algorithme 2.1 : (Kruskal) Recherche d’un arbre de poids minimum. Pour une
implantation efficace, il faut utiliser une structure de données adéquate d’en-
sembles disjoints pour pouvoir tester si l’arête que l’on tente d’ajouter fait partie de
la même composante connexe ou non. Dans ce cas, la complexité de l’algorithme
est en O(|E| log |E|).
Entrées : R = (V, E, w) connexe

17
Résultat : Arbre recouvrant T = (V, ET ) de poids minimum
1 Trier et renuméroter les arêtes par poids non décroissant
w(e1 ) 6 w(e2 ) 6 · · · 6 w(e|E| );

20
2 ET = ∅;
3 pour k = 1 . . . |E| faire
4 si ET ∪ {ek } ne forme pas un cycle alors
5 ET ← ET ∪ {ek }

e
br
em
pt

Algorithme 2.2 : (Prim) Recherche d’un arbre de poids minimum. Pour une im-
plantation efficace, il faut utiliser une structure de données adéquate pour extraire
se

le sommet de L avec le plus petit poids (ligne 8) et pour modifier les valeurs des
poids (ligne 14). Un tas de Fibonacci ou une queue de Brodal permettent une
implantation de l’algorithme en O(|E| + |V | log |V |).
Entrées : R = (V, E, w) connexe, un sommet particulier s ∈ V
25

Résultat : Arbre recouvrant T = (V, ET ) de poids minimum


1 pour tous les Sommets i ∈ V faire
2 λi ← ∞ ; // Coût pour faire entrer i dans l’arbre
3 predi ← ∅ ; // Prédécesseur de i
g

4 λs = 0 ; ET ← ∅;
Al

5 L←V ; // Liste des sommets à introduire dans T


6 tant que L 6= ∅ faire
8 Retirer de L le sommet i ayant le plus petit λi ;
T_

9 si i 6= s alors
10 ET ← ET ∪ {pi , i}
11 pour tous les Sommets v adjacent à i faire
12 si j ∈ L et λj > w({i, j}) alors
14 λj ← w({i, j});
15 pj ← i;
2.1 A RBRES OPTIMAUX 37

tous ces arbres en un seul alors que Prim part d’un arbre constitué d’un seul
sommet et cherche à le faire croître jusqu’à tous les intégrer.

2.1.2 Arbre de Steiner


Le problème de l’arbre de Steiner est très proche de celui de l’arbre re-
couvrant de poids minimum. La seule différence est que les sommets d’un
sous-ensemble S ⊂ V ne doivent pas nécessairement figurer dans l’arbre. S
constitue les sommets de Steiner. La version euclidienne de l’arbre de Stei-

17
ner consiste à relier un ensemble donné de points du plan par des lignes
dont la longueur est la plus faible possible. La figure 2.1 montre que l’arbre
de poids minimum qui n’utilise que des arêtes reliant directement les sommets

20
qui doivent figurer dans l’arbre peut avoir un poids supérieur à un arbre où l’on
a ajouté des nœuds de Steiner judicieusement choisis. Le choix des sommets
à ajouter engendre une combinatoire qui rend le problème NP-difficile.

e
br Nœuds de Steiner
em
Nœuds ordinaires
pt

(a) Arbre de poids minimum


se
25
g
Al
T_

(b) Arbre de Steiner

F IGURE 2.1 – Arbre de poids minimum 2.1(a) sur un ensemble n’utilisant que les nœuds
ordinaires, qui sont donc directement reliés entre eux et arbre de Steiner de poids mini-
mum 2.1(b) où l’on peut utiliser des nœuds supplémentaires.

Deux modélisations du problème de l’arbre de Steiner peuvent naturelle-


ment être imaginées :
— Sommets de Steiner à retenir Une solution peut être représentée par
les sommets de Steiner à conserver dans l’arbre. Connaissant ces som-
38 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

mets, l’arbre est facile à reconstituer par l’application de l’algorithme de


Prim ou celui de Kruskal.
— Arêtes à conserver Une solution peut également être représentée par
un ensemble d’arêtes. Ces arêtes doivent former un graphe connexe et
toucher tous les nœuds obligatoires

2.2 Chemins optimaux

17
La recherche de chemins optimaux est un problème vieux comme le monde
et bien connu du grand public, en particulier depuis que les automobiles sont

20
équipées en série de systèmes de navigation automatisés. Connaissant sa po-
sition actuelle sur un réseau de transport, il s’agit de trouver le meilleur chemin
vers une destination donnée. Le critère usuellement retenu pour l’optimalité du
chemin est le temps, mais il peut également s’agir de la distance, notamment

e
s’il s’agit d’un trajet à faire à pied.

2.2.1 Plus court chemin br


em
Formellement, on dispose d’un réseau R = (V, E, w) et on veut connaître
un chemin dont la somme des poids des arcs d’un sommet de départ s vers un
sommet-destination t est la plus faible possible. On utilisera ici de façon abu-
pt

sive le qualificatif de longueur du chemin pour désigner cette somme des poids,
étant sous-entendu que les poids peuvent représenter autre chose qu’une dis-
tance, comme par exemple un temps, une consommation d’énergie, etc. Au
se

niveau de la complexité algorithmique, il n’est pas plus coûteux, dans le pire


des cas, de trouver un chemin optimum vers un sommet particulier t ou pour
l’ensemble de tous les sommets de V .
Il convient de préciser que cette formulation peut être problématique dans
25

le cas d’une fonction de pondération quelconque : en effet, si l’on a des poids


négatifs, le plus court chemin peut ne pas exister si l’on a un circuit de longueur
négative. L’algorithme le plus efficace pour trouver le plus court chemin dans un
réseau où la fonction de pondération avec w(e) > 0 ∀e ∈ E est celui de Dijks-
g

tra. Il est présenté dans l’algorithme 2.3. Pour une implantation efficace, il faut
Al

utiliser une structure de données adéquate pour extraire le sommet de L avec


le plus petit poids (ligne 7) et pour modifier les valeurs des poids (ligne 11).
Comme pour l’algorithme de Prim 2.3, un tas de Fibonacci ou une queue de
T_

Brodal permettent une implantation de l’algorithme en O(|E| + |V | log |V |).


On remarquera la très forte similarité entre cet algorithme et celui de
Prim 2.2 pour la recherche d’un arbre de poids minimum. La recette qui a
fonctionné pour l’arbre de poids minimum fonctionne encore, avec quelques
restrictions, pour la recherche d’un plus court chemin. La trame générale des
méthodes gloutonnes, sur laquelle se base cette recette, est présentée dans
la section 3.3 du chapitre consacré aux méthodes constructives. Le code 2.1
donne une implantation de l’algorithme de Dijkstra, lorsque le réseau est suf-
fisamment dense pour qu’il soit raisonnable de le spécifier par une matrice
carrée, donnant pour chaque arc (i, j) sa longueur dij . Il est intéressant de
constater que le code 3.1 d’une des heuristiques gloutonnes les plus connues
2.2 C HEMINS OPTIMAUX 39

Algorithme 2.3 : (Dijkstra) Recherche d’un plus court chemin de s à tous les
autres sommets dans un réseau à pondération non négative. On a indiqué en
couleur les deux différences qu’il y a entre l’algorithme de Dijkstra et celui de
Prim.
Entrées : Réseau R = (V, E, w) orienté avec w(e) > 0 ∀e ∈ E, donné
sous la forme de listes des successeurs succ(i) de chaque
sommet i ∈ V , un sommet de départ particulier s
Résultat : Prédécesseur predj immédiat de j sur un plus court chemin
de s à j, ∀j ∈ V et longueur λj du plus court chemin de s à j.

17
1 pour tous les Sommets i ∈ V faire
2 λi ← ∞ ; // Longueur connue du plus court chemin de s à i
3 predi ← ∅ ;

20
4 λs = 0 ; L ← V ; // Sommets pour lesquels le plus court chemin n’est pas
définitif
5 tant que L 6= ∅ faire
7 Retirer de L le sommet i ayant le plus petit λi ;

e
8 pour tous les Sommets j ∈ succ(i) faire

11
12
9 si j ∈ L et λj > λi + w(i, j) alors
λj ← λi + w(i, j));
predj ← i br
em

pour le problème du voyageur de commerce a exactement la même structure


pt

que le code 2.1.


se

Listing 2.1 – dijkstra.c Implantation en C de l’algorithme de Dijkstra, dans le cas où


le réseau est complet, et spécifié par une matrice (dij ) donnant le poids de chaque arc
(i, j).
void d i j k s t r a ( i n t n , / ∗ Number o f c i t i e s ∗/
25

double ∗∗d , / ∗ D i s t a n c e m a t r i x , w i t h o u t any v a l u e < 0 ∗/


int s, /∗ S t a r t i n g c i t y ∗/
double lambda [ ] , / ∗ −−> Out lambda [ i ] : S h o r t e s t l e n g t h s −> i ∗/
i n t pred [ ] ) / ∗ −−>Out pred [ i ] immediate predecessor o f i ∗/
{ i n t i , j , j _ k e p t =−1;
i n t ∗known = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
g

f o r ( i = 0 ; i < n ; i ++)
{ lambda [ i ] = i n f i n i t e ; known [ i ] = i ; }
Al

lambda [ s ] = 0 ;
swap ( known +s , known + 0 ) ; / ∗ Only s h o r t e s t path t o known [ 0 ] = s a l r e a d y known ∗ /

f o r ( i = 1 ; i < n−1; i = i + 1 ) / ∗ I d e n t i f y t r u e s h o r t e s t path t o known [ i ] ∗/


T_

{ f o r ( j = i ; j < n ; j = j +1)
i f ( lambda [ known [ i −1]] + d [ known [ i − 1 ] ] [ known [ j ] ] < lambda [ known [ j ] ] )
{ lambda [ known [ j ] ] = lambda [ known [ i −1]] + d [ known [ i − 1 ] ] [ known [ j ] ] ;
pred [ known [ j ] ] = known [ i −1];
j_kept = j ;
}
swap ( known + i , known + j _ k e p t ) ; / ∗ s h o r t e s t path i d e n t i f i e d t o known [ i ] ∗/
}

f r e e ( known ) ;
} /∗ d i j k s t r a ∗/

Lorsque l’on a des pondérations négatives, les plus courts chemins n’existent
que s’il n’y a pas de circuit de longueur négative dans le réseau. Un algorithme
plus général pour trouver ces plus courts chemins a été proposé par Bellman
40 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

et Ford (voir l’algorithme 2.4). Il est basé sur la vérification, pour chaque arc,
des condition de Bellman : λj 6 λi + w(i, j). Autrement dit, la longueur du plus
court chemin de s à j ne doit pas dépasser celle de s à i à laquelle on ajoute la
longueur de l’arc (i, j). En effet, si c’était le cas, il existerait un chemin encore
plus court jusqu’à j, passant par i.

Algorithme 2.4 : (Bellman-Ford) Recherche d’un plus court chemin de s à tous


les autres sommets dans un réseau à pondération quelconque. L’algorithme in-
dique si le réseau comporte un circuit de longueur négative accessible depuis s,

17
ce qui signifie que la longueur (négative) du plus court chemin n’est pas bornée.
Cet algorithme est excessivement simple à programmer (le code n’est guère plus
long que le pseudo-code donné ici) ; sa complexité est en O(|E||V |).

20
Entrées : Réseau R = (V, E, w) orienté, donné sous la forme de listes
d’arcs, un sommet de départ particulier s
Résultat : Prédécesseur predj immédiat de t sur un plus court chemin
de s à j avec sa longueur λj , ∀j ∈ V , ou indication de

e
l’existence d’un circuit de longueur négative
1
2
pour tous les i ∈ V faire
λi ← ∞ ; predi ← ∅
λs ← 0;
br
em
3
4 k←0; // Compteur du nombre d’étapes
5 Continuer ← vrai ; // Au moins un λ a été modifié à la dernière étape
6 tant que k < |V | et Continuer faire
Continuer ← f aux;
pt

7
8 k ← k + 1;
9 pour tous les arc (i, j) ∈ E faire
se

10 si λj > λi + w(i, j) alors


11 λj ← λi + w(i, j);
12 predj ← i;
13 Continuer ← vrai
25

14 si k = |V | alors
15 Il y a un circuit de longueur négative accessible depuis s
g
Al

Le principe de fonctionnement de cet algorithme repose sur des bases diffé-


rentes des algorithmes gloutons que l’on a vu jusqu’ici. Plutôt que d’ajouter de
manière définitive un élément à une solution partielle à chaque étape, l’idée est
T_

de partir d’une solution de départ complète, même très mauvaise mais facile à
construire, et de tenter de l’améliorer. La trame générale de cet algorithme est
celle d’une méthode d’amélioration locale. À chaque étape de l’algorithme, on
vérifie si les conditions de Bellman sont satisfaites pour l’ensemble des arcs. Si
c’est le cas, on a l’ensemble des plus courts chemins. Si on trouve un sommet
j pour lequel λj < λi + w(i, j), on met à jour le meilleur chemin connu jusqu’au
sommet j en lui fixant le sommet i comme sommet prédécesseur. Lorsque l’on
fait une telle modification, cela peut invalider la condition de Bellman pour des
arcs qui la satisfaisaient. Il faut donc revérifier pour l’ensemble des arcs si une
modification n’en implique pas d’autres.
Se pose alors la question : Sans autre précaution, un algorithme basé sur
2.2 C HEMINS OPTIMAUX 41

ce principe de modification d’étiquettes s’arrête-t-il pour n’importe quelle en-


trée ? La réponse est non : si le réseau possède un circuit de longueur né-
gative, on va procéder à des modification sans fin. Par contre, si le réseau n’a
pas de circuit de longueur négative, alors l’algorithme s’arrêtera après un maxi-
mum de |V | vérifications des conditions de Bellman pour l’ensemble de tous
les arcs de E. En effet, si un plus court chemin existe, il a au plus |V | − 1 arcs
et à chaque vérification de l’ensemble des arcs, au moins un ce ces derniers
satisfera de manière définitive la condition de Bellman.
L’algorithme de Bellman-Ford est donc basé sur une méthode d’améliora-

17
tion avec un critère d’arrêt bien défini : Si l’on a fait |V | étapes et qu’il y a
encore eu des modifications, alors on peut s’arrêter en indiquant que le ré-
seau possède un circuit de longueur négative. Si à une étape on vérifie que les

20
conditions de Bellman sont satisfaites pour tous les arcs, alors on peut s’arrêter
car on a l’ensemble des plus courts chemins.
La recherche de chemins optimaux apparaît dans de nombreuses appli-
cations, en particulier en planification de projet et en ordonnancement. Les

e
problèmes qui peuvent être résolus par une technique connue sous le nom de
programmation dynamique peuvent se formuler sous la forme de la recherche

br
d’un chemin optimal dans un réseau en couches. Cette technique utilise la to-
pologie particulière du réseau pour trouver la solution du problème sans avoir
à construire explicitement le réseau.
em
Formulation du plus court chemin en termes de PL
pt

Il est relativement aisé de formuler la recherche d’un plus court chemin


d’un sommet s à un sommet t dans un réseau sous la forme d’un programme
linéaire. Pour cela, on introduit des variables xij qui indiquent si l’arc (i, j)
se

est utilisé par le plus court chemin. La formulation ci-dessous peut paraître
incomplète : en effet, on voudrait que les variables xij prennent soit la valeur
0 (auquel cas l’arc (i, j) ne fait pas partie du plus court chemin), soit la valeur
1 (l’arc en fait partie). Les contraintes 2.4 sont suffisantes, car si une variable
25

prend une valeur fractionnaire, cela signifie qu’il existe plusieurs plus courts
chemins de s à t. La contrainte 2.3 impose en effet qu’il y ait une « quantité »
unité qui arrive en t. Cette quantité peut être fractionnée, mais chaque fraction
doit utiliser un plus court chemin, à l’optimum. Les contraintes 2.2 imposent
g

que pour tout sommet intermédiaire j, la quantité arrivant dans ce sommet doit
Al

en repartir. Il n’est pas nécessaire d’imposer qu’une quantité unité parte de s,


car cette contrainte serait redondante avec 2.3. L’objectif 2.1 est de minimiser
le coût des arcs empruntés.
T_

X
Minimiser z= w(i, j)xij (2.1)
i,j
n
X n
X
xij − xjk = 0 ∀j 6= s, j 6= st (2.2)
i=1 k=1
Xn Xn
xit − xtk = 1 (2.3)
i=1 k=1
xij > 0 ∀i, j (2.4)
42 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

Une autre formulation de ce problème revient à chercher directement les


longueurs λi des plus courts chemins en imposant que les conditions de Bell-
man soient satisfaites. On obtient le programme linéaire suivant, qui est le pro-
blème dual du précédent.

Maximiser λt (2.5)
Sous λj − λi 6 w(i, j) ∀i, j (2.6)
Contraintes λs = 0 (2.7)

17
La dualité joue un rôle important en programmation linéaire. On peut en
effet montrer que toute solution admissible du premier problème a une valeur

20
qui ne peut être inférieure à une solution admissible du second. Si l’on trouve
une solution au premier problème qui vaut exactement une solution du second,
alors ces deux solutions sont optimales. Pour le problème du plus court che-
min, la valeur optimale de λt correspond à la somme des longueurs des arcs

e
qu’il faut utiliser dans un chemin optimum de s à t.

2.2.2 br
Plus court chemin élémentaire
em
Le problème du plus court chemin est mal défini, en raison des circuits de
longueur négative. Par contre, on pourrait ajouter une contrainte très naturelle,
qui le rend parfaitement défini : chercher le plus court chemin élémentaire d’un
pt

sommet particulier s à tous les autres. Dans ce cas, même s’il y a des circuits
de longueur négative, le problème a bien une solution finie, car le fait d’exiger
que le chemin soit élémentaire empêche de passer deux fois pas le même
se

sommet. Malheureusement, l’ajout de cette petite contrainte rend le problème


difficile. En effet, on peut montrer que le problème du voyageur de commerce,
notoirement N P -difficile peut se transformer polynomialement en un problème
25

de plus court chemin élémentaire.

2.2.3 Voyageur de commerce


g

Le problème du voyageur de commerce peut se formuler ainsi : étant donné


Al

un réseau R = (V, E, w), dont l’ensemble V peut être interprété comme des
villes, on cherche un circuit de longueur minimale passant une et une seule fois
par chacune des villes. Ce problème est l’archétype de l’optimisation combina-
T_

toire difficile, d’une part en raison de la simplicité avec laquelle il se formule et


d’autre part, parce qu’il présente de nombreuses applications notamment dans
l’élaboration de tournées. Comme nous le verrons plus loin, il peut apparaître
dans d’autres problèmes qui n’ont rien à voir avec une recherche d’itinéraire.
En optimisation combinatoire, le problème du voyageur de commerce est sans
doute celui qui a reçu le plus d’attention. Des problèmes euclidiens de grande
taille — plus de 104 sommets — ont été résolus optimalement, et on connaît
des solutions ne s’écartant pas de plus d’une fraction de pour-cent de l’opti-
mum pour des exemples à plusieurs millions de villes. Mais comme ce pro-
blème est N P -difficile, il existe des exemples beaucoup plus petits qui mettent
en difficulté les méthodes de résolution.
2.2 C HEMINS OPTIMAUX 43

On peut transformer polynomialement le problème du voyageur de com-


merce en un plus court chemin élémentaire : Pour cela, un sommet est du-
pliqué en deux sommets s et t et le poids w(e) des arcs est remplacé par
w(e) − M , où M est une constante positive de valeur plus élevée que le poids
du plus lourd arc. S’il n’y a pas d’arc direct entre s et t, le plus court chemin
élémentaire de s à t correspond à une tournée de longueur minimale dans le
réseau du voyageur de commerce. La figure 2.2 illustre le principe de cette
transformation. Sachant que le problème du voyageur de commerce est N P -
difficile, cela prouve que le problème de la recherche d’un chemin élémentaire

17
optimal l’est également.

1 s t

20
10 15
−40 −35
2 5 2 5
32 25 −18
12 −23 −37

e
18 29 −32 −21

3
27 13

4 br −38

3
−25
4
em
9 −41
F IGURE 2.2 – Transformation polynomiale d’un problème de voyageur de commerce
vers un problème de plus court chemin élémentaire.
pt

Il existe de nombreuses modélisation du problème du voyageur de com-


se

merce sous la forme de programme linéaire en nombres entiers. L’une d’elle


consiste à envoyer un flux de valeur n − 1 à partir du sommet 1 et d’exiger que
chaque autre sommet en consomme une unité exactement. On introduit donc
des variables indicatrices xij qui prendront la valeur 1 si l’arc (i, j) est utilisé
25

par la tournée et 0 autrement.

X
Minimiser z= w(i, j)xij (2.8)
g

(i,j)
Al

n
X
xij = 1 ∀j (2.9)
i=1
T_

Xn
xij = 1 ∀i (2.10)
j=1
Xn
y1j = n − 1 (2.11)
j=2
n
X Xn
yik − xkj = 1 ∀k 6= 1 (2.12)
i=1 j=1

yij 6 (n − 1) · xij ∀arc (i, j) (2.13)


xij ∈ 0, 1 ∀i, j (2.14)
44 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

La contrainte 2.9 impose que l’on entre exactement une fois dans chaque
ville et la contrainte 2.10 qu’on en ressorte exactement une fois. Le flux à tra-
vers l’arc (i, j) est donné par les variables yij . On impose que la somme des
flux sortant du sommet 1 par 2.11 et la consommation unitaire de chaque som-
met par 2.12. Finalement, on empêche de faire passer un flux à travers un
arc non utilisé par 2.13. Cette formulation n’est sans doute pas la plus effi-
cace pour résoudre pratiquement des problèmes de voyageur de commerce,
mais elle présente relativement peu de variables (2 par arc) et un nombre de
contraintes proportionnel au nombre d’arcs du problème.

17
2.2.4 Tournées de véhicules

20
Des problèmes utilisant celui du voyageur de commerce comme sous-
problème apparaissent naturellement dans l’élaboration de tournées de vé-
hicule. Dans sa forme la plus simple, celui-ci peut se formuler ainsi : Un en-
semble V de clients demandant des quantités qi de biens (i = 1, . . . , |V |)

e
doivent être desservis avec un véhicule de capacité Q à partir d’un entre-
pôt d. Il faut déterminer une décomposition de l’ensemble des clients en m

br
P
sous-ensembles V1 , . . . Vm tels que i∈Vi qi 6 Q et trouver pour chaque sous-
ensemble Vj ∪ {d}, (j = 1, . . . , m) une tournée de voyageur de commerce de
em
sorte que la distance totale parcourue par le véhicule soit aussi faible que pos-
sible.
pt
se
25

Dépôt
g
Al
T_

F IGURE 2.3 – Exemple de problème d’élaboration de tournées de véhicules. Les trajets


en partance du dépôt ou y retournant ne sont pas dessinés pour ne pas surcharger
l’illustration. Cette solution a été découverte il y a une vingtaine d’années, mais il n’est
pas prouvé qu’elle soit la meilleure possible.

Ce problème intervient naturellement dans la distribution ou la collecte de


2.3 O RDONNANCEMENT 45

biens et dans la planification de services à domicile. Dans les applications


réelles, de nombreuses complications existent :
— Le nombre m de tournées peut être fixé a priori ou minimisé
— La longueur maximale des tournées peut être limitée
— Les clients spécifient une ou plusieurs fenêtre de temps durant lesquelles
ils doivent recevoir la visite du véhicule
— Les commandes peuvent être fractionnées au besoin, ce qui implique
plusieurs passages chez le même client

17
— Une tournée mêle collecte et distribution
— On a plus d’un entrepôt

20
— Les entrepôts abritent une flotte de véhicules hétérogènes ou non
— La position des entrepôts peuvent être choisies
— Etc.
Comme il s’agit de trouver dans quel ordre desservir les clients, les pro-

e
blèmes d’élaboration de tournées font également partie des problèmes d’or-

br
donnancement. Du reste, dans la littérature anglo-saxonne, on rencontre aussi
bien le terme de « vehicle routing » que celui de « vehicle scheduling ».
em
2.3 Ordonnancement
Les problèmes d’ordonnancement regroupent tous ceux dont le but est de
pt

déterminer dans quel ordre effectuer un certain nombre d’opérations. La réa-


lisation de ces dernières consomme des ressources, généralement du temps
se

sur une machine. Des opérations ayant une forte interdépendance sont regrou-
pées en tâches. Par exemple, une tâche peut représenter l’ensemble des opé-
rations qu’un objet doit subir. Souvent, ces dernières ne peuvent être réalisées
dans n’importe quel ordre ; on parle alors de gamme opératoire.
25

L’objectif des problèmes d’ordonnancement est d’optimiser la consomma-


tion des ressources. Divers critères d’optimisation sont couramment utilisés :
minimiser l’heure à laquelle la dernière opération se termine ; minimiser la
somme des heures de terminaison des tâches ; minimiser le retard moyen ;
g

etc.
Al

La principale contrainte que l’on rencontre en ordonnancement est qu’une


ressource ne peut réaliser plusieurs opérations simultanément et que deux
opérations d’une tâche ne peuvent être réalisées en même temps. Les opéra-
T_

tions peuvent avoir diverses caractéristiques selon les applications :


Ressource Une opération doit avoir lieu sur une ressource donnée ou un
sous-ensemble de ressources ou encore mobiliser plusieurs ressources
simultanément
Durée La réalisation d’une opération prend un certain temps, qui peut dé-
pendre de la ressource utilisée
Mise en place Avant de réaliser une opération, la ressource nécessite un
temps de réglage dépendant de l’opération précédemment réalisée
Interruption Une fois qu’une opération a débuté, elle peut être mise en attente
avant de se terminer
46 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

Préemption Une ressource peut interrompre une opération pour en réaliser


une autre
Attente Il peut y avoir un temps mort entre deux opérations successives d’une
même tâche
Disponibilité Une opération ne peut avoir lieu avant une certaine heure
Délai Une opération ne peut avoir lieu après une certaine heure
Les ressources peuvent également avoir diverses caractéristiques. Elles
peuvent être mobiles dans le cas de transporteurs, ce qui entraîne des pro-

17
blèmes de collision. Il peut y avoir plusieurs machines du même type, des ma-
chines pouvant réaliser diverses opérations, etc.

20
Exemple : atelier de peinture Un des problèmes d’ordonnancement les plus
simples à formule est celui de la peinture d’objets. Il n’y a ici qu’une seule res-
source : la machine qui permet de déposer la peinture sur les objets. Chaque
tâche ne comporte qu’une opération : peindre un objet i (i = 1, . . . , n) dans

e
une couleur donnée, ce qui prend un temps ti . Après avoir peint un objet i, il

br
faut nettoyer la machine pour pouvoir peindre le suivant, j, dans une autre cou-
leur, ce qui prend un temps sij . Notons que généralement sij 6= sji : en effet,
des traces d’une teinte foncée dans une couleur claire ont plus d’impact que
em
le contraire. Après avoir peint tous les objets, il faut nettoyer la machine pour
qu’elle soit prête pour le jour suivant, ce qui prend un temps r. L’objectif est de
trouver l’ordre dans lequel faire passer les objets sur la machine pour minimi-
ser l’heure à laquelle on P termine le travail. On cherche donc une permutation p
pt

n−1
des n objets minimisant i=1 (tpi + spi pi+1 ) + tpn + r.
Ce problème d’ordonnancement se ramène à celui d’un voyageur de com-
se

merce à n + 1 villes. Pour cela, on pose wij = ti + sij (i, j = 1, . . . , n), wi0 = r
et w0i = 0, (i = 1, . . . , n). On vérifie que la tournée la plus courte sur les villes
0, . . . , n donne l’ordre optimal dans lequel il faut peindre les objets, en interpré-
tant l’« objet » 0 comme le début d’une journée de travail.
25

2.3.1 Chaîne de traitement à gamme opératoire unique


Un autre problème d’ordonnancement de base est celui de la chaîne de
g

traitement à gamme opératoire unique ou chaîne de traitement en ligne, connu


Al

dans la littérature anglo-saxonne sous le terme de « permutation flowshop ».


Ce problème intervient par exemple dans une chaîne de montage dans laquelle
les n objets produits doivent passer successivement sur les postes 1, 2, . . . , m
T_

dans cet ordre. Un objet j doit donc subir m opérations qui prennent un temps
tij , (i = 1, . . . , m, j = 1, . . . , n). Il s’agit de déterminer dans quel ordre faire
passer les objets sur la chaîne de traitement, autrement dit, trouver une per-
mutation des objets telle que la durée des travaux soit minimisée. Il faut noter
qu’il y a un espace tampon entre chaque poste, où l’on peut au besoin stocker
des objets en attendant que le poste termine le traitement d’un objet arrivé
plut tôt. Une façon commode de représenter une solution pour la planification
de tâches est le diagramme de Gannt dans lequel l’axe des abscisses repré-
sente le temps et celui des ordonnées les ressources. La figure 2.4 donne le
diagramme de Gannt d’une solution quelconque, où chaque opération a été
planifiée le plus tôt possible ainsi qu’un ordonnancement optimal au plus tard.
2.3 O RDONNANCEMENT 47

Machine

Temps
Étendue des travaux
(a) Ordonnancement quelconque au plus tôt

17
Machine

20
Temps
Étendue des travaux
(b) Ordonnancement optimal au plus tard

e
br
F IGURE 2.4 – Chaîne de traitement à gamme opératoire unique. Diagramme de Gannt
d’un ordonnancement quelconque au plus tôt pour un petit exemple à 4 ressources et
em
5 tâches 2.4(a) et ordonnancement optimal au plus tard 2.4(b) pour le même exemple.

Dans le cas où le nombre de machines est limité à 2, il existe un algo-


rithme glouton produisant une solution optimale à ce problème. On ordonne
pt

dans une liste toutes les opérations par durée croissante. On sélectionne de
la liste l’opération dont la durée est la plus petite, si cette opération a lieu sur
se

la première machine, la tâche correspondante est placée en tout début de sé-


quence ; si l’opération a lieu sur la 2e machine la tâche est placée en toute fin
de séquence. Les deux opérations de la tâche sont supprimées de la liste avant
d’examiner l’opération suivante. On remplit ainsi la séquence en progressant
25

vers son milieu.


À partir de 3 machines, le problème devient N P -difficile. Une formulation
en termes de programme linéaire de l’ordonnancement à gamme opératoire
unique est la suivante :
g
Al

Minimiser dω (2.15)
dmj + tmj 6 dω (j = 1 . . . n) (2.16)
T_

dij + tij 6 di+1j (i = 1, . . . m − 1, j = 1 . . . n) (2.17)


dij + tij 6 dik + M · (1 − yjk ) (i = 1, . . . m, j = 1 . . . n, j < k = 2 . . . n)
(2.18)
dik + tik 6 dij + M · yjk (i = 1, . . . m, j = 1 . . . n, j < k = 2 . . . n) (2.19)
dij > 0 (i = 1, . . . m, j = 1 . . . n) (2.20)
yjk ∈ {0, 1} (j = 1 . . . n, j < k = 2 . . . n) (2.21)

L’objectif 2.15 consiste à minimiser l’heure de fin de la production dω . Les


contraintes 2.16 imposent que l’heure de fin de traitement de chaque objet j sur
la dernière machine survient avant la fin de la production. Un objet j doit avoir
48 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

terminé son traitement sur une machine i avant de passer sur la machine i + 1
(2.17). Les variables yjk , indiquent si l’objet j doit être traité avant l’objet k ; il
est nécessaire de n’introduire que n·(n−1)/2 de ces variables, étant donné que
ykj devrait prendre la valeur complémentaire 1 − yjk . Les deux contraintes 2.18
et 2.19 font intervenir une grande constante M et permettent l’introduction de
contraintes disjonctives : soit l’objet j passe avant l’objet k, soit c’est l’inverse.
Si yjk = 1, j passe avant k et les contraintes 2.19 sont trivialement satisfaites
pour toute machine i, si M est suffisamment grand. Inversement, si yjk =
0, ce sont les contraintes 2.18 qui sont trivialement satisfaites alors que les

17
contraintes 2.19 imposent de terminer le traitement de l’objet k sur la machine
i avant que cette dernière ne puisse commencer le traitement de l’objet j.

20
2.3.2 Gamme opératoire variable
Un problème un peu plus général est celui de l’ordonnancement à gamme
opératoire variable, connu dans la littérature anglo-saxonne sous le terme de

e
« jobshop ». Ici, chaque tâche doit subir un certain nombre d’opérations sur

br
des machines données. La séquence des opérations pour une tâche est fixée,
mais deux tâches n’ont pas forcément la même séquence et toutes les tâches
ne passent pas forcément sur toutes les machines.
em
Machine 3
6 4 3
3
pt
se

0 4
α 4 7 ω
0 2
2 2 3
Machine 2
25

4
3
1 5
Machine 1
g

F IGURE 2.5 – Graphe correspondant à une solution d’un problème d’ordonnancement


Al

à gamme opératoire variable. Une tâche est composée de 3 opérations et deux autres
de 2. Trois machines sont impliquées. La pondération des arcs correspond à la durée
de l’opération correspondante. Les arcs représentant les relations de précédence des
T_

opérations d’une même tâche sont en pointillés. Le chemin critique, c’est-à-dire le plus
long chemin de α à ω est indiqué en gras.

On peut formule ce problème en termes de graphe : Chaque opération est


représentée par un sommet. On ajoute deux sommets fictifs début (α) et fin
(ω). Si l’opération k suit immédiatement l’opération i sur la même tâche, alors
on introduit un arc (i, j) La longueur de l’arc et ti , la durée de l’opération i.
On ajoute des arcs de longueur nulle du sommet début vers les premières
opérations de chaque tâche et des arcs des dernières opérations de chaque
tâche vers le sommet fin. La longueur de ces arcs correspondant à la durée
2.4 P ROBLÈMES D ’ AFFECTATION 49

de l’opération correspondante. Toutes les opérations devant avoir lieu sur la


même machine sont reliées en une clique. Le but du problème est d’orienter
les arêtes de ces cliques de sorte à minimiser la longueur du plus long chemin
de début à fin.
Une formulation de ce problème en terme de programme linaire est la sui-
vante :

Minimiser dω (2.22)

17
di + ti 6 dj ∀(i, j) (2.23)
di + ti 6 dω ∀i (2.24)
di + ti 6 dk + M · (1 − yik ) ∀i, k sur une même machine (2.25)

20
dk + tk 6 di + M · yik ∀i, k sur une même machine (2.26)
di > 0 ∀i (2.27)
yik ∈ {0, 1} ∀i, k sur une même machine (2.28)

e
Les contraintes 2.23 imposent de terminer l’opération i qui précède l’opé-

br
ration j d’une tâche donnée avant de pouvoir débuter le traitement de cette
dernière. Les contraintes 2.24 imposent que les heures de fin de traitement de
em
toutes les opérations précèdent la fin du traitement. Les variables yik associées
aux contraintes disjonctives 2.25, 2.26 déterminent si l’opération i précède ou
non l’opération k qui a lieu sur la même machine.
pt

2.4 Problèmes d’affectation


se

Les problèmes d’affectation ou de couplage surviennent fréquemment en


pratique. Il s’agit d’apparier les éléments de deux ensembles différents comme
par exemple des enseignants à des classes, des symboles aux touches d’un
25

clavier, des postes de travail à des employés. Certains de ces problèmes peu-
vent être résolus efficacement en les modélisant sous la forme de problèmes
de flots dans des réseaux.
g

2.4.1 Flot dans les réseaux


Al

La forme la plus simple des problèmes de flots est la suivante : dans un


réseau R = (V, E, w), on cherche les flux xij à faire passer dans les arcs
T_

(i, j) ∈ E de sorte à maximiser la somme des flux qui sortent d’un sommet
particulier s pour aller vers un autre sommet t tout en respectant les contraintes
de conservation pour les autres sommets — la somme des flux entrants est
égale à celle des flux sortants — et de capacité — les flux xij doivent être
positifs, sans dépasser la valeur w(i, j) associés aux arcs.
Pour résoudre ce problème, Ford et Fulkerson ont proposé un algorithme
assez simple ( 2.5), basé sur une méthode d’amélioration : On part d’un flot nul
(qui est admissible) et on l’augmente à chaque étape, le long d’un chemin de
s à t jusqu’à obtenir le flot optimum. La première étape de cet algorithme est
illustrée dans la figure 2.6. Pour ne pas se retrouver bloqué dans une situation
où il n’existe plus de chemin de s à t mais sans que le flot soit maximal, comme
50 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

Capacité = 2

s 1 2 t

Capacité = 1
(a) Flot de départ nul

17
Flux = 0

20
s 1 2 t

e
Flux = 1
(b) Flot bloquant

br
em
F IGURE 2.6 – Représentation graphique d’un problème de flot. Un triangle vide indique
une unité de capacité non utilisée alors qu’elle l’est pour un triangle rempli. L’algorithme
de Ford et Fulkerson part d’un flot nul 2.6(a) et l’augmente au maximum sur un chemin
de s à t. Si le premier chemin trouvé est s − 1 − 2 − t on ne peut augmenter le flot que
d’une unité le long de ce trajet. On obtient un flot bloquant 2.6(b), car il n’existe plus de
pt

chemin de s à t pour lequel on pourrait augmenter le flot.


se

dans la 2.6(b), il convient de remarquer que l’on peut augmenter virtuellement


le flux d’un sommet j à un sommet i en diminuant un flux réel de i à j.
25

s 1 2 t
g
Al

F IGURE 2.7 – Réseau d’augmentation associé au flot bloquant de la figure 2.6(b). Le


T_

chemin s − 2 − 1 − t permet d’augmenter le flot de s à t

Ainsi, à chaque étape de l’algorithme, on ne cherche pas un chemin avec


des capacités résiduelles dans le réseau d’origine, mais dans un réseau des
augmentations ou encore appelé réseau des résidus. On procède de la façon
suivante pour construire ce réseau : Un arc (i, j) de capacité w(i, j) dans lequel
circule un flux xij sera remplacé par deux arcs, l’un du sommet i au sommet j
de capacité w(i, j) − xij et l’autre de j à i de capacité xij . La figure 2.7 illustre
ce principe. Une fois un flot trouvé dans le réseau des augmentations, on le
superpose au flot obtenu précédemment. Ceci est illustré dans la figure 2.8
2.4 P ROBLÈMES D ’ AFFECTATION 51

s 1 2 t

V \A

F IGURE 2.8 – Superposition du flot du réseau d’augmentation de la figure 2.7 au flot

17
bloquant de la figure 2.6(b), ce qui permet d’obtenir le flot optimum. La preuve de l’op-
timalité découle du fait que la capacité de la coupe A séparant s de t indiquée en ligne
de traits est égale à la valeur du flot.

20
Algorithme 2.5 : (Ford-Fulkerson) Recherche d’un flot maximum de s à t.
Entrées : Réseau R = (V, E, w) orienté, un sommet-source s et un

e
sommet-puits t
Résultat : Flot optimum de s à t
1 Partir d’un flot nul dans tous les arcs;
2 répéter br
em
3 Construire le réseau des augmentations R∗ correspondant au flot
courant;
4 si Un chemin de s à t existe dans R∗ alors
5 Chercher le flux maximum que l’on peut faire passer le long du
pt

chemin de s à t dans R∗ ;
6 Superposer ce flux au flot courant (diminuer le flot dans les arcs
(i, j) de R qui apparaissent inversés (j, i) sur le chemin de R∗ )
se

7 jusqu’à ce qu’il n’existe plus de chemin de s à t dans R∗ ;


25

La complexité de cet algorithme dépend de la taille du réseau, en particulier


parce qu’il faut rechercher un chemin de s à t avant chaque augmentation
de flot, mais également du nombre de ces augmentations. Malheureusement,
dans le pire des cas, il se peut que chaque augmentation de flux ne soit que
g

d’une unité, pour des réseaux à capacités entières. Si le flot maximum dans un
Al

réseau est de valeur m, la complexité de l’algorithme est en O(m · (|E| + |V |)).


Du moment que m est petit, par exemple lorsque la capacité de tous les arcs
est de 1, l’algorithme de Ford et Fulkerson est rapide. Nous verrons dans la
T_

section 2.5.1 comment résoudre le problème de la coloration des arêtes d’un


graphe biparti en résolvant des problèmes de flot maximum dans un réseau où
toutes les capacité sont unitaires.
Sa complexité peut être sensiblement diminuée, en n’utilisant pas n’importe
quel sous-algorithme pour découvrir un chemin de s à t dans le réseau des
augmentations, mais en faisant une recherche en largeur, ce qui implique la
découverte du chemin le plus court à chaque étape. Cette amélioration a été
proposée par Edmons et Karp. Comme on peut montrer que le nombre d’arcs
du chemin ne peut décroître d’une étape à la suivante, que l’on a au maximum
|E| étapes avec un nombre donné d’arcs et que ce nombre est compris entre 1
et |V |, on en déduit que la complexité peut être ramenée à O(|V ||E|·(|V |+|E|)).
52 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

Dans le cas d’un réseau dense (|E| ∈ O(|V 2 |)), cette complexité se simplifie
en O(|V |5 ).
De nombreux algorithmes ont été proposés pour la résolution du problème
du flot maximum. Au niveau de la complexité, celui de Malhotra, Kumar, Mahe-
shwari, en O(|V |3 ) est un des meilleur.
Dans de nombreuses applications, faire passer une unité de flux à travers
un arc (i, j) coûte c(i, j). On a donc un réseau R = (V, E, w, c), où w(i, j) est la
capacité de l’arc (i, j) et c(i, j) le coût unitaire d’une unité de flux traversant cet

17
arc. Se pose alors le problème du flot maximum à coût minimum. Ce problème
peut être résolu avec l’algorithme de Busacker et Gowen 2.6 lorsque le réseau
de départ ne possède pas de circuit à coût négatif.

20
Algorithme 2.6 : (Busacker et Gowen) Recherche d’un flot maximum à coût
minimum de s à t.

e
Entrées : Réseau R = (V, E, w, c) orienté, sans circuit à coût négatif, un

1 br
sommet-source s et un sommet-puits t
Résultat : Flot maximum à coût minimum de s à t
Partir d’un flot nul dans tous les arcs;
em
2 répéter
3 Construire le réseau des augmentations R∗ correspondant au flot
courant;
4 si Un chemin de s à t existe dans R∗ alors
pt

5 Chercher le flux maximum que l’on peut faire passer le long du


plus court chemin de s à t dans R∗ ;
se

6 Superposer ce flux au flot courant


7 jusqu’à ce qu’il n’existe plus de chemin de s à t dans R∗ ;
25

Comme ce qui avait été constaté pour les algorithmes de Prim et Dijks-
tra, on remarque une différence minime entre les algorithmes de Ford & Ful-
kerson 2.5 (ou plutôt son amélioration par Edmons & Karp) et Busacker &
g

Gowen 2.6. À nouveau, on ne change pas une formule gagnante ! Lors de


Al

la construction du réseau des augmentations, il convient de tenir compte des


coûts. Si un flux xij > 0 traverse l’arc (i, j), alors le réseau des augmentations
comprendra un arc (i, j) de capacité w(i, j) − xij (pour autant que cette capa-
T_

cité soit positive) avec coût c(i, j) inchangé et un arc inversé (j, i) de capacité
xij et de coût −c(i, j).
Dans le cas général, le problème du flot maximum à coût minimum est N P -
difficile. On peut en effet transformer polynomialement le problème du voyageur
de commerce dans ce problème, de façon similaire à la transformation du plus
court chemin élémentaire (voir figure 2.2).
Si les algorithmes pour trouver des flots optimaux présentés ci-dessus peu-
vent résoudre de nombreux problème directement liés à la gestion de flux,
comme l’acheminement d’énergie électrique ou certains problèmes de trans-
port, leur principale application est le traitement de problèmes d’affectation.
2.4 P ROBLÈMES D ’ AFFECTATION 53

2.4.2 Affectation linéaire


Le problème de l’affectation linéaire peut se formaliser ainsi : Étant donné
une matrice de coût C = (ciu ), carrée de dimension n × n, on cherche une
affectation xiu de chaque élément i ∈ I à un élément u ∈ u (i, u = 1, . . . , n)
minimisant la somme des coûts 2.29. Ce problème peut se modéliser par un
programme linéaire en nombres entiers :

n X
n

17
X
Minimiser ciu xiu (2.29)
i=1 u=1
Sous contraintes

20
Xn
xiu = 1 u = 1, . . . , n (2.30)
i=1
Xn
xiu = 1 i = 1, . . . , n (2.31)

e
u=1
xiu ∈ {0, 1}

br (i, u = 1, . . . , n)

La contrainte 2.30 oblige d’attribuer exactement un élément de U à chaque


(2.32)
em
élément de I et la contrainte 2.31 que chaque élément de U ait été attribué à
un élément de I. La contrainte d’intégrité 2.32 empêche d’avoir des éléments
de I qui se partagent des fractions d’éléments de U .
Si cette modélisation est à la fois concise et rigoureuse, elle n’indique pas
pt

comment un exemple de problème peut être résolu. L’utilisation d’un logiciel


général pour la programmation linéaire en nombres entiers pourrait ne pas
se

être approprié — à moins que ce logiciel ne détecte automatiquement les


contraintes d’affectation 2.30 et 2.31 et intègre un algorithme ad hoc pour les
traiter, ce qui est souvent les cas.
L’affectation linéaire se modélise facilement par un problème de flot : pour
25

cela on construit un réseau R = (I ∪U ∪{s}∪{t}, E, w, c) de la façon suivante :


Toutes les paires (i ∈ I, u ∈ U ) sont reliées par un arc (i, u) de capacité
w(i, u) = 1 et de coût c(i, u). Un arc (s, i) de capacité w(s, i) = 1 et de coût nul
relie s à chaque sommet-élément i ∈ I et un arc (u, t) également de capacité
g

w(u, t) = 1 et de coût nul relie chaque sommet-élément u ∈ U à t.


La recherche d’un flot maximal à coût minimum dans R permet de trouver
Al

l’affectation optimale en temps polynomial, par exemple avec l’algorithme 2.6.


Des algorithmes spécifiques plus efficaces ont été mis au point pour le pro-
T_

blème de l’affectation linéaire.


Une autre formulation plus concise du problème de l’affectation linéaire est
de
Pn trouver une permutation p des n éléments de l’ensemble U qui minimise
i=1 ci pi ; la valeur pi étant l’élément de U affecté à i.

2.4.3 Affectation quadratique


Dans certains problèmes, les éléments de l’ensemble I ont des interactions
entre eux et l’affectation choisie pour un élément i ∈ I a des répercussions
pour l’ensemble de tous les éléments de I. Prenons l’exemple de l’attribution
de n bureaux à un ensemble de n employés. Dans le problème de l’affectation
54 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

linéaire, le cœfficient ciu mesure uniquement l’intérêt que l’employé i porte au


bureau u, et le fait de lui attribuer ce bureau n’a pas d’autre conséquence que
ce bureau n’est plus disponible pour un autre employé.
En pratique, les employés sont amenés à collaborer, ce qui les amène à
devoir se déplacer d’un bureau à l’autre. Notons aij la fréquence à laquelle
l’employé i doit se rendre dans le bureau de l’employé j. La durée du trajet pour
se rendre d’un bureau u à un bureau v sera notée buv . Si on attribue le bureau u
à l’employé i et le bureau v à l’employé j, le temps moyen perdu par l’employé
i dans ses déplacements sera de aij · buv . Le problème de la minimisation des

17
pertes de temps peut se modéliser par le programme quadratique en variables
0 − 1 suivant, dans lequel la variable xiu prend la valeur 1 si l’employé i occupe
le bureau u et la valeur 0 sinon :

20
n X
X n X
n X
n
Minimiser aiu bjv xiu xjv (2.33)
i=1 j=1 u=1 v=1

e
Sous contraintes
n

br
X
xiu = 1 u = 1, . . . , n (2.34)
i=1
n
em
X
xiu = 1 i = 1, . . . , n (2.35)
u=1
xiu ∈ {0, 1} (i, u = 1, . . . , n) (2.36)
pt

Cette formulation fait bien ressortir le côté quadratique de l’objectif en rai-


son du produit des variables xiu · xjv et les contraintes montrent qu’il s’agit
d’un problème d’affectation. Une modélisation plus concise, sous la forme de
se

la recherche d’une
Pn permutation
Pn p se formule :
Minimiser i=1 j=1 aij · bpi pj .
De nombreuses applications peuvent le formuler comme un problème d’af-
25

fectation quadratique :
Attribution de bureaux à des employés C’est l’exemple qui vient d’être donné.
Attribution de blocs dans un FPGA La programmation d’un réseau de
portes programmables in situ (Field Programmable Gate Array en an-
g

glais) nécessite de connecter entre eux des blocs logiques présent sur
Al

une puce de silicium. Ces blocs permettent d’implanter des équations lo-
giques, des multiplexeurs ou des registres à décalage. Lorsque l’on veut
programmer un FPGA pour qu’il réalise une fonctionnalité donnée, on
T_

commence par établir un schéma dans lequel des on connecte des mo-
dules. On peut décrire ce schéma au moyen d’une matrice de routage
A = (aij ) qui donne le nombre de connexions entre les modules i et j.
Ensuite, il faut attribuer à chaque module i un bloc logique pi sur la puce.
Cependant, on doit prendre soin de ne pas réaliser cette affectation n’im-
porte comment car le temps de propagation des signaux dépend de la
longueur des liaisons. Connaissant la longueur buv de la liaison entre les
blocs logiques u et v, le problème de la minimisation de la somme des
temps de propagation est donc un problème d’affectation quadratique.
Configuration d’un clavier Pour saisir un texte sur le clavier d’un téléphone,
les 26 lettres de l’alphabet ainsi que l’espace on été attribuées aux touches
2.5 C OLORATION DE GRAPHES 55

0, 2, 3, . . . , 9. De manière standard, ces 27 signes sont répartis selon la


configuration de la figure 2.9(a).

17
(a) Clavier standard (b) Clavier optimisé

20
F IGURE 2.9 – Clavier de téléphone standard 2.9(a) et clavier optimisé pour la saisie de
texte français 2.9(b)

e
En supposant que la frappe d’une touche prenne une unité de temps, que
le déplacement d’une touche à une autre prenne deux unités de temps

br
et qu’il faille attendre 6 unités de temps avant de pouvoir commencer à
saisir un nouveau symbole placé sur la même touche que le précédent,
em
on peut calculer qu’il faut 70 unités de temps pour taper le texte « a ce
soir bisous » : en effet, il faut 1 unité pour saisir le « a » sur la touche 2, se
déplacer sur la touche 0, ce qui prend deux unités, appuyer une fois sur
cette touche pour l’espace, 1 unité, se déplacer à nouveau sur la touche
pt

2 et appuyer 3 fois pour le « c », ce qui prend 5 unités, etc.


Avec le clavier optimisé pour le français donné en figure 2.9(b), on calcule
se

qu’il faut seulement 51 unités de temps, soit près d’un tiers de moins. Ce
clavier optimisé a été obtenu en résolvant un problème d’affectation qua-
dratique pour lequel les cœfficients aij représente la fréquence d’appari-
tion du symbole j après le symbole i dans un texte-type et buv représente
25

le délai entre la frappe d’un symbole placé en position u et un autre en


position v.
Le problème de l’affectation quadratique est N P -difficile. En pratique c’est
un des plus difficile de cette classe, car des exemples de problèmes de taille
g

n = 30 ne sont toujours pas résolus optimalement. De nombreux problèmes


Al

N P -difficiles peuvent être transformés très simplement en problèmes d’affec-


tation quadratique. Sans être exhaustif, on peut citer celui du voyageur de com-
merce, celui de l’ordonnancement linéaire ou celui de la bipartition de graphe.
T_

Naturellement, ce n’est pas en les modélisant sous la forme de problèmes d’af-


fectation quadratique que l’on aboutira aux méthodes de résolution efficaces.

2.5 Coloration de graphes


La coloration des arêtes ou des sommets d’un graphe permettent de se
représenter mentalement des problèmes de séparation d’éléments incompa-
tibles. Deux élément compatibles peuvent recevoir la même « couleur » alors
qu’il doivent être colorés différemment s’ils sont incompatibles. Un couleur
représente donc une classe d’éléments compatibles. Dans la coloration des
56 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

3 e 2 e
a b
4
d f a b
c

1 G → L(G) d c f
g

17
5 g

F IGURE 2.10 – Graphe et son graphe représentatif des arêtes, montrant que les pro-

20
blème de la coloration des sommets et des arêtes sont des problèmes équivalents

arêtes d’un graphe, deux arêtes ayant un sommet incident commun doivent

e
recevoir des couleurs différentes. Pour la coloration des sommets, on veut que

br
deux sommets adjacents reçoivent une couleur différente.
Les deux problèmes sont équivalents : À partir d’un graphe G = (V, E), on
peut construire le graphe représentatif des arêtes L(G) = (E, F ), où il existe
em
une arête f ∈ F entre les sommets e et e0 ∈ E de L(G) si ces deux arêtes de G
ont un sommet en commun. Cette construction est illustrée dans la figure 2.10.
Ainsi à une coloration des arêtes de L(G) correspond une coloration des som-
mets de G et vice-versa.
pt

Le problème d’optimisation combinatoire que l’on cherche à résoudre est


de trouver le nombre ou l’indice chromatique du graphe, soit de minimiser le
se

nombre de couleurs nécessaire à sa coloration. Ce problème est N P -difficile


en général, mais polynomial pour la coloration des arêtes d’un graphe biparti.
25

2.5.1 Coloration des arêtes d’un graphe biparti


Un cas particulier de coloration des arêtes est celle d’un graphe biparti.
En effet, dans ce cas, on peut trouver une coloration optimale en temps po-
g

lynomial. Pour cela, on commence par compléter le graphe biparti G = (V =


Al

X ∪ Y, E) en lui ajoutant des sommets au plus petit des sous-ensemble X ou


Y de telle sorte qu’ils aient le même nombre de sommets. Ensuite, on ajoute
des arêtes, tout en maintenant le graphe biparti, de sorte que tous les som-
T_

mets aient le même degré, équivalent au sommet de plus grand degré de G.


Notons G0 le graphe biparti ainsi obtenu. Puis on trouve un couplage parfait
dans G0 en résolvant un problème de flot maximum. Les arêtes de ce couplage
sont colorées toutes avec la couleur 1. Ensuite, on retire de G0 les arêtes de ce
couplage, pour obtenir un graphe G” qui a les mêmes propriétés que G0 , à sa-
voir que les deux sous-ensembles de sommets sont de même cardinal et que
tous les sommets sont de même degré. On peut donc à nouveau trouver un
couplage parfait dans G” et attribuer la couleur 2 aux arêtes de ce couplage.
On réitère ainsi jusqu’à ce que le graphe n’ait plus d’arête. La coloration ainsi
obtenue est optimale pour G0 et pour G car on a réussi à colorer ses arêtes
avec un nombre de couleurs égal au sommet de plus grand degré de G.
2.6 E NSEMBLE STABLE 57

2.6 Ensemble stable


Trouver le plus grand ensemble d’éléments indépendants — un stable maxi-
mal — est un problème classique de la théorie des graphes. Ce problème est
N P -difficile. La section 1.2.3 esquisse le principe de transformation polyno-
miale d’un problème d’acceptabilité en un problème de stable. Ce dernier est
équivalent à celui de la recherche d’un plus grand sous-ensemble d’éléments
complètement dépendants — une clique maximale — dans le graphe complé-
mentaire. Une variante du stable maximal est celle du stable de poids maximal

17
lorsque l’on associe un poids à chaque sommet. On cherche dans ce cas un
sous-ensemble de sommets indépendants dont la somme des poids est la plus
élevée possible. Naturellement, si le poids associé à chaque sommet est uni-

20
taire, cette variante est équivalente au stable maximal.

2.6.1 Étiquetage de plans

e
br
em
pt

F IGURE 2.11 – Problème de l’étiquetage d’un plan : On désire placer le nom de trois
se

objets sur un plan de sorte que les textes ne se recouvrent pas, pour en conserver la li-
sibilité. Ici, on retient 4 possibilités pour le placement de l’étiquette d’un objet. En termes
de graphe, ce problème peut se modéliser sous la forme d’un stable maximum, les som-
mets du stable correspondant aux places finalement choisies pour les étiquettes. Dans
cet exemple, le nom de chaque ville pourrait être placé en haut et à droite.
25

Une application du problème de stable de poids maximal survient pour l’éti-


quetage de plans. Lorsqu’on désire associer des informations textuelles à des
g

objets représentés sur un plan, il s’agit de choisir la place de ces informations


Al

de sorte à ce qu’elles ne se chevauchent pas ou qu’elles ne se superposent


pas à des objets devant être représentés sur le plan. La figure 2.11 illustre un
tout petit problème consistant à étiqueter 3 villes.
T_

Ce problème peut être transformé en celui du stable maximal comme suit :


On crée un sommet pour chaque position potentielle d’étiquette. L’ensemble
des sommets-étiquettes correspondant à un même objet est relié en une clique,
car on ne veut pas étiqueter deux fois le même objet. Deux sommets-étiquettes
incompatibles sont également reliés entre eux par une arête. Un stable corres-
pond à un placement des étiquettes sans chevauchement. On désire trouver un
stable maximum dans ce graphe, afin d’afficher autant de noms que possible
sur le plan.
En pratique, toutes les positions ne sont pas équivalentes. En effet, selon la
langue et la culture, certaines positions doivent être privilégiées, par exemple,
en français on préfère placer les noms en haut à droite plutôt qu’en bas à
58 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

gauche. Les préférences peuvent être modélisées sous la forme de poids as-
sociées aux position. Le problème de l’étiquetage consiste alors à trouver un
stable de poids maximum.
D’autres problèmes peuvent se modéliser exactement de la même ma-
nière : on mentionnera tout d’abord celui de l’attribution de la position sur un
quai pour un bateau faisant escale dans un port. Traduit en termes d’étique-
tage, une étiquette aura comme largeur la durée prévue de l’escale et comme
hauteur la longueur de quai nécessaire pour ce bateau. Les positions possibles
pour cette étiquette sont déterminées par l’heure à laquelle le bateau arrive et

17
les emplacements du ou des quais pouvant recevoir le bateau.
Une autre application de ce problème est l’attribution de niveaux de vol
pour des avions commerciaux. Connaissant les heures de départ prévues de

20
chaque avion et les trajets qu’ils empruntent, on peut déterminer des zones de
collision potentielle entre avion. La dimension de ces zone dépend de l’incer-
titude sur les heures de départ effectives et les trajets réellements suivis. Une
étiquette correspondra donc à une zone. Les positions possibles des étiquettes

e
seront les divers niveaux de vol que l’avion pourrait utiliser.

2.7 Classification br
em
pt
se
25
g
Al
T_

F IGURE 2.12 – Classement de 800 éléments du plan (petits cercles) en 80 groupes. La


taille des disques remplis indique le rayon de chaque groupe.
2.7 C LASSIFICATION 59

De même que la théorie des graphes, la classification automatique est un


outil de modélisation très utile. On peut citer notamment toutes les applications
de reconnaissance, que ce soit de formes en vision artificielle, des textes, pour
la recherche de documents sur le web, ou de voix, pour la commande vocale.
Il existe des algorithmes spécifiques pour réaliser ces tâches automatique-
ment. Notamment, les réseaux neuronaux artificiels sont fréquemment utilisés
en classification supervisée, c’est-à-dire lorsque l’on dispose d’un ensemble
d’éléments-témoins dont on connaît la classe dont ils font partie. Ces tech-
niques sortent du cadre de cet ouvrage. Ne seront également pas traités la

17
construction d’arbres phylogénétiques, popularisé par Darwin au XIXe siècle,
qui consiste à trouver des relations de « parenté » entre les éléments, chaque
nœud de l’arbre représentant un « ancêtre » commun.

20
En toute généralité, la classification consiste à regrouper les éléments qui
sont similaires et à séparer ceux qui ne le sont pas. Cela suppose que l’on
puisse quantifier la « dissimilarité » d(i, j) 6 0 qu’il y a entre deux éléments i
et j appartenant à l’ensemble E que l’on cherche à classer. Souvent, la fonc-

e
tion d(i, j) est une distance, (si l’on a symétrie : d(i, j) = d(j, i), séparation :
d(i, j) = 0 ⇐⇒ i = j et inégalité triangulaire : d(i, k) 6 d(i, j) + d(j, k)), mais

br
pas nécessairement. Pour garantir la stabilité des algorithmes, on supposera
toutefois que d(i, j) > 0 et d(i, i) = 0, ∀i, j ∈ E.
Sitôt que l’on dispose une telle fonction, on peut mesurer l’homogénéité
em
d’un groupe G ⊂ E. Plusieurs définitions ont été proposées pour cette mesure :
Diamètre d’un groupe Valeur maximale de la fonction d(i, j) pour deux enti-
tés i et j appartenant à G : maxi,j∈G d(i, j)
pt

Rayon Dissimilarité maximale qu’il y a entre l’élément le plus central et un


autre de G : mini∈G maxj∈G d(i, j)
se

Clique
PSommeP des dissimilarités entre toutes les paires d’éléments de G :
i∈G j∈G d(i, j)

Étoile Somme desPdissimilarités entre l’élément le plus central de G et les


25

autres : mini j∈G d(i, j)


On peut également mesurer l’hétérogénéité qu’il y a entre deux groupes
G et H. Plusieurs définitions ont été proposées pour mesurer la séparation
existante entre G et H :
g

Séparation Distance minimale entre deux éléments appartenant à des groupes


Al

différents : mini∈G,j∈H d(i, j)


Coupe
P Somme
P des dissimilarités entre éléments de deux groupes différents :
T_

i∈G j∈H d(i, j)


Coupe normaliséeP Moyenne
P des dissimilarités entre éléments de deux groupes
différents : i∈G j∈H d(i, j)/(|G| · |H|)
Une fois un critère d’homogénéité ou d’hétérogénéité défini, on peut formu-
ler le problème de la classification en p groupes G1 , . . . Gp par un problème
d’optimisation en recourant à un objectif global :
— Maximiser la plus petite séparation (ou la plus petite coupe) entre élé-
ments de groupes différents
— Minimiser le plus grand diamètre (ou le plus grand rayon, la plus grande
clique ou encore la plus grande étoile) d’un groupe
60 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

— Minimiser la somme des étoiles (ou la somme des diamètres, rayons,


clique)

2.7.1 P-médiane
Le problème de la p-médiane est un des plus connus en classification non
supervisée. En reprenant les définitions présentées ci-dessus, il s’agit de mini-
miser la somme des étoiles. EnP d’autres termes, il faut trouver les p éléments
c1 , . . . , cp de E qui minimisent : i∈E minr=1,...,p d(i, cr ) Ce problème est N P -

17
difficile.
Un algorithmes heuristiques pour ce problème est la méthode d’améliora-
tion PAM (Partition Around Medoids) 2.7.

20
Algorithme 2.7 : (PAM) Méthode d’amélioration pour le partitionnement autours
de médians.
Entrées : Ensemble E d’éléments avec une fonction mesurant la

e
dissimilarité d(i, j) entre éléments i et j ; p éléments médians
c1 , . . . , cp de E

1 répéter br
Résultat : Groupes G1 , . . . , Gp ⊂ E
em
2 Associer chaque élément i ∈ E au médian le plus proche, et créer
les groupes G1 , . . . , Gp ⊂ E;
3 pour chaque Médian cj faire
4 pour chaque Élément i ∈ E faire
pt

5 Echanger i et cj et calculer le coût total de la configuration;


6 Retenir la meilleure configuration comme nouvel ensemble de
se

médians;
7 jusqu’à ce que les p médians ne bougent plus;
25

L’algorithme PAM a une complexité de Ω(p · n2 ) : En effet, le calcul du coût


de la nouvelle configuration en ligne 5 de l’algorithme nécessite un calcul pro-
portionnel à n, car il faut vérifier, pour chaque élément non associé à cj , si le
nouveau médian i est plus proche de l’actuel. Pour les éléments précédem-
g

ment associés au médian cj , le meilleur médian est soit le second meilleur de


Al

l’ancienne configuration, ce qui peut être pré-calculé et mémorisé en ligne 2,


soit le nouveau médian i essayé. Le nombre de répétitions des lignes 2 à 6
est difficile à évaluer. On observe cependant un nombre relativement faible en
T_

pratique, plus ou moins indépendant de la taille du problème.

2.7.2 Somme des moyennes


Lorsque les éléments sont des vecteurs numériques et que la mesure de
la dissimilarité correspond au carré de la distance (norme l2 ), le point µ qui
minimise le critère d’homogénéité de l’étoile associée à un groupe G est la
moyenne arithmétique des éléments de G (le centre de gravité).
L’algorithme heuristique k-means 2.8 (ou des k-moyennes ; où k fait réfé-
rence au nombre de groupe désirés) pour ce problème est sans doute le plus
connu en classification non supervisée. Comme pour l’algorithme PAM, il s’agit
2.8 S AC DE MONTAGNE 61

Algorithme 2.8 : (k-moyenne) Méthode d’amélioration pour le partitionnement


en p groupes, lorsque les éléments à classer sont des vecteurs numérique en d
dimensions et la mesure de la dissimilarité la norme l2 .
Entrées : Ensemble E d’éléments-vecteurs de Rd avec une fonction
mesurant la norme l2 entre élément ; p centres c1 , . . . , cp de Rd
Résultat : Groupes G1 , . . . , Gp ⊂ E
1 répéter
2 Associer chaque élément i ∈ E au centre le plus proche, et créer les
groupes G1 , . . . , Gp ⊂ E;

17
3 pour chaque i ∈ 1, . . . , n faire
4 ci = centre de gravité de Gi
jusqu’à ce que les p centres ne bougent plus;

20
5

d’une méthode d’amélioration qui démarre avec des centres placés généra-

e
lement aléatoirement. Il alterne une phase d’association des éléments à leur

br
centre le plus proche (ligne 2) et une phase de repositionnement optimal des
centres pour chaque groupe précédemment construit (ligne 4). L’algorithme
s’arrête lorsqu’il n’y a plus de modification dans la position des centres. Cet
em
algorithme est relativement rapide, en Ω(p · n), mais il est très sensible à la
solution initiale fournie ainsi qu’aux mesures extrêmes. Si la dispersion des
éléments est élevée, on a intérêt à utiliser une autre mesure de la dissimilarité,
par exemple la distance ordinaire (norme l1 ), ce qui implique de modifier la
pt

ligne 4 pour replacer les centres. On a alors affaire au problème de Weber.


se

2.8 Sac de montagne


25

Le problème du sac de montagne est certainement celui faisant partie de


la classe N P -difficile qui est le plus simple à formuler en termes de program-
mation linéaire :
g
Al

n
X
Maximiser ci · x i (2.37)
i=1
T_

Sous contraintes
n
X
vi · xi 6 V (2.38)
i=1
xi ∈ {0, 1} (i = 1, . . . , n) (2.39)

On cherche à remplir un sac de volume total V avec des objets dont on


connaît le volume vi et la valeur ci , (i = 1, . . . , n), de sorte à avoir un char-
gement de valeur maximale. Ce problème survient dans diverses situations
et sera utilisé dans cet ouvrage pour illustrer le fonctionnement de certaines
méthodes.
62 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

2.9 Modélisation : Fonction-objectif et fonction-


utilité
Au risque d’énoncer une tautologie, la toute première étape de la résolution
d’un problème est de comprendre ce dernier ! Pour s’assurer que l’on a bien
compris le problème, il faut en extraire la substantifique moelle, ce qui consiste
à exprimer formellement ou à modéliser son noyau. Un problème peut être mo-
délisé de différentes manières, ce qui impliquera l’utilisation de méthodes de
résolution adaptées au modèle choisi. Cette section illustrera diverse modéli-

17
sation d’un même problème, celui de la coloration des sommets d’un graphe.

20
e
br
F IGURE 2.13 – Coloration d’un graphe avec un nombre minimum de couleur. On peut
em
montrer que cette coloration est optimale, car le graphe contient une clique de quatre
éléments.
pt

En section 1.1, nous avons vu que ce problème pouvait se modéliser sous


la forme d’un problème d’acceptabilité, ou plus précisément, si l’on cherche
une coloration en un nombre minimum de couleurs, en une suite de problèmes
se

d’acceptabilité. À moins d’avoir à travailler sur de tout petits graphes et de dis-


poser d’un programme résolvant les problèmes d’acceptabilité, cette approche
n’est guère envisageable. Une autre modélisation, présentée dans la même
25

section, consiste à formuler un programme linéaire en nombres entiers. Celle-


ci utilise un objectif (1.4) qui dépend directement du nombre de couleurs uti-
lisées. En termes généraux, un problème d’optimisation combinatoire peut se
formuler comme
g

Optimiser : f (s) (2.40)


Al

Sous contrainte : s ∈ S (2.41)


Les correspondances entre cette formulation générale et le programme li-
T_

néaire présenté en page 12 sont les suivantes : l’objectif (2.40) consiste à mini-
miser (1.4), qui est équivalente à minimiser l’indice de la couleur la plus élevée
attribué à un sommet du graphe. La contrainte (2.41) résume l’ensemble des
contraintes (1.5) (1.6) (1.7) (1.8).
De manière un peu moins formelle, on peut exprimer le problème de la
coloration de graphe comme :
Minimiser : c = f1 (s) (2.42)
Sous contraintes : 2 sommets adjacents ont des couleurs différentes
(2.43)
et : Nombre de couleurs utilisées par s 6 c (2.44)
2.9 M ODÉLISATION : F ONCTION - OBJECTIF ET FONCTION - UTILITÉ 63

F IGURE 2.14 – Coloration d’un graphe avec une couleur de trop. Un certain nombre de

17
changements sont nécessaires pour la supprimer. Pour cette solution, on a f1 = 5 alors
que pour celle de la figure 2.13 on a f1 = 4.

20
Un objectif consistant à minimiser un maximum — ou à maximiser un mini-
mum — comme (2.42) n’est pas propice à la découverte ou à l’amélioration de
solutions satisfaisant toutes les contraintes. Que faire si une solution que l’on

e
a découverte utilise une couleur de plus que l’optimum ? On ne sait pas s’il y
a juste un sommet qui utilise la couleur supplémentaire ou s’il y en a un grand
nombre.
br
em
pt
se

F IGURE 2.15 – Coloration non admissible d’un graphe avec un nombre donné de cou-
leurs. Pour cette solution, on a f2 = 4 + 2λ alors que pour celle de la figure 2.13 on a
25

f2 = 4 et pour celle de la figure 2.14, on a f2 = 5.

On remplace donc souvent la fonction-objectif par une fonction-utilité inté-


g

grant des contraintes qui ont été relaxées. En l’occurrence, on peut relaxer (2.43)
et formuler le problème, où λ est une constante suffisamment grande :
Al

Minimiser : f2 (s) = c + λ · nombre de violations de (2.43) (2.45)


T_

Sous contraintes : (2.44)

Il est facile de voir que pour une valeur de λ suffisemment grande (par
exemple en posant λ = nombre chromatique), une solution optimisant (2.45)
est également optimale pour (2.42). Ainsi, un triangle coloré avec une seule
couleur aura une valeur de 1 + 3λ, avec deux couleurs on aura une valeur de
2 + λ alors que la coloration optimale a une valeur de 3. Pour 0 < λ < 1/2,
l’optimum de f2 a lieu pour une couleur, pour 1/2 < λ < 1 pour deux couleurs
et pour λ > 1 pour trois couleurs. Par exemple, la solution de la figure 2.13
a une valeur de f2 = 4, celle de la figure 2.14 est de f2 = 5 et celle de la
figure 2.15 est de f2 = 4 + 2λ.
64 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

Cette façon de procéder est directement inspirée de la technique des multi-


plicateurs de Lagrange. Généralement, la valeur du multiplicateur λ associé à
une contrainte relaxée qui a été placée dans la fonction-utilité est modulée en
fonction du succès de la recherche d’une solution : si une solution admissible a
été trouvée, la valeur de λ est diminuée et inversément, si toutes les solutions
générées violaient la contrainte relaxée, la valeur de λ est augmentée.

17
20
F IGURE 2.16 – Coloration partielle d’un graphe avec un nombre donné de couleurs.

e
Pour cette solution, on a f3 = 1.

br
Au lieu de relaxer la contrainte stipulant que deux sommets adjacents ne
doivent pas recevoir la même couleur, on aurait pu relaxer celle qui impose
em
d’attribuer une couleur à chaque sommet :

Minimiser : f3 (s) = Nombre de sommets non colorés (2.46)


pt

Sous contraintes : (2.43)

Plutôt que d’utiliser une fonction-utilité agrégée, on peut également passer


se

par des objectifs hiérarchiques. Dans le cas de la coloration une résolution


passe par la fixation du nombre de couleurs, puis ensuite par une minimisation
du nombre de violation de contraintes. Une fois que l’on a trouvé une solution
admissible, on peut tenter de diminuer le nombre de couleurs avant de recom-
25

mencer. Au contraire, si aucune solution sans violation de contraintes n’est


trouvée, on peut augmenter le nombre de couleurs, sans perdre complètement
le travail fait jusque là.
g
Al
T_

F IGURE 2.17 – Coloration d’un graphe obtenue par orientation sans circuit de ses
arêtes. Le plus long chemin est indiqué en gras. Pour cette solution, on a f4 = 4 (pour
une coloration en cinq couleurs).

La dernière modélisation du problème de la coloration des sommets d’un


graphe que l’on verra ici est moins intuitive : elle consiste à orienter les arêtes
2.10 O PTIMISATION MULTIOBJECTIFS 65

du graphe sans créer de circuit et en cherchant à minimiser la longueur du plus


long chemin dans le graphe ainsi orienté :

Minimiser : f4 (s) = Plus long chemin dans G orienté (2.47)


Sous contraintes : L’orientation des arêtes de G est sans circuit

En effet, une fois que l’on a une telle orientation, on peut facilement trou-
ver une coloration admissible : Les sommets sans prédécesseur reçoivent la
couleur 1 ; ils ne peuvent être connectés par une arête, donc il n’y a pas de vio-

17
lation de contrainte. On peut les retirer du graphe avant d’attribuer la couleur 2
à ceux qui restent et qui n’ont pas de prédécesseur, etc. Ainsi, le nombre de
couleurs obtenues vaut un de plus que la longueur du plus long chemin.

20
Le choix d’une modélisation a une influence majeure sur la capacité de ré-
solution du problème par une méthode donnée. Il convient donc de prêter une
très grande attention à la phase d’analyse du problème. Par exemple, si on
choisit de résoudre un problème d’établissement d’horaire à l’aide de la colo-

e
ration de graphe, l’utilisateur ne cherchera pas nécessairement à trouver un
horaire utilisant la plus petite grille possible — ce qui se traduit par la recher-

br
che d’une coloration avec un nombre minimum de couleur. Il spécifiera plutôt
que la grille comportera un nombre donné de périodes et que le problème con-
siste à trouver un horaire pouvant s’intégrer dans cette grille. Dans ce cas, des
em
fonctions-utilité du type f2 (avec λ proche de 0 et c fixé au nombre de périodes
désirées) ou f3 conviendront certainement mieux que f1 ou f4 .
La technique de relaxation de contraintes par l’intégration d’une mesure
de leurs violations dans une fonction-utilité ne peut être envisagée que pour
pt

un nombre relativement faible de contraintes. Elle est cependant très courante


lorsque l’on a affaire à des contraintes « molles », correspondant à des pré-
se

férences plutôt que des conditions rédhibitoires. Une approche plus souple et
fréquemment employée est de considérer plusieurs objectifs simultanément et
de laisser à l’utilisateur le choix du compromis — choisir une solution privi-
légiant tel objectif plutôt que tel autre. Mais pour cela, les méthodes doivent
25

pouvoir proposer plusieurs solutions variées en lieu et place de celle qui opti-
miserait un unique objectif.
g

2.10 Optimisation multiobjectifs


Al

Un problème d’optimisation avec K objectifs peut se formuler de façon gé-


nérale par :
T_

« Minimiser » : f~(s) = (f1 (s), . . . , fK (s)) (2.48)


Sous contraintes : s ∈ S

Cette formulation suppose que l’on cherche à minimiser chaque objectif,


ce qui ne constitue pas une perte de généralité par rapport à une formulation
où il serait plus naturel d’exprimer une maximisation pour l’un ou l’autre des
objectifs. On dit qu’une solution s1 domine une solution s2 si s1 est meilleure
que s2 sur au moins un objectif et au moins aussi bonne que s2 sur les autres
objectifs.
66 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

Le but de l’optimisation multi-objectifs est donc d’exhiber l’ensemble des


solutions non-dominées. Ces solutions sont qualifiées de Pareto-optimales ou
d’efficaces. Dans une représentation où chaque axe représente la valeur de
chaque objectif, les solutions qui se situent sur l’enveloppe convexe du front
Pareto sont appelées solution supportées. Le choix final d’une solution au
problème étant laissé au décideur, qui se basera notamment sur des consi-
dérations politiques, étiques ou autres qui ne peuvent être raisonnablement
quantifiées et donc introduites soit dans les objectifs, soit dans les contraintes.

17
2.10.1 Ensemble Pareto

20
Aéroport 1

30/120 200/45

e
15/12 35/15

Départ 3/22 Gare


br
19/55
Aéroport 3 Destination
em
3/30

Aéroport 2 250/55
110/50
pt

F IGURE 2.18 – Exemple de problème multi-objectifs : Pour se rendre d’un lieu de départ
à une destination, on a le choix entre plusieurs itinéraires. Chaque itinéraire a un coût
et une durée donnés, indiqués en regard des arcs. Depuis le lieu de départ, on peut se
se

rendre à la gare, soit en bus, soit en taxi, ou encore aller directement en taxi à l’aéroport
le plus proche. Depuis la gare, on peut rejoindre soit l’aéroport le plus proche, soit un
autre aéroport, un peu plus éloigné mais mieux desservi et moins cher. Ensuite, on
prend l’avion pour arriver à l’aéroport le plus proche de la destination, où l’on prend à
25

nouveau soit un bus soit un taxi pour la destination finale.

Un exemple typique d’optimisation multi-objectifs est celui de l’établisse-


g

ment d’itinéraires : On veut se rendre d’un point A à un point B, en utilisant


Al

un réseau de transport donné (ce qui constitue les contraintes) en minimisant


le temps du trajet, en minimisant la consommation d’énergie et en maximisant
l’intérêt touristique du trajet. Ces objectifs sont généralement contradictoires
T_

(un même itinéraire peut se faire en diminuant la consommation mais en aug-


mentant le temps) et l’utilisateur va choisir un itinéraire efficace sur une base
plus subjective : par exemple parce qu’en augmentant « un tout petit peu » le
temps, on diminue « sensiblement » la consommation et on passe dans une
contrée « pittoresque ».
La figure 2.18 illustre le cas d’une personne devant effectuer un trajet en
avion et qui a le choix entre plusieurs moyens de transport pour se rendre à un
aéroport et pour rejoindre sa destination. Les sommets de l’enveloppe convexe
correspondent à des solutions non-dominées ; il existe cependant d’autres so-
lutions non-dominées qui ne sont pas situées sur l’enveloppe convexe, comme
le montre la figure 2.19.
2.10 O PTIMISATION MULTIOBJECTIFS 67

17
20
e
br
F IGURE 2.19 – Représentation des solutions du problème de la figure 2.18 dans un
diagramme coût/temps. Les 9 solutions non-dominées sont mises en évidence. Seules
les 5 solutions supportées pourront être découvertes par une méthode scalaire exacte.
em

2.10.2 Scalarisation
pt

Une technique pour produire diverses solutions à un problème multi-objectifs


se

est de générer un problème mono-objectif avec autant de paramètres que d’ob-


jectifs du problème initial. Ainsi, le problème multi-objectifs 2.48 se transfor-
mera en un problème mono-objectifs avec paramètres w1 , . . . , wK :
25

K
X
Minimiser : wi · fi (s) (2.49)
g

i=1
Sous contraintes : s∈S
Al

P
Généralement on utilise 0 6 wi 6 1 et i wi = 1. Cette technique est
T_

connue sous le nom d’agrégation.


En supposant qu’une méthode exacte permette de résoudre efficacement
le problème 2.49, on peut trouver les solutions efficaces se trouvant sur l’en-
veloppe convexe des solution Pareto-optimales en faisant varier la valeur des
poids wi . Par exemple, en posant wi = 1 pour un i donné et des poids nuls pour
les autres objectifs, on trouvera la solution la meilleure sur le ie critère. Une
fois ces K solutions connues, on peut en connaître une autre, s’il en existe,
en considérant des wi qui forment un vecteur orthogonal à l’hyperplan sup-
porté par les objectifs de ces K solutions. En réitérant le processus avec cette
nouvelle solution, il est possible d’engendrer l’ensemble complet des solutions
supportées.
68 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

2.10.3 Sous-but à atteindre


Le principal défaut de la méthode d’agrégation donnée ci-dessus est que
les solutions efficaces non supportées ne sont pas atteignables. Le cas ex-
trême étant que les seules solutions supportées soient les K qui optimisent
individuellement un seul objectif. On peut extraire les solutions non suppor-
tées en fixant la qualité minimale d’une solution sur un ou plusieurs critères, ce
qui revient à ajouter une ou plusieurs contraintes tout en supprimant le même
nombre d’objectifs. Si l’on impose que les solutions doivent avoir au plus une
valeur v1 pour le premier objectif, on aura le problème à d − 1 objectifs :

17
Minimiser : f~(s) = (f2 (s), . . . , fK (s)) (2.50)
Sous contrainte : f1 (s) 6 v1

20
avec : s ∈ S

Dans l’exemple de la figure 2.18, en se fixant un budget maximal v1 =


250, on trouve la solution de coût 248 pour un temps de 207, qui n’est pas

e
supportée.

br
em
pt
se
25
g
Al
T_
2.10 O PTIMISATION MULTIOBJECTIFS 69

Exercices
Exercice 2.1 (Connexion de points du plan). Un ensemble V de points du plan
doivent être connectés. Comment réaliser les connexions pour que la longueur
totale de ces dernières soit aussi faible que possible ? Application : considérer
les 3 points (0, 0), (30, 57), et (66, 0).
Exercice 2.2 (Accessibilité par des poids lourds). Dans le réseau routier de la
figure 2.20, la charge maximale (en tonnes) est donnée en regard de chaque
tronçon. Quel est le poids du véhicule le plus lourd pouvant aller de A à B ?

17
33 87
1 5 47
6 B

20
49 55
28 42
A 3
49
50

e
32

2
48 85

br
4 8
em
59
65 7 34
pt

F IGURE 2.20 – Problème de charge maximale


se

Exercice 2.3 (Calcul de fiabilité). La figure 2.21 donne un réseau de com-


munication où Les connexions sont sujettes à des pannes. La fiabilité des
connexions est donnée en regard des arêtes. Par quels chemins transmettre
un message du sommet s aux autres avec la plus grande fiabilité possible ?
25

3
0,729 0,81
1
g

1 6
0,81 0,9 0,729 0,81
Al

s 0,9 4 0,9 8
0,81
0,729
T_

1 0,9
2 0,9 7
0,729 0,81
5

F IGURE 2.21 – Problème de fiabilité

Exercice 2.4 (Dégénérescence de l’algorithme de Ford & Fulkerson). Montrer


que l’algorithme de Ford & Fulkerson pour la recherche d’un flot maximum n’est
pas polynomial.
70 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

Exercice 2.5 (Affectation de projets à des étudiants). Quatre étudiants


(A, B, C, D) d’une classe doivent choisir parmi 4 projets de semestre (1, 2, 3, 4).
Chaque étudiant pronostique la note qu’il pense obtenir pour chacun des pro-
jets. Quels doivent être les choix des étudiants pour maximiser la moyenne du
groupe ?
Projet
1 2 3 4
A 6 5 5.8 5.5
Étudiant B 6 5.5 4.5 4.8

17
C 4.5 6 5.4 4
D 5.5 4.5 5 3.8

Exercice 2.6 (Placement d’unités de production). Une entreprise dispose de

20
trois unités de production notées 1, 2 et 3 et veut créer trois nouvelles unités,
notées 4, 5 et 6. Pour cela, elle a retenu trois emplacements notés a, b et c. Une
représentation de la disposition des unités de production est donnée dans la
figure 2.22. Les pièces produites doivent être transférées d’une unité existante

e
vers une nouvelle unité en utilisant uniquement les connexions représentées

6 a
br
sur la figure. Par exemple, la distance entre les unités 1 et b est de 3 + 2 = 5.
em
5 3

4 2
pt

3 b
se

1 1 c
25

1 2 3 4 5 6

F IGURE 2.22 – Problème de localisation de nouvelles unités de production


g

Les nombres de transferts journaliers entre les unités existantes et celle à


Al

construire sont donnés dans le tableau suivante :


T_

4 5 6
1 9 4 0
2 2 7 5
3 3 0 10
Quelle nouvelle unité (4, 5 ou 6) placer en a, (respectivement en b et en
c) de manière à minimiser la distance totale à parcourir chaque jour lors des
transferts de pièces entre les unités de production existantes et les nouvelles ?
Si les nouvelles unités doivent également transférer des pièces entre elles,
peut-on résoudre le problème avec la même technique ?

Exercice 2.7 (Examen oraux). 6 étudiants (A, . . . , F ) doivent passer des exa-
mens oraux pour différents modules (1, . . . , 5). La durée de chaque examen est
2.10 O PTIMISATION MULTIOBJECTIFS 71

d’une heure. Comment construire un horaire aussi court que possible pour le
passage des étudiants, sachant qu’un étudiant ne peut faire qu’un examen à
la fois et un professeur ne peut évaluer qu’un étudiant à la fois ?

Étudiant
A B C D E F
1 × × ×
2 × × × × ×
Module 3 × ×

17
4 × × ×
5 × ×
Exercice 2.8 (Examen écrit). Le tableau suivant résume les inscriptions aux

20
examens de divers modules par les étudiants A, . . . , M . Si chaque candidat
pas au plus un examen par jour, combien de jours sont nécessaires, au mini-
mum, pour organiser la session d’examens ? Tous les étudiants devant passer
le même module sont examinés en même temps.

e
Étudiant

1
A B C D
×
E
× ×br
F G H I
×
J
×
K L M
em
2 × × × ×
3 × × × ×
4 × ×
Module 5 × × × ×
pt

6 × ×
7 × × × ×
8 × × ×
se

Exercice 2.9 (Formulation du TSP). Formuler le problème du voyageur de


commerce sous la forme de la recherche d’une permutation optimale.
Exercice 2.10 (QAP avec plus de positions que d’éléments). Comment adap-
25

ter ou modifier la formulation du QAP lorsqu’il y a moins d’éléments à placer


(n) que de positions (m) ?
Même question s’il y a un coût fixe cir d’affectation de l’élément i à la posi-
g

tion r.
Exercice 2.11 (Configuration des touches d’un téléphone portable). On dé-
Al

sire reconfigurer les touches d’un téléphone portable. On désire placer unique-
ment les 26 lettres minuscules ainsi que l’espace sur les touches 0, 2, 3, . . . , 9.
T_

On peut placer au maximum quatre caractères par touche. On connaît, pour


la langue considérée, la fréquence fi d’apparition du caractère i ainsi que la
fréquence gij d’apparition du caractère j après le caractère i. Pour saisir un
caractère en position p sur une touche, il faut la presser p fois, ce qui prend
p unités de temps. Pour passer d’une touche à une autre, le temps de dépla-
cement est d’une unité de temps. Pour saisir deux caractères placés sur la
même touche, cela prend 6 unités de temps. Comment construire un exemple
de problème d’affectation quadratique pour la configuration du clavier ?
Exercice 2.12 (Transformation de bipartion et du TSP en QAP). Le problème
de la bipartition d’un graphe consiste à séparer ses sommets en deux sous-
ensembles X et Y de même taille (on suppose un nombre pair de sommets)
72 E XEMPLES ET MODÉLISATION DE PROBLÈMES COMBINATOIRES

de sorte que le nombre d’arêtes ayant une extrémité dans X et l’autre dans
Y soit aussi faible que possible. Comment construire un exemple de problème
d’affectation quadratique pour la bipartition d’un graphe ? Même question pour
la transformation du TSP en QAP.
Exercice 2.13 (Bipartition spéciale). On considère un jeu de cartes numéro-
tées de 1 à 50. On désire former deux tas avec ces cartes, le premier avec une
somme des valeurs numérotées de 1170 et l’autre avec un produit de 36000
Comment coder une tentative de solution à ce problème ? Comment évaluer la
qualité d’une tentative de solution ?

17
Exercice 2.14 (Carré magique). On désire créer un carré magique d’ordre n.
Ce carré comporte n × n cases devant être remplies avec les nombres de 1 à

20
n2 . La somme des nombres dans chaque ligne, colonne et diagonale doit valoir
(n3 − n)/2. On donne ci-dessous un exemple de carré magique d’ordre 4.

34

e
%
4 14 15 1 → 34
9
5 br
7 6 12 →
11 10 8 →
34
34
em
16 2 3 13 → 34
↓ ↓ ↓ ↓ &
34 34 34 34 34
Comment coder une tentative de solution à ce problème ? Comment éva-
pt

luer la qualité d’une tentative de solution ?


Exercice 2.15 (Critère d’optimalité). Prouver que l’ordonnancement au plus
se

tard donné en exemple est optimal.

Exercice 2.16 (Évaluation de l’objectif pour la chaîne de traitement). Connais-


sant le temps tij du traitement de l’objet i sur la machine j pour une chaîne de
25

traitement à séquence fixée, comment calculer les heures de fin au plus tôt fij
et de début au plus tard dij de chaque opération si les objets passent dans un
ordre donné par une permutation p ?
g

Exercice 2.17 (Fabrication de plaques de verre). Pour la fabrication de plaques


de verre, le verre fondu passe sur une chaîne de m machines dans l’ordre
Al

1, 2, . . . , m. Selon les caractéristiques désirées pour chaque plaque, le temps


de traitement sur chaque machine diffère. On suppose que l’on a n plaques
T_

différentes à produire (dans un ordre qui peut être choisi par le gestionnaire de
la chaîne) et que l’on connaît le temps tij du traitement de la plaque i sur la
machine j. De plus, lorsqu’une machine a terminé le traitement d’une plaque,
cette dernière doit immédiatement passer sur la machine suivante, qui doit la
traiter sans attendre pour qu’elle ne refroidisse pas. Une machine ne traite
qu’une plaque à la fois. Le gestionnaire de la chaîne doit déterminer dans quel
ordre produire les n plaques pour terminer la production aussi rapidement que
possible. Comment modéliser ce problème sous la forme d’un voyageur de
commerce ?
17
20
Deuxième partie

e
br
Techniques heuristiques de
em
base
pt
se
25
g
Al
T_
T_
Al
g
25
se
pt
em
br
e
20
17
Chapitre 3

17
Méthodes constructives

20
3.1 Construction systématique

e
br
Lorsque l’on doit trouver la meilleure solution possible à un problème d’op-
timisation combinatoire, la première idée qui vient est d’essayer de construire
toutes les solutions du problème, d’évaluer leur faisabilité et leur qualité et de
em
retourner la meilleure qui satisfait l’ensemble des contraintes. Évidemment,
cette approche ne peut se prêter qu’à des problèmes de taille limitée. Prenons
l’exemple d’un tout petit problème de sac de montagne en variables 0 − 1 à
deux contraintes :
pt

max r = 9x1 + 5x2 + 7x3 + 3x4 + x5


sous 4x1 + 3x2 + 5x3 + 2x4 + x5 6 10
se

(3.1)
contraintes 4x1 + 2x2 + 3x3 + 2x4 + x5 6 7
xi ∈ {0, 1}(i = 1, . . . , 5)
25

Pour énumérer systématiquement l’ensemble des solutions de ce problème,


on construit un arbre d’énumération : le premier nœud sépare les solutions
pour lesquelles x1 = 0 de celles où x1 = 1. Au second niveau, on aura les
deux nœuds séparant x2 = 0 et x2 = 1, etc. Potentiellement, ce problème a
g

25 = 32 solutions, dont un grand nombre ne sont pas réalisable, car violant


l’une ou l’autre ou les deux contraintes. Formellement, le premier nœud crée
Al

deux sous-problèmes qui seront résolus de façon récursive. Le premier sous-


problème est obtenu en remplaçant x1 par 0 dans 3.1 :
T_

max r = 0 + 5x2 + 7x3 + 3x4 + x5


sous 3x2 + 5x3 + 2x4 + x5 6 10
contraintes 2x2 + 3x3 + 2x4 + x5 6 7
xi ∈ {0, 1}(i = 2, . . . , 5)

Le second en remplaçant x1 par 1 dans (3.1) :

max r = 9 + 5x2 + 7x3 + 3x4 + x5


sous 3x2 + 5x3 + 2x4 + x5 6 6
contraintes 2x2 + 3x3 + 2x4 + x5 6 3
xi ∈ {0, 1}(i = 2, . . . , 5)
76 M ÉTHODES CONSTRUCTIVES

Pour éviter d’énumérer inutilement des solutions, on peut élaguer l’arbre en


remarquant que si l’une ou l’autre des contraintes est violée dans un nœud,
toutes les branches découlant de de nœud mèneront à des solutions inadmis-
sibles car tous les coefficients des contraintes sont non négatifs. Par exemple,
si les variables x1 = x2 = x3 = 1 sont déjà fixées, les deux contraintes sont
violées et tous les sous-problèmes que l’on pourrait créer à partir de là n’auront
pas de solutions admissibles. Par conséquent, il est inutile de développer cette
branche en essayant de fixer des valeurs pour les variables x4 et x5 .
Une autre façon d’élaguer les branches non prometteuses est d’évaluer

17
sommairement si un sous-problème ne peut mener à une solution meilleure
que la meilleure connue jusque là. Il s’agit de la méthode d’évaluation et sépa-
ration.

20
3.1.1 Évaluation et séparation

e
Pour estimer rapidement si un sous-problème peut avoir une solution, et si
cette dernière est prometteuse, une technique consiste à relaxer une ou plusi-

br
eurs contraintes. La solution optimale du problème relaxé n’est pas forcément
admissible pour le problème initial. Par contre, il est possible de faire quelques
em
déductions à partir de la résolution du problème relaxé : si ce dernier n’a pas
de solutions ou qu’il a une solution optimale plus mauvaise que la meilleure
solution admissible connue du problème initial, il est inutile de continuer à dé-
velopper la branche partant de ce sous-problème. Si le sous-problème relaxé
pt

a une solution optimale qui est admissible pour le problème initial, il est éga-
lement inutile de développer la branche, puisqu’on connaît déjà comment fixer
optimalement les variables encore libres de cette branche.
se

Plusieurs techniques sont couramment utilisées pour simplifier un sous-


problème par la relaxation de contraintes :

Intégralité des variables Ce qui rend le problème (3.1) difficile, c’est que l’on
25

impose aux variables de prendre des valeurs entières. On peut donc re-
laxer cette contrainte et résoudre le problème :

max S = 9x1 + 5x2 + 7x3 + 3x4 + x5


g

sous 4x1 + 3x2 + 5x3 + 2x4 + x5 6 10


(3.2)
Al

contraintes 4x1 + 2x2 + 3x3 + 2x4 + x5 6 7


0 6 xi 6 1(i = 1, . . . , 5)
T_

En résolvant ce problème linéaire pour lequel on connaît des algorithmes


polynomiaux et efficaces, on trouve la solution optimale (0, 5; 1; 1; 0; 0)
de valeur 16, 5 qui comporte une valeur fractionnaire, ce qui n’est pas
admissible pour le problème initial. Par contre, on sait dorénavant qu’il
n’existe aucune solution au problème (3.1) dont la valeur dépasse 16, 5
(ou même 16 puisque tous les coefficients sont entiers) . Si l’on avait pu
« deviner » la solution (1; 0; 1; 0; 0), du problème initial, de valeur 16, la
résolution du programme linéaire aurait démontré qu’elle est optimale.
Agrégation des contraintes Un certain nombre de contraintes sont addition-
nées (éventuellement avec des coefficients multiplicatifs) pour en obtenir
3.1 C ONSTRUCTION SYSTÉMATIQUE 77

une autre. Dans l’exemple, cela donne :


max S = 9x1 + 5x2 + 7x3 + 3x4 + x5
sous 8x1 + 5x2 + 8x3 + 4x4 + 2x5 6 17 (3.3)
contraintes xi ∈ {0, 1}(i = 1, . . . , 5)

Ce problème est un sac de montagne classique, plus facile à résoudre


que le problème initial. La solution (1, 1, 0, 1, 0) est optimale pour le pro-
blème relaxé mais n’est pas admissible pour le problème initial car la se-
conde contrainte est violée. Comme le problème relaxé est N P -difficile,

17
sa résolution pourrait parfois soulever certaines difficultés.
Combinaison de relaxations Il est évidemment possible de combiner plusi-
eurs types de relaxation, par exemple l’agrégation de contraintes et l’in-

20
tégralité des variables. Dans l’exemple, cela donne :
max S = 9x1 + 5x2 + 7x3 + 3x4 + x5
sous 8x1 + 5x2 + 8x3 + 4x4 + 2x5 6 17 (3.4)

e
contraintes 0 6 xi 6 1(i = 1, . . . , 5)

br
Ce problème peut être résolu en O(n log n) de la façon suivante : Les
variables sont triées dans l’ordre des ri /vi décroissants (où ri est le re-
venu de l’objet i et vi son volume (agrégé) ; dans l’exemple, les indices
em
sont déjà triés) puis on prend les objets les uns après les autres dans
cet ordre jusqu’à ce qu’il soit impossible d’ajouter entièrement un nouvel
objet (ce qui donne x1 = x2 = 1). L’objet suivant est fractionné de façon
à remplir totalement le sac ( =⇒ x3 = 4/8 pour une valeur totale du sac
pt

S = 9 + 5 + 7 · 4/8 = 17, 5). Comme tous les coefficients sont entiers


dans l’exemple, S = b17, 5c = 17 est également une borne supérieure à
se

l’optimum du problème initial.


La trame 3.1 donne une technique générale de la méthode d’évaluation et
séparation. On remarquera que trois de ses composantes doivent être spéci-
fiées par l’utilisateur avant d’aboutir à un algorithme complet. Tout d’abord, il
25

faut spécifier comment l’ensemble Q des sous-problèmes en attente de traite-


ment doit être géré. Si Q est géré en queue, on aura une exploration en largeur.
Si Q est géré en pile, on aura une exploration en profondeur, ce qui favorise
l’obtention rapide d’une solution admissible au problème initial. Q est cepen-
g

dant souvent géré en queue de priorité, ce qui suppose le calcul d’une valeur
Al

pour chaque sous-problème, valeur que devrait être fortement corrélée avec
celle de la meilleure solution pouvant être obtenue en développant la branche
(par exemple, la valeur S du problème relaxé). Souvent, le choix d’une méthode
T_

de gestion de l’ensemble Q est réalisé de façon très empirique.


La seconde composante à définir par l’utilisateur est la technique de re-
laxation. C’est sans doute un des points les plus délicats de l’adaptation d’un
algorithme de séparation et évaluation pour un problème donné. Ce point dé-
pend non seulement fortement du problème à résoudre mais également des
données numériques. Une technique, connue sous le nom de séparation et
coupe est d’ajouter des contraintes au sous-problème relaxé pour supprimer
des solutions non réalisables, comme par exemple certaines valeurs fraction-
naires pour des variables devant être entière dans le problème initial.
Finalement il faut faire un choix pour séparer le problème, si la résolution
d’une relaxation indique que l’on peut obtenir, potentiellement, des solutions en
78 M ÉTHODES CONSTRUCTIVES

17
Algorithme 3.1 : Trame d’une méthode d’évaluation et séparation pour un ob-
jectif f à maximiser. Il est nécessaire de fournir trois méthodes : une pour la ges-
tion des sous-problèmes à résoudre (généralement, une queue de priorité (basée

20
sur un critère heuristique) ou une pile), une méthode de calcul de relaxation des
sous-problèmes et une heuristique choisissant la prochaine variable sur laquelle
séparer un problème en plusieurs sous-problèmes.
Entrées : Un problème à n variables x1 , . . . , xn , politique α de gestion

e
des sous-problèmes, méthode β de relaxation, politique γ de

1 f ∗ ← −∞;
branchement

br
Résultat : Une solution optimale x∗ de valeur f ∗
// Valeur de la meilleure solution trouvée
em
2 F ←∅; // Ensemble des variables fixées
3 L ← {x1 , . . . , xn } ; // Ensemble des variables libres
4 Q ← {(F, L)} ; // Ensemble des sous-problèmes à résoudre
5 tant que Q 6= ∅ faire
pt

6 Retirer un problème P = (F, L) de Q selon la politique α;


7 si P peut potentiellement avoir des solutions admissibles avec les
se

valeurs déjà fixées dans F alors


8 Calculer, avec la méthode β, une relaxation x de P en ne
modifiant que les variables xk ∈ L;
9 si x est admissible pour le problème initial et f ∗ < f (x) alors
25

10 x∗ ← x;
11 f ∗ ← f (x)
12 sinon si f (x) > f ∗ alors
13 Choisir un xk ∈ L selon la politique γ; // Développer la branche
g

14 pour chaque Valeur v possible de xk faire


Q ← Q ∪ {(F ∪ {xk = v}, L \ {xk })}
Al

16

17 sinon
Élaguer la branche ; // Elle n’a pas de solution meilleure que x∗
T_

18
3.2 C ONSTRUCTION ALÉATOIRE 79

développant un nœud. Une politique simple est de choisir la variable d’indice


le plus faible, ou une variable non entière dans la solution du problème relaxé.
Mais ici également, la politique utilisée est très empirique.
Une mise en œuvre simple de cette trame est l’algorithme de recherche A*.
Dans cet algorithme, les politiques α et γ de retrait d’un sous-problème et de
développement d’une branche sont basées sur la valeur de la relaxation. Cela
suppose donc que l’on évalue cette valeur heuristique avant d’insérer un sous-
problème dans l’ensemble Q et que ce dernier est géré en queue de priorité.
Dans certains cas, le nombre de valeurs possibles pour la prochaine va-

17
riable xk à fixer est très grand ; notamment lorsque xk peut prendre n’im-
porte quelle valeur entière. Une technique de branchement est de considérer
la valeur y non entière d’une variable xk pour le problème relaxé et de créer

20
deux branches, l’une avec la contrainte supplémentaire xk 6 byc et l’autre
xk > byc + 1. Dans ce cas, les ensembles de variables fixées et libres ne sont
pas modifiés à la ligne 16. Cette technique a été proposée par [?].
Ces dernières années, les méthodes dites exactes pour la résolution de

e
programmes linéaires en nombres entiers ont fait de gros progrès, notamment
grâce au développement de relaxations, de politiques de séparation et de bran-

br
chement de plus en plus élaborées. Certains logiciels, comme CPLEX ou Gu-
robi, intègrent des méthodes basées sur des métaheuritiques pour le calcul
em
de bornes ou pour l’obtention de solutions de bonne qualité, ce qui permet
d’élaguer plus rapidement l’arbre d’énumération. Malgré cela, on n’échappe
pas à une croissance exponentielle du temps de résolution lorsque la taille des
problèmes augmente.
pt

3.2 Construction aléatoire


se

Une méthode simple et rapide pour obtenir une solution est de la générer
aléatoirement parmi l’ensemble des solutions admissibles. On ne peut évidem-
25

ment espérer trouver ainsi de manière fiable une excellente solution, mais cette
méthode est largement employée dans des trames itératives où l’on répète une
phase constructive suivie d’une phase d’amélioration avec une recherche lo-
cale.
g

Notons qu’il n’est pas forcément évident d’écrire une procédure qui per-
mette de générer chaque solution avec la même probabilité. L’exercice 3.1
Al

traite l’exemple de la génération d’une permutation aléatoire de n éléments.


Des approches naïves comme celles données par les algorithmes 3.5 et 3.6
T_

peuvent mener à des solutions non efficaces ou/et non uniformes.

3.3 Construction gloutonne


Dans le chapitre 2, les premiers algorithmes classiques de graphes passés
en revue — Prim et Kruskal pour la construction d’arbres de poids optimaux,
Dijkstra pour la recherche de plus courts chemins — étaient des algorithmes
gloutons. Ceux-ci construisent une solution en ajoutant un élément à chaque
étape. L’élément qui est ajouté l’est définitivement, sur la base d’une fonction
évaluant sa pertinence pour la solution partielle en cours de construction.
80 M ÉTHODES CONSTRUCTIVES

En supposant qu’une solution est composée d’éléments e ∈ E et que l’on


peut associer à une solution partielle s une fonction de coût incrémental c(e, s)
si on ajoute e à s, l’algorithme 3.2 donne la trame d’une construction gloutonne.

Algorithme 3.2 : Trame d’une méthode gloutonne. Il ne s’agit pas d’un algo-
rithme à proprement parler, car différentes implantations sont possibles, selon la
définition de l’ensemble E des éléments constituant les solutions et la fonction de
coût incrémental.
Entrées : s solution partielle triviale (généralement ∅) ; ensemble E

17
d’éléments dont sont constituées les solutions du problème ;
fonction de coût incrémental c(s, e)
Résultat : Solution complète s

20
1 R ← E; // Éléments pouvant encore être ajoutés à s
2 tant que R 6= ∅ faire
3 ∀e ∈ R, évaluer c(s, e);
4 Choisir un e0 optimisant c(s, e0 );

e
5 s ← s ∪ e0 ; // Ajouter e0 à la solution partielle s
6
compléter s;
br
Retirer de R les éléments qui ne peuvent plus être utilisés pour
em
Des algorithmes aux performances très variées peuvent être obtenus selon
la définition de E et c(s, e). Si l’on prend l’exemple de l’arbre de Steiner, on
pourrait considérer que E est l’ensemble des arêtes du problème et la fonction
pt

de coût incrémental le poids de chaque arête. Une solution partielle est alors
constituée d’une forêt.
se

Une autre modélisation pourrait être de considérer E comme les points


de Steiner. La fonction de coût incrémental consisterait à calculer un arbre de
poids minimum sur l’ensemble des nœuds ordinaires, ceux déjà introduits dans
s et celui que l’on tente d’ajouter à s.
25

Nous allons maintenant donner quelques exemples d’heuristiques glou-


tonnes qui ont été proposées pour divers problèmes d’optimisation combina-
toire.
g
Al

3.3.1 Méthodes gloutonnes pour le problème du voyageur


de commerce
T_

Glouton sur les arêtes

La manière la plus simple de concevoir un algorithme glouton pour le voya-


geur de commerce est de considérer que les éléments e que l’on va ajouter
à une solution partielle s sont des arêtes, avec comme fonction de coût incré-
mental le poids de l’arête. Initialement, on part d’une solution partielle s = ∅.
L’ensemble R est constitué des arêtes que l’on peut ajouter à la solution, sans
créer de sommet de degré > 2 ni de cycle ne comportant pas toutes les villes.
La figure 3.1 illustre l’exécution de cette heuristique sur un petit exemple de
problème.
3.3 C ONSTRUCTION GLOUTONNE 81

F IGURE 3.1 – Exécution d’un algorithme glouton basé sur le poids des arêtes pour le
voyageur de commerce.

17
Plus proche voisin
Une méthode gloutonne des plus simples à programmer pour le problème

20
du voyageur de commerce est celle connue sous le nom de plus proche voisin.
Les éléments à insérer sont les villes plutôt que les arêtes. Une solution par-
tielle s est donc un chemin dans lequel les villes sont visitées dans l’ordre de
leur insertion. Le coût incrémental correspond au poids de l’arête qui permet

e
de relier la prochaine ville. La figure 3.2 illustre l’exécution de cette heuristique
sur le même exemple de problème que précédemment. Le fait d’obtenir une

br
solution identique à la méthode précédente est une coïncidence. Elle peut être
programmée de façon très concise en Θ(n2 ), où n est le nombre de villes,
em
comme le montre le code 3.1.
pt
se

F IGURE 3.2 – Exécution du plus proche voisin pour le problème du voyageur de com-
merce.
25

Listing 3.1 – tsp_nearest_neighbour.c Code C de l’heuristique du plus proche voisin


pour le problème de voyageur de commerce. Remarquer l’extrême similitude de ce code
avec l’implantation de l’algorithme de Dijkstra donné par le code 2.1.
g

double t s p _ n e a r e s t _ n e i g h b o u r ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , /∗ Distance matrix ∗/
int s, /∗ S t a r t i n g c i t y ∗/
Al

int solution [ ] ) / ∗ −−>Out Order o f t h e c i t i e s ∗/


{ i n t i , j , j _ k e p t = −1;
double d i s t _ i n s , l e n g t h = 0 . 0 ; / ∗ Cost o f i n s e r t i n g c i t y j , path l e n g t h ∗/
T_

f o r ( i = 0 ; i < n ; i ++)
solution [ i ] = i ;
swap ( s o l u t i o n + s , s o l u t i o n + 0 ) ; / ∗ Tour s t a r t s from c i t y s ∗ /

f o r ( i = 1 ; i < n−1; i ++) / ∗ C i t i e s s o l u t i o n [ 0 ] t o s o l u t i o n [ i −1] f i x e d ∗ /


{ dist_ins = i n f i n i t e ;
f o r ( j = i ; j < n ; j ++) / ∗ Choose n e x t c i t y t o i n s e r t ∗ /
i f ( d [ solution [ i −1]][ solution [ j ] ] < d i s t _ i n s )
{ d i s t _ i n s = d [ solution [ i −1]][ solution [ j ] ] ;
j_kept = j ;
}
l e n g t h += d i s t _ i n s ;
swap ( s o l u t i o n + i , s o l u t i o n + j _ k e p t ) ;
}
return length + d [ solution [ n−1]][ solution [ s ] ] ;
} /∗ tsp_nearest_neighbour ∗/
82 M ÉTHODES CONSTRUCTIVES

Regret le plus grand

Si l’on examine le comportement de l’heuristique du plus proche voisin,


on se rend compte, et cela apparaît dans la figure 3.2, que l’on risque d’oublier
temporairement des villes, ce qui occasionne ultérieurement de larges détours.
Pour tenter d’éviter ce genre de situation, on peut évaluer le regret que cause-
rait la non visite de la ville e juste après la dernière ville i du chemin partiel s :
la ville e devra de toute façon figurer dans la tournée finale et il en coûtera au
moins minj,k∈R dje + dek pour la visiter. Par contre, si l’on visite e juste après i,
cela coûtera au moins minr∈R die + der

17
L’heuristique du regret le plus grand choisit donc la ville e qui maximise
c(s, e) = minj,k∈R dje + dek − minr∈R die + der .

20
Insertion la moins coûteuse

L’heuristique de l’insertion la moins coûteuse consiste à insérer une ville

e
dans une tournée partielle. L’ensemble E est donc celui des villes et la solution
triviale de départ un cycle sur les deux villes les plus proches. Le coût incré-

br
mental c(s, e) d’une ville est le détour minimal qu’il faut consentir pour insérer
la ville e dans la tournée partielle s entre deux villes successives de s.
em
pt

F IGURE 3.3 – Exécution de l’heuristique de l’insertion la moins coûteuse.


se
25

Insertion la plus coûteuse

L’heuristique de l’insertion la plus coûteuse est similaire à la précédente,


mais elle choisit à chaque étape la ville dont l’insertion occasionne le plus
grand détour. Chaque ville est toutefois insérée à la meilleure place possible
g

dans la tournée. Il pourrait paraître contre-intuitif de choisir à chaque étape la


Al

ville la plus problématique. Cependant, une analyse montre que ce mode de


construction est moins myope et produit souvent de meilleures solutions finales
que l’heuristique précédente.
T_

F IGURE 3.4 – Exécution de l’heuristique de l’insertion la plus coûteuse.

Nous n’avons donné ici qu’une toute petite palette des méthodes construc-
tives gloutonnes qui ont été proposées pour le voyageur de commerce. La
3.4 A MÉLIORATION DE LA CONSTRUCTION GLOUTONNE 83

qualité des solutions qu’elles produisent est très variable. Il n’est généralement
pas très difficile de trouver des exemples de problèmes pour lesquels l’heuris-
tique gloutonne se fourvoie et fait des choix de plus en plus mauvais. Sur des
semis de point uniformément distribués dans un carré du plan euclidien, elles
fournissent des solutions dont la longueur dépasse de quelques dizaines de
pour-cent celle de l’optimum.

3.3.2 Méthode gloutonne pour la coloration de sommets

17
Méthode DSATUR

Une méthode gloutonne relativement élaborée pour la coloration des som-

20
mets d’un graphe essaie de déterminer le sommet pour lequel l’attribution
d’une couleur risque d’être la plus problématique. La méthode DSATUR [?]
fait l’hypothèse que ce sera le sommet qui a déjà de nombreux voisins colorés
avec une large palette de couleur. On définit donc le degré de saturation d’un

e
sommet v, noté DS(v), le nombre de couleurs différentes employées par les
sommets adjacents de v. À degré de saturation égal — notamment au départ,

br
lorsqu’aucun sommet n’est coloré — on choisira le sommet de degré le plus
élevé. À degré de saturation et degré égaux, les sommets sont départagés
em
arbitrairement.

Algorithme 3.3 : Algorithme DSATUR pour la coloration de graphe. Le critère


glouton utilisé par cet algorithme est le degré de saturation des sommets, c’est-à-
pt

dire le nombre de couleurs différentes utilisées par les sommets adjacents.


Entrées : Graphe non orienté G = (V, E);
se

Résultat : Coloration des sommets


1 Colorer le sommet v de plus grand degré avec la couleur 1;
2 R ← V \ v;
3 couleur ← 1;
25

4 tant que R 6= ∅ faire


5 ∀v ∈ R, évaluer DS(v);
6 Choisir un v 0 maximisant DS(v 0 ), de degré le plus élevé possible;
7 Trouver k le plus petit possible (1 6 k 6 couleur + 1) tel que la
g

couleur k soit admissible pour v 0 ;


8 Colorer v 0 avec la couleur k;
Al

9 si k > couleur alors


10 couleur = k
T_

11 R ← R \ v0 ;

3.4 Amélioration de la construction gloutonne


Le principal défaut d’une construction gloutonne est qu’elle ne remet jamais
en cause un choix qui a été fait de façon myope. À l’inverse, le défaut d’une
méthode énumérative complète est la croissance exponentielle de l’effort de
calcul en fonction de la taille du problème. Pour limiter cette croissance, il faut
84 M ÉTHODES CONSTRUCTIVES

Solution partielle de départ


Élément ajouté à la solution de départ
p meilleurs candidats du niveau 1
p meilleurs candidats du niveau 2

Meilleur candidat au niveau k

17
F IGURE 3.5 – Recherche en faisceaux avec p = 3 et k = 3. Avant de choisir l’élément à
insérer dans la solution partielle, on fait une énumération en largeur jusqu’à une profon-
deur de k, en ne retenant à chaque profondeur que les p candidats jugés les meilleurs.

20
donc limiter le développement de certaines branches, ce qui se fait générale-
ment sur la base de critères gloutons.

e
Dans cette section, nous présentons deux techniques d’énumération par-

br
tielles qui ont été proposées pour améliorer un algorithme glouton. La pre-
mière, la recherche en faisceaux (Beam Search dans la littérature anglo-
saxonne) a été proposée dans le cadre d’une application en reconnaissance
em
de la parole [?]. La seconde, proposée par [?] est la méthode pilote, plus ré-
cente, a été présentée directement comme la trame d’une méta-heuristique.
D’autres trames en ont été dérivées [?].
pt

3.4.1 Recherche en faisceaux


se

La recherche en faisceaux est une trame d’énumération procédant en lar-


geur. Au lieu de conserver toutes les branches, seules p sont conservées au
maximum à chaque niveau, sur la base d’une fonction c(s, e) qui donne un coût
25

heuristique d’ajout de l’élément e à la solution partielle s. Lorsqu’on arrive au


niveau k, ou si on a une solution complète, on ajoute à la solution du premier
niveau de l’arbre d’énumération l’élément e qui mène à la meilleure solution au
dernier niveau. La figure 3.5 illustre le principe d’une recherche en faisceaux.
g

Il est possible de généraliser la recherche en faisceaux en ne considérant


pas qu’un sous-ensemble de nœuds à chaque niveau de l’arbre d’énumération,
Al

mais en faisant une énumération complète jusqu’à une profondeur telle que
l’on ait plus de p nœuds au dernier niveau. De l’ensemble de ces nœuds, on
T_

en retient les p meilleurs qui sont utilisés pour générer les candidats au niveau
suivant.

3.4.2 Méthode pilote


La trame de la méthode pilote nécessite une heuristique dite pilote per-
mettant de compléter une solution partielle en une solution complète. Cette
heuristique pilote peut être une simple méthode gloutonne, par exemple l’heu-
ristique du plus proche voisin pour le problème du voyageur de commerce,
mais elle peut également être une méthode beaucoup plus sophistiquée, telles
que celles présentées dans les chapitres suivants.
3.4 A MÉLIORATION DE LA CONSTRUCTION GLOUTONNE 85

Solution partielle de départ


Élément ajouté à la solution de départ

Prochaine solution partielle

Complétions avec l’heuristique pilote

17
20
Meilleure solution complète
F IGURE 3.6 – Méthode pilote. On ajoute à la solution de départ un élément, puis on
applique une heuristique pilote qui la complète totalement avant de répéter le processus
avec un autre élément ajouté à la solution de départ. L’élément finalement inséré est

e
celui ayant mené à la meilleure des solutions complètes.

br
em
Cette trame énumère toutes les solutions partielles qu’il est possible d’ob-
tenir en ajoutant un élément à la solution de départ. On applique ensuite à
toute ces solutions partielles l’heuristique pilote pour aboutir à autant de solu-
tion complètes. La solution partielle qui a été à l’origine de la meilleure solution
pt

complète est utilisée comme nouvelle solution de départ, jusqu’à ce qu’il n’y ait
plus d’élément à ajouter. La figure 3.6 illustre une étape de la méthode.
se
25
g
Al
T_
86 M ÉTHODES CONSTRUCTIVES

Algorithme 3.4 : Trame d’une méthode pilote.


Entrées : sp solution partielle triviale ; ensemble E d’éléments dont sont
constituées les solutions du problème ; heuristique pilote h(se )
permettant de compléter totalement une solution se ; fonction
f (s) de calcul du coût d’une solution admissible s
Résultat : Solution complète s∗
1 R ← E; // Éléments pouvant encore être ajoutés à s
2 tant que R 6= ∅ faire
3 v ← ∞;

17
4 pour tous les e ∈ R faire
5 Compléter sp avec e pour obtenir se ;
6 Appliquer h(se ) pour obtenir une solution complète s;

20
7 si f (s) 6 v alors
8 v ← f (s);
9 sr ← se ;
10 si s est meilleure que s∗ alors

e
11 s∗ ← s; // Mémoriser la solution complète s
12
13
sp ← sr ;
br
// Ajouter un élément à la solution partielle sp
Retirer de R les éléments qui ne peuvent plus être utilisés pour
compléter sp ;
em
La trame 3.4 précise le fonctionnement de cette méta-heuristique. Notons
que dans cette trame, la dernière des solutions «partielles» est une solution
pt

complète admissible qui n’est pas forcément la solution retournée par cet algo-
rithme. En effet, l’heuristique pilote peut générer une solution complète qui ne
se

comporte pas forcément les éléments de la solution partielle de départ, notam-


ment si elle comporte une technique d’amélioration plus évoluée qu’une simple
complétion gloutonne. Cette possibilité est illustrée par le code 3.2.
25
g
Al
T_
3.4 A MÉLIORATION DE LA CONSTRUCTION GLOUTONNE 87

Listing 3.2 – tsp_pilot_nearest_neighbour.c Implantation d’une méthode pilote qui


utilise comme heuristique pilote celle du plus proche voisin, suivie d’une méthode
d’amélioration présentée plus loin 4.3.
double t s p _ p i l o t _ n e a r e s t _ n e i g h b o u r 2 o p t ( i n t n , / ∗ Number o f c i t i e s ∗ /
double ∗∗d , /∗ Distance matrix ∗/
i n t s o l u t i o n [ ] ) / ∗ −>Out Order o f t h e c i t i e s ∗ /
{ i n t i , j , q , r , r _ k e p t = −1, j _ k e p t =−1; /∗ Indices ∗/
double cost , c o s t _ i n s _ r , d i s t _ i n s ; / ∗ Cost o f i n s e r t i n g n e x t c i t y ∗ /
i n t ∗s = ( i n t ∗) m a l l o c ( n ∗ s i z e o f ( i n t ) ) ; / ∗ Copy o f s o l u t i o n ∗ /

f o r ( i = 0 ; i < n ; i ++) / ∗ A l l c i t i e s must be i n s o l u t i o n ∗ /


solution [ i ] = i ;

17
f o r ( q = 0 ; q < n−1; q++) / ∗ c i t i e s up t o q a t t h e i r f i n a l pos . i n s o l u t i o n ∗ /
{ / ∗ Choosing t h e n e x t c i t y r t o i n s e r t a t p o s i t i o n q ∗ /
cost_ins_r = i n f i n i t e ;
f o r ( r = q ; r < n ; r ++)

20
{ f o r ( i = 0 ; i < n ; i ++)
s [ i ] = solution [ i ] ;
swap (& s [ q ] , &s [ r ] ) ;
/ ∗ n e a r e s t neighbour on c i t i e s from q+1 ∗ /
f o r ( i = q +1; i < n−1; i = i + 1 )
{ dist_ins = i n f i n i t e ;

e
f o r ( j = i ; j < n ; j = j +1)
i f ( d [ s [ i −1]][ s [ j ] ] < d i s t _ i n s )

br
{ d i s t _ i n s = d [ s [ i −1]][ s [ j ] ] ;
j_kept = j ;
}
swap(& s [ i ] , &s [ j _ k e p t ] ) ;
em
} /∗ f o r i ∗/
cost = tsp_length ( n , d , s ) ;
t s p _ 2 o p t _ f i r s t ( n , d , s , &c o s t ) ;
i f ( cost_ins_r > cost )
{ cost_ins_r = cost ;
r_kept = r ;
pt

}
} /∗ f o r r ∗/
swap(& s o l u t i o n [ r _ k e p t ] , & s o l u t i o n [ q ] ) ;
} /∗ f o r q ∗/
se

free ( s ) ;
cost = tsp_length ( n , d , s o l u t i o n ) ;
t s p _ 2 o p t _ f i r s t ( n , d , s o l u t i o n , &c o s t ) ;
return cost ;
}
25
g
Al
T_
88 M ÉTHODES CONSTRUCTIVES

3.5 Exercices
Exercice 3.1. Permutation aléatoire Écrire une procédure pour générer une
permutation aléatoire de n éléments contenus dans un tableau p. On désire
que la probabilité de trouver l’élément pi en j ième position dans p après permu-
tation soit 1/n. Décrire les défaut des algorithmes 3.5 et 3.6.

Algorithme 3.5 : Mauvais algorithme pour générer une permutation aléatoire


de n éléments

17
Entrées : Un ensemble de n éléments e1 , . . . , en
Résultat : Une permutation p des éléments
1 i ← 0; // Nombre d’éléments choisis

20
2 tant que i 6= n faire
3 Tirer un nombre aléatoire u uniformément entre 1 et n;
4 si eu n’a pas déjà été choisi alors
5 i ← i + 1;

e
6 p i ← eu

br
em
Algorithme 3.6 : Autre mauvais algorithme pour générer une permutation aléa-
toire de n éléments
Entrées : Un ensemble de n éléments e1 , . . . , en
Résultat : Une permutation p des éléments
pt

1 i ← 0; // Nombre d’éléments choisis


2 tant que i 6= n faire
se

3 Tirer un nombre aléatoire u uniformément entre 1 et n;


4 i ← i + 1;
5 si eu a déjà été choisi alors
6 Trouver le prochain u0 tel que eu0 n’ait pas été choisi;
25

7 pi ← eu0
8 sinon
9 p i ← eu
g
Al

Exercice 3.2. Algorithme glouton pour le sac de montagne Proposer trois


algorithmes gloutons différents pour le problème du sac de montagne
T_

Exercice 3.3. Algorithme glouton pour voyageur de commerce sur le De-


launay On désire construire la tournée d’un voyageur de commerce (dans le
plan) en n’utilisant que des arêtes appartenant à une triangulation de Delaunay.
Est-ce toujours possible ? Si ce n’est pas le cas, donner un contre-exemple,
autrement, proposer une méthode gloutonne et analyser sa complexité.

Exercice 3.4. Voyageur de commerce avec limitation des voisins Pour ac-
célérer une méthode gloutonne pour le TSP, on ne considère que les arêtes
des 40 plus proches voisins de chaque sommets. Est-ce susceptible de dimi-
nuer la complexité algorithmique de la méthode ? Est-ce que cela peut soulever
certains problèmes ?
3.5 E XERCICES 89

Exercice 3.5. Complexité de méthodes constructives Quelle est la com-


plexité de l’heuristique du plus proche voisin pour le TSP ? Même question
si on utilise cette heuristique dans une recherche en faisceaux en retenant
p nœuds à chaque profondeur et que l’on va jusqu’à la profondeur k. Même
question pour la méthode pilote où l’on utilise également l’heuristique du plus
proche voisin comme pilote.
Exercice 3.6. Implantation de méthodes gloutonnes pour problème d’or-
donnancement Proposer deux heuristiques gloutonnes pour le problème de
la chaîne de traitement à séquence fixée. Comparer leur qualité sur des pro-

17
blèmes de la littérature.
Exercice 3.7. Méthodes gloutonnes pour l’élaboration de tournées Propo-

20
ser deux heuristiques gloutonnes pour le problème de l’élaboration de tournées
de véhicules.
Exercice 3.8. Heuristique pilote avec recherche locale Le code 3.2 fait in-

e
tervenir comme heuristique pilote une complétion de la solution partielle avec
l’heuristique du plus proche voisin (voir l’algorithme 3.1, suivie d’une amélio-

br
ration de la solution complète avec une recherche locale tsp_2opt_first.
Est-ce que la suppression de l’optimisation de la solution complète qui a été
construite, juste avant le return final a une grande incidence sur la qualité de
em
la solution retournée par la méthode ? Est-ce qu’une méthode pilote où l’heu-
ristique pilote est simplement l’heuristique du plus proche voisin (qui peut être
obtenue par simple suppression des deux appels à tsp_2opt_first, bien que
pt

ce ne soit pas la meilleure façon de la coder) produit des solutions nettement


plus mauvaises que la méthode où l’on a uniquement supprimé le dernier appel
à tsp_2opt_first ?
se
25
g
Al
T_
90 M ÉTHODES CONSTRUCTIVES

17
20
e
br
em
pt
se
25
g
Al
T_
Chapitre 4

17
Améliorations locales

20
En examinant les solutions produites par des heuristiques constructives

e
gloutonnes comme celles présentées au chapitre précédent, on remarque im-
médiatement qu’elles ne sont pas optimales. Par exemple, la solution du pro-

br
blème du voyageur de commerce euclidien obtenue par l’heuristique du plus
proche voisin présentée en figure 3.2 comporte des arêtes qui se croisent,
ce qui est évidemment sous-optimal. En effet, il est possible de remplacer les
em
deux arêtes qui se croisent par deux autres dont la somme des longueurs est
moindre tout en conservant une tournée. Ce processus peut ensuite être ré-
itéré jusqu’à l’obtention d’une solution qui ne peut plus être améliorée par le
même procédé, comme illustré en figure 4.1
pt
se

4.1 Trame
L’idée générale est donc de partir d’une solution obtenue à l’aide d’une mé-
25

thode constructive et de l’améliorer localement. On réitère le procédé jusqu’à


ce qu’on ne trouve plus d’amélioration. Cette trame est bien connue en optimi-
sation continue, pour rechercher un optimum d’une fonction différentiable avec
les méthode de gradient. En optimisation discrète, la notion de gradient per-
g

mettant de trouver une direction d’amélioration n’existe pas ; elle est remplacée
Al
T_

F IGURE 4.1 – Améliorations successives d’une solution de problème de voyageur de


commerce avec une recherche locale de type 2-opt, où deux arêtes (en couleur) sont
remplacées par deux autres (en pointillé) dont la somme des longueurs est plus faible.
92 A MÉLIORATIONS LOCALES

par la définition de « petites » modifications de la solution, ou de voisinage ou


encore de mouvement.

Algorithme 4.1 : Trame générale d’une méthode d’amélioration locale. On sup-


pose disposer d’une solution au problème ainsi que d’une méthode permettant, à
partir de toute solution, d’en générer un certain nombre d’autres.
Entrées : Solution s, méthode de modification des solutions du problème
Résultat : Solution s améliorée
1 répéter

17
2 Chercher une modification de s en s0 qui l’améliore;
3 si s0 est meilleure que s alors
4 s ← s0 ;

20
5 jusqu’à ce qu’on ne trouve plus de modifications améliorant s;

e
4.2 Voisinage
br
Pour pouvoir appliquer la trame 4.1 d’amélioration, il faut définir comment
em
obtenir les solutions voisines. Formellement, on doit définir, pour toute solution
s ∈ S, un ensemble V (s) ⊂ S. Dans la trame, la recherche d’une modification
de s passe donc par l’énumération des solutions de V (s) pour en extraire une,
s0 , qui soit meilleure que s.
pt

Une manière commode pour définir un voisinage V (s) est de spécifier les
modifications, appelés communément les mouvements que l’on peut apporter
se

à la solution s. Dans l’exemple de la figure 4.1 pour le problème du voyageur


de commerce, un mouvement m peut être spécifié par une paire de villes [i, j]
consistant à remplacer les arêtes [i, si ] et [j, sj ] par les arêtes [i, j] et [si , sj ],
où si et sj sont, respectivement, les villes qui suivent i et j dans la solution s.
25

Ce voisinage, consistant à remplacer deux arêtes par deux autres est connu
dans la littérature sous le nom de 2-opt. L’ensemble M (s) des mouvements de
type 2-opt que l’on peut appliquer à la solution s peut être défini formellement
par M (s) = {[i, j], i, j ∈ s, i 6= j, j 6= si , i 6= sj }.
g

L’application d’un mouvement m ∈ M (s) à la solution s est parfois noté


s ⊕ m. La définition du voisinage peut être faite à l’aide de celle de l’ensemble
Al

des mouvements : V (s) = {s0 |s0 = s ⊕ m, m ∈ M (s)}.


Dans le cas du voisinage 2-opt, on vérifie que sa taille |V (s)| = Θ(|s|2 ).
T_

L’application d’une méthode d’amélioration au problème du voyageur de com-


merce peut donc se réaliser raisonnablement en énumérant les solutions voi-
sines. Cette énumération peut se faire selon deux politiques : celle du premier
mouvement améliorant ou celle du meilleur mouvement.

4.2.1 Politique du premier mouvement améliorant


Dans cette politique, on modifie immédiatement la solution courante dès
qu’un mouvement améliorant est identifié. Le voisinage n’est donc pas examiné
entièrement à chaque itération. La trame d’une méthode d’amélioration suivant
cette politique est donnée par l’algorithme 4.2.
4.2 VOISINAGE 93

Algorithme 4.2 : Trame d’une méthode d’amélioration avec politique du premier


mouvement améliorant.
Entrées : Solution s, spécification du voisinage V (·), et de la
fonction-objectif f (·) à minimiser.
Résultat : Solution s améliorée
1 pour tous les s0 ∈ V (s) faire
2 si f (s0 ) < f (s) alors
3 s ← s0 ; // Sortir de la boucle courante et initier la suivante

17
4.2.2 Politique du meilleur mouvement

20
Dans cette politique, on examine entièrement le voisinage à chaque itéra-
tion. La solution voisine choisie comme solution courante pour l’itération sui-
vante est la meilleure identifiée.

e
Algorithme 4.3 : Trame d’une méthode d’amélioration avec politique du meilleur
mouvement.
br
Entrées : Solution s, spécification du voisinage V (·), et de la
em
fonction-objectif f (·) à minimiser.
Résultat : Solution s améliorée
1 répéter
2 f in ← vrai;
pt

3 valeur_meilleur_voisin ← ∞;
4 pour tous les s0 ∈ V (s) faire
si f (s0 ) < valeur_meilleur_voisin alors
se

5
6 valeur_meilleur_voisin ← f (s0 );
7 meilleur_voisin ← s0
si valeur_meilleur_voisin < f (s) alors
25

8
9 s ← s0 ;
10 f in ← faux
11 jusqu’à f in;
g
Al

Parfois, l’ensemble V (s) est si grand que son énumération se fait soit im-
plicitement pour en extraire la meilleure solution voisine, soit de façon heuris-
T_

tique ; nous y reviendrons en particulier au chapitre 5 avec la technique de


recherche dans de grands voisinages 5.4.1.

4.2.3 Optima locaux


En appliquant la trame 4.1 on obtient une solution localement optimale re-
lativement au voisinage utilisé. En effet, rien n’assure que la solution retournée
est la meilleure possible pour le problème considéré. On oppose donc les so-
lutions globalement optimales à celles qui ne le sont que localement.
Toutefois, pour certains problèmes cette trame permet d’obtenir des so-
lutions globalement optimales. On peut citer en particulier la recherche d’un
94 A MÉLIORATIONS LOCALES

104

Temps de calcul
103
102
10
1
10−1 2-opt best
10−2 2-opt first

17
10−3 Θ(n3.25 )
- −4
10 Θ(n2.33 )
−5
10

20
10 102 103 104 105
Taille du problème

e
F IGURE 4.2 – Évolution du temps de calcul en fonction du nombre de villes d’un pro-
blème de voyageur de commerce pour deux variantes de méthodes d’amélioration.

br
em
chemin optimum avec l’algorithme 2.4 de Bellman-Ford et la programmation
linéaire avec l’algorithme du Simplexe.
Il faut insister sur le fait qu’un optimum local relativement à un voisinage
n’en est pas forcément un pour un autre voisinage.
pt

Comme l’ensemble des solutions d’un problème combinatoire est fini et que
les trames 4.2 et 4.3 n’effectuent une modification que si la solution est stric-
se

tement améliorée, on en déduit que les algorithmes dérivés de ces trames se


terminent après un temps fini. Par contre, leur temps de calcul n’est pas forcé-
ment polynomial, même si la taille du voisinage l’est. En pratique, comme pour
l’algorithme du Simplexe on n’observe pas une telle dégénérescence. Dans
25

la figure 4.2 on a représenté l’évolution du temps moyen de calcul de deux


variantes de méthodes d’améliorations pour le problème du voyageur de com-
merce (politique du meilleur mouvement ou du premier mouvement améliorant)
en fonction du nombre de villes. La solution de départ a été générée aléatoire-
g

ment et les exemples de problèmes euclidiens ont été tirés de la TSPLIB [?].
Comme les échelles sont logarithmiques, des temps de calculs approximative-
Al

ment alignés sur une droite indiquent une dépendance polynomiale.


T_

TSP 3-opt

Au début de ce chapitre, nous avons vu une application d’une méthode


d’amélioration pour le voyageur de commerce basée sur le remplacement de
deux arêtes par deux autres arêtes. Il est naturellement possible de définir
d’autres voisinages, par exemple le remplacement de trois arêtes (ou arcs dans
le cas d’un problème non symétrique) par trois autres. Ce type de modifica-
tions, appelé 3-opt, est illustré en figure 4.3. Une propriété intéressante de ce
voisinage est qu’il ne modifie pas le sens de parcours des chemins entre les
trois nœuds dont on modifie les successeurs. En représentant une solution au
moyen d’une permutation s dont l’élément si donne la ville qui est visitée juste
4.2 VOISINAGE 95

après la ville i, on peut implanter facilement en temps constant la modification


d’une solution par un mouvement de type 3-opt.
Vérifier qu’une solution est 3-optimale peut se faire en O(n3 ). Sans utiliser
des techniques de limitation du voisinage, il ne peut donc raisonnablement être
utilisé que pour de relativement petits exemples de problèmes.
Le code de l’algorithme 4.1 implante une recherche locale pour le problème
du voyageur de commerce. Les mouvements sont de type 3-opt ; dès qu’un
mouvement améliorant est identifié, il est effectué. Dans ce code, on notera
encore qu’une solution n’est modifiée que si elle est améliorée de plus de . En

17
effet deux solutions voisines de même coût pourraient être considérées toutes
deux meilleures l’une que l’autre, suite à des imprécisions numériques. En ac-
ceptant toutes les solutions dont la différence de coût est fautivement négative,

20
on s’exposerait à un code sans fin. En choisissant correctement la valeur de ,
on s’affranchit de ce problème. En pratique, on peut choisir  = 10−14 · max dij ,
la limite de la précision relative du type double étant approximativement 10−15
(voir code A.4).

e
br
Listing 4.1 – tsp_ 3opt_ first.c Implantation en C d’une méthode d’amélioration basée
sur le voisinage 3-opt. En pratique sa complexité en Ω(n3 ) la rend difficilement utilisable
pour des problèmes présentant plusieurs centaines de villes.
em
void t s p _ 3 o p t _ f i r s t ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , / ∗ D i s t a n c e m a t r i x , symmetry n o t r e q u i r e d ∗/
i n t best_sol [ ] , / ∗ InOut S o l u t i o n p r o v i d e d and r e t u r n e d ∗/
double ∗ b e s t _ c o s t ) / ∗ InOut Length o f t h e b e s t t o u r ∗/
pt

{
i n t ∗s = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ; / ∗ Successors o f c i t i e s ∗/
i n t i , j , k , temp , / ∗ indexes ∗/
/ ∗ L a s t v a l u e s o f indexes ∗/
se

i_end , j_end , k_end ;


double d e l t a ; / ∗ Cost o f a move ∗/

f o r ( i = 1 ; i < n ; i ++) / ∗ B u i l d s o l u t i o n r e p r e s e n t a t i o n by successors ∗ /


s [ b e s t _ s o l [ i −1]] = b e s t _ s o l [ i ] ;
s [ b e s t _ s o l [ n −1]] = b e s t _ s o l [ 0 ] ;
25

i = 0; j = s [ i ] ; k = s [ j ] ;
i_end = i ; j_end = j ; k_end = k ;
do
{ delta = d [ i ] [ s [ j ] ] + d [ j ] [ s [ k ] ] + d [ k ] [ s [ i ] ] / ∗ Computation o f move c o s t ∗ /
−d [ i ] [ s [ i ] ] − d [ j ] [ s [ j ] ] − d [ k ] [ s [ k ] ] ;
g

i f ( d e l t a < −e p s i l o n ) / ∗ I m p r o v i n g move ? ∗ /
{ temp = s [ i ] ; s [ i ] = s [ j ] ; s [ j ] = s [ k ] ; s [ k ] = temp ; / ∗ Perform move ∗ /
temp = j ; j = k ; k = temp ; / ∗ Replace j between i and k ∗ /
Al

∗best_cost = ∗best_cost + delta ; / ∗ Update s o l u t i o n c o s t ∗ /


i_end = i ; j_end = j ; k_end = k ; / ∗ Update l a s t v a l u e s o f indexes ∗ /
}
T_

k = s[k]; / ∗ Next k ∗ /
i f ( k == i )
{ j = s[ j ]; k = s[ j ];} / ∗ k a t i t s l a s t value , n e x t j ∗ /
i f ( k == i )
{ i = s[ i ]; j = s[ i ]; k = s[ j ];} / ∗ j a t i t s l a s t value , n e x t i ∗ /
} / ∗ A complete t o u r performed w i t h o u t improvement ∗ /
w h i l e ( i ! = i_end | | j ! = j_end | | k ! = k_end ) ;

/ ∗ R e b u i l d s o l u t i o n under t h e form o f a p e r m u t a t i o n o f c i t i e s ∗ /
f o r ( j = 0 , i = 0 ; i < n ; j = s [ j ] , i ++)
best_sol [ i ] = j ;

free ( s ) ;
}
96 A MÉLIORATIONS LOCALES

17
F IGURE 4.3 – Mouvement de type 3-opt où trois arcs sont remplacés par trois autres
arcs. Les autres chemins de la solution sont parcourus dans le même sens, avant et

20
après modification. Une autre façon d’appréhender le voisinage 3-opt est le déplace-
ment d’un sous-chemin ailleurs dans la tournée.

e
br
em
pt
se

F IGURE 4.4 – Mouvement de type Or-opt où trois sommets successifs sont déplacés à
l’intérieur de la tournée. Dans certains cas, il est souhaitable de modifier l’ordre respectif
de visite des trois sommets.
25
g

TSP Or-opt
Al

Un autre type de voisinage proposé par [?] consiste à raisonner sur le dé-
placement de villes à l’intérieur de la tournée. L’idée est d’examiner s’il est
T_

possible de placer ailleurs trois villes qui sont visitées successivement dans la
solution courante. L’originalité de la méthode proposée par Or est de ne pas
se contenter d’un seul voisinage : Une fois qu’il n’est plus possible d’améliorer
la solution en déplaçant trois villes, on cherche à n’en déplacer que deux. Dès
qu’un déplacement de deux villes permet d’améliorer la solution, on revient
au premier voisinage. Ensuite, lorsqu’on a une solution localement optimale
relativement à ces deux voisinages, on essaie de ne déplacer qu’une ville.
Le voisinage est différent d’une limitation du voisinage 3-opt dans lequel un
sous-chemin serait limité à 3, 2 ou 1 ville. En effet, il est possible d’inverser
l’ordre de parcours du chemin avec ce voisinage.
Il est possible de tester en Θ(n2 ) si une solution est Or-optimale.
4.2 VOISINAGE 97

17
20
F IGURE 4.5 – Structure de données permettant d’effectuer un mouvement de type 2-
opt en temps constant. Les entrées 2i et 2i + 1 d’un tableau donnent les indices du
même tableau identifiant les deux villes adjacentes à la ville i. En partant de l’indice

e
0, on peut reconstituer la tournée en allant de ville adjacente en ville adjacente et en
partant de l’indice 1, on peut reconstituer la tournée dans l’autre sens. La réalisation
d’un mouvement 2-opt s’effectue par modification de 4 entrées du tableau.
br
em
Structure de données pour TSP 2-opt

Le voisinage 2-opt renverse l’ordre de parcours d’un chemin. Si cela semble


pt

visuellement anodin pour un exemple de problème symétrique, il n’en est pas


ainsi pour la représentation informatique d’une solution. Une structure de don-
se

née, inspirée des travaux de [?], permettant de réaliser un mouvement 2-opt


en temps constant est la suivante : chaque ville mémorise ses deux villes ad-
jacentes. La ville i est donc représentée par deux valeurs, 2i et 2i + 1, selon
que l’on tourne dans un sens ou dans l’autre.
25

Une solution sera représentée par un tableau t de 2n indices, avec initia-


lement t2i /2 donnant le numéro de la ville qui succède à i et (t2i+1 − 1)/2
le numéro de la ville qui précède i. Un mouvement de type 2-opt consiste à
modifier 4 valeurs du tableau t, ce qui peut se réaliser en temps constant. La
g

figure 4.5 illustre le principe de fonctionnement de cette structure de données.


Al

Listing 4.2 – build_ 2opt_ data_ structure.c Implantation en C de l’initialisation de la


structure de donnée présentée en figure 4.5 pour permettre d’effectuer un mouvement
2-opt en temps constant à partir d’une solution fournie sous la forme de la suite des
T_

villes à visiter.
void build_2opt_data_structure ( i n t n ,
const i n t s o l u t i o n [ ] ,
int t [])
{ int i ;
/ ∗ Forward t o u r ∗ /
f o r ( i = 0 ; i < n−1; i = i + 1 )
t [2∗ s o l u t i o n [ i ] ] = 2∗ s o l u t i o n [ i + 1 ] ;
t [2∗ s o l u t i o n [ n −1]] = 2∗ s o l u t i o n [ 0 ] ;
/ ∗ Backward t o u r ∗ /
f o r ( i = 1; i < n ; i = i + 1)
t [2∗ s o l u t i o n [ i ] + 1 ] = 2∗ s o l u t i o n [ i −1]+1;
t [2∗ s o l u t i o n [ 0 ] + 1 ] = 2∗ s o l u t i o n [ n−1]+1;
}
98 A MÉLIORATIONS LOCALES

L’initialisation d’un tableau t implantant cette structure de donnée à partir


d’une solution donnée sous la forme d’une permutation dont la composante i
donne le numéro de la iième ville peut se faire à l’aide de l’algorithme 4.2.
Le code de l’algorithme 4.3 implante une méthode d’amélioration basée
sur ce principe. Il fait usage de l’opérateur de décalage i >> 1 pour évaluer
rapidement l’expression i/2 qui donne le numéro de la ville d’indice i ainsi
que de l’opérateur « ou exclusif » i  1 pour calculer rapidement l’expression
i+1-2*(i%2) qui donne l’indice de t permettant de connaître l’autre ville adja-
cente.

17
Listing 4.3 – tsp_ 2opt_ first.c Implantation en C d’une méthode d’amélioration pour
le voyageur de commerce basée sur le voisinage 2-opt. Cette implantation utilise la
structure de donnée présentée en figure 4.5 permettant d’effectuer un mouvement en

20
temps constant.
void t s p _ 2 o p t _ f i r s t ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , / ∗ D i s t a n c e m a t r i x , must be s y m m e t r i c a l ∗/
i n t best_sol [ ] , / ∗ InOut S o l u t i o n p r o v i d e d and r e t u r n e d ∗/
double ∗ b e s t _ c o s t ) / ∗ InOut Length o f t h e b e s t t o u r ∗/

e
{ int ∗t ; / ∗ Doubly connected edge l i s t f o r e f f i c i e n t l y p e r f o r m i n g moves ∗ /

i n t i , j , next_i , next_j , l a s t _ i ;
double d e l t a ;
br /∗ Indices ∗/
/ ∗ Cost d i f f e r e n c e ∗ /
em
t = ( i n t ∗) m a l l o c ( ( s i z e _ t ) ( 2 ∗ n ) ∗ s i z e o f ( i n t ) ) ;
build_2opt_data_structure ( n , best_sol , t ) ;

i = l a s t _ i = 0; / ∗ S t a r t moves e v a l u a t i o n from c i t y 0 ∗ /
w h i l e ( t [ t [ i ]] > >1 ! = l a s t _ i ) / ∗ Index i has made 1 t u r n w i t h o u t impovement ∗ /
{ j = t [ t [ i ]];
pt

w h i l e ( j >>1 ! = l a s t _ i && ( t [ j ] > >1 ! = l a s t _ i | | i >>1 ! = l a s t _ i ) )


{ d e l t a = d [ i > > 1 ] [ j > >1] + d [ t [ i ] > > 1 ] [ t [ j ] > >1]
− d [ i > > 1 ] [ t [ i ] > >1] − d [ j > > 1 ] [ t [ j ] > > 1 ] ;
i f ( d e l t a < −e p s i l o n )
se

{ next_i = t [ i ] ; next_j = t [ j ] ; / ∗ Perform move ∗ /


t [ i ] = j ^1; t [ j ] = i ^1;
t [ next_i ^1] = next_j ; t [ next_j ^1] = next_i ;

∗best_cost = ∗best_cost + delta ; / ∗ Update s o l u t i o n c o s t ∗ /


25

l a s t _ i = i > >1; / ∗ S o l u t i o n improved : i must make a n o t h e r t u r n ∗ /


j = t [ i ];
}
j = t [ j ];
} /∗ while j ∗/
i = t [ i ];
g

} /∗ while i ∗/

/ ∗ R e b u i l d s o l u t i o n : number o f c i t y i n j t h p o s i t i o n ∗ /
Al

f o r ( i = 0 , j = 0 ; j < n ; i = t [ i ] , j ++)
b e s t _ s o l [ j ] = i > >1;
T_

free ( t ) ;
} / ∗ t s p 2−o p t ∗ /

4.2.4 Propriétés recherchées pour un voisinage


Un voisinage met en relation des solutions du problème. On peut donc le
représenter sous la forme d’un graphe, où les sommets sont les solutions.
Deux sommets sont reliés par une arête (ou un arc, si les mouvements ne
sont pas immédiatement réversibles) si les solutions associées sont voisines.
Pour être efficace, un voisinage, ou son graphe représentatif, devrait posséder
certaines propriétés.
4.2 VOISINAGE 99

Connexité

La propriété de connexité d’un voisinage stipule qu’à partir de toute solu-


tion admissible du problème, on doit pouvoir atteindre au moins une solution
globalement optimale. En d’autre terme, il doit exister un chemin de n’importe
quel sommet à celui (ou un de ceux) représentant une solution optimale.

Faible diamètre

17
Un voisinage devrait permettre d’atteindre une solution optimale en peu
d’étapes. Par définition, le diamètre d’un graphe est la longueur maximale d’un

20
plus court chemin reliant deux sommets.

Faible rugosité

e
Un voisinage devrait posséder un nombre d’optima locaux aussi faible que

br
possible et une forte corrélation entre les valeur des solutions voisines. L’idéal
serait qu’il n’en possède qu’un, qui serait alors l’optimum global, atteignable
em
à tous les coups en partant de n’importe quelle solution. Évidemment, cette
propriété n’est pas remplie pour les problèmes difficiles. Néanmoins, trouver
un voisinage adéquat pour le problème considéré est essentiel pour le succès
d’une méthode d’amélioration.
pt

Pour des problèmes comme le voyageur de commerce, de nombreux voisi-


nages ont été imaginés, certains étant particulièrement efficaces pour obtenir
se

d’excellentes solutions. Ceci peut vraisemblablement s’expliquer par le côté


très visuel du problème, ce qui nous aide fortement dans le choix des modi-
fications à apporter à une solution pour l’améliorer. Pour d’autres problèmes,
il est difficile d’imaginer des voisinages, et ces derniers mènent parfois à des
25

paysages du type « boîte à œufs », très mal adaptés à l’optimisation.


Une possibilité pour lisser un voisinage est de modifier la fonction-utilité. La
méthodes des éléphants volants de √ [?] procède par le remplacement de termes
en |x|
√ dans la fonction utilité par x2 + τ 2 et de termes du type max(0, x) par
g

2 2
(x+ x + τ )/2, où τ est un paramètre que l’on fait tendre vers 0 si l’on veut se
Al

rapprocher de la fonction-utilité originale. La métaphore des éléphants volants


vient du fait que si on lâche un objet arrondi et volumineux sur un terrain, il
roulera plus loin, vers une altitude plus basse que si on lâche à partir du même
T_

point un petit objet, qui s’arrêtera au premier minuscule accident du terrain.

Faible taille

Les méthodes d’amélioration étant basées sur l’évaluation systématique de


solutions voisines, ces dernières ne devraient pas être excessivement nom-
breuses. Par exemple, un voisinage de type 2-opt pour le problème du voya-
geur de commerce, en O(n2 ), permet d’attaquer des problèmes avec plusi-
eurs milliers de villes, ce qui n’est pas envisageable avec le vosinage 3-opt, en
O(n3 ).
100 A MÉLIORATIONS LOCALES

Facilité d’évaluation

Finalement, l’évaluation de la qualité des solutions voisines doit pouvoir se


réaliser avec un algorithme dont la complexité est aussi faible que possible. Par
exemple, pour un problème de voyageur de commerce asymétrique, l’avantage
que pourrait procurer la faible taille d’un voisinage 2-opt par rapport à 3-opt
est annihilé par le fait que l’évaluation du coût d’un mouvement ne peut plus
être faite en temps constant, comme c’est le cas pour 3-opt. De plus, on peut
imaginer que la rugosité du voisinage 2-opt sera plus élevée que celle de 3-opt
pour des problèmes fortement asymétriques.

17
4.3 Limitation du voisinage

20
Typiquement, la taille d’un voisinage croît de façon quadratique ou cubique
avec la taille du problème. Par conséquent, une recherche locale nécessitant

e
d’examiner de nombreuses fois l’ensemble du voisinage requiert un effort de
calcul prohibitif lorsque la taille du problème augmente. Diverses techniques

br
ont été proposées pour limiter la croissance des calculs.
em
4.3.1 Liste de candidats
Une première idée consiste à faire l’hypothèse qu’un mouvement favorable
pour une solution restera bon pour des solutions pas trop différentes. Une
pt

technique générale de limitation de l’effort de calcul est d’évaluer l’ensemble


des mouvement applicables à une solution donnée et de mémoriser dans une
se

liste de mouvements candidats, dont la taille est limitée, les caractéristiques


des meilleurs mouvements trouvés. Pendant un certain nombre d’itérations, on
n’évalue que les mouvements contenus dans la liste. Périodiquement, il faut
toutefois évaluer l’ensemble du voisinage, car la solution est susceptible d’avoir
25

été passablement modifiée ; des mouvements qui n’étaient pas favorables peu-
vent donc le devenir et vice versa.
g

Liste de candidats pour le voyageur de commerce euclidien


Al

Dans le cas du problème du voyageur de commerce, l’évaluation d’un mou-


vement est indépendante de la solution. Une liste de mouvements candidats
n’a donc pas besoin d’être reconstruite périodiquement. En revanche, il faut
T_

mettre au point un mécanisme permettant de détecter si un mouvement parti-


culier est valide, par exemple qu’il ne crée pas deux ou plusieurs sous-cyles.
Si les villes d’un problème de voyageur de commerce sont placées sur le
plan euclidien on peut construire en O(n log n) une triangulation de Delaunay
et tenter de ne considérer que des tournées faisant usage d’arêtes présentes
dans la triangulation. Le nombre d’arêtes de celle-ci est en Θ(n) et le degré
moyen des sommets de 6.
Dans la figure 4.6 on a représenté la triangulation de Delaunay associée
à un problème de voyageur de commerce euclidien, superposée à la solution
optimale de ce problème. À moins d’être manchot, le lecteur pourra compter
sur ses doigts les arêtes de la solution optimale qui ne font pas partie de la
4.3 L IMITATION DU VOISINAGE 101

17
20
e
br
em
pt
se
25
g
Al
T_

F IGURE 4.6 – Tournée optimale à l’exemple de problème de voyageur de commerce


pr2392 sur laquelle on a superposé la triangulation de Delaunay associée aux sommets
du réseau.
102 A MÉLIORATIONS LOCALES

triangulation. Ceci suggère qu’une heuristique travaillant sur des solutions ba-
sées essentiellement sur les arêtes de la triangulation de Delaunay peut don-
ner d’excellent résultats tout en nécessitant un effort de calcul très limité. En
particulier, une recherche locale basée sur un voisinage de type k-opt pourra
fonctionner même pour des valeurs de k valant 5 ou 6, s’il est restreint aux
arêtes du Delaunay, puisque le nombre de solutions voisines d’un problème de
taille n sera en O(n · 6k ).

17
Limitation du voisinage pour le voyageur de commerce avec 1-arbres

Malheureusement, tous les problèmes ne sont pas euclidiens, et il n’est


donc pas toujours possible de construire une triangulation de Delaunay. Une

20
technique plus générale de limitation du voisinage pour le problème du voya-
geur de commerce, proposée par [?], est basée sur le concept de 1-arbre, qui
n’est rien d’autre qu’une forme de relaxation lagrangienne.
Un 1-arbre dans un réseau comportant des sommets 1, 2, . . . , n est un arbre

e
de poids minimum sur les sommets 2, . . . , n auquel on ajoute les deux arêtes

br
adjacentes au sommet 1 qui ont le poids le plus faible. Le nœud 1 joue ici
un rôle particulier, d’où le terme de 1-arbre. On peut reformuler le problème
du voyageur de commerce en spécifiant que l’on cherche un 1-arbre de poids
em
minimum pour lequel le degré de tous les sommets est 2.
P
min z = d x
Pn ij ij
(i,j)∈H
pt

sous j=1 xij = 2(i = 1, . . . , n) (4.1)


contraintes H est un 1-arbre
se

En relaxant les contraintes sur le degré de chaque sommet et en les inté-


grant avec un multiplicateur de lagrange dans l’objectif, on obtient :
25

P Pn Pn
min z(λ) = (i,j)∈H dij xij + i=1 λi ( j=1 xij − 2)
(4.2)
sous contrainte H est un 1-arbre

Pour des λi fixés, ce problème revient à recherche un 1-arbre de poids


g

minimum dans un réseau dont le poids de l’arête (i, j) est modifiée en dij +
Al

λi + λj . Avec ces poids modifiés, on peut constater que la longueur d’une


tournée est la même qu’avec les poids non modifiés, mais augmenté de 2 ·
P
i λi , puisqu’il faut entrer une fois dans chaque sommet i et en ressortir une
T_

fois, en devant « payer » deux fois une pénalité λi .


La valeur z(λ) permet donc d’obtenir un borne inférieure à la longueur de la
tournée optimale. On peut améliorer la valeur de cette borne en trouvant des
λi maximisant z(λ).
En première approximation, l’idée de [?] pour limiter le voisinage d’une
recherche locale, est de calculer, pour chaque arête (i, j) le surcoût qu’elle
engendrerait si on imposait qu’elle fasse partie du 1-arbre et de ne retenir que
quelques arêtes adjacentes à chaque sommet, celles dont le surcoût est le plus
faible. Cette technique de modification de la longueur des arêtes a également
comme propriété de lisser certains voisinages. Elle présente également des
similarités avec la recherche granulaire.
4.4 E XTENSION DU VOISINAGE 103

4.3.2 Recherche granulaire


La recherche granulaire consiste à éliminer a priori les solutions présen-
tant certaines caractéristiques. Par exemple, pour le problème d’élaboration
de tournées de véhicules, on peut faire l’hypothèse que les bonnes solutions
ne comporteront pas de trajets reliant directement des clients très éloignés.
Pour ce problème, [?] ont proposé d’ignorer les solutions qui comporteraient
des trajets entre deux clients dont la longueur est supérieure β fois la lon-
gueur moyenne des trajets d’une solution obtenue à l’aide d’une heuristique
constructive rapide, où β est un paramètre généralement légèrement supé-

17
rieur à 1 contrôlant ce qui a été appelé la granularité de la recherche locale.
Pour le problème de distribution, il est toutefois nécessaire de conserver les
longs trajets directs que l’on pourrait avoir entre clients et dépôt.

20
Une technique similaire a été abondamment utilisée pour le problème du
voyageur de commerce : au lieu de considérer un graphe complet où chaque
ville est reliée à toutes les autres, on se contente d’un graphe où chaque ville
n’est connectée qu’à ses p plus proches voisines, avec p limité à quelques

e
dizaines. Ainsi, la taille d’un voisinage 2-opt est en n · p2 au lieu de n2 . La

br
perte sur la qualité des solutions obtenues avec un tel voisinage réduit est
souvent négligeable. Par contre, l’implantation de cette idée n’est pas triviale :
tout d’abord, il se peut que le graphe où chaque nœud n’est relié qu’à ses p
em
plus proches voisins ne soit pas connexe. Il faut donc ajouter des connexions
plus longues pour qu’il contienne un cycle passant par tous les nœuds. Ensuite,
l’implantation de la recherche locale est plus complexe. Par exemple, pour le
voisinage 2-opt, on ne peut plus exploiter directement la structure de données
pt

présentée dans la figure 4.5 permettant de réaliser un mouvement en temps


constant. En effet, s’il est facile de déterminer la ville si qui succède à la ville
se

i et une ville j proche de i (il n’y en a plus que p), on ne peut plus identifier
la ville sj qui succède à j en parcourant la tournées dans le sens i → si . De
la même manière, pour le voisinage 3-opt, on peut rapidement détecter trois
villes i, j et k proches qui seraient candidates pour un mouvement 3-opt, mais
25

on ne peut pas déterminer en temps constant si, en partant de i, on va visiter


d’abord la ville j avant la ville k.
g

4.4 Extension du voisinage


Al

Pour d’autres problèmes il est au contraire difficile d’imaginer des voisi-


nages raisonnables qui modifient une solution autrement que de façon margi-
T_

nale. Se pose donc le problème de construire des modifications conséquentes


d’une solution à partir d’un voisinage simple et limité. Notons au passage qu’il
est parfaitement possible d’une part de limiter la taille d’un voisinage simple
avec les techniques décrites plus haut pour en éliminer les mouvements qui
ne mèneront jamais à de bonnes solutions tout en étendant ce voisinage limité
avec les techniques que l’on va étudier.

4.4.1 Recherche en éventail


Pour construire un voisinage étendu Ve à partir de la définition d’un faible
ensemble M de mouvements applicables à une solution, il suffit de considérer
104 A MÉLIORATIONS LOCALES

Solution de départ Mouvements applicables à la solution de départ

p meilleurs voisins du niveau 1


p meilleurs voisins du niveau 2
Niveau k

17
Meilleure solution visitée : solution de départ pour la prochaine itération

F IGURE 4.7 – Recherche en éventail avec p = 3 et k = 3. À chaque niveau, on retient


au maximum p solutions voisines. La prochaine solution courante sera la meilleure de

20
celles énumérées.

e
k modifications successives : Ve (s) = {s0 |s0 = s ⊕ m1 ⊕ · · · ⊕ mk , m1 , . . . mk ∈
M (s)} La taille de Ve croît exponentiellement avec k. Pour éviter une telle crois-

br
sance, on peut utiliser la stratégie de la recherche en faisceaux présentée à la
section 3.4.1, mais adaptée à une recherche locale plutôt qu’à une méthode
em
constructive. Cette technique a été appelée recherche en éventail avec filtre. À
chaque niveau, on ne retient que les p meilleures solutions voisines (qui peu-
vent être moins bonnes que la solution de départ) et on évalue les voisins de
ces dernière avant de réitérer le processus jusqu’au niveau k. Ainsi, à chaque
pt

étape, on effectue jusqu’à k modifications selon le voisinage d’origine. Il faut


noter ici que la meilleure solution rencontrée lors de l’évaluation du voisinage
étendu n’est pas forcément une de celles du dernier niveau.
se

Ce processus est illustré en figure 4.7.


Une variante de la recherche en éventail est de ne pas retenir à chaque
niveau un nombre statique p de solutions voisines, mais toutes les solutions
25

voisines améliorantes. Le choix de la solution voisine qui sera finalement rete-


nue au niveau 1 ne sera pas celle qui permet d’aboutir à la meilleure solution
du niveau k, mais celle qui permet d’ouvrir le plus l’éventail, c’est-à-dire, la
solution du niveau k − 1 qui a le plus de solutions améliorantes au niveau k.
g
Al

4.4.2 Chaîne d’éjections


Une autre technique de construction d’un voisinage étendu à partir de mo-
T_

difications élémentaires consiste à passer par des solutions non réalisables.


Partant d’une solution, on transforme cette dernière en un objet appelé struc-
ture de référence qui n’est pas une solution mais qui peut facilement être trans-
formé soit en une autre structure de référence, soit en une solution admissible.
La solution de départ est perturbée par l’éjection d’un de ses éléments constitu-
tifs pour obtenir une structure de référence qui peut elle aussi être transformée
par éjection d’un autre élément. Cette chaîne d’éjections se termine soit lors-
qu’une solution meilleure que celle de départ a pu être identifiée, soit lorsque
tous les éléments éjectables l’ont été. Si une meilleure solution est trouvée,
le processus peut réitéré à partir de cette dernière, sinon on initie la chaîne
en essayant d’éjecter un autre élément de la solution de départ. Le processus
4.4 E XTENSION DU VOISINAGE 105

Tournée initiale

a d c b

Chaîne

Structure de référence

17
20
Nouvelle chaîne
a0 d0 c0 b0

e
Nouvelle structure

br
em
Nouvelle tournée
pt

F IGURE 4.8 – Principe de fonctionnement d’une chaîne d’éjections pour le problème du


voyageur de commerce : éjecter une arête [a, b] pour obtenir une chaîne, insérer une
se

arête [b, d] pour obtenir une structure de référence qui peut être transformée soit en une
autre structure de référence par éjection de l’arête [c, d] et ajout d’une autre arête, soit
en une tournée par éjection de la même arête et ajout de l’arête [a, c].
25

s’arrête lorsque l’on a tenté vainement toutes les initialisations possibles de


chaînes. Pour éviter un processus sans fin, on s’interdit d’ajouter à la structure
g

de référence un élément qui aurait été au préalable éjecté ou au contraire, de


propager la chaîne en éjectant un élément qui aurait été ajouté à la structure
Al

de référence.
T_

Voisinage de Lin-Kernighan Un des voisinages les plus efficaces pour le


problème du voyageur de commerce est celui de Lin & Kernighan. Il est basé
sur l’idée de chaînes d’éjections. La tournée initiale est transformée en une
chaîne par suppression d’une arête [a, b]. Cette chaîne est transformée en une
structure de référence, constituée d’une chaîne reliée à un cycle par adjonction
d’une arête [b, d]. En supprimant l’arête [c, d] faisant partie du cycle de la struc-
ture de référence, on transforme cette dernière en une autre chaîne, qui peut
elle-même être transformée en une tournée par l’adjonction de l’arête [a, c] ou
en une autre structure de référence par l’adjonction d’une autre arête incidente
à c (qui joue le rôle du b de l’étape précédente).
Le principe de fonctionnement de ce processus est illustré en figure 4.8. Ce
106 A MÉLIORATIONS LOCALES

17
Solution de départ Chaîne Structure 1

20
e
br
em
Structure 2 Structure 3 Solution acceptée
pt

F IGURE 4.9 – Application d’une chaîne d’éjection sur un petit problème de voyageur de
commerce. Après 4 éjections, on réussit à améliorer la solution de départ.
se

mécanisme peut sembler artificiel dans cette figure, mais avec des villes bien
25

réparties sur le plan, on se rend compte qu’il est possible d’obtenir des modi-
fications relativement complexes et améliorant des solutions pas franchement
mauvaises, comme illustré en figure 4.9.
g
Al
T_
4.4 E XTENSION DU VOISINAGE 107

17
Algorithme 4.4 : Trame d’une méthode d’amélioration par chaîne d’éjections

20
pour le problème du voyageur de commerce.
Entrées : Solution p d’un voyageur de commerce
Résultat : Solution p améliorée
1 répéter

e
2 Initier la chaîne par l’éjection d’une arête [a, b];
3 répéter
4

br
Trouver l’arête [b, d] qui, une fois ajoutée, minimise le poids de la
structure de référence et telle que l’arête [c, d] n’ait pas encore été
em
supprimée dans la chaîne d’éjections courante;
5 si L’arête [b, d] a été trouvée et Le poids de la structure de
référence est inférieure au poids de la tournée p alors
6 si L’ajout de [a, c] et la suppression de [c, d] améliore la
pt

solution alors
7 Succès : Remplacer la solution p par celle qui a été
trouvée;
se

8 sinon
9 Ajouter l’arête [b, d];
10 Supprimer l’arête [c, d];
25

11 b ← c;
12 sinon
13 Échec de la chaîne : revenir à la solution p et tenter une autre
g

éjection
14 jusqu’à ce qu’aucune arête [b, d] convenable existe;
Al

15 jusqu’à ce que toutes les arêtes de la solution p ont initié une chaîne
sans succès;
T_
108 A MÉLIORATIONS LOCALES

Listing 4.4 – tsp_ LK.c Chaîne d’éjections pour le voyageur de commerce.


v o i d tsp_LK ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗D, / ∗ D i s t a n c e m a t r i x , must be s y m m e t r i c a l ∗/
i n t best_sol [ ] , / ∗ InOut S o l u t i o n p r o v i d e d and r e t u r n e d ∗/
double ∗ b e s t _ c o s t ) / ∗ InOut Length o f t h e b e s t t o u r ∗/
{ int∗ s; / ∗ Reference s t r u c t u r e : successors o f each c i t y ∗/
i n t a , end_a , b , c , d , best_c , i , j , s i , s s i ; /∗ Indices ∗/
double l e n g t h _ p a t h , c o s t _ r e f _ s t r u c t ; / ∗ Cost o f r e f e r e n c e s t r u c t u r e k e p t ∗/
i n t ∗∗ tabu ; / ∗ tabu [ i ] [ j ] i n d i c a t e t h a t edge i −j cannot be removed ∗/
i n t p a t h _ m o d i f i e d , n o _ i t e r ; / ∗ s has been m o d i f i e d , outermost l o o p i t e r a t i o n ∗/
i n t improved ; / ∗ s o l u t i o n improved d u r i n g t h i s i t e r a t i o n ∗/
s = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
tabu = ( i n t ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ∗ ) ) ;

17
f o r ( i = 0 ; i < n ; i ++) tabu [ i ] = ( i n t ∗) c a l l o c ( ( s i z e _ t ) n , s i z e o f ( i n t ) ) ;
f o r ( i = 0 ; i < n ; i ++) s [ b e s t _ s o l [ i ] ] = b e s t _ s o l [ ( i +1)%n ] ;
no_iter = 0;
a = end_a = 0 ; / ∗ I n i t i a t e e j e c t i o n c h a i n from c i t y 0 ∗/

20
do
{ b = s[a];
length_path = ∗best_cost − D[ a ] [ b ] ;
n o _ i t e r ++;
improved = 0 ;
do / ∗ I d e n t i f y b e s t r e f e r e n c e s t r u c t u r e w i t h edge ( a−b ) removed ∗/

e
{ path_modified = 0;
cost_ref_struct = i n f i n i t e ;
best_c = c = s [ b ] ;
while ( s [ c ] != a )
{ d = s[c];

{
br / ∗ E j e c t i o n can be propagated

i f ( length_path − D[ c ] [ d ] + D[ c ] [ a ] + D[ b ] [ d ] + epsilon < ∗best_cost )


/ ∗ An i m p r o v i n g s o l u t i o n i s i d e n t i f i e d ; change i t i m m e d i a t e l y
∗/

∗/
em
best_c = c ;
c o s t _ r e f _ s t r u c t = length_path − D[ c ] [ d ] + D[ c ] [ a ] + D[ b ] [ d ] ;
break ;
}
i f ( tabu [ c ] [ d ] ! = n o _ i t e r && / ∗ edge c − d has n o t been added ∗/
length_path + D[ b ] [ d ] < c o s t _ r e f _ s t r u c t )
pt

{ c o s t _ r e f _ s t r u c t = length_path + D[ b ] [ d ] ;
best_c = c ;
}
se

c = d; / ∗ Next v a l u e f o r d ( and c ) ∗/
}
i f ( c o s t _ r e f _ s t r u c t + e p s i l o n < ∗ b e s t _ c o s t ) / ∗ Adm. r e f . s t r u c t . found ∗/
{ path_modified = 1;
c = best_c ;
d = s[c]; / ∗ Update r e f e r e n c e s t r u c t u r e ∗/
25

tabu [ c ] [ d ] = tabu [ d ] [ c ] = n o _ i t e r ; / ∗ Prevent remove again edge c−d ∗/


l e n g t h _ p a t h += (D [ b ] [ d ] − D [ c ] [ d ] ) ;
i = b; / ∗ Reverse path b −> c ∗/
si = s [ i ] ;
s[b] = d;
while ( i != c )
g

{ ssi = s [ si ] ; s [ si ] = i ; i = si ; si = ssi ; }
b = c;
Al

i f ( length_path + D[ a ] [ b ] + epsilon < ∗best_cost )


{ ∗best_cost = length_path + D[ a ] [ b ] ;
s[a] = b;
end_a = s [ a ] ;
T_

improved = 1 ;
f o r ( i = 0 , j = 0 ; j < n ; j ++) / ∗ S t o r e improved s o l u t i o n ∗/
{ best_sol [ j ] = i ; i = s [ i ] ; }
}
}
}
while ( path_modified ) ;
f o r ( i = 0 ; i < n ; i ++) s [ b e s t _ s o l [ i ] ] = b e s t _ s o l [ ( i +1)%n ] ;
a = s[a];
}
w h i l e ( a ! = end_a | | improved ) ; / ∗ a has made 1 t u r n w i t h o u t improvement ∗/
f o r ( i = 0 ; i < n ; i ++) f r e e ( tabu [ i ] ) ;
f r e e ( tabu ) ;
free ( s ) ;
} / ∗ t s p LK ∗ /
4.5 U TILISATION DE PLUSIEURS VOISINAGES OU PLUSIEURS MODÈLES 109

4.5 Utilisation de plusieurs voisinages ou plusi-


eurs modèles
Comme un optimum local est relatif à une structure de voisinage don-
née, il est possible d’utiliser plusieurs voisinages simultanément. Par exemple,
une solution d’un voyageur de commerce 2-optimale n’est pas forcément 3-
optimale. Une fois que l’on a trouvé une solution 2-optimale, il est potentielle-
ment possible de l’améliorer avec une méthode utilisant un voisinage de type
3-opt. De même, une solution 3-optimale n’est pas 2-optimale, on peut donc ré-

17
péter alternativement des processus d’amélioration tant que la solution trouvée
n’est pas un optimum local relativement à toutes les structures de voisinage
considérées.

20
Finalement, mentionnons que l’on peut encore passer d’une modélisation
du problème à une autre. Dans la mesure où la structure de voisinage n’est
pas la même pour les diverses modélisations, il est également possible d’itérer
des méthodes d’améliorations utilisant divers modèles. Cette technique n’est

e
pas forcément applicable telle quelle, puisqu’une solution admissible pour un

br
modèle ne l’est pas forcément pour un autre. Dans ce cas, il faut prévoir des
méthodes de réparation lorsqu’on change de modèle, ce qui peut impliquer que
le processus n’est plus une méthode d’amélioration stricte. Un corollaire est
em
que la recherche pourrait « tourner en rond », la réparation suivie de « l’amé-
lioration » avec un modèle pouvant défaire les modifications réalisées par un
autre modèle.
pt

4.6 Optimisation multiobjectif par améliorations lo-


se

cales
Diverses techniques relativement simple ont été proposées pour réaliser
25

un optimisation multi-objectifs par recherche locale. Nous allons examine deux


approches assez simples à mettre en œuvre et produisant de bonnes solutions.
g

4.6.1 Scalarisation des objectifs


Al

Une technique mentionnée en section 2.10.3 pour l’optimisation multi-


objectifs est celle de l’agrégation des objectifs en associant un poids wi au
T_

iième objectif. En se donnant un vecteur de poids et en transmettant à une mé-


thode de recherche locale une unique fonction agrégeant les objectifs, on peut
donc trouver une approximation d’une solution supportée. En faisant varier le
vecteur de poids, on pourra en trouver d’autres.
Cependant, une telle technique ne produira au plus qu’une solution approxi-
mant l’ensemble Pareto pour chaque exécution de la recherche locale. Sans
avoir besoin de beaucoup plus d’efforts de programmation, il est possible d’ob-
tenir une meilleure approximation de l’ensemble Pareto en transmettant à la re-
cherche locale l’ensemble des objectifs, de sorte à pouvoir vérifier pour chaque
solution voisine que l’on évalue si elle n’améliore pas l’approximation de l’en-
semble Pareto. Une mise en œuvre élémentaire de ce principe est donné par
110 A MÉLIORATIONS LOCALES

l’algorithme 4.5 La figure 4.10 illustre le fonctionnement de l’algorithme 4.5 sur


trois itérations de scalarisation des objectifs.

Algorithme 4.5 : Trame d’une méthode d’amélioration pour l’optimisation multi-


objectifs. L’utilisateur doit fournir un paramètre Imax donnant le nombre de vecteur
de pondération des objectifs. Dans cet algorithme, les poids sont simplement gé-
nérés aléatoirement.
Entrées : Solution s, spécification du voisinage V (·), et des


fonctions-objectifs f (·) à minimiser ; paramètre Imax

17
Résultat : Approximation P de l’ensemble Pareto
1 P = s;
2 pour Imax itération faire

20
3 Générer une vecteur de pondérations → −
w;
4 répéter
5 f in ← vrai;
6 valeur_meilleur_voisin ← ∞;

e
7 pour tous les s0 ∈ V (s) faire
si s0 n’est pas dominée par les solutions de P alors
8
9
br
Insérer s0 dans P et retirer de P les solutions dominées
par s0
em


10 si →

w · f (s0 ) < valeur_meilleur_voisin alors


11 valeur_meilleur_voisin ← → −w · f (s0 );
12 meilleur_voisin ← s0
pt



13 si valeur_meilleur_voisin < →

w · f (s) alors
14 s ← s0 ;
se

15 f in ← faux
16 jusqu’à f in;
25

4.6.2 Recherche locale Pareto


g

Une autre approche basée sur une recherche locale pour estimer l’en-
semble Pareto ne passe pas par une scalarisation. L’idée de [?] est de par-
Al

tir d’une solution quelconque au problème qui formera la première estimation


— de qualité déplorable — de l’ensemble Pareto. Ensuite, tant que l’ensemble
T_

Pareto n’est pas stabilisé, on considère toutes les solutions voisines de celles
de l’ensemble Pareto et on met à jour ce dernier avec celles-ci. La méthode
se programme récursivement de façon très concise, comme le montre l’algo-
rithme 4.6.
Le code 4.5 implante une recherche locale Pareto pour le problème du
voyageur de commerce.
4.6 O PTIMISATION MULTIOBJECTIF PAR AMÉLIORATIONS LOCALES 111

Solution de départ

3e optimum local

17
Trajectoire de la recherche locale

20
e
Solutions ayant fait avancer le front Pareto

br
em
Front Pareto après 200 scalarisations
pt

Meilleur Pareto connu


se
Objectif 2

25

Optimum local, 1ère scalarisation

2e optimum local
g

Objectif 1
Al

F IGURE 4.10 – Trajectoire et évolution d’une méthode d’amélioration itérée pour un


exemple de problème de voyageur de commerce bi-objectif ( EuclidAB100) à l’aide de
T_

la technique d’agrégation des objectifs. La méthode d’amélioration est basée sur les
chaînes d’éjections et les pondérations des objectifs sont tirées aléatoirement chaque
fois que la recherche atteint un optimum local. La solution de départ est celle que l’on
obtient à l’aide d’une méthode constructive gloutonne ne travaillant que sur le premier
objectif. Il est intéressant de constater que le troisième optimum local est meilleur que
la solution de départ, pour les deux objectifs.
112 A MÉLIORATIONS LOCALES

Algorithme 4.6 : Trame d’une recherche locale pour l’optimisation multi-


objectifs. L’intérêt de la méthode est de ne comporter aucun paramètre.
1 Énumération_voisinage;
Entrées : Solution s ; connaît une spécification du voisinage V (·) et des


fonctions-objectifs f (·) à minimiser
Résultat : Ensemble Pareto P enrichi des voisins de s
2 pour tous les s0 ∈ V (s) faire


3 Mise_a_jour_Pareto(s0 , f (s0 ))

17
4 Mise_a_jour_Pareto;
Entrées : Solution s, valeurs des objectifs →

v
Résultat : Ensemble Pareto P mis à jour
si (s, →

20
5 v ) domine une solution de P ou si P = ∅ alors
6 Retirer de P toutes les solutions dominées par (s, →

v );
7


P ← P ∪ (s, v );
8 Énumération_voisinage(s);

e
br
Listing 4.5 – tsp_3opt_pareto.c Code en C d’une recherche locale Pareto basée sur
les mouvements de type 3-opt pour le problème du voyageur de commerce. Cette fonc-
em
tion en utilise une autre qui met à jour l’ensemble Pareto pour chaque solution voisine
de la solution qui lui est fournie. La structure de donnée utilisée pour stocker l’ensemble
Pareto est discutée en section 4.6.3.
/ ∗ F u n c t i o n update_pareto_3opt w i l l b u i l d t h e neighbour s o l u t i o n i f necessary ∗ /
pt

/ ∗ I t r e c u r s i v e l y c a l l s t s p _ 3 o p t _ p a r e t o w i t h t h e neighbour s o l u t i o n ∗/
v o i d update_pareto_3opt (NODE ∗∗ pareto , POINT p o i n t ,
i n t n , i n t ∗s , i n t i , i n t j , i n t k , double ∗∗∗d ) ;
se

void tsp_3opt_pareto ( i n t n , / ∗ Number o f c i t i e s ∗ /


double∗∗∗ d , / ∗ D i s t a n c e m a t r i c e s , symmetry n o t r e q u i r e d ∗ /
i n t ∗ succ , / ∗ S o l u t i o n p r o v i d e d as successors ∗ /
POINT costs , / ∗ Lengths o f s ∗ /
NODE ∗∗ p a r e t o ) / ∗ p a r e t o s e t updated w i t h neighbours o f s ∗ /
25

{
i n t i , j , k , dim ; / ∗ indexes ∗ /
POINT c o s t s _ n e i g h b o u r ; / ∗ Costs o f a neighbour s o l u t i o n ∗ /
i n t ∗s = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n∗ s i z e o f ( i n t ) ) ; / ∗ update_pareto a l t e r s succ ∗ /
memcpy ( s , succ , ( s i z e _ t ) n∗ s i z e o f ( i n t ) ) ; / ∗ make a copy ∗/
i = 0; j = s [ i ] ; k = s [ j ] ;
g

do
{
Al

f o r ( dim = 0 ; dim < K ; dim ++)


c o s t s _ n e i g h b o u r [ dim ] = c o s t s [ dim ]
+d [ dim ] [ i ] [ s [ j ] ] + d [ dim ] [ j ] [ s [ k ] ] + d [ dim ] [ k ] [ s [ i ] ]
−d [ dim ] [ i ] [ s [ i ] ] − d [ dim ] [ j ] [ s [ j ] ] − d [ dim ] [ k ] [ s [ k ] ] ;
T_

update_pareto_3opt ( pareto , costs_neighbour , n , s , i , j , k , d ) ;


k = s[k]; / ∗ Next k ∗ /
i f ( k == i )
{ j = s[ j ]; k = s[ j ];} / ∗ k a t i t s l a s t value , n e x t j ∗ /
i f ( k == i )
{ i = s[ i ]; j = s[ i ]; k = s[ j ];} / ∗ j a t i t s l a s t value , n e x t i ∗ /
}
while ( s [ s [ i ] ] ) ; / ∗ Whole neighbourhood examined ∗ /
free ( s ) ;
}

On peut cependant accélérer la méthode en ne débutant pas avec une so-


lution quelconque, mais en l’appelant plusieurs fois avec de bonnes solutions
obtenues avec des optimisations mono-objectif avec scalarisation. En effet, il
existe souvent des méthodes très efficaces pour la résolution des problèmes
4.6 O PTIMISATION MULTIOBJECTIF PAR AMÉLIORATIONS LOCALES 113

mono-objectif, ce qui permet donc d’obtenir tout de suite d’excellentes solutions


supportées. En démarrant la recherche locale Pareto avec une bonne estima-
tion de l’ensemble Pareto, le nombre de mise à jour de l’ensemble est limité
et la recherche locale s’arrête plus rapidement. Cela évite également d’avoir
des appels récursifs trop profonds, susceptibles de faire déborder la pile de
récursion.

4.6.3 Structures de données en l’optimisation multi-objectifs

17
Les deux techniques présentées ci-dessus pour l’optimisation multi-objectifs
peuvent être relativement peu efficaces si l’on n’utilise pas une structure de
données adéquate pour stocker l’ensemble Pareto. En effet, les évaluations

20
des objectifs d’une solution voisine peuvent souvent se faire en temps cons-
tant, soit un temps se mesurant en nano-secondes sur les ordinateurs actuels.
Si l’ensemble Pareto contient p solutions et en utilisant une simple liste pour les
stocker, vérifier si une solution voisine n’est pas dominée va prendre beaucoup

e
plus de temps et la recherche locale va en être ralentie d’un facteur proportion-
nel à p.

br
Il n’est pas rare que l’ensemble Pareto contienne des milliers de solutions.
Il est donc nécessaire d’utiliser une structure de données permettant de tester
em
la dominance d’une solution en un temps ne croissant pas linéairement avec
la taille de l’ensemble Pareto.

Casiers
pt

La structure de données la plus simple et pouvant être extrêmement effi-


cace est l’utilisation d’un tableau de dimension K − 1, où K est le nombre d’ob-
se

jectifs, en supposant que ces derniers prennent un nombre limité de valeurs


entières. La taille de ce tableau dans une dimension est donnée par l’étendue
de la variation possible de l’objectif correspondant. La valeur d’une entrée de
25

ce tableau, ou casier, donne la valeur de la meilleure solution trouvée pour le


K ième objectif. Cette structure de donnée est limitative, car les objectifs ne sont
pas forcément entiers ni ne prennent un nombre raisonnable de valeurs diffé-
rentes. Cependant, si cette structure de données est utilisable en pratique, elle
g

est incomparablement rapide, puisqu’il est possible de savoir si une solution


est dominée ou non en un temps constant.
Al

Arbre KD
T_

Dans le cas général, une structure de données dont le temps pour faire une
requête croît faiblement avec p est l’arbre KD. Il s’agit d’un arbre de recherche
binaire, où un nœud à la profondeur d discrimine les autres éléments de l’arbre
sur la dimension d modulo K. Le code 4.6 donne les procédures élémentaires
d’ajout d’un nouvel élément dans un arbre KD et le parcours de ce dernier.
114 A MÉLIORATIONS LOCALES

Listing 4.6 – KD_tree_add_scan.c Codes en C permettant d’ajouter un élément à un


arbre KD et permettant de parcourir l’ensemble de l’arbre. La procédure de parcours
détruit les éléments au fur et à mesure de leur examen.
t y p e d e f double POINT [ K ] ; / ∗ K−d i m e n s i o n a l p o i n t ∗/
t y p e d e f s t r u c t NODE NODE; / ∗ Node o f a KD t r e e ∗/
s t r u c t NODE{ POINT key ; / ∗ A node s p l i t t h e t r e e a c c o r d i n g t o key [ deepness ] ∗/
int ∗info ; /∗ information to store ∗/
NODE ∗ r ; NODE ∗L ; } ; / ∗ R i g h t and l e f t s u b t r e e s ∗/

/ ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ Add element t o KD−Tree t r e e ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ /


v o i d KD_add (NODE ∗∗ t r e e , NODE ∗element , i n t deepness )
{

17
i f (∗ t r e e == NULL )
∗ t r e e = element ;
e l s e i f ( ( ∗ t r e e )−>key [ deepness%K ] < element−>key [ deepness%K ] )
KD_add(&(∗ t r e e )−>r , element , deepness + 1 ) ;
else

20
KD_add(&(∗ t r e e )−>L , element , deepness + 1 ) ;
}

/ ∗ ∗∗∗∗∗∗∗∗∗ Enumerate a l l t h e elements o f a KD−t r e e and f r e e memory ∗∗∗∗∗∗∗∗∗∗ ∗ /


v o i d KD_scan_and_delete (NODE ∗ t r e e , i n t n )
{

e
int i ;
i f ( tree )

br
{ KD_scan_and_delete ( t r e e −> L , n ) ;

fo r ( i = 0; i < K; i ++)
p r i n t f ( "%g ", t r e e −>key [ i ] ) ;
em
fo r ( i = 0; i < n; i ++)
p r i n t f ( "%d ", t r e e −>i n f o [ i ] ) ;
putchar ( ’ \ n ’ ) ;

KD_scan_and_delete ( t r e e −> r , n ) ;
f r e e ( t r e e −>i n f o ) ;
pt

free ( tree ) ;
}
}
se

La procédure la plus délicate à programmer pour un arbre KD est la sup-


pression d’un nœud donné. Contrairement à un arbre binaire à une seule di-
mension, on ne peut pas remplacer ce nœud par celui le plus à droite du sous-
arbre gauche ou le plus à gauche du sous-arbre droit. En effet, comme un arbre
25

KD discrimine sur une dimension différente à chaque niveau, il faut parcourir


l’ensemble des deux sous-arbres pour trouver le nœud qui a la plus petite ou la
plus grande valeur, sur la même dimension que le nœud à éliminer. Le nœud
de remplacement sera lui-même récursivement remplacé, jusqu’à ce que l’on
g

tombe sur une feuille, qui est simplement éliminée. Le code 4.7 implante une
Al

procédure d’élimination d’un nœud donné à l’intérieur d’un arbre KD.


T_
4.6 O PTIMISATION MULTIOBJECTIF PAR AMÉLIORATIONS LOCALES 115

Listing 4.7 – KD_tree_delete.c Codes en C permettant de supprimer un élément d’une


arbre KD.
/ ∗ ∗∗ Find t h e node o f t r e e w i t h max o r min ( = 1 ) c o o r d i n a t e i n dimension dim ∗∗ ∗ /
NODE∗∗ KD_find_opt (NODE ∗∗ t r e e , i n t dim , i n t deep , NODE ∗∗opt ,
i n t min , double ∗value , i n t ∗deep_opt )
{
double v a l = (∗∗ t r e e ) . key [ dim ] ;
i f ( ( min && ∗ v a l u e > v a l ) | | ( ! min && ∗ v a l u e < v a l ) )
{ opt = t r e e ;
∗value = val ;
∗deep_opt = deep ;
}
i f ((∗∗ tree ) . L )

17
o p t = KD_find_opt (&(∗∗ t r e e ) . L , dim , deep +1 , opt , min , value , deep_opt ) ;
i f ((∗∗ tree ) . r )
o p t = KD_find_opt (&(∗∗ t r e e ) . r , dim , deep +1 , opt , min , value , deep_opt ) ;
r e t u r n opt ;

20
}

/ ∗ ∗∗∗∗∗∗∗∗∗ Remove t h e r o o t node from a ( sub−)KD−t r e e a t deepness deep ∗∗∗∗∗∗∗ ∗ /


v o i d KD_delete (NODE ∗∗node , i n t deep )
{
NODE ∗∗ r e p l a c i n g ; / ∗ Node t h a t w i l l r e p l a c e t h e removed node ∗ /

e
double v a l _ r e p l ;
i n t deep_repl ;

i f ( ! ( ∗ ∗ node ) . L && ! ( ∗ ∗ node ) . r )


{
f r e e ( (∗∗ node ) . i n f o ) ;
f r e e (∗ node ) ;
br
em
∗node = NULL ;
return ;
}

i f ( ( ∗ ∗ node ) . L ) / ∗ Find t h e r e p l a c i n g node w i t h maximal c o o r d i n a t e a t l e f t ∗ /


pt

{
val_repl = −i n f i n i t e ;
r e p l a c i n g = KD_find_opt (&(∗∗ node ) . L , deep%K , deep +1 , NULL ,
0 , &v a l _ r e p l , &deep_repl ) ;
se

}
else / ∗ Find t h e r e p l a c i n g node w i t h minimal c o o r d i n a t e a t r i g h t ∗ /
{
val_repl = i n f i n i t e ;
r e p l a c i n g = KD_find_opt (&(∗∗ node ) . r , deep%K , deep +1 , NULL ,
1 , &v a l _ r e p l , &deep_repl ) ;
25

f o r ( i n t i = 0 ; i < K ; i ++)
(∗∗ node ) . key [ i ] = (∗∗ r e p l a c i n g ) . key [ i ] ;
KD_delete ( r e p l a c i n g , deep_repl ) ;
}
g
Al

Finalement, pour utiliser un arbre KD pour mettre à jour un ensemble Pa-


reto, il faut disposer d’une procédure qui recherche un point de l’arbre qui domi-
nerait une solution essayée. Pour cela, il faut chercher si l’arbre KD comporte
T_

un point situé entre le point idéal, qui est celui dont les valeurs sur toutes les di-
mensions sont celles de l’optimum des objectifs pris séparément. En pratique,
le point idéal n’est pas connu, mais on peut se contenter d’une approximation,
qui peut être aussi grossière que l’on veut, par exemple (−∞, . . . , −∞) si tous
les objectifs doivent être minimisés. Si l’arbre KD comporte un tel point, alors
celui-ci domine la solution essayée, qui est donc ignorée. Sinon, la nouvelle
solution en domine d’autres, qui doivent être éliminées, et elle est ajoutée à
l’arbre KD.
Le code 4.8 permet d’effectuer la mise à jour d’un ensemble Pareto lors-
qu’on cherche à y inclure un nouveau point.
116 A MÉLIORATIONS LOCALES

Listing 4.8 – KD_tree_update_pareto.c Codes en C permettant de mettre à jour un


ensemble Pareto représenté au moyen d’un arbre KD.
/ ∗ ∗∗∗∗∗∗ Test i f node i s i n t h e r e c t a n g u l a r box d e l i m i t e d by min and max ∗∗∗∗∗ ∗ /
i n t KD_in (NODE ∗node , POINT min , POINT max )
{ i n t i , res = 1;
f o r ( i = 0 ; i < K && r e s ; i ++)
r e s = min [ i ] < node−>key [ i ] && max [ i ] > node−>key [ i ] ;
r e t u r n res ;
}

/ ∗ ∗ Returns a node o f t r e e i n box [ min , max ] w i t h i t s deepness ; NULL i f none ∗ ∗ /


NODE ∗∗KD_find (NODE ∗∗ t r e e , POINT min , POINT max , i n t deep , i n t ∗deep_found )
{

17
NODE ∗∗ r e s ;
i f (!(∗ tree ) ) / ∗ t r e e empty : no node found ∗ /
r e t u r n NULL ;
i f ( KD_in (∗ t r e e , min , max ) ) / ∗ The r o o t o f t r e e i s i n t h e box ∗ /

20
{
∗deep_found = deep ;
return tree ;
}
i f ( max [ deep%K ] > (∗ t r e e )−>key [ deep%K ] && / ∗ Look a t r i g h t sub−t r e e ∗ /
( r e s = KD_find (&(∗ t r e e )−>r , min , max , deep +1 , deep_found ) ) )

e
r e t u r n res ;
i f ( min [ deep%K ] < (∗ t r e e )−>key [ deep%K ] ) / ∗ Look a t t h e l e f t ∗ /
r e t u r n KD_find (&(∗ t r e e )−>L , min , max , deep +1 , deep_found ) ;

}
r e t u r n NULL ;

br / ∗ No node found ∗ /

/ ∗ ∗∗ Looks i f p o i n t should be added t o a p a r e t o s e t r e p r e s e n t e d by a KD−t r e e ∗ ∗ /


em
/ ∗ I f p o i n t i s added , b u i l d t h e neighbour o f s w i t h 3−o p t move ( i , j , k ) ∗/
/ ∗ Remove dominated p o i n t s and then r e c u r s i v e l y add non−dominated neighbours ∗ /
v o i d update_pareto_3opt (NODE ∗∗ pareto , POINT p o i n t ,
i n t n , i n t ∗s , i n t i , i n t j , i n t k , double ∗∗∗d )
{
pt

POINT min , max ;


i n t deepness , dim ;
NODE ∗∗dominant ;
se

f o r ( dim = 0 ; dim < K ; dim ++)


{ min [ dim ] = 0 . 0 ; max [ dim ] = p o i n t [ dim ] + e p s i l o n ; }
dominant = KD_find ( pareto , min , max , 0 , &deepness ) ;
i f ( ! dominant ) / ∗ p o i n t improves p a r e t o f r o n t ∗ /
{
f o r ( dim = 0 ; dim < K ; dim ++) / ∗ Remove dominated elements , i f any ∗ /
25

{ min [ dim ] = p o i n t [ dim ] − e p s i l o n ; max [ dim ] = i n f i n i t e ; }


w h i l e ( ( dominant = KD_find ( pareto , min , max , 0 , &deepness ) ) )
KD_delete ( dominant , deepness ) ;

NODE ∗element= m a l l o c ( s i z e o f (NODE ) ) ; / ∗ Create a new element f o r p a r e t o ∗ /


memcpy ( element−>key , p o i n t , s i z e o f ( POINT ) ) ;
g

element−>i n f o = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
memcpy ( element−>i n f o , s , ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
Al

element−>i n f o [ i ] = s [ j ] ; element−>i n f o [ j ] = s [ k ] ; element−>i n f o [ k ] = s [ i ] ;


element−>L = element−>r = NULL ;

KD_add ( pareto , element , 0 ) ;


T_

t s p _ 3 o p t _ p a r e t o ( n , d , element−>i n f o , p o i n t , p a r e t o ) ;
}
}
4.7 E XERCICES 117

4.7 Exercices
Exercice 4.1. Propriétés des voisinges 2-opt et 3-opt Montrer les propriétés
suivantes des voisinages 2-opt et 3-opt :
— L’inversion de deux villes ou un mouvement de type 3-opt peut être ob-
tenu par une succession de mouvements 2-opt
— 2-opt et 3-opt sont des voisinages possédant la propriété de connectivité.
Donner une borne supérieur au diamètre de ces voisinages

17
Exercice 4.2. Limitation du voisinage 3-opt Pour limiter la taille du voisinage
d’un problème de voyageur de commerce, seules les 40 villes les plus proches
de chaque ville sont considérées. Avec une telle limitation, quelle est la com-

20
plexité de la vérification qu’une solution est 3-optimale ? A-t-on besoin d’une
structure de données particulière pour atteindre une complexité algorithmique
minimale ? Le voisinage engendré par une telle limitation est-il connexe.

e
Exercice 4.3. Voisinages pour l’élaboration de tournées de véhicules Pro-
poser 4 voisinages différents pour le problème de distribution de biens. Donner

br
la taille de ces voisinages en fonction du nombre n de clients du problème
ainsi que du nombre m de tournées d’une solution. Préciser si ces voisinages
em
disposent de la propriété de connectivité, selon la modélisation du problème.
Exercice 4.4. Voisinages pour l’arbre de Steiner Deux représentations de
solutions ont été proposées à la section 2.1.2 pour l’arbre de Steiner. Donner
des voisinages adaptés à chacune de ces modélisations du problème.
pt

Exercice 4.5. Chaîne d’éjections pour l’élaboration de tournées de véhi-


se

cules Proposer une technique basée sur les chaînes d’éjections pour le pro-
blème de distribution de bien. Préciser comment initialiser la chaîne, comment
la propager et comment la terminer. Estimer la complexité algorithmique de
l’évaluation d’une chaîne pour une solution avec n clients et m tournées.
25
g
Al
T_
118 A MÉLIORATIONS LOCALES

17
20
e
br
em
pt
se
25
g
Al
T_
Chapitre 5

17
Méthodes de décomposition

20
5.1 Considérations sur la taille des problèmes

e
La complexité algorithmique très brièvement exposée en section 1.2, a pour

br
but d’évaluer les ressources de calcul nécessaire à l’exécution d’un algorithme
en fonction de la taille des données qu’on lui fournit. On ne peut pas classer
em
les problèmes — petits ou grands — uniquement en fonction de leur taille ab-
solue : trier un tableau de 1000 éléments est assurément beaucoup plus facile
que de trouver la tournée optimale d’un voyageur de commerce sur 100 villes.
Le temps à disposition pour trouver une solution entre évidemment en ligne de
pt

compte : la perception de ce qu’est un gros problème ne sera pas la même


si l’on doit faire un traitement en quelques micro-secondes dans une applica-
tion temps-réel ou une planification à long terme pour laquelle un calcul d’une
se

journée est parfaitement envisageable.


Très grossièrement, on peut distinguer quelques catégories de taille de pro-
blèmes, pour ceux faisant partie de la classe NP-difficile :
25

Les problèmes-jouet Taille typique : n ≈ 10. Pour s’assurer qu’un algorithme


fonctionne correctement, on l’exécute à la main ou bien on programme un
autre algorithme, plus simple à implanter mais nettement moins efficace.
Par exemple, celui-ci peut être une énumération exhaustive de toutes les
g

solutions. Actuellement, on peut empiriquement considérer qu’un ordina-


teur est capable d’effectuer 109 opérations élémentaires par seconde. Si
Al

l’on dispose d’un budget-temps de cet ordre de grandeur, on peut envi-


sager une énumération exhaustive de toutes les solutions d’un problème
T_

de recherche de permutations pour n ≈ 10 ; pour un problème en va-


riables binaires, on aura n ≈ 20. Naturellement, pour des algorithmes
polynomiaux, les tailles d’exemples que l’on peut traiter en une seconde
varient de n ≈ 50 pour une complexité en O(n3 ) à n ≈ 108 pour une com-
plexité linéaire, en passant par n ≈ 104 pour une complexité quadratique
et n ≈ 106 pour un algorithme en O(n log n).
Les petits problèmes Taille typique : 10 / n / 102 Lorsque leur taille ne
permet plus une énumération exhaustive des solutions, on passe dans
la catégorie des petits problèmes. On pourrait les caractériser par ceux
pour lesquels on connaît des algorithmes robustes permettant d’obtenir
une solution optimale en un temps raisonnable. Il convient de mentionner
120 M ÉTHODES DE DÉCOMPOSITION

que la littérature regorge d’algorithmes exacts permettant de résoudre


des exemples de problèmes « difficiles » de taille nettement plus élevée
que celle mentionnée ci-dessus. Cependant, il faut être prudent avec ce
genre d’affirmations : il est vrai que les solutions optimales de voyageur
de commerce ou de sac de montagne avec des dizaines de milliers d’élé-
ments ont été trouvées, mais il est certainement possible de générer des
exemples de problèmes beaucoup plus petits mettant en difficulté ces
programmes.
Les problèmes de petite taille sont fréquemment utilisés pour la concep-

17
tion et la calibration des méthodes heuristiques. En effet, la connaissance
des solutions optimales permet de déterminer la qualité de l’heuristique
et d’optimiser la valeur de ses paramètres en conservant des temps de

20
calcul raisonnables

Les problèmes standards Taille typique : 102 / n / 104 Les problèmes de


taille moyenne constituent le domaine d’application privilégié des méta-

e
heuristiques. Ces problèmes, fréquemment rencontrés dans les applica-
tions réelles, sont de taille trop importante pour pouvoir être résolus ef-

br
ficacement par des méthodes exactes ou pour qu’un humain réussisse
à deviner des solutions de qualité suffisante. La taille maximale des pro-
em
blèmes traitables par une métaheuristique n’utilisant pas de méthodes de
décomposition est lié à sa complexité algorithmique que ce soit au niveau
du temps de calcul ou de la mémoire. Avec plus de 104 éléments, il de-
vient en effet difficilement envisageable d’utiliser une méthode construc-
pt

tive ou une taille de voisinage en O(n2 ), et ce, d’autant plus si l’on doit
mémoriser, pour des raisons d’efficacité, une matrice n × n. La com-
plexité algorithmique d’un programme basé sur une métaheuristique est
se

fréquemment supérieure à O(n3 ), ce qui fait que de nombreux auteurs


parlent déjà de « grand » problème pour une taille de 100.

Les grands problèmes Taille typique : 103 / n / 107 Certains problèmes


25

réels comportent souvent un nombre d’éléments plus élevés que ceux


des problèmes standards, ou bien doivent être résolus avec un effort de
calcul moindre que ce que prendrait une méthode directe. On peut pen-
g

ser par exemple à l’élaboration de tournées pour la distribution du cour-


rier ou encore l’étiquetage des éléments sur une carte de géographie, où
Al

une taille de 105 n’est pas exceptionnelle. Dans ce cas, on doit utiliser des
méthodes de décomposition. Ce chapitre présente quelques techniques
générales permettant d’aborder les problèmes de grande taille. Il faut ce-
T_

pendant noter que ces techniques peuvent parfois avantageusement être


appliquées à des problèmes de taille relativement modeste, avec parfois
guère plus de quelques dizaines d’éléments.

Les très grands problèmes Taille : n > 107 éléments. Lorsque la taille du
problème dépasse 107 à 109 éléments, il n’est plus possible de stocker
les données entièrement en mémoire vive. Il est nécessaire dans ce cas
de travailler sur des portions du problème, généralement à l’aide d’algo-
rithmes parallèles pour conserver des temps de traitement convenables.
Le traitement de ce type de problèmes soulève des questions d’ordre
essentiellement techniques et sort du cadre de cet ouvrage.
5.2 A LGORITHMES RÉCURSIFS 121

5.2 Algorithmes récursifs


Lorsque l’on doit résoudre un problème de grande taille avec un effort de
calcul limité, on le décompose en petits morceaux, que l’on résout indépen-
damment pour finalement les assembler afin de recomposer une solution au
problème complet. Un gain en efficacité n’est possible par une telle technique
que par la conjonction de plusieurs conditions :
— La résolution directe du problème demande un effort de calcul plus que
linéaire, sinon un décomposition n’a de sens que pour un calcul parallèle

17
— Les morceaux doivent être indépendants les uns des autres
— L’assemblage des morceaux doit être d’une complexité inférieure à celle

20
de la résolution directe du problème
Toute la difficulté vient de la manière dont on définit les morceaux : ils doivent
représenter une portion logique du problème pour que leur assemblage, une
fois résolus, soit simple. Les algorithmes récursifs pour le tri d’un tableau consti-

e
tuent un exemple typique de technique de décomposition : on découpe le ta-

br
bleau en deux parties à peu près égales, celles-ci sont triées par deux appels
récursifs, si elles contiennent plus d’un élément ; finalement les deux parties
localement triées sont parcourues pour reconstituer l’ensemble du tableau.
em
5.2.1 Théorème général de récurrence
L’efficacité d’un algorithme récursif peut s’évaluer dans un certain nombre
pt

de cas par le théorème général de récurrence : Supposons que le temps pour


traiter un problème de taille n soit donné par T (n). L’algorithme procède par
se

découpage des données en b parties de taille approximativement égales, n/b,


dont a sont résolues récursivement. Ensuite ces parties sont assemblées pour
reconstituer une solution au problème initial, ce qui engendre un temps de
f (n). Pour évaluer la complexité d’un tel algorithme, il faut résoudre l’équation
25

fonctionnelle T (n) = a · T (n/b) + f (n) dont la solution dépend de l’effort que


requiert la reconstitution :
— Si f (n) = O(nlogb (a)− ) alors T (n) = Θ(nlogb (a) )
g

— Si f (n) = Θ(nlogb (a) ), alors T (n) = Θ(nlogb a · log n)


— Si f (n) = Ω(nlogb (a)+ ) et si p · f (n/p) < c · f (n)), avec c < 1, constante,
Al

alors T (n) = Θ(f (n))


Dans les expressions ci-dessus  est une constante positive qui force la fonc-
T_

tion à être soit plus petite, soit plus grande que nlogb (a) .
Souvent, a = b : on a un appel récursif pour toutes les parties. Dans ce
cas, le théorème établit que si la reconstitution peut se faire en un temps sub-
linéaire, alors on peut traiter le problème en temps linéaire ; si la reconstitution
prend un temps linéaire — ce qui est typiquement le cas pour les algorithmes
de tri — le problème peut se résoudre en O(n log n). Le dernier cas indique
simplement que toute la difficulté de l’algorithme est concentré dans les opéra-
tions de reconstitution. Finalement, il faut mentionner que le théorème ne traite
pas tous les cas pour la fonction f (n).
On rencontre également des cas où a 6= b. Par exemple, la recherche par di-
chotomie dans un tableau trié procède par division du tableau en b = 2 parties
122 M ÉTHODES DE DÉCOMPOSITION

dont une seule (a = 1) devra être traitée récursivement. Pour ce problème, il n’y
a pas de « reconstitution », mais l’effort de calcul à réaliser entre deux appels
récursifs est constant (f (n) = Θ(1)). En appliquant le second cas ci-dessus,
on trouve que T (n) = Θ(nlog2 1 · log n) = Θ(log n).
Un autre exemple est celui de la recherche d’un point du plan parmi un
ensemble de n points stockés sous la forme d’un arbre 2D équilibré (voir la
structure de données discutée en section 4.6.3). Avec une telle structure de
données, on peut diviser par deux le nombre de points restant à examiner
en traitant au maximum a = 2 parties parmi b = 4. En effet, contrairement

17
à un arbre binaire en une dimension, on ne peut pas assurer de diviser par
deux ce nombre à chaque étage de l’arbre, mais seulement tous les deux
étages. Le problème étant celui d’une recherche, il n’y a pas de reconstruction

20
et f (n) = O(1). En remarquant que log4 (2) = 1/2 et en choisissant  = 1/2,
on remarque que l’on est dans le premier cas. On en déduit que la complexité
d’une recherche dans un arbre 2D est en Θ(n1/2 ). En pratique cependant, si
les point sont bien répartis, on observe un comportement nettement plus favo-

e
rable, se rapprochant de log n.
Dans le cas d’algorithmes heuristiques procédant par récursion, on arrête

br
communément cette dernière prématurément, avant que les morceaux soient
d’une taille si faible que leur résolution devienne triviale. En effet, la procédure
de découpe d’un problème et celle de reconstitution d’une solution à partir des
em
morceaux se font de manière heuristique, car on ne peut en général garantir
l’optimalité de la reconstitution à partir de morceaux, même si ces derniers ont
été résolus exactement. Cela signifie que les « zones frontières » entre deux
pt

morceaux présentent des caractéristiques de non optimalité plus ou moins


évidentes. Pour limiter cet effet de sous-optimalité, il convient d’assembler le
moins possible de morceaux, tout en étant capable de traiter ces derniers. En
se

effet, s’ils sont trop gros, leur résolution exacte prend trop de temps ou l’appli-
cation d’une heuristique risque de produire des morceaux de basse qualité.
25

5.3 Méthodes constructives


Les trames d’amélioration partielles présentées plus loin, LNS, POPMUSIC
et Corridor supposent toutes qu’une solution initiale du problème est dispo-
g

nible. La résolution d’un problème de grande taille implique une limitation sur
Al

la complexité de la méthode de construction d’une solution initiale. Cela signi-


fie que même un algorithme comme la plus élémentaire méthode gloutonne
n’est pas appropriée. En effet, si la fonction c(s, e) d’évaluation de l’ajout d’un
T_

élément e dépend effectivement de la solution partielle s, sa complexité est en


en Ω(n2 ), car avant d’ajouter l’un des n éléments, il faut avoir évalué c(s, e)
pour tous les éléments restants. Une construction aléatoire en temps linéaire
ne l’est pas plus, en raison de la qualité de la solution produite. Il faut donc
« tricher », en faisant l’hypothèse que tous les éléments du problèmes n’ont
pas une relation directe avec tous les autres. En d’autres termes, un élément
est en relation avec un relativement faible nombre d’autres éléments et cette
relation présente une certaine symétrie.
On peut raisonnablement faire l’hypothèse qu’il est possible de quantifier la
proximité qu’il y a entre deux éléments. Dans un tel cas, on s’affranchit d’une
complexité en O(n2 ) par échantillonnage et récursion. On peut limiter le phé-
5.3 M ÉTHODES CONSTRUCTIVES 123

17
(a) Ensemble des éléments (b) Échantillon

20
e
br
em
(c) Centres (d) Groupes
pt

F IGURE 5.1 – Illustration de la méthode de décomposition d’un problème : 5.1(a)


se

L’ensemble des éléments d’un problème. 5.1(b) Échantillonnage des éléments. 5.1(c)
Centres des groupes trouvés avec les éléments de l’échantillon. 5.1(d) Affectation de
l’ensemble des éléments aux centres les plus proches.
25

nomène de sous-optimalité dû à l’assemblage des morceaux en arrêtant la


récursion dès le premier ou le second niveau.
Il existe de relativement bonnes heuristiques en classification automatique
g

pour découper un problème de taille n en p groupes. Bien que N P -difficile,


le problème de la p-médiane permet de réaliser une telle découpe heuristique
Al

avec une complexité de O(p · n + ( np )2 ) 1 . Cette complexité peut être minimisée



en choisissant√ p = n. Ainsi, il est possible de découper un √ problème de
T_

taille n en n portions comportant chacune approximativement n éléments


en O((n3/2 ). Sans pour autant diminuer la complexité algorithmique, on peut
notablement accélérer cette procédure en procédant par échantillonnage : Un
élément médian de chaque groupe n’est pas déterminé en utilisant l’intégralité
des éléments, mais en n’en conservant qu’une fraction. Cette méthode est
illustrée en figure 5.1.
Il est possible de procéder à une décomposition plus fine en arrêtant la

1. On ne peut utiliser la notation O(·) ici car on fait l’hypothèse que les p groupes contiennent
approximativement le même nombre d’éléments. Dans le pire des cas, quelques groupes pour-
raient en contenir un nombre en O(n), et O(n) groupes pourraient en contenir un nombre en
O(1), ce qui impliquerait une complexité théorique en O(n2 ).
124 M ÉTHODES DE DÉCOMPOSITION

17
20
e
br
em
pt
se
25

F IGURE 5.2 – Décomposition à deux niveaux d’un problème. Les éléments sont re-

g

groupés en Θ( n) gros groupes de taille approximativement identique. Une relation de


proximité, illustrée par des traits gras, est définie entre ces groupes. Ces derniers sont

Al

eux-même décomposés en Θ( n) petits groupes. Le processus a une complexité en


3/2
O(n ). Il peut être appliqué à des problèmes non géométriques.
T_
5.3 M ÉTHODES CONSTRUCTIVES 125

récursion au second niveau plutôt qu’au premier : Le problème est découpé


en a gros morceaux de taille approximativement égales comme on l’a vu plus
haut. On définit une relation de proximité entre les gros morceaux, de sorte
que chacun ait O(1) voisins. Une définition rudimentaire de proximité est la
suivante : si un élément a pour plus proche centre ci et comme second plus
proche cj , alors ci et cj sont considérés comme voisins. Chaque gros morceau
est ensuite découpé en b petits morceaux. On définit de même une relation
de proximité entre les petits morceaux, en considérant tous ceux issus de la
décomposition du même gros morceau ou d’un voisin de ce dernier.

17

√En procédant par échantillonnage, et en choisissant a = Θ( n) et b =
Θ( n), on obtient en O(n3/2 ) une décomposition en un nombre de petits mor-

20
ceaux proportionnel à n dont la taille est approximativement identique ce qui,
pour certains problème peut avoir un sens : Par exemple, pour l’élaboration de
tournées de véhicules, le nombre maximum de clients que l’on peut placer sur
une tournée dépend de l’application (réparateur, distribution de colis, ramas-

e
sage d’ordures) et non du nombre total de clients que l’on a dans le problème.
Un exemple de gain possible de complexité par

br
√ rapport à une méthode directe
qui serait en O(n2 ) est de choisir a = b = Θ( n).
em
Cette technique de décomposition est illustrée en figure 5.2, où l’on a super-
posé les relations de proximités entre les gros morceaux et les groupes d’envi-
ron 15 éléments obtenus par décomposition des gros morceaux. Les éléments
pt

de ces derniers sont représentés par des points de même couleur.


se

À partir d’une telle décomposition et avec les relations de proximité ainsi


définie, il devient possible de créer efficacement une solution à un problème
de grande taille. À titre indicatif, le temps de calcul pour obtenir les structures
de la figure 5.2, comportant plus de 16’000 entités, est de l’ordre de la seconde.
25

Pour illustrer l’utilisation de ces structures, voici une technique de construc-


tion d’une tournée d’un voyageur de commerce : En admettant que l’on dispose
g

d’une procédure en O(n2 ) pour construire une tournée, une construction récur- √
sive peut se faire en O(n3/2 ) : Tout d’abord, on cherche une tournée sur les n
Al

centres correspondant
√ aux centres des gros morceaux. Ceci nécessite un tra-
vail en O(n · n). Ensuite, pour chaque gros morceau, on cherche une tournée
T_

sur les entités du morceau, auxquelles on ajoutera deux unités fictives, cor-
respondant aux connexions qu’il faudra réaliser avec les deux gros morceaux
adjacents.

Un exemple de construction pour le problème plus complexe d’élaboration


de tournées de véhicules avec localisation de dépôts a été proposé dans [?].
Dans cette référence, les grands principes de construction efficace d’une so-
lution sont proposés. Cette dernière est ensuite améliorée, au moyen de la
technique POPMUSIC que l’on détaillera en section 5.4.2. Examinons mainte-
nant quelques techniques d’amélioration adaptées aux problèmes de grande
taille.
126 M ÉTHODES DE DÉCOMPOSITION

5.4 Méthodes d’amélioration pour problèmes de


grande taille
5.4.1 Recherche dans de grands voisinages (LNS)
La recherche dans de grands voisinages Large Neighborhood Search (LNS)
a été proposée par [?]. L’idée générale est d’améliorer graduellement une so-
lution en alternant des phases de destruction et de réparation. Pour illustrer
ce principe, prenons l’exemple d’un programme linéaire en nombre entiers. La

17
phase de destruction consiste à sélectionner un sous-ensemble de variables,
en incorporant une certaine stochasticité dans ce processus. Dans sa forme la
plus simple, celle-ci consiste à sélectionner un nombre constant de variables,

20
de façon totalement aléatoire. Un forme plus élaborée est de sélectionner aléa-
toirement une variable-germe et un certain nombre d’autres, qui sont le plus
en relation avec la variable-germe. La phase de réparation consiste à tenter
d’améliorer la solution en résolvant un sous-problème sur les variables qui ont

e
été sélectionnées, tout en fixant la valeur des autres variables à celle prise
dans la solution de départ.

br
Le nom de cette technique vient du fait qu’un très grand nombre de possibi-
lités existe pour reconstruire une solution, nombre croissant exponentiellement
em
avec la taille du problème ou du moins plus élevé que celui que l’on pourrait rai-
sonnablement énumérer extensivement. Ainsi la phase de reconstruction con-
siste à choisir une solution parmi un grand nombre de possibilités. Comme la
majeur partie des variables conservent leur valeur d’une solution à la suivante,
pt

il s’agit bien, conceptuellement, d’une recherche locale, mais avec une taille de
voisinage élevée. La trame de LNS est donnée par l’algorithme 5.1.
se

Algorithme 5.1 : Trame de LNS. Les fonctions de destruction, de réparation et


d’acceptation doivent être spécifiées par le programmeur, de même que le critère
d’arrêt.
25

Entrées : Solution s, Méthode de destruction d(·), méthode de


réparation r(·), critère d’acceptation a(·, (·))
Résultat : Solution améliorée s∗
1 s∗ ← s;
g

2 tant que Condition d’arrêt non satisfaite faire


Al

3 s0 ← r(d(s));
4 si a(s, s0 ) alors
5 s ← s0
T_

6 si s0 meilleure que s∗ alors


7 s ← s0

On remarque que cette trame laisse une très grande liberté au program-
meur pour choisir diverses options :
Méthode de destruction d(·) Cette méthode est censée détruire une partie
de la solution courante. Les auteurs préconisent qu’elle ne soit pas déter-
ministe, de sorte que deux appels successifs détruisent des portions dif-
férentes. Une autre vision de cette méthode est de fixer un certain nom-
5.4 M ÉTHODES D ’ AMÉLIORATION POUR PROBLÈMES DE GRANDE TAILLE 127

bre de variables du problème et de libérer les autres, qui pourront être


modifiées. Cette méthode comporte également un paramètre qui permet
de moduler l’importance de la destruction. En effet, si le nombre de va-
riables modifiables est trop restreint, la méthode de réparation aura trop
de contraintes pour pouvoir reconstruire la solution différemment, et l’al-
gorithme n’arrivera pas à améliorer la solution courante. Inversement, si
la destruction est trop importante, la méthode de reconstruction pourra
rencontrer des difficultés à améliorer la solution courante, notamment si
on veut une reconstruction exacte impliquant un volume de calcul prohi-

17
bitif.
Méthode de reconstruction r(·) Cette méthode est censée reconstruire la
partie d’une solution qui serait détruite. Une autre vision de cette mé-

20
thode est de réoptimiser la portion du problème correspondant aux va-
riables qui ont été libérées par la méthode de destruction. Une option
possible pour la méthode de reconstruction est d’utiliser une méthode
exacte, notamment de la programmation par contrainte. Une autre option

e
est d’utiliser une méthode heuristique, qu’elle soit simple, comme un al-
gorithme glouton, ou plus évoluée, comme une recherche avec tabous,
une recherche à voisinage variable ou autre.
br
Critère d’acceptation a(·, ·) Le plus simple des critères d’acceptation est d’uti-
em
liser la valeur de la fonction-utilité des deux solutions passées en para-
mètre :

V rai Si s0 meilleure que s


pt


0
a(s, s ) =
F aux Sinon
se

D’autres critères ont été proposés, notamment ceux utilisés par des mé-
thodes de type recuit simulé (c.f. section 6.1).
Critère d’arrêt La trame ne fournit aucune suggestion concernant le critère
25

d’arrêt à utiliser. Les auteurs utilisent fréquemment la limite de leur pa-


tience, exprimée en secondes, lorsque ce n’est pas celle d’auteurs ayant
proposé une méthode concurrente ! Ce genre de critère d’arrêt n’est guère
convaincant. Nous verrons plus loin que la trame assez proche de POP-
g

MUSIC incorpore un critère d’arrêt naturel.


Al

À titre d’illustration d’une implantation de cette méthode, prenons celle d’où


elle a reçu son nom [?], qui est une adaptation pour problèmes d’élaboration de
tournées de véhicules. Pour ce problème, la méthode de destruction consiste
T_

à choisir un client-germe au hasard. Les autres clients sont triés à l’aide d’une
fonction mesurant la relation existante avec le client-germe. Cette fonction est
inversement proportionnelle à la distance entre clients, et au fait que les clients
font partie de la même tournée. L’idée est de sélectionner un sous-ensemble
de clients proches, faisant partie de tournées différentes. Ces clients sont choi-
sis aléatoirement, mais avec un biais pour favoriser le choix de ceux les plus
fortement en relation avec le client-germe.
La méthode de reconstruction est basée sur un modèle de programme li-
néaire en nombres entiers qui est résolu avec une technique de séparation
et évaluation avec propagation de contraintes. On contraint cette méthode à
ne modifier que les variables associées aux clients choisis par la méthode de
128 M ÉTHODES DE DÉCOMPOSITION

17
20
(a) Solution initiale

e
br
em
pt
se

(b) Solution détruite


25
g
Al
T_

(c) Solution reconstruite

F IGURE 5.3 – Illustration de la méthode LNS sur un problème d’élaboration de tournées


de véhicules : Certains clients de la solution initiale 5.3(a) sont retirés pour obtenir une
solution partielle non admissible 5.3(b) puis sont réinsérés pour obtenir une solution
complète améliorée 5.3(c).
5.4 M ÉTHODES D ’ AMÉLIORATION POUR PROBLÈMES DE GRANDE TAILLE 129

destruction. De plus, pour éviter que le temps de calcul n’explose, ce qui sur-
vient fréquemment avec les méthodes exactes, l’arbre d’énumération n’est pas
examiné complètement, mais élagué heuristiquement. Un cycle de destruction-
reconstruction est illustré en figure 5.3.
Il existe des algorithmes basés sur la trame de LNS qui ont été proposés
bien avant cette dernière. On peut citer notamment l’algorithme de déplace-
ment du goulot d’étranglement [?] pour un problème d’ordonnancement. Dans
cet article, la méthode de destruction sélectionne la machine qui constitue le
goulot d’étranglement. La méthode de reconstruction réordonne les opérations

17
de cette machine, en considérant que les séquences sur les autres machines
ne sont pas modifiées. Cela signifie que pour chaque opération sur la machine-
goulot, on a un délai avant lequel l’opération ne peut avoir lieu (parce que l’élé-

20
ment sur lequel elle a lieu doit subir d’autres opérations sur d’autres machines
préalablement) et un délai après lequel l’opération ne doit pas être faite si l’on
s’interdit de dégrader la solution (parce que l’élément sur lequel elle a lieu doit
subir d’autres opérations sur d’autres machines ultérieurement). Comme tous

e
les choix sont déterministes, que les réoptimisations se font de manière exacte,
et que la solution courante n’est modifiée que si la réoptimisation l’améliore

br
strictement, la méthode a un critère d’arrêt naturel.
La méthode POPMUSIC présentée à la section suivante a été développée
em
indépendamment de LNS. Elle peut être vue comme une méthode de type LNS
un peu plus rigide, dans le sens où elle dirige mieux le programmeur dans le
choix des options, notamment en ce qui concerne le critère d’arrêt.
pt

5.4.2 POPMUSIC
se

L’idée à la base de POPMUSIC est d’optimiser localement une portion


d’une solution, une fois cette dernière disponible. Ces améliorations sont ré-
pétées jusqu’à ce qu’on n’en trouve plus. Il s’agit donc d’une recherche locale,
au même titre que celles qui ont été présentées dans le chapitre 4. Originel-
25

lement cette méthode a reçu l’acronyme moins attractif de LOPT (pour Local
Optimizations) [?, ?].
Pour les problèmes de grande taille, on peut considérer qu’une solution
est composée d’un certain nombre de parties, parties qui sont elles-mêmes
g

composées d’un certains nombre d’éléments. En prenant l’exemple du pro-


Al

blème de classification, chaque groupe d’éléments peut constituer une partie.


De plus, on fera l’hypothèse que l’on peut définir une mesure de proximité entre
les parties et que ces dernières ont une certaine indépendance les unes des
T_

autres dans la solution. Dans le cas du problème de classification, il y a des


groupes proches, car contenant des éléments dont on pourrait raisonnable-
ment modifier l’affectation, et des groupes éloignés, contenant des éléments
dont on ne pourrait pas raisonnablement échanger l’affectation. Si ces hypo-
thèses sont satisfaites, on a les conditions spéciales nécessaires pour mettre
au point un algorithme basé sur la trame de POPMUSIC, qui tire son nom
de Partial OPtimization Metaheuristic Under Special Intensification Condition,
acronyme proposé par S. Voß.
Faisons donc l’hypothèse qu’une solution s peut être représentée par un
ensemble de q parties s1 , . . . , sq et que l’on dispose d’une méthode quantifiant
la proximité qu’il existe entre deux parties. L’idée à la base de POPMUSIC est
130 M ÉTHODES DE DÉCOMPOSITION

Parties indépendantes

17
20
Sous-problème

e
Partie-Germe

br
em
F IGURE 5.4 – Pour appliquer la trame POPMUSIC à un problème de classification
pt

avec centres, on peut définir une partie comme l’ensemble des éléments rattachés à
un même centre. Les éléments du groupe de la partie-germe, auxquels on adjoint les
parties les plus proches forment un sous-problème que l’on tente d’optimiser indépen-
se

damment. L’optimisation de groupes très distants ne peut amener de bénéfice, car ces
parties sont de facto indépendantes.
25

Algorithme 5.2 : Trame de POPMUSIC.


Entrées : Solution initiale s composée de q parties disjointes s1 , . . . , sq ,
méthode d’amélioration de sous-problèmes
g

Résultat : Solution s améliorée


Al

1 U = {s1 , . . . , sq };
2 tant que U 6= ∅ faire
3 Sélectionner sg ∈ U // sg : partie-germe ;
T_

4 Construire un sous-problème R composé des r parties de s les plus


proches de sg ;
5 Tenter d’optimiser R;
6 si R a été amélioré alors
7 Mettre la solution s à jour;
8 Retirer de U les parties qui ne font plus partie de s;
9 Insérer dans U les parties du sous-problème optimisé R;
10 sinon // R non amélioré
11 Retirer sg de U ;
5.4 M ÉTHODES D ’ AMÉLIORATION POUR PROBLÈMES DE GRANDE TAILLE 131

17
20
e
br
em
pt
se
25
g
Al

F IGURE 5.5 – Pour le problème d’élaboration de tournées de véhicules, la définition


d’une partie dans la trame POPMUSIC peut être une tournée entière. Ici, la proxi-
mité entre tournées est mesurée par la distance de leur centre de gravité et un sous-
T_

problème est constitué des clients desservis par 6 tournées.


132 M ÉTHODES DE DÉCOMPOSITION

de sélectionner une partie-germe sg et un nombre r < q de parties les plus


proches de sg pour former un sous-problème R. Avec une définition appro-
priée des parties, une amélioration de la solution globale s peut être trouvée
si l’on arrive à améliorer le sous-problème R. La figures 5.4, 5.5 illustrent ce
que peuvent être une partie et un sous-problème pour diverses applications.
Pour éviter que l’on tente d’optimiser le même sous-problème plusieurs fois,
on mémorise dans un ensemble U les parties-germes qui peuvent potentielle-
ment définir un sous-problème qu’il est possible d’améliorer. Si l’optimisation
d’un sous-problème ne mène pas à une amélioration, alors la partie-germe à

17
l’origine de sa définition est retirée de l’ensemble U . Une fois que U est vide,
le processus s’arrête. Si un sous-problème R a été amélioré avec succès, cela
signifie qu’un certain nombre de parties ont été modifiées. De nouvelles amé-

20
liorations deviennent possible dans leur voisinage. Dans ce cas, toutes les par-
ties de U qui n’existent plus dans la solution améliorée en sont retirées avant
d’y incorporer l’ensemble des parties de R. La trame 5.2 formalise la méthode
POPMUSIC. Pour transcrire cette trame en un code pour un problème donné,

e
plusieurs choix doivent être pris :

br
Obtention de la solution initiale La méthode a besoin d’une solution avant
de démarrer. La technique présentée dans la section 5.3 permet d’obtenir
une solution initiale appropriée pour la trame POPMUSIC avec un effort
em
de calcul limité. Cependant, une méthode basée sur POPMUSIC peut
très bien s’avérer efficace pour des problème de taille limitée et on peut
démarrer avec un solution obtenue avec un algorithme plus gourmand en
ressources de calcul.
pt

Définition d’une partie La définition de ce qu’est une partie n’est de loin pas
unique pour un problème donné. Par exemple, pour les problèmes d’éla-
se

boration de tournée de véhicules, on peut considérer que l’ensemble des


clients sur la même tournée forme une partie, comme cela a été fait
dans [?, ?]. Pour le même problème, il est également possible de définir
une partie comme un unique client, comme dans [?].
25

Définition de la distance entre parties Pour certains problèmes, la défini-


tion de la distance entre deux parties peut être relativement aisée et lo-
gique. Par exemple, [?] utilise la distance euclidienne entre les centres
g

des groupes pour un problème de classification. Pour le problème d’éti-


quetage de plan 2.6.1, on construit un graphe dont les sommets sont
Al

les objets à étiqueter et les arêtes représentent une potentielle super-


position des étiquettes. La distance est mesurée par le nombre mini-
T_

mum d’arête d’une chaîne connectant l’objet-germe, comme illustré en


figure 5.6. Par contre cette définition peut être délicate pour certains pro-
blème. On peut citer à ce propos l’élaboration de tournées de véhicules
avec fenêtre de temps : Deux clients géométriquement proche peuvent
avoir des fenêtre de temps incompatibles et doivent par conséquent être
considérés comme distants.
Sélection de la partie-germe Il n’existe à notre connaissance pas d’étude
approfondie sur l’impact du processus de sélection de la partie-germe.
Dans les publications, seules des méthodes très simples sont utilisées :
choix aléatoire ou gestion de l’ensemble U en pile.
Paramètre r La taille des sous-problèmes dépend de r, l’unique paramètre
5.4 M ÉTHODES D ’ AMÉLIORATION POUR PROBLÈMES DE GRANDE TAILLE 133

17
20
F IGURE 5.6 – Pour l’étiquetage de plans, une partie peut être un objet devant être
étiqueté. Ici, on considère 4 positions possibles pour l’étiquette de chaque objet. Deux

e
objets seront à une distance de 1 si leurs étiquettes peuvent se chevaucher. Le chiffre

br
à l’intérieur de chaque disque représente sa distance à l’objet-germe, noté 0. Un sous-
problème sera constitué des r = 25 objets les plus proches de l’objet-germe (dont
la distance est ici au maximum 4) auxquels ont adjoint les objets dont les étiquettes
em
pourraient entrer en collisions avec ces r objets. Seules les positions des étiquettes de
ces derniers peuvent être modifiées lors de l’optimisation d’un sous-problème.
pt

explicite de la trame POPMUSIC. Ce paramètre doit être modulé en fonc-


se

tion de la capacité de résolution de la méthode d’optimisation des sous-


problèmes. Il faut trouver un compromis entre une valeur trop faible qui
ne permet que des améliorations mineures mais avec un effort de calcul
réduit et une valeur trop élevée, qui pourrait impliquer un effort de calcul
25

excessif. On peut même imaginer de le faire varier en cours d’exécution,


comme cela a été fait dans [?] ou [?].
g

Méthode d’optimisation Une grande latitude est laissée au programmeur


concernant la méthode d’optimisation des sous-problèmes. Il convient
Al

de préciser ici que l’implantation de celle-ci est facilitée par le fait que
la taille des sous-problèmes peut être déterminée, notamment en ce qui
T_

concerne l’ajustement de ses paramètres. Lorsque l’optimisation est une


méthode exacte, on parle de matheuristique.

Avec un critère d’arrêt basé sur le fait que l’ensemble U est vide, l’effort de
calcul pourrait potentiellement devenir prohibitif pour des problèmes de grande
taille, sachant que plusieurs parties sont susceptibles d’y être introduites pour
chaque optimisation de sous-problème. En pratique, on observe qu’il n’en est
rien : le nombre de sous-problèmes à résoudre croît quasi-linéairement avec la
taille du problème. Ceci est illustré en figure 5.7 pour un problème de localisation-
routage [?].
134 M ÉTHODES DE DÉCOMPOSITION

17
Temps de calcul [s]

105

20
104

e
103
br
em
102

Optimisation des sous-problèmes


pt

10 Θ(n)
Solution initiale
se

Θ(n3/2 )
1
104 105 106
25

Taille du problème

F IGURE 5.7 – Temps de calcul observés pour la création d’une solution initiale d’un
problème de localisation-routage avec la technique présentée en section 5.3 et temps
global d’optimisation des sous-problèmes avec la trame POPMUSIC. On remarque que
g

la croissance du temps de calcul semble inférieure à l’analyse de Θ(n3/2 ) qui a été faite
Al

en section 5.3 et que le temps pour l’optimisation des sous-problèmes est pratiquement
linéaire.
T_
5.4 M ÉTHODES D ’ AMÉLIORATION POUR PROBLÈMES DE GRANDE TAILLE 135

POPMUSIC pour le problème du voyageur de commerce

Une implantation élémentaire de la technique POPMUSIC au problème du


voyageur de commerce est donnée par le code 5.1. Dans cette adaptation, une
partie est une ville, la distance entre parties est mesurée non par la matrice
des distances, mais par le nombre de villes intermédiaires qu’il y a en suivant
la tournée courante. Un sous-problème est donc un chemin dont on fixe les
deux extrémités, séparées d’au plus 2r villes à l’intérieur duquel on cherche
à déplacer un sous-chemin d’au plus r villes. L’ensemble U n’est pas repré-
senté explicitement car il « colle » à la solution. On optimise des sous-chemins

17
chaque fois décalés d’une ville. Pour déterminer s’il faut continuer de tenter des
optimisations, on mémorise la ville initiale de la dernière portion de chemin qui
a été optimisée avec succès. Si l’on fait un tour complet sans amélioration, le

20
processus peut s’arrêter.

Listing 5.1 – tsp_3opt_limited.c Implantation de POPMUSIC pour le voyageur de


commerce.

e
void tsp_3opt_limited ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , /∗ Distance matrix ∗/
int r ,
i n t best_sol [ ] ,
double ∗ b e s t _ c o s t )
br
/ ∗ Maximum n r o f nodes o f subpath o p t i m i z e d
/ ∗ InOut S o l u t i o n p r o v i d e d and r e t u r n e d
/ ∗ InOut Length o f t h e b e s t t o u r
∗/
∗/
∗/
em
{
i n t ∗s = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ; / ∗ Successors o f c i t i e s ∗/
i n t i , j , k , t , u , temp , / ∗ indexes ∗/
i_end ; /∗ Last values of index i ∗/
double d e l t a ; / ∗ Cost o f a move ∗/
pt

i f ( r > n − 2) / ∗ Max subpath l e n g t h should n o t be l a r g e r than n − 2 ∗ /


r = n − 2;
f o r ( i = 1 ; i < n ; i ++) / ∗ B u i l d s o l u t i o n r e p r e s e n t a t i o n by successors ∗ /
se

s [ b e s t _ s o l [ i −1]] = b e s t _ s o l [ i ] ;
s [ b e s t _ s o l [ n −1]] = b e s t _ s o l [ 0 ] ;

i_end = i = 0 ; / ∗ S t a r t moves e v a l u a t i o n from c i t y 0 ∗ /


do
{ f o r ( j = s [ i ] , t =0; t < r && s [ s [ j ] ] ! = i_end ; t ++ , j = s [ j ] )
25

f o r ( k = s [ j ] , u =0; u < r && s [ k ] ! = i_end ; u++ , k = s [ k ] )


{
delta = d [ i ] [ s [ j ] ] + d [ j ] [ s [ k ] ] + d [ k ] [ s [ i ] ] / ∗ Move c o s t ∗ /
−d [ i ] [ s [ i ] ] − d [ j ] [ s [ j ] ] − d [ k ] [ s [ k ] ] ;
i f ( d e l t a < −e p s i l o n ) / ∗ I m p r o v i n g move ? ∗ /
{ temp = s [ i ] ; s [ i ] = s [ j ] ; s [ j ] = s [ k ] ; s [ k ] = temp ; / ∗ Perform move ∗ /
g

temp = j ; j = k ; k = temp ; / ∗ Replace j between i and k ∗ /


∗best_cost = ∗best_cost + delta ; / ∗ Update s o l u t i o n c o s t ∗ /
Al

i_end = i ; / ∗ Update l a s t v a l u e s o f i n d e x i ∗ /
}
}
i = s[ i ];
T_

}
w h i l e ( i ! = i_end ) ; / ∗ A complete t o u r scanned w i t h o u t improvement ∗ /

j = 0; / ∗ R e b u i l d s o l u t i o n under t h e form o f a p e r m u t a t i o n o f c i t i e s ∗ /
f o r ( i = 0 ; i < n ; i ++)
{ best_sol [ i ] = s [ j ] ; j = s [ j ] ; }

free ( s ) ;
}

Pour appliquer la technique POPMUSIC au problème du voyageur de com-


merce de manière efficace, il faut cependant prendre en considération :
— La solution initiale doit déjà avoir une bonne structure ; pour un problème
euclidien par exemple, elle ne devrait pas comporter d’arêtes se croisant
136 M ÉTHODES DE DÉCOMPOSITION

situées dans des portions de séquence éloignées, car la procédure d’op-


timisation ne pourra pas à les décroiser.

— Plutôt que de mettre au point une recherche locale ad-hoc comme celle
du code 5.1 pour optimiser des sous-chemins, il serait préférable d’utili-
ser une méthode générale de résolution d’un problème de voyageur de
commerce, comme par exemple le code 4.4.

— Finalement, il faut éviter d’optimiser une nouvelle fois un sous-chemin


que l’on a déjà optimisé.

17
Pour démarrer avec une solution avec une bonne structure sans utiliser
un algorithme de complexité trop élevée, on peut s’inspirer de la technique

20
présentée en section 5.3. On commence par échantillonner aléatoirement k
des n villes, avec k < n, un paramètre à choisir en fonction de n de telle sorte
que la complexité algorithmique de la méthode soit aussi faible que possible ;
on y reviendra. Un problème de voyageur de voyageur de commerce est résolu

e
(éventuellement de façon heuristique) sur les villes échantillonnées à l’aide

br
d’une méthode d’optimisation de complexité c(k). On trouve pour chacune des
n − k villes restantes la ville de l’échantillon qui lui est la plus proche. Ceci peut
se faire trivialement en Θ(k(n − k)). Chaque ville restante est ensuite insérée
em
(dans un ordre quelconque) dans la tournée partielle, juste après la ville de
l’échantillon qui lui est le plus proche. Ceci peut se faire également trivialement
en Θ(n − k).
On obtient ainsi une tournée mauvaise, mais qui a de bonne propriétés
pt

pour une optimisation de sous-chemins. On optimise tout d’abord tous les


sous-chemins comportant les villes insérées après deux villes successives de
se

l’échantillon. L’optimisation de chacun de ces k sous-chemins se fait avec une


méthode de complexité d(r), pour un sous-chemin comportant r villes. La tour-
née ainsi obtenue peut être optimisée à l’aide de POPMUSIC en considérant
comme sous-problème des sous-chemins comportant un nombre constant de
25

villes, par exemple 50.


g

Optimisation de la complexité empirique


Al

Une très bonne tournée sur un échantillon de k villes peut être obtenue avec
le code 4.4 implantant des chaînes d’éjections. On observe empiriquement
T_

une complexité c(k) = Ô(k 2.78 ) pour ce code. L’optimisation de sous-chemins


de r villes peut se faire plus rapidement, avec le code 4.3qui présente une
complexité empirique d(r) = Ô(r2.29 ). En choisissant k = Θ(n0.56 ), on aboutit
à une méthode dont la complexité empirique globale est en Ô(n1.6 ).
Pour pouvoir utiliser directement un code résolvant un problème de voya-
geur de commerce pour optimiser des sous-chemins, il suffit de modifier la
matrice des distances des villes d’un sous-chemin. Si les deux villes aux extré-
mités du chemin sont v1 et vr , on posera dv1 ,vr = dvr ,v1 = 0 et on augmentera
d’une valeur élevée (par exemple, donnée par la longueur totale L du chemin)
la distance entre les v1 et vr et les villes à l’intérieur du chemin. Les autres
distances restent inchangées. On utilise donc par exemple la matrice des dis-
5.4 M ÉTHODES D ’ AMÉLIORATION POUR PROBLÈMES DE GRANDE TAILLE 137

17
20
e
br
em
pt
se

(a) Échantillon et tournée complète en cours (b) Tournée optimisée avec POPMUSIC et,
d’optimisation en superposition, la tournée optimale
25

F IGURE 5.8 – Génération d’une solution initiale à un problème de voyageur de com-


merce de grande taille : On échantillonne des villes du problème initiale pour laquelle
et on trouve une tournée partielle à l’aide d’une recherche locale basée sur sur les
chaînes d’éjection (Code 4.4). On insère successivement chacune des villes restantes
g

sur cette tournée partielle juste après la ville de l’échantillon qui lui est le plus proche.
Ensuite, on améliore avec le voisinage 2-opt (Code 4.3) des sous-chemins compor-
Al

tant deux groupes de villes insérées après deux villes successives de l’échantillon.
La figure 5.8(a) montre la tournée sur l’échantillon ainsi que la tournée complète en
cours d’optimisation. Finalement, des sous-chemins de 50 villes sont optimisés à l’aide
T_

de POPMUSIC en utilisant une recherche locale basée sur les chaînes d’éjection
(Code 4.4). La tournée optimale est superposée en trait fin à celle obtenue par POP-
MUSIC.
138 M ÉTHODES DE DÉCOMPOSITION

tances D suivante :
 
0 d12 + L d13 + L ... 0

 d21 + L 0 d23 ... d2r + L 

D=
 d31 + L d32 0 ... d3r + L 

 .. .. .. .. .. 
 . . . . . 
0 dr2 + L dr3 + L ... 0

Finalement, il n’est pas nécessaire d’optimiser plusieurs fois le même sous-

17
chemin. Pour éviter cela, on peut associer à chaque ville un drapeau indiquant
si elle a déjà été la ville de départ d’un sous-chemin optimisé. Lors d’une opti-
misation réussie, on peut abaisser tous les drapeaux des villes qui se trouvent

20
jusqu’à 50 position avant ou après une séquence de ville qui a été modifiée
durant l’optimisation (tout en laissant levé le drapeau de la ville de départ du
sous-chemin).

e
5.4.3 Commentaires

br
La principale différence entre LNS et POPMUSIC est que cette dernière
fixe le critère d’arrêt et celui d’acceptation d’une solution du large voisinage.
em
En effet, dans la trame de POPMUSIC on accepte de modifier la solution que
si on a une amélioration stricte. Pour plusieurs problèmes, cette trame semble
suffisante pour obtenir des solution de bonne qualité, cette dernière étant for-
tement conditionnée à la capacité de la méthode d’optimisation utilisée. La phi-
pt

losophie de POPMUSIC est de conserver une trame aussi simple que possible
et d’améliorer au besoin la méthode d’optimisation pour qu’elle puisse mieux
traiter des sous-problèmes de plus grande taille plutôt que de complexifier la
se

trame en ajoutant des critères d’acceptation ou d’arrêt baroques.


La définition des parties et de leur proximité dans POPMUSIC est une
façon peut-être plus intuitive que dans LNS pour formaliser un ensemble de
25

contraintes que l’on ajoute au problème sur la base d’une solution existante.
Ces contraintes permettent d’utiliser une méthode d’optimisation qui serait in-
applicable au problème entier. Du reste, [?] dans leur Méthode du Corridor
prennent la problématique par l’autre bout : étant donné une méthode d’opti-
g

misation qui fonctionne bien — en l’occurrence la programmation dynamique


— comment peut-on ajouter des contraintes au problème pour que l’on puisse
Al

continuer à utiliser cette méthode d’optimisation.


Il faut noter que les composantes ou options d’une méthode sont souvent
T_

toutes interdépendantes. Le choix d’une option ayant une incidence sur les
autres explique en partie pourquoi des méthodes en réalité très similaires sont
présentées par des trames et des noms différents.
5.5 E XERCICES 139

5.5 Exercices
Exercice 5.1. Complexité de la recherche dichotomique En appliquant le
théorème général de récurrence de la section 5.2.1, déterminer la complexité
algorithmique de la recherche d’un élément dans un tableau trié au moyen
d’une recherche dichotomique
Exercice 5.2. POPMUSIC pour le problème de la chaîne de traitement
Dans le cadre de la méthode de décomposition POPMUSIC, comment définir
une partie et un sous-problème pour le problème de la chaîne de traitement ?

17
Comment tenir compte de l’interaction entre le sous-problème et les parties qui
ne doivent pas être optimisées ?

20
Exercice 5.3. Complexité algorithmique de POPMUSIC Si la taille des sous-
problèmes est indépendante de la taille du problème, on peut considérer qu’un
sous-problème peut être résolu en temps constant. Des observations empi-
riques, comme celles présentées dans la figure 5.7 montrent que le nombre de

e
fois qu’une partie est insérée dans U est également indépendant de la taille du
problème, en moyenne. Si ces hypothèses sont satisfaites, quelles sont les par-

br
ties les plus complexes de la trame de POPMUSIC, en termes de complexité
algorithmique ?
em
Exercice 5.4. Complexité minimale de POPMUSIC pour le voyageur de
commerce Justifier le choix de la taille de l’échantillon en Θ(n0.56 ) suggéré en
page 136 pour une implantation de complexité empirique minimale de POP-
pt

MUSIC pour le voyageur de commerce.


se
25
g
Al
T_
140 M ÉTHODES DE DÉCOMPOSITION

17
20
e
br
em
pt
se
25
g
Al
T_
17
20
Troisième partie

e
br
Techniques populaires
em
pt
se
25
g
Al
T_
T_
Al
g
25
se
pt
em
br
e
20
17
Chapitre 6

17
Méthodes randomisées

20
En appliquant les principes présentés dans les chapitres précédents, nous
arrivons à construire une solution et à l’améliorer jusqu’à trouver un optimum

e
local. De plus, si le problème est compliqué ou de grande taille, il faut le dé-

br
composer en sous-problèmes plus simples à résoudre. Que faire si en utilisant
ces techniques on obtient des solutions dont la qualité n’est pas suffisante et
que l’on a la possibilité d’investir plus d’effort de calcul pour tenter d’autres
em
améliorations ?
Une première option venant à l’esprit est d’essayer de mettre en place un
processus d’apprentissage, ce que nous examinerons dans des chapitres ul-
térieurs.
pt

Une deuxième option — plus simple à mettre en œuvre a priori — est d’in-
corporer une composante aléatoire dans une méthode « d’amélioration » où
se

l’on s’autorise le choix de solutions voisines de qualité moindre que celle de


départ. Comme on n’a plus une amélioration à chaque itération de telles mé-
thodes, basées sur des modifications de solutions, on parlera de recherche
locale. Cette voie est suivie par des méthodes très semblables dans leur im-
25

plantation, le recuit simulé, l’acceptation à seuil, la méthode du grand déluge,


et celle du démon. Toutes ces méthodes peuvent être généralisées dans une
trame unique, les méthodes de bruitage.
Une troisième option est de répéter des constructions avec des choix aléa-
g

toires, suivies éventuellement d’améliorations locales. C’est la voie suivie par


Al

la méthode GRASP.
Finalement, on peut mettre en œuvre une stratégie dans laquelle on fait
alterner des phases d’intensification et de diversification de la recherche. La
T_

recherche à voisinage variable fait usage de cette stratégie, en itérant des mé-
thodes d’améliorations utilisant un voisinage de base après avoir dégradé la
solution par des mouvements choisis aléatoirement dans d’autres voisinages.

6.1 Recuit simulé


La méthode du recuit simulé est une des premières techniques de recher-
che locale qui n’améliore pas strictement la qualité de la solution à chaque
itération. Cette méthode s’inspire d’un processus physique, le recuit, qui per-
met d’obtenir un matériau dont l’agencement des molécules minimise l’énergie
144 M ÉTHODES RANDOMISÉES

interne.

État visqueux

17
Refroidissement lent Refroidissement rapide

20
Recuit Trempe

e
br
em
pt

État cristallin État polycristallin ou amorphe


se

F IGURE 6.1 – Processus physiques de recuit et de trempe. Un matériaux est porté à


une température telle que ses molécules ont une énergie suffisante pour se déplacer.
En le refroidissant lentement, les molécules ont le temps de se mettre dans un état
cristallin minimisant leur énergie, c’est le processus de recuit. Si le refroidissement est
25

plus rapide, on parle de trempe et les cristaux se forment de façon désordonnée. Dans
certaines conditions, un refroidissement très rapide ne laisse pas le temps aux cristaux
de se former et la matière reste dans un état amorphe.
g

Certains matériaux, comme des métaux, voient leur structure interne se


Al

modifier selon la température à laquelle ils sont portés. En refroidissant rapi-


dement ces matériaux, les molécules n’auront pas le temps de s’agencer pour
retrouver la structure habituelle à basse température, mais vont former des
T_

grains qui sont de petits cristaux dont l’orientation est différente pour chaque
grain. Il s’agit du processus de trempe, qui est utilisé notamment pour durcir
certains aciers.
Au contraire, si le refroidissement est lent, les molécules arriveront à former
des cristaux beaucoup plus grands, correspondant à leur état d’énergie mini-
male. En répétant le procédé, on peut encore augmenter la taille des cristaux,
voire à obtenir un mono-cristal, c’est le procédé de recuit.
[?] et [?] ont eu indépendamment l’idée de simuler ce processus en optimi-
sation combinatoire, en faisant l’analogie entre une fonction-objectif à minimi-
ser et l’énergie des molécules.
Si à haute température une molécule a une énergie suffisante pour aller
6.1 R ECUIT SIMULÉ 145

combler un trou du cristal ou de modifier sa configuration, elle a en revanche


une probabilité nettement moindre de le faire si la température est plus basse.
Traduire ceci en termes d’optimisation combinatoire revient à modifier locale-
ment de façon aléatoire une solution et d’accepter sa dégradation avec une
certaine probabilité. Cette dernière doit être d’autant plus faible que la dégra-
dation est élevée.
Exprimé en termes de recherche locale, cela revient à générer un mou-
vement m ∈ M aléatoirement et de calculer la différence de coût ∆ entre la
solution modifiée et celle de départ : ∆ = f (s⊕m)−f (s). Si ∆ < 0, ce qui signi-

17
fie que le mouvement m améliore la solution s, alors on l’accepte et la nouvelle
solution devient s⊕m. Sinon, le mouvement m est tout de même accepté, mais
avec une probabilité proportionnelle à e−∆/T , où T est un paramètre simulant

20
la température.
À chaque étape, la température T est diminuée. Plusieurs formules ont été
proposées pour ajuster la température. Parmi les plus fréquemment rencon-
T
trées, citons T ← α · T et T ← 1+αT , où 0 < α < 1 est un paramètre réglant la

e
vitesse de décroissance de la température.
La méthode comporte encore deux paramètres, au minimum : Tinit et Tf in ,

br
les températures initiales et finales. L’algorithme 6.1 donne la trame d’un recuit
simulé de base.
em
Algorithme 6.1 : Trame d’un recuit simulé élémentaire. D’innombrables va-
riantes d’algorithmes basés sur cette trame ont été proposés.
Entrées : Solution initiale s ; fonction utilité f à minimiser ; structure de
pt

voisinage M , paramètres Tinit , Tf in < Tinit et 0 < α < 1


Résultat : Solution s modifiée
se

1 T ← Tinit ;
2 tant que T > tf in faire
3 Générer un mouvement m aléatoirement dans M ;
4 ∆ = f (s ⊕ m) − f (s);
25

5 Générer un nombre aléatoire u uniformément entre 0 et 1;


6 si ∆ < 0 ou e−∆/T > u alors
7 s←s⊕m
8 T ←α·T
g
Al

En pratique, il est rare de rencontrer un algorithme suivant exactement cette


trame. Tout d’abord, les paramètres définissant les températures initiales et fi-
T_

nales ont une influence très différente selon l’unité de mesure de la fonction
utilité f . En effet, si f mesure la longueur d’une tournée de voyageur de com-
merce, il convient d’adapter ces paramètres selon que cette mesure est expri-
mée en mètres ou en kilomètres.
Pour rendre l’algorithme plus robuste, on ne demande pas à l’utilisateur de
fournir directement des températures, mais par exemple des taux d’acceptation
de mouvements dégradants τinit et τf in , ce qui est beaucoup plus intuitif. Les
températures sont alors calculées automatiquement en fonction de ces taux,
en effectuant quelques centaines ou milliers de pas d’une marche aléatoire,
par enregistrement de statistiques sur les valeurs moyennes des ∆.
La figure 6.2 illustre l’évolution de la longueur de la tournée d’un voyageur
146 M ÉTHODES RANDOMISÉES

17
20
Longueur de la tournée

e
br
em
Amélioration de la solution
pt

Température (x100)
se

Itérations

F IGURE 6.2 – Évolution de la longueur de la tournée d’un voyageur de commerce et de


25

la température lors de l’exécution d’un recuit simulé.


g

de commerce sur 225 villes en fonction du nombre d’itérations pour une exé-
cution de l’algorithme 6.1 avec comme température initiale 5 · dmax /n, comme
Al

température finale 20 · dmax /n2 et α = 0.99. Il est fourni à l’algorithme une so-
lution de relativement bonne qualité. On remarque une importante dégradation
T_

de cette dernière durant les premières itérations, à température élevée. Cette


dégradation est nécessaire pour briser la structure de la solution de départ afin
d’arriver à de meilleures solutions. Environ la moitié des itérations sont réali-
sée inutilement dans cette exécution, la valeur de la meilleure solution trouvée
n’évoluant plus.
6.1 R ECUIT SIMULÉ 147

Listing 6.1 – tsp_SA.c Code C implantant une variante de recuit simulé pour le pro-
blème du voyageur de commerce symétrique. La fonction build_2opt_data_structure
qui initialise la structure de donnée décrite en section 4.2.3 pour effectuer un mouve-
ment de type 2opt en temps constant est données par le code 4.2.
v o i d tsp_SA ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , / ∗ D i s t a n c e m a t r i x , must be s y m m e t r i c a l ∗/
i n t best_sol [ ] , / ∗ InOut S o l u t i o n p r o v i d e d and r e t u r n e d ∗/
double ∗ b e s t _ c o s t , / ∗ InOut Length o f t h e b e s t t o u r ∗/
double i n i t i a l _ t e m p e r a t u r e , / ∗ SA Parameters ∗/
double f i n a l _ t e m p e r a t u r e ,
double alpha )

17
{ int∗ t ; / ∗ Successor and predecessor o f each c i t y [ see tsp −2o p t ] ∗/
i n t i , j , next_i , next_j , r , s ; /∗ indices ∗/
long i t e r a t i o n ; /∗ I t e r a t i o n counter ∗/
double l e n g t h = ∗ b e s t _ c o s t ; / ∗ Length o f c u r r e n t t o u r ∗/
double T = i n i t i a l _ t e m p e r a t u r e ; /∗ Current temperature ∗/

20
double d e l t a ; / ∗ Cost o f a t r i a l move ∗/

t = ( i n t ∗) m a l l o c ( ( s i z e _ t ) ( 2 ∗ n ) ∗ s i z e o f ( i n t ) ) ;
build_2opt_data_structure ( n , best_sol , t ) ;

i t e r a t i o n = 0; / ∗ Number o f i t e r a t i o n s performed ∗/

e
while (T > final_temperature ) / ∗ Repeat , w h i l e t e m p e r a t u r e h i g h enough ∗/
{ i = 0; / ∗ S t a r t moves e v a l u a t i o n from c i t y 0 ∗/

{ j = t [ t [ i ]];
w h i l e ( j >>1 && ( t [ j ] > >1 | | i > >1) )
{ delta = d [ i > > 1 ] [ j > >1] br
w h i l e ( t [ t [ i ]] > >1 && t [ i ] > >1) / ∗ Index i a r r i v e d a t t h e l a s t t o c o n s i d e r ?

+ d [ t [ i ] > > 1 ] [ t [ j ] > >1]


∗/
em
− d [ i > > 1 ] [ t [ i ] > >1] − d [ j > > 1 ] [ t [ j ] > > 1 ] ;
i f ( d e l t a < −e p s i l o n | | exp(− d e l t a / T ) > rando ( ) ) / ∗ Move accepted ∗/
{ next_i = t [ i ] ; next_j = t [ j ] ;
t [ i ] = j ^1; t [ next_i ^1] = next_j ;
t [ j ] = i ^1; t [ next_j ^1] = next_i ;
length = length + delta ;
pt

i = t [ i ]; /∗ Explanation l e f t in exercise ∗/
j = t [ i ];
se

i f ( l e n g t h < ∗ b e s t _ c o s t − e p s i l o n ) / ∗ Memorize improved b e s t s o l u t i o n ∗ /


{ ∗best_cost = length ;
/ ∗ R e b u i l d t h e s o l u t i o n under t h e form o f t h e sequence o f c i t i e s ∗/
r = 0;
f o r ( s = 0; s < n ; s = s + 1)
{ b e s t _ s o l [ s ] = r > >1; r = t [ r ] ; }
25

p r i n t f ( "SA %l d %f \ n " , i t e r a t i o n , l e n g t h ) ;
}
} / ∗ Move accepted ∗ /

i t e r a t i o n ++;
i f ( i t e r a t i o n % ( n∗n ) == 0 ) / ∗ Temperature decrease every n∗n i t e r . ∗ /
g

T ∗= alpha ;
j = t [ j ]; / ∗ Next j ∗ /
Al

}
i = t [ i ] ; / ∗ Next i ∗ /
}
} /∗ while (T > final_temperature ) ∗/
T_

free ( t ) ;
}

Le code 6.1 implante une sorte de recuit simulé pour le problème du voya-
geur de commerce. Il est basé sur une structure de voisinage 2-opt. Afin de
pouvoir évaluer un mouvement et le réaliser en temps constant, la structure de
données introduite en section 4.2.3 a été utilisée. Cependant, cette structure
de données ne permet pas d’évaluer en un temps constant un mouvement
(i, j) tiré aléatoirement, car, étant donné une ville i et celle qui lui succède
si lorsqu’on fait le parcours dans un sens donné, on ne peut pas identifier la
ville sj qui succède à j autrement qu’en suivant les successeur de i jusqu’à
atteindre j puis sj .
148 M ÉTHODES RANDOMISÉES

L’artifice utilisé dans ce code est de ne pas tirer les mouvement aléatoire-
ment, mais d’examiner systématiquement tout le voisinage. L’autre adaptation
de la trame 6.1 est de ne pas diminuer la température à chaque itération, mais
seulement toutes les n2 itérations. Ainsi, une valeur de α entre 0.8 et 0.99
donne des résultats acceptables, indépendamment de la taille du problème, et
donc du nombre d’itérations nécessaires à l’obtention de bonnes solutions. Fi-
nalement, mentionnons que l’utilisateur doit fournir les températures initiales et
finales de façon absolue. En pratique, Tinit = 5 · dmax /n et Tf in = 20 · dmax /n2
sont des valeurs qui peuvent convenir pour démarrer un ajustement de ces

17
paramètres.

20
6.2 Acceptation à seuil
La méthode de l’acceptation à seuil est une recherche locale pure, dans la
mesure où l’on ne fait que se déplacer d’une solution à l’une de ses voisines.

e
Tout comme les méthodes du démon, du grand déluge ou du recuit simulé,
les mouvements sont choisis aléatoirement, mais ne sont pas systématique-

br
ment appliqués à la solution courante. Dans le cas où le mouvement permet
une amélioration, la solution voisine est acceptée. Si par contre le mouvement
em
détériore la solution, le mouvement n’est accepté que si la détérioration est
inférieure à un certain seuil. Ce dernier est progressivement diminué jusqu’à
prendre une valeur nulle, de sorte que la méthode s’arrête dans un optimum
local.
pt

Algorithme 6.2 : Trame d’une acceptation à seuil. Les valeurs des seuils T1 à
se

TImax ne sont pas forcément fournis explicitement mais calculés, par exemple en
fournissant uniquement le seuil initial et en le multipliant par un autre paramètre α
à chaque ronde de R itérations.
Entrées : Solution initiale s ; fonction utilité f à minimiser ; structure de
25

voisinage M , paramètres T , R, τ1 , . . . τT
Résultat : Solution s∗
1 s∗ ← s;
2 pour t allant de 1 à T faire
g

3 pour R itérations faire


Al

4 Générer un mouvement m aléatoirement dans M ;


5 si f (s ⊕ m) − f (s) < τt alors
6 s ← s ⊕ m;
T_

7 si f (s∗ ) > f (s) alors


8 s∗ ← s

[?] ont proposé une méthode automatique pour fixer les seuils : on com-
mence par effectuer des mouvements aléatoires en enregistrant les variations
de la valeur de la fonction-objectif (en valeur absolue). Cela permet de déter-
miner la fonction de distribution empirique F de l’amplitude des mouvements.
On fixe les seuils en utilisant l’inverse de cette fonction (voir illustration en fi-
gure 6.3) : Ti = F −1 (0.8·(Imax −i)/Imax ). Autrement dit, le premier seuil permet
6.3 G RAND DÉLUGE 149

Proportion de |∆| < x


1
F

0.8

17
20
x

e
0
τT = 0 τ2 τ1 ∆max

br
F IGURE 6.3 – Technique de détermination des seuils τ1 , . . . τT pour l’acceptation à
em
seuils. La fonction de répartition empirique F est obtenue en effectuant un certain nom-
bre de mouvements et en enregistrant leur amplitude en valeur absolue.
pt

d’accepter environ 80% des mouvements dégradants alors que le dernier ne


permet que des mouvements améliorants.
se

6.3 Grand déluge


25

La méthode du grand déluge présente des similarités avec la précédente,


cependant ce n’est pas l’amplitude des mouvements qui limite la progression
de la recherche, mais la valeur de la fonction-utilité. Le nom de cette méthode
est tiré de la légende qui veut qu’à la suite de pluies ininterrompues, les êtres
g

terrestres finirent tous noyé, sauf ceux ayant été embarqués sur l’arche de
Noé. On imagine que les animaux restés à terre, pris de panique, couraient
Al

en tous sens, n’importe où sauf là où il y avait de l’eau. L’analogie avec un


processus de maximisation se fait en considérant des mouvements aléatoires
T_

qui sont acceptés tant qu’ils ne mènent pas à une solution dont la qualité est
inférieur à un seuil L — le niveau de l’eau — que l’on augmente de P — le
débit de la pluie — à chaque itération. Le processus s’arrête lorsque la valeur
de la solution courante est inférieure à L. L’algorithme 6.3 donne la trame de
cette méthode.
150 M ÉTHODES RANDOMISÉES

Algorithme 6.3 : Algorithme du grand déluge. Cet algorithme peut s’adapter à


des problèmes de minimisation, mais il faut alors simuler le comportement des
poissons lors de la baisse des eaux !
Entrées : Solution s, fonction-utilité f à maximiser, structure de

17
voisinage M , paramètres L et P
Résultat : s∗
1 s∗ ← s;

20
2 tant que f (s) < L faire
3 Tirer un mouvement m aléatoirement dans M ;
4 si f (s ⊕ m) > L alors
5 s ← s ⊕ m;

e
6 si f (s) < f (s∗ ) alors
s∗ ← s
7

8 L ← L + P;
br
em
pt
se
25
g
Al
T_

(a) Début de pluie (b) (c) (d) Fin du déluge

F IGURE 6.4 – Illustration de la méthode du grand déluge. 6.4(a) État du paysage au


début de la pluie. Le niveau de l’eau augmente jusqu’à ce qu’émergent seulement les
plus hauts sommets 6.4(d)
6.4 A LGORITHME DU DÉMON 151

6.4 Algorithme du démon


L’algorithme du démon simule le comportement d’un joueur invétéré qui
mise toujours plus gros. Le démon du jeu le pousse à dépenser futilement son
argent si ses gains dépassent un certain seuil Dmax . Une fois ce seuil atteint,
il continue à jouer. Le joueur entre au casino avec un montant de D en poche
et n’en ressort que lorsqu’il est épuisé, après Imax tours de jeu ; notons que ce
dernier paramètre intervient dans de nombreuses recherche locales itératives
car il permet de régler directement l’effort de calcul.

17
Traduit en termes de recherche locale, une mise consiste à autoriser un
mouvement dégradant la solution d’une quantité au plus égale au montant à
disposition. Si la modification améliore la solution, le budget est augmenté d’au-

20
tant, jusqu’à concurrence du seuil maximum. L’algorithme 6.4 donne la trame
de cette méthode.

Algorithme 6.4 : Algorithme du démon. Cet algorithme est relativement simple

e
à implanter, mais, comme pour l’acceptation à seuil, ses paramètres doivent être
ajustés en fonction de la valeur numérique des données.

br
Entrées : Solution s, fonction-utilité à minimser f , structure de voisinage
M , paramètres Imax , D, Dmax
em
Résultat : s∗
1 s∗ ← s;
2 pour Imax itérations faire
3 Tirer un mouvement m aléatoirement dans M ;
pt

4 ∆ = f (s ⊕ m) − f (s);
5 si ∆ 6 D alors
se

6 si D − ∆ > Dmax alors


7 D ← Dmax
8 sinon
9 D ←D−∆
25

10 s ← s ⊕ m;
g
Al

6.5 Méthode de bruitage


T_

Les méthodes de bruitage font l’hypothèse que les données du problème


ne sont pas connues avec une précision infinie. Dans ces conditions, même si
le problème est convexe et simple, une méthode d’amélioration peut se trouver
piégée dans des optima locaux résultant d’artefacts. Pour rendre cette mé-
thode plus robuste, on ajoute un bruit aléatoire aux données ou à l’évaluation
de la fonction-objectif, de sorte que la fonction-utilité résultante, prenant des
valeurs stochastiques, n’ait plus d’optima locaux. Ces derniers sont en quel-
que sorte gommés par le bruit aléatoire.
La trame générale des méthodes de bruitage est donnée par l’algorithme 6.5.
On fournit à la méthode une loi de probabilité, paramétrée par le numéro d’ité-
ration. Chaque fois que l’on évalue une solution, on génère une occurrence
152 M ÉTHODES RANDOMISÉES

Algorithme 6.5 : Trame d’une méthode de bruitage. À chaque modification de


solution essayée, on génère une occurrence de bruit aléatoire selon la loi de pro-
babilité bruit(i), dont la variance diminue généralement avec i.
Entrées : Solution s, fonction à minimiser f , structure de voisinage M ,
paramètres Imax , bruit(i)
Résultat : s∗
1 s∗ ← s;
2 pour i allant de 1 à Imax faire
3 Tirer un mouvement m aléatoirement dans M ;

17
4 si f (s ⊕ m) + bruit(i) < f (s) alors
5 s ← s ⊕ m;
6 si f (s) < f (s∗ ) alors

20
7 s∗ ← s

e
de bruit aléatoire. Généralement, l’espérance de la loi est nulle et sa variance

br
diminue avec le numéro d’itération, ce qui fait qu’à la fin de l’algorithme, la
méthode se rapproche de plus en plus d’une méthode d’amélioration.
em
Répartition des niveaux de bruit
pt
se

0
25

Itérations
g
Al

F IGURE 6.5 – Exemple habituel de l’évolution de la distribution du bruit aléatoire en


T_

fonction du nombre d’itérations effectuées par une méthode de bruitage. La densité de


la couleur représente la densité de probabilité.

La variance de la fonction de bruit doit naturellement dépendre des données


numériques du problème. Pour ce faire, on peut incorporer l’évaluation de la
fonction-objectif dans la loi de probabilité. Selon les choix réalisés pour la loi
de probabilité, on peut rendre une méthode de bruitage équivalente à un recuit
simulé, à une méthode d’acceptation à seuil ou aux autres techniques décrites
plus haut.
6.6 GRASP 153

Listing 6.2 – tsp_noising.c Implantation d’une méthode de bruitage pour le problème


de voyageur de commerce. La distribution du bruit est uniforme et décroît exponentiel-
lement avec le nombre d’itérations effectuées.
void tsp_noising ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , / ∗ D i s t a n c e m a t r i x , must be s y m m e t r i c a l ∗/
i n t best_sol [ ] , / ∗ InOut S o l u t i o n p r o v i d e d and r e t u r n e d ∗/
double ∗ b e s t _ c o s t , / ∗ InOut Length o f t h e b e s t t o u r ∗/
double i n i t i a l _ n o i s e , / ∗ Parameters ∗/
double f i n a l _ n o i s e ,
double alpha )

{ int∗ t ; / ∗ Successor and predecessor o f each c i t y [ see t s p _ 2 o p t _ f i r s t ] ∗/

17
i n t i , j , next_i , next_j , r , s ; /∗ indices ∗/
long i t e r a t i o n ; /∗ I t e r a t i o n counter ∗/
double l e n g t h = ∗ b e s t _ c o s t ; / ∗ Length o f c u r r e n t t o u r ∗/

double noise , c u r r e n t _ n o i s e = i n i t i a l _ n o i s e ; / ∗ C u r r e n t maximal n o i s e ∗ /

20
double d e l t a ; / ∗ Cost o f a t r i a l move ∗ /

t = ( i n t ∗) m a l l o c ( ( s i z e _ t ) ( 2 ∗ n ) ∗ s i z e o f ( i n t ) ) ;
build_2opt_data_structure ( n , best_sol , t ) ;
i t e r a t i o n = 0; / ∗ Number o f i t e r a t i o n s performed ∗/
while ( current_noise > final_noise ) / ∗ Repeat , w h i l e n o i s e h i g h enough ∗/

e
{ i = 0; / ∗ S t a r t moves e v a l u a t i o n from c i t y 0 ∗/
w h i l e ( t [ t [ i ]] > >1 && t [ i ] > >1) / ∗ Index i a r r i v e d a t t h e l a s t t o c o n s i d e r ? ∗/

br
{ j = t [ t [ i ]];
w h i l e ( j >>1 && ( t [ j ] > >1 | | i > >1) )
{ delta = d [ i > > 1 ] [ j > >1] + d [ t [ i ] > > 1 ] [ t [ j ] > >1]
− d [ i > > 1 ] [ t [ i ] > >1] − d [ j > > 1 ] [ t [ j ] > > 1 ] ;
em
n o i s e = ( rando ( ) −0.5) ∗ c u r r e n t _ n o i s e ;
i f ( d e l t a + noise < 0) / ∗ Move accepted ∗ /
{ next_i = t [ i ] ; next_j = t [ j ] ;
t [ i ] = j ^1; t [ next_i ^1] = next_j ;
t [ j ] = i ^1; t [ next_j ^1] = next_i ;
length = length + delta ;
pt

i = t [ i ]; / ∗ To a v o i d r e v e r s i n g i m m e d i a t e l y a degrading move ∗ /
j = t [ i ];
se

i f ( l e n g t h < ∗ b e s t _ c o s t − e p s i l o n ) / ∗ Memorize improved b e s t s o l u t i o n ∗ /


{ ∗best_cost = length ;
/ ∗ R e b u i l d t h e s o l u t i o n under t h e form o f t h e sequence o f c i t i e s ∗/
r = 0;
f o r ( s = 0; s < n ; s = s + 1)
25

{ b e s t _ s o l [ s ] = r > >1; r = t [ r ] ; }
p r i n t f ( " N o i s i n g method improvement %l d : %f \ n " , i t e r a t i o n , l e n g t h ) ;
}
} / ∗ Move accepted ∗ /
i t e r a t i o n ++;
i f ( i t e r a t i o n % ( n∗n ) == 0 ) / ∗ Noise decrease every n∗n i t e r . ∗ /
g

c u r r e n t _ n o i s e ∗= alpha ;
j = t [ j ]; / ∗ Next j ∗ /
}
Al

i = t [ i ] ; / ∗ Next i ∗ /
}
} /∗ while ( current_noise > f i n a l _ n o i s e ) ∗/
T_

free ( t ) ;
}

6.6 GRASP
La méthode GRASP, dont le nom ne vient pas de l’anglais « empoigner »,
mais qui est l’acronyme de Greedy Randomized Adaptive Search Procedure,
soit une recherche gloutonne randomisée suivie d’une méthode d’amélioration.
Cette méthode comporte deux paramètres, Imax , le nombre de répétitions de
la boucle la plus externe de l’algorithme et α, permettant de régler le degré de
154 M ÉTHODES RANDOMISÉES

randomisation. La trame de la méthode est donnée par l’algorithme 6.6.

Algorithme 6.6 : Trame d’une méthode GRASP. Le programmeur doit au préa-


lable concevoir une méthode a d’amélioration d’une solution et l’utilisateur doit
fournir deux paramètres, Imax qui règle l’effort de calcul, et α qui règle le niveau
de choix aléatoire. Les différence avec la trame de construction gloutonne 3.2 sont
mises en évidence
Entrées : ensemble E d’éléments dont sont constituées les solutions du
problème ; fonction de coût incrémental c(s, e) ; fonction utilité

17
f à minimiser, paramètres Imax et 0 6 α 6 1, méthode
d’amélioration a
Résultat : Solution complète s∗

20
1 f ∗ ← ∞;
2 pour Imax itérations faire
3 Initialiser s à une solution partielle triviale;
4 R ← E; // Éléments pouvant encore être ajoutés à s

e
5 tant que R 6= ∅ faire
Trouver cmin = mine∈R c(s, e) et cmax = maxe∈R c(s, e);

br
6
7 Choisir aléatoirement, uniformément un e0 ∈ R tel que
cmin 6 c(s, e0 ) 6 cmin + α(cmax − cmin );
em
8 s ← s ∪ e0 ; // Ajouter e0 à la solution partielle s
9 Retirer de R les éléments qui ne peuvent plus être utilisés pour
compléter s;
10 s0 ← a(s); // Trouver l’optimum local associé à s
pt

11 si f ∗ > f (s0 ) alors


12 f ∗ ← f (s0 );
se

13 s∗ ← s0

Avec un paramètre α = 0, on a une construction purement gloutonne ;


25

à moins que plusieurs éléments aient les mêmes coûts incrémentaux, la ré-
pétition de constructions n’a pas de sens. Pour un paramètre α = 1, on a
une construction purement aléatoire. La méthode se transforme en répétitions
d’une méthode d’amélioration partant de solutions aléatoires ; cette technique
g

est souvent pratiquée car elle permet d’obtenir de bien meilleures solutions
Al

qu’une recherche locale unique, avec un effort de codage négligeable.


Pour bénéficier des avantages de la méthode GRASP, il faut calibrer la
valeur de α. Elle donnera son plein potentiel généralement pour des valeurs
T_

proches, mais différentes de 0. Il faut également noter que l’initialisation de la


solution partielle peut comporter une composante aléatoire, par exemple, pour
le voyageur de commerce, on peut tirer aléatoirement la ville de départ et utili-
ser une fonction de coût incrémental correspondant au critère du plus proche
voisin.
6.7 M ÉTHODE À VOISINAGE VARIABLE 155

Listing 6.3 – tsp_GRASP.c Implantation en C d’une méthode GRASP pour le problème


du voyageur de commerce avec construction basée sur l’heuristique gloutonne du
plus proche voisin randomisée. La procédure d’amélioration est basée sur les chaînes
d’éjections (code 4.4)
double tsp_GRASP ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , / ∗ D i s t a n c e m a t r i x , must be s y m m e t r i c a l ∗/
i n t best_sol [ ] , / ∗ Best t o u r found ∗/
int iterations , / ∗ Number o f i t e r a t i o n s ∗/
double alpha ) / ∗ Randomness i n greedy c o n s t r u c t i o n ∗/
{ int∗ solution ; /∗ Current s o l u t i o n ∗/
double b e s t _ c o s t = i n f i n i t e ; / ∗ Length o f b e s t s o l u t i o n found ∗/
int i , j ; /∗ Indices ∗/

17
double l e n g t h ; / ∗ Cost o f c u r r e n t s o l u t i o n ∗/
int nr_iteration ;
double cmin , cmax ;

s o l u t i o n = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;

20
f o r ( n r _ i t e r a t i o n = 0 ; n r _ i t e r a t i o n < i t e r a t i o n s ; n r _ i t e r a t i o n ++)
{ generate_random_permutation ( n , s o l u t i o n ) ;
f o r ( i = 0 ; i < n−1; i ++) /∗ s o l u t i o n [ i ] i s the l a s t c i t y i n s e r t e d ∗/
{ / ∗ Determine min and max i n c r e m e n t a l c o s t s ∗ /
cmin = i n f i n i t e ; cmax = − i n f i n i t e ;
f o r ( j = i +1; j < n ; j ++)

e
{ i f ( cmin > d [ s o l u t i o n [ i ] ] [ s o l u t i o n [ j ] ] )
cmin = d [ s o l u t i o n [ i ] ] [ s o l u t i o n [ j ] ] ;

}
br
i f ( cmax < d [ s o l u t i o n [ i ] ] [ s o l u t i o n [ j ] ] )
cmax = d [ s o l u t i o n [ i ] ] [ s o l u t i o n [ j ] ] ;
em
/ ∗ Find t h e n e x t c i t y t o i n s e r t , biased on l o w e r c o s t ∗ /
f o r ( j = i +1; d [ s o l u t i o n [ i ] ] [ s o l u t i o n [ j ] ] > cmin + alpha ∗(cmax−cmin ) ; j ++)
{ } / ∗ C i t i e s t o i n s e r t a l r e a d y i n random o r d e r ; f i r s t c h o i c e i s random ∗ /
swap(& s o l u t i o n [ i + 1 ] , & s o l u t i o n [ j ] ) ;
} / ∗ s o l u t i o n i s complete now ∗ /
pt

length = tsp_length (n , d , solution ) ;


tsp_LK ( n , d , s o l u t i o n , &l e n g t h ) ;
se

i f ( length < best_cost − epsilon ) / ∗ S t o r e improved b e s t s o l u t i o n ∗ /


{ f o r ( i = 0 ; i < n ; i ++)
best_sol [ i ] = solution [ i ] ;
best_cost = length ;
p r i n t f ( "GRASP %d %f \ n " , n r _ i t e r a t i o n , l e n g t h ) ;
}
25

}
free ( solution ) ;
return best_cost ;
} / ∗ tsp_GRASP ∗ /
g
Al

6.7 Méthode à voisinage variable


La méthode à voisinage variable met en œuvre une stratégie de recher-
T_

che appelée parfois oscillations stratégiques qui consiste à alterner des phase
d’intensification et de diversification de la recherche. L’idée à la base de cette
méthode est de s’appuyer sur plusieurs voisinages M1 . . . Mp . Le voisinage
M1 est utilisé de façon standard pour trouver des optima locaux ; il s’agit d’une
des manière les plus simple d’intensifier la recherche. Les autres voisinages
permettent de s’échapper de ces optima en effectuant des mouvements aléa-
toires qui, généralement, détruisent de plus en plus leur structure. Le tirage
de mouvement aléatoires est également une des manière les plus simples de
diversifier la recherche, pour explorer d’autres portions de l’espace des solu-
tions. La trame d’une méthode à voisinage variable de base est donnée par
l’algorithme 6.7.
156 M ÉTHODES RANDOMISÉES

Algorithme 6.7 : Méthode à voisinage variable. Lorsque l’on dispose d’un faible
nombre p de voisinage, on répète plusieurs fois l’algorithme.
Entrées : Solution s, fonction-utilité f à minimiser, structures de
voisinage M1 . . . Mp
Résultat : s∗
1 s∗ ← s;
2 k ← 1;
3 tant que k 6 p faire
4 Tirer un mouvement aléatoire m ∈ Mk ;

17
5 s ← s ⊕ m;
6 Trouver l’optimum local s0 associé à s dans le voisinage M1 ;
7 si f (s0 ) < f (s∗ ) alors

20
8 s∗ ← s0 ;
9 k←1
10 sinon
s ← s∗ ;

e
11
12 k ←k+1

br
em
Listing 6.4 – tsp_VNS.c Implantation d’une méthode à voisinage variable pour le pro-
blème du voyageur de commerce. Le voisinage Mk consiste à échanger deux villes k
fois. La méthode permettant de réparer une solution perturbée est une chaîne d’éjec-
tions. La particularité de cette implantation, outre son extrême simplicité, est de ne
pt

comporter aucun paramètre.


v o i d tsp_VNS ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , / ∗ D i s t a n c e m a t r i x , must be s y m m e t r i c a l ∗/
se

i n t best_sol [ ] , / ∗ InOut S o l u t i o n p r o v i d e d and r e t u r n e d ∗/


double ∗ b e s t _ c o s t ) / ∗ InOut Length o f t h e b e s t t o u r ∗/
{ int∗ solution ; /∗ Current s o l u t i o n ∗/
int i , k ; /∗ Indices ∗/
double l e n g t h ; /∗ Current s o l u t i o n cost ∗/
i n t i t e r a t i o n = 0; / ∗ Number o f 2−o p t c a l l s ∗/
25

s o l u t i o n = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
k = 1;
while ( k < n)
{ f o r ( i = 0 ; i < n ; i ++)
solution [ i ] = best_sol [ i ] ;
g

f o r ( i = 0 ; i < k ; i ++)
swap(& s o l u t i o n [ u n i f ( 0 , n −1)] , & s o l u t i o n [ u n i f ( 0 , n − 1 ) ] ) ;
Al

length = tsp_length (n , d , solution ) ;


tsp_LK ( n , d , s o l u t i o n , &l e n g t h ) ;
i t e r a t i o n ++;
T_

i f ( length < ∗best_cost − epsilon ) / ∗ S t o r e improved b e s t s o l u t i o n ∗ /


{ f o r ( i = 0 ; i < n ; i ++)
best_sol [ i ] = solution [ i ] ;
∗best_cost = length ;
p r i n t f ( "VNS %d %d %f \ n " , i t e r a t i o n , k , l e n g t h ) ;
k = 1;
}
else
k ++;
}
free ( solution ) ;
} / ∗ tsp_VNS ∗ /
6.7 M ÉTHODE À VOISINAGE VARIABLE 157

Exercice 6.1. Durée d’un recuit Combien d’itération va effectuer un recuit


simulé partant avec une température initiale T0 et finale Tf si le facteur de
décroissance choisi est α ?
Exercice 6.2. Détail d’implantation du recuit Dans l’algorithme 6.1, lors-
qu’un mouvement [i, j] est retenu, on avance les deux indices avec les instruc-
tions i = t[i]; et j = t[i];, alors que dans l’algorithme 4.3, on se contente
d’avancer uniquement l’indice j. Expliquer la raison de ce traitement différen-
cié.

17
20
e
br
em
pt
se
25
g
Al
T_
158 M ÉTHODES RANDOMISÉES

17
20
e
br
em
pt
se
25
g
Al
T_
Chapitre 7

17
Apprendre à construire

20
Après les quatre principes de base vus précédemment — modélisation,

e
décomposition, construction et amélioration — nous abordons dans ce cha-
pitre le cinquième principe : celui de l’apprentissage. Les algorithmes vus dans

br
le chapitre précédent se basent uniquement sur le hasard pour tenter d’ob-
tenir des solutions meilleures que celles que pourraient fournir des méthodes
em
constructives gloutonnes ou des recherches locales. Ceci n’est sans doute pas
très satisfaisant du point de vue intellectuel, bien que, comme dit l’adage, « le
hasard fait bien les choses ». Sans y renoncer totalement, nous examinerons
dans ce chapitre comment mettre en œuvre des techniques d’apprentissage
pt

pour construire de nouvelles solutions.


En examinant le processus d’apprentissage, on se rend compte que trois
se

ingrédients sont nécessaires :

— Répéter des expériences et analyser les succès (ou les échecs, car on
apprend peut-être plus en faisant des erreurs !)
25

— Mémoriser ce qui a été fait.


— Oublier certains détails, ce qui donne la faculté de généraliser lorsque
l’on se trouve dans une situation similaire mais différente.
g
Al

La technique des fourmis artificielles permet de mettre en œuvre très sim-


plement ces ingrédients d’apprentissage pour construire de nouvelles solu-
tions.
T_

7.1 Fourmis artificielles


Le comportement social de certains animaux a toujours fasciné, en parti-
culier lorsqu’une population arrive à des réalisations complètement hors de la
portée d’un individu isolé. C’est le cas des abeilles, des thermites ou des four-
mis : bien que chaque individu ait un comportement extrêmement simple, une
colonie arrive à construire des nid complexes et à s’approvisionner efficace-
ment.
160 A PPRENDRE À CONSTRUIRE

17
20
e
br
em
pt
se

(a) Situation initiale (b) Situation finale


25

F IGURE 7.1 – Comportement d’une colonie de fourmi séparée d’une source de nour-
riture par un parcours qui bifurque. Initialement les fourmis se répartissent également
dans les deux branches 7.1(a). Les fourmis ayant emprunté le chemin le plus court
g

vont arriver avant à la source de nourriture et vont donc déposer plus rapidement une
quantité additionnelle de phéromones sur le chemin du retour. La quantité de phéro-
Al

mones déposée sur le plus court chemin croît plus rapidement. Après un certain temps,
pratiquement toutes les fourmis vont utiliser la branche la plus courte 7.1(b)
T_
7.1 F OURMIS ARTIFICIELLES 161

7.1.1 Observations avec des fourmis réelles


Suite aux travaux de [?] qui ont décrit le comportement presque algorith-
miques des fourmis, des chercheurs ont eu l’idée de simuler ce comportement
pour tenter de résoudre des problèmes difficiles. Le principe de fonctionnement
d’une fourmi est illustré en figure 7.1 par une expérience faite avec une colonie
réelle qui a été isolée. Cette dernière ne peut s’approvisionner en nourriture
que par un unique orifice ouvert sur un conduit se séparant en deux branches
se rejoignant plus loin. La branche de gauche est plus courte que celle de
droite. Comme les fourmis n’ont initialement aucune information sur ce fait, les

17
éclaireurs vont se répartir également dans les deux branches 7.1(a). Tout en
explorant, chaque fourmi dépose une trace chimique qu’elle est capable de dé-
tecter avec ses antennes, ce qui l’aidera lors de son retour dans la fourmilière.

20
Une telle substance chimique porteuse d’information est appelée phéromone.
Une fourmi ayant découvert une source de nourriture va déposer une quan-
tité d’autant plus grande de phéromones sur le chemin du retour que la source
est importante. Naturellement, une fourmi ayant découvert un chemin court

e
va pouvoir retourner plus rapidement que celle qui a emprunté la mauvaise

br
branche. Par conséquent, la quantité de phéromones déposées sur le plus
court chemin croît plus rapidement. Le corollaire est qu’une nouvelle fourmi
disposera d’une information sur le chemin à prendre et biaisera son choix
em
en faveur de la branche la plus courte. Après un certain temps, on observe
que pratiquement toutes les fourmis utilisent la branche la plus courte 7.1(b).
Ainsi, la colonie arrive à déterminer collectivement un chemin optimal, alors
que chaque individu ne voit pas plus loin que le bout de ses antennes.
pt

7.1.2 Transcription en processus d’optimisation


se

Si une colonie de fourmis arrive à optimiser la longueur d’un chemin, même


dans un contexte dynamique, on devrait pouvoir transcrire le comportement de
chaque individu en un processus simple pour l’optimisation de problèmes plus
25

difficiles. Cette transcription peut s’effectuer ainsi :


— Une fourmi sera un processus exécutant une procédure de construction
d’une solution, dotée d’une composante aléatoire. Plusieurs de ces pro-
g

cessus pourront s’exécuter en parallèle.


Al

— Les traces de phéromones seront des valeurs τe qui seront associées à


chaque élément e pouvant constituer une solution.
— Les traces jouent le rôle d’une mémoire collective. Après la construction
T_

d’une solution, les valeurs des éléments constituant cette dernière seront
augmentées d’une quantité d’autant plus grande que la solution est de
bonne qualité.
— Le phénomène d’oubli sera simulé par l’évaporation des traces au cours
du temps.
Reste ensuite à préciser comment toutes ces composantes peuvent être
mises en place. Le processus de construction va utiliser une technique de
construction randomisée, presque similaire à la méthode GRASP, si ce n’est
que la composante aléatoire doit être biaisée non seulement par la fonction
ce coût incrémental c(s, e), qui représente l’intérêt a priori d’inclure l’élément
162 A PPRENDRE À CONSTRUIRE

e dans la solution partielle, mais également par la valeur τe qui sera l’intérêt
a posteriori de cet élément, intérêt qui ne sera connu qu’après avoir construit
une multitude de solutions. Le mariage de ces deux formes d’intérêts se réa-
lise en choisissant le prochain élément e à inclure dans la solution partielle s
avec une probabilité proportionnelle à τeα · c(s, e)β , ou α > 0 et β < 0 sont deux
paramètres de la méthode permettant de balancer l’importance que l’on donne
respectivement à la mémoire et au coût incrémental.
La mise à jour des phéromones artificielles se fait en deux étapes, néces-
sitant chacune un paramètre. Tout d’abord, on simule l’évaporation des phéro-

17
mones en multipliant toutes les valeurs τe par 1 − ρ, où 0 6 ρ 6 1 représente
le taux d’évaporation. Ensuite, chaque élément e constituant une solution s ve-
nant d’être construite verra sa valeur τe renforcée d’une quantité 1/f (s), où

20
f (s) est la valeur de la solution, que l’on suppose supérieure à 0.

7.1.3 Système de fourmi MAX-MIN

e
Les premières applications de colonies de fourmis artificielles ne compor-

br
taient que les composantes décrites plus haut. Il a été observé que la rétro-
action positive engendrée par la mise à jour des traces de phéromones artifi-
cielles était difficile à contrôler à l’aide des trois paramètres α, β et ρ. En effet,
em
le point de basculement entre un processus presque aléatoire dépourvu d’ap-
prentissage et un processus qui apprend trop rapidement à répéter la construc-
tion d’une même solution est difficile à trouver.
Pour y remédier, [?] ont suggéré de limiter les valeurs des traces entre deux
pt

bornes τmin et τmax , de sorte à conserver une probabilité minimale de choisir


n’importe quel élément à ajouter à chaque solution, tout en évitant que certains
se

éléments voient leur valeur grandir tellement qu’il ne deviendrait plus possible
de construire une solution sans eux.
On aboutit ainsi à la trame présentée plus loin, qui s’est révélée beau-
coup plus efficace que de nombreuses autres trames proposées antérieure-
25

ment. Cette trame comporte une méthode d’amélioration. En effet, les implan-
tations de colonies de fourmis artificielles « pures » basées uniquement sur
la construction de solutions se sont révélées peu performantes et difficiles à
mettre au point. Il peut exister des exceptions, notamment pour le traitement
g

de problèmes hautement dynamiques où une situation d’optimalité à un instant


ne l’est plus à un autre.
Al

L’algorithme 7.1 présente un avantage théorique : il peut être montré que


si le nombre d’itérations Imax → ∞ et si τmin > 0, alors il va trouver une
T_

solution globalement optimale au problème avec une probabilité tendant vers


1. La démonstration repose sur le fait que τmin > 0 implique que la probabilité
de construire une solution globalement optimale n’est pas nulle. En pratique
cependant, un tel résultat théorique n’est pas d’une grande utilité.

7.1.4 Système de fourmis rapide


Un des défauts de nombreuses trames de méthodes basées sur des four-
mis artificielles est leur grand nombre de paramètres et la difficulté de leurs
ajustements. C’est la raison pour laquelle nous n’avons notamment pas pré-
senté ici Ant System (AS [?]) ou Ant Colony System (ACO [?]). De plus, il
7.1 F OURMIS ARTIFICIELLES 163

Algorithme 7.1 : Trame de MAX-MIN ant system.


Entrées : ensemble E d’éléments dont sont constituées les solutions du
problème ; fonction de coût incrémental c(s, e) > 0 ; fonction
utilité f à minimiser, paramètres Imax , m, α, β, τmin , τmax , ρ et
méthode d’amélioration a(·)
Résultat : Solution complète s∗

1 f ← ∞;
2 pour ∀e ∈ E faire
3 τe ← τmax

17
4 pour Imax itérations faire
5 pour k = 1 . . . m faire
Initialiser s à une solution partielle triviale;

20
6
7 R ← E; // Éléments pouvant encore être ajoutés à s
8 tant que R 6= ∅ faire
9 Choisir aléatoirement e ∈ R avec probabilité proportionnelle à
τeα · c(s, e)β ;

e
// Formule des colonies de fourmis
10 s ← s ∪ e;
11
pour compléter s;
br
Retirer de R les éléments qui ne peuvent plus être utilisés
em
12 sk ← a(s); // Trouver l’optimum local sk associé à s
13 si f ∗ > f (sk ) alors
14 f ∗ ← f (sk );
15 s∗ ← sk ; // Mettre à jour la meilleure solution connue
pt

16 pour ∀e ∈ E faire
17 τe ← (1 − ρ) · τe ; // Évaporation des traces de phéromones
se

18 sb ← meilleure des solutions de {s1 , . . . , sm };


19 pour ∀e ∈ sb faire
20 τe ← τe + 1/f (sb ); // Renforcement des traces
25

peut être délicat pour certains problèmes de concevoir une fonction de coût
g

incrémental donnant l’intérêt a priori d’insérer un élément dans une solution


partielle.
Al

C’est pourquoi une trame simplifiée appelée FANT (pour Fast ANT system)
a été proposée. En plus du nombre d’itérations Imax , cette trame ne comporte
T_

qu’un paramètre, τb , que l’utilisateur doit spécifier. Ce paramètre correspond


au renforcement des traces de phéromones artificielles qui est appliqué systé-
matiquement à chaque itération sur les éléments de la meilleure solution trou-
vée jusque là. Le renforcement des traces associé aux éléments de la solution
construite à l’itération courante, τc , est un paramètre auto-adaptatif. Initiale-
ment, ce paramètre vaut 1.
Lorsque l’on se rend compte que l’on a trop appris parce que l’on a gé-
néré une nouvelle fois la meilleure solution, τc est incrémenté pour augmenter
la diversité des solutions générées et toutes les traces sont réinitialisées à la
valeur de τc . Si l’on a amélioré la meilleure solution, alors τc est réinitialisé à
1 pour donner plus de poids aux éléments constituant cette solution amélio-
164 A PPRENDRE À CONSTRUIRE

225

Nombre d'arêtes différentes


200

175

Avant optimisation
150
Après optimisation
125 Amélioration

100

17
75

50

20
25

0
0 100 200 300 400 500 600 700 800

e
Itérations

br
em
F IGURE 7.2 – Comportement de FANT sur un problème de voyageur de commerce à
225 villes. Ce diagramme donne, en fonction du nombre de solutions construites par
la méthode, le nombre d’arêtes qui diffèrent de la meilleure solution trouvée jusque là,
juste après la construction au moyen des traces de phéromones artificielles et après
amélioration à l’aide de la technique de chaînes d’éjections. Les lignes verticales in-
pt

diquent les améliorations de la meilleure solution trouvées. Dans cette expérience, la


dernière de ces améliorations correspond à la solution optimale.
se

rée. Finalement, FANT incorpore une méthode d’amélioration locales sur les
solutions construites au moyen des traces. Il a en effet été remarqué, pour de
25

nombreuses variantes de méthodes basées sur les colonies de fourmis, que


la qualité des solutions produites avec le seul mécanisme d’apprentissage de
construction de solutions était très souvent médiocre. L’algorithme 7.2 donne
la trame de FANT.
g

La figure 7.2 illustre le comportement de FANT sur un problème de voya-


Al

geur de commerce à 225 villes. Dans cette expérimentation, la valeur de τb a


été fixée à 50. Cette figure donne le nombre d’arêtes différentes de la meilleure
solution trouvée jusque là, avant et après optimisation locale.
T_

L’implantation de FANT pour le problème du voyageur de commerce néces-


site de recourir à une matrice τ plutôt qu’à un vecteur. En effet, un élément e
d’une solution est une arête [i, j], définie par ses deux sommets adjacents. La
valeur τij sera donc l’intérêt a posteriori de construire une solution avec l’arête
[i, j]. L’initialisation de cette matrice de trace et sa mise à jour pourra donc être
implantée au moyen des procédures décrite dans le code 7.1.
Le cœur d’une heuristique basée sur une colonie de fourmis artificielles
est la construction d’une nouvelle solution en exploitant les traces de phéro-
mones. Une procédure d’exploitation ne faisant pas intervenir l’intérêt a priori
de chaque élément de la solution est donnée par le code 7.2. Dans cette im-
plantation, la ville de départ est choisie aléatoirement en tirant une permutation
7.1 F OURMIS ARTIFICIELLES 165

Algorithme 7.2 : Trame de FANT. Bien que pouvant paraître complexe, la plus
grande partie de cette trame consiste à adapter automatiquement le poids res-
pectif τc que l’on donne à la solution nouvellement construite en regard du poids
τb associé à la meilleure solution construite et à réinitialiser les traces si l’on a trop

17
appris ou si on vient d’améliorer la meilleure solution connue.
Entrées : ensemble E d’éléments dont sont constituées les solutions du
problème ; fonction utilité f à minimiser, paramètres Imax , τb et

20
méthode d’amélioration a(·)
Résultat : Solution complète s∗
1 f ∗ ← ∞;
τc ← 1;

e
2
3 pour ∀e ∈ E faire
4

5
τe ← τc
pour Imax itérations faire br
em
6 Initialiser s à une solution partielle triviale;
7 R ← E; // Éléments pouvant encore être ajoutés à s
8 tant que R 6= ∅ faire
9 Choisir aléatoirement e ∈ R avec probabilité proportionnelle à τe ;
pt

10 s ← s ∪ e;
11 Retirer de R les éléments incompatibles pour compléter s;
se

12 s0 ← a(s); // Trouver l’optimum local s0 associé à s


13 si s0 = s∗ alors
14 τc ← τc + 1; // Donner plus de poids aux solutions construites
15 pour ∀e ∈ E faire
25

16 τe ← τc ; // Effacer toutes les traces

17 si f ∗ > f (sk ) alors


18 f ∗ ← f (sk );
s∗ ← sk ;
g

19 // Mettre à jour la meilleure solution connue


20 τc ← 1; // Donner moins de poids aux solutions construites
Al

21 pour ∀e ∈ E faire
22 τe ← τc ; // Effacer toutes les traces
T_

23 pour ∀e ∈ s0 faire
24 τe ← τe + τc ; // Renforcement des traces de la solution courante

25 pour ∀e ∈ s faire
26 τe ← τe + τb ; // Renforcement des traces de la meilleure solution
166 A PPRENDRE À CONSTRUIRE

p aléatoire. À l’itération i de la construction, les i premiers éléments de p ont


été choisis de façon définitive. On tire ensuite l’élément suivant avec une pro-
babilité proportionnelle aux valeurs des traces pour les éléments restants.
Listing 7.1 – init_update_trail.c Implantation de l’initialisation de la matrice des traces
et de sa mise à jour dans la méthode FANT pour un problème d’optimisation où l’on
recherche une permutation. Si l’on remarque que l’on vient de générer une nouvelle fois
la meilleure solution connue, on réinitialise toutes les traces. Autrement, on renforce à
la fois les traces de la solution courante et de la meilleure solution trouvée.
void i n i t _ t r a i l ( i n t n , / ∗ Problem s i z e ∗ /

17
i n t increment , / ∗ Reinforcement o f l o c a l s o l u t i o n ∗ /
int∗ trail []) / ∗ Pheromone t r a i l s ∗ /
{ int i , j ;
f o r ( i = 0 ; i < n ; i ++)
f o r ( j = 0 ; j < n ; j ++)

20
t r a i l [ i ] [ j ] = increment ;
f o r ( i = 0 ; i < n ; i ++)
t r a i l [ i ] [ i ] = 0;
}

e
void u p d a t e _ t r a i l ( i n t n , / ∗ Problem s i z e ∗/
const i n t p [ ] , /∗ Local s o l u t i o n ∗/
c o n s t i n t best_p [ ] , /∗ Global best s o l u t i o n ∗/

{ i n t i = 0;
i n t ∗increment ,
i n t R,
int∗ trail [])
br / ∗ Reinforcement o f l o c a l s o l u t i o n
/ ∗ Reinforcement o f g l o b a l b e s t s o l u t i o n
∗/
∗/
em
w h i l e ( i < n && p [ i ] == best_p [ i ] ) i ++;
i f ( i == n ) / ∗ New s o l u t i o n p same as b e s t s o l u t i o n found ∗/
{
(∗ i n c r e m e n t ) + + ;
i n i t _ t r a i l ( n , ∗increment , t r a i l ) ;
}
pt

else
f o r ( i = 0 ; i < n ; i ++)
{ t r a i l [ p [ i ] ] [ p [ ( i +1)%n ] ] += ∗ i n c r e m e n t ;
se

t r a i l [ best_p [ i ] ] [ best_p [ ( i +1)%n ] ] += R ;


}
}

Une fois que les trois procédures données dans les codes 7.1 et 7.2 ainsi
25

qu’une procédure de recherche locale sont disponibles, l’implantation de FANT


est très simple. Une telle implantation faisant usage d’une recherche locale
basée sur des chaînes d’éjection est donnée par le code 7.3
g
Al
T_
7.1 F OURMIS ARTIFICIELLES 167

Listing 7.2 – generate_solution_trail Implantation de la génération d’une permutation


en n’exploitant que les informations contenues dans les traces de phéromones artifi-
cielles.
double g e n e r a t e _ s o l u t i o n _ t r a i l ( i n t n ,
double ∗∗d , /∗ Distance matrix ∗/
int p[] , / ∗ S o l u t i o n generated ∗/
i n t ∗ const t r a i l [ ] )
{
int i , j , /∗ Indices ∗/
t a r g e t , sum ; / ∗ For a r o u l e t t e wheel s e l e c t i o n o f n e x t element ∗/
generate_random_permutation ( n , p ) ;
f o r ( i = 1 ; i < n−1; i ++)

17
{ sum = 0 ;
f o r ( j = i + 1 ; j < n ; j ++)
sum += t r a i l [ p [ i − 1 ] ] [ p [ j ] ] ;
t a r g e t = u n i f ( 0 , sum−1);
f o r ( j = i , sum = t r a i l [ p [ i − 1 ] ] [ p [ j ] ] ; sum < t a r g e t ; j ++)

20
sum += t r a i l [ p [ i − 1 ] ] [ p [ j + 1 ] ] ;
swap(&p [ j ] , &p [ i ] ) ;
}
return tsp_length (n , d , p ) ;
}

e
Listing 7.3 – tsp_FANT Implantation de la méthode FANT pour le problème du voya-

double tsp_FANT ( i n t n ,
double∗∗ d , br
geur de commerce. La recherche locale utilisée est celle donnée dans le code 4.4
/ ∗ Number o f c i t i e s
/∗ Distance matrix
∗/
∗/
em
i n t best_sol [ ] , / ∗ Out S o l u t i o n r e t u r n e d ∗/
i n t R, / ∗ FANT Parameters ∗/
int iterations ) / ∗ Number o f s o l u t i o n s generated ∗/
{ int i , j , nr_iteration , /∗ Indices ∗/
increment = 1; / ∗ Reinforcement o f elements o f t h e s o l u t i o n generated ∗/
double c o s t ; / ∗ Cost o f s o l u t i o n generated by t h e a n t ∗/
pt

double b e s t _ c o s t = i n f i n i t e ; / ∗ Length o f t h e b e s t t o u r ∗/
int∗ p; / ∗ S o l u t i o n generated by an a n t process ∗/
i n t ∗∗ t r a i l ; / ∗ Pheromone t r a i l m a t r i x ∗/
se

p = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
t r a i l = ( i n t ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ∗ ) ) ;
f o r ( i = 0 ; i < n ; i ++)
t r a i l [ i ] = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
25

i n i t _ t r a i l ( n , increment , t r a i l ) ;

/ ∗ FANT i t e r a t i o n s ∗ /
f o r ( n r _ i t e r a t i o n = 0 ; n r _ i t e r a t i o n < i t e r a t i o n s ; n r _ i t e r a t i o n ++)
{ / ∗ B u i l d a new s o l u t i o n ∗ /
cost = g e n e r a t e _ s o l u t i o n _ t r a i l ( n , d , p , t r a i l ) ;
g

/ ∗ Improve s o l u t i o n w i t h a l o c a l search ∗ /
tsp_LK ( n , d , p , &c o s t ) ;
Al

/ ∗ Best s o l u t i o n improved ? ∗ /
i f ( cost < best_cost − epsilon )
{ best_cost = cost ;
T_

p r i n t f ( "FANT %d %f \ n " , n r _ i t e r a t i o n , c o s t ) ;
f o r ( j = 0 ; j < n ; j ++) b e s t _ s o l [ j ] = p [ j ] ;
increment = 1;
i n i t _ t r a i l ( n , increment , t r a i l ) ;
}
else
/ ∗ Memory update ∗ /
u p d a t e _ t r a i l ( n , p , b e s t _ s o l , &increment , R, t r a i l ) ;
};

free (p ) ;
f o r ( i = 0 ; i < n ; i ++)
free ( t r a i l [ i ] ) ;
free ( t r a i l ) ;
return best_cost ;
} / ∗ tsp_FANT ∗ /
168 A PPRENDRE À CONSTRUIRE

17
20
(a) Une excellente solution (b) Tournées rapidement obtenues

e
F IGURE 7.3 – Une très bonne solution à un problème d’élaboration de tournées de
véhicules 7.3(a) et quelques tournées obtenues rapidement à l’aide de recherches avec

br
tabou sommaires 7.3(b). On remarque une grande similitudes entre ces dernières et
celles de la bonne solution.
em
7.2 Construction de vocabulaire
pt

La construction de vocabulaire est une méthode d’apprentissage plus glo-


bale que le sont à la base les colonies de fourmis artificielles. L’idée consiste
à mémoriser des parties de solutions, qui sont appelées des mots, et de cons-
se

truire de nouvelles solutions à partir de ces parties. En d’autre terme, on se


dote d’un dictionnaire qui sera utilisé pour construire, de façon randomisée, une
tentative de phrase. Cette tentative de solution est améliorée à l’aide d’une pro-
cédure ad-hoc pour la rendre réalisable et en accroître la qualité. Finalement
25

cette nouvelle solution-phrase est décomposée en de nouveaux mots qui vont


enrichir le dictionnaire.
Cette méthode a été proposée par F. Glover et n’est encore pas très utili-
sée en pratique, bien qu’elle se soit révélée efficace pour un certain nombre de
g

problèmes. Parmi ceux-ci, l’élaboration de tournées de véhicules se prête na-


Al

turellement à son utilisation. En effet, il est relativement aisé de construire des


solutions comportant des tournées similaires à celles des meilleures solutions
connues. Ceci est illustré en figure 7.3.
T_

En construisant de nombreuses solutions à l’aide de méthodes randomi-


sées —sans apprentissage— on peut se doter d’un premier dictionnaire de
portions de solution. Ceci est illustré en figure 7.4.
Une fois un premier dictionnaire constitué, on construit une tentative de so-
lution, par exemple en sélectionnant un sous-ensemble de tournées ne com-
portant pas de clients communs. Cette solution n’est pas forcément réalisable,
car il se peut fort bien que, durant le processus de construction, le dictionnaire
ne comporte pas de tournées regroupant certains clients non encore couverts.
Il est donc nécessaire de réparer cette tentative de solution, par exemple au
moyen de la même méthode que celle utilisée pour créer le premier diction-
naire, mais démarrant avec la tentative de solution. Cette phase de la méthode
7.2 C ONSTRUCTION DE VOCABULAIRE 169

est illustrée en figure 7.5. La solution améliorée est susceptible de contenir


des tournées qui ne figurent pas encore dans le dictionnaire. Celles-ci y seront
incorporées et l’enrichiront pour des itérations ultérieures.

17
20
e
br
em
pt
se
25

F IGURE 7.4 – Fragments de solutions (tournées) constituant le dictionnaire. On construit


une solution partielle en sélectionnant, de façon randomisée, un certain nombre de ces
fragments (indiqués en couleur).
g

La technique peut être adaptée à d’autres problèmes, comme par exemple


Al

celui du voyageur de commerce. Les mots du dictionnaire dans ce cas peu-


vent être constitués d’ensemble de villes connectées par un chemin. Dans la
T_

figure 7.6, on a représenté toutes les arêtes présentes dans plus de deux tiers
des 100 tournées obtenues en appliquant une méthode d’amélioration basée
sur un voisinage de chaînes d’éjections démarrant avec une solution aléatoire.
La solution optimale de ce problème étant connue, il a été possible de
mettre en évidence la quinzaine d’arêtes fréquemment obtenues qui ne font
pas partie de la solution optimale. Il est intéressant de remarquer que près
des 80% des arêtes de la solution optimale ont été identifiées en initialisant le
dictionnaire avec une simple méthode d’amélioration.
170 A PPRENDRE À CONSTRUIRE

17
(a) Tentative de solution (b) Solution complétée et améliorée

20
F IGURE 7.5 – Une tentative de phrase est construite en choisissant de façon randomi-
sée des mots du dictionnaire 7.5(a). Cette tentative est complétée et améliorée 7.5(b).

e
Exercices
br
Exercice 7.1. Colonie de fourmis pour l’arbre de Steiner Pour le problème
em
de l’arbre de Steiner, comment définir les traces d’une colonie de fourmis arti-
ficielles ? Décrire comment ces traces sont exploitées.
Exercice 7.2. Ajustement du paramètre de FANT Trouver de bonnes valeurs
pour le paramètre R de la méthode tsp_FANT donnée par le code 7.3 lorsque
pt

cette dernière effectue 300 itérations.


se
25
g
Al
T_
7.2 C ONSTRUCTION DE VOCABULAIRE 171

17
20
e
br
em
pt
se
25
g
Al
T_

F IGURE 7.6 – Fragments de solutions (chaînes) constituant un dictionnaire initial pour


un exemple de problème de voyageur de commerce. Les chaînes sont obtenues en
itérant 100 recherches locales sur des solutions aléatoires et en ne conservant que
les arêtes apparaissant dans plus des 2/3 des optima locaux. Il est intéressant de re-
marquer la grande similarité entre ces fragments et la solution optimale donnée en
figure 4.6.
172 A PPRENDRE À CONSTRUIRE

17
20
e
br
em
pt
se
25
g
Al
T_
Chapitre 8

17
Apprendre à modifier

20
Les recherches locales jouent un rôle central dans les méta-heuristiques.

e
Pratiquement toutes les méthodes heuristiques efficaces incorporent ces tech-
niques. Du reste, les méta-heuristiques sont parfois définies comme un pro-
cessus maître guidant une recherche locale.
br
Dans le chapitre 4, nous avons déjà vu quelques techniques d’adaptation
em
d’un voisinage de base, en particulier sa limitation au moyen de liste de mou-
vements candidats ou la recherche granulaire et son extension par une re-
cherche en éventail ou une chaîne d’éjections. Le chapitre 6 consacré aux
méthodes randomisées présente de nombreuses extensions de recherches lo-
pt

cales n’utilisant aucun processus d’apprentissage, si ce n’est la mémorisation


de la meilleure solution trouvée ou un auto-calibrage des paramètres pour tenir
compte de l’unité de mesure de la fonction-objectif.
se

Le pas suivant dans la sophistication des méta-heuristiques est d’apprendre


à modifier localement des solutions d’un problème. Parmi les techniques po-
pulaires, la recherche avec tabous propose de nombreuses stratégies et en
25

particulier des méthodes d’apprentissage pour une recherche locale.

8.1 Recherche avec tabous


g
Al

Proposée par Fred Glover en 1986, l’idée de base de la recherche avec


tabous est de poursuivre une recherche locale au-delà d’un optimum local tout
en incorporant un mécanisme pour éviter le phénomène de cyclage, soit le fait
T_

de visiter cycliquement un sous-ensemble restreint de solutions. Le concept le


plus simple à imaginer est de mémoriser les solutions qui ont été successive-
ment rencontrées durant une recherche locale utilisant la politique du meilleur
voisin mais d’interdire à cette dernière de choisir une solution voisine qui aurait
déjà été énumérée. Les solutions visitées deviennent donc taboues.
Ce concept est simple, mais peu commode à mettre en œuvre : il faut ima-
giner qu’une recherche locale peut nécessiter des millions d’itérations, ce qui
signifie de mémoriser autant de solutions. Pour chaque solution voisine, il faut
vérifier qu’elle n’a pas été déjà visitée. Sachant qu’un voisinage peut contenir
des milliers de solutions, on se rend rapidement compte que cette voie devient
impraticable, que ce soit en raison de la place mémoire nécessaire à stocker
174 A PPRENDRE À MODIFIER

les solutions visitées ou de l’effort de calcul pour les comparer aux solutions
voisines.

8.1.1 Table de hachage


Pour mettre en œuvre une approximation de ce principe d’interdiction de so-
lutions déjà visitées, une technique simple est d’utiliser une table de hachage.
On associe à chaque solution du problème s une valeur entière h(s). Si on vi-
site la solution si à l’itération i de la recherche, on mémorisera dans un tableau

17
T de m éléments la valeur i dans son entrée h(si ) mod m. Ainsi, la valeur tk
de l’entrée k du tableau T indique à quelle itération une solution dont la valeur
de hachage (modulo m) a été visitée.

20
La fonction h n’est généralement pas bijective sur l’ensemble des solutions
du problème, ce qui fait que plusieurs solutions différentes peuvent avoir la
même valeur de hachage et la taille m du tableau T doit être limitée en rai-
son de la mémoire disponible. Cette technique est donc une approximation du

e
concept d’interdiction de solutions déjà visitées. En effet, non seulement ces

leurs de hachage.
br
dernières sont interdites, mais également toutes celles qui ont les mêmes va-

De plus, comme la valeur de m est limitée, on ne peut interdire ad æter-


em
nam de revenir à une solution de valeur de hachage donnée, car, après m
itération au plus tard, toutes les solutions seraient interdites. Il faut donc mettre
en œuvre une caractéristique-clé du processus d’apprentissage : l’oubli. Ces
considérations amènent donc à introduire le principal paramètre d’une recher-
pt

che avec tabous : la durée des interdiction, parfois appelé longueur de la liste
de tabous.
se

Fonctions de hachage

Le choix d’une fonction de hachage pour implanter une recherche avec ta-
25

bous n’est pas très difficile. Dans certains cas, la valeur de la fonction-objectif
convient parfaitement, notamment lorsque le voisinage comporte de nombreux
mouvements à coût nul. En effet, les modifications neutres rendent l’appren-
tissage difficile, dans la mesure où l’on choisit à chaque itération le meilleur
g

mouvement autorisé du voisinage. Si l’on se trouve sur un plateau, c’est-à-dire


Al

un optimum local avec de nombreux voisins de même coût, le choix de l’un ou


l’autre est difficile et on risque de tourner en rond. Dans le cas où la fonction-
objectif prend un large éventail de valeurs, interdire pendant un certain nombre
T_

d’itérations de revenir à une valeur donnée permet dans bien des cas de casser
la structure d’un optimum local et d’en découvrir un autre.
Une fonction de hachage générale est la suivante : en considérant qu’une
solution est composée d’éléments e ∈ E, pour reprendre la notation introduite
dans le chapitre 3 sur les méthodes constructives, on peut associer à tous les
éléments e des valeurs entières ze . Ces valeurs sont générées aléatoirement
au début Pde l’algorithme. La valeur de hachage d’une solution s est donnée par
h(s) = e∈s ze .
Une technique de hachage plus sophistiquée, utilisant de multiples tables,
est discutée dans [?]. Elle permet d’obtenir l’équivalent d’une table très grande,
tout en limitant l’espace-mémoire.
8.1 R ECHERCHE AVEC TABOUS 175

8.1.2 Interdictions sur les mouvements

L’utilisation d’interdictions basées sur un fonction de hachage calculée sur


les solutions visitées n’est de loin pas la plus courante dans les implantations
de recherches avec tabous. Il est beaucoup plus fréquent d’interdire certains
mouvements. Cette interdiction peut être indirecte : un mouvement pourra être
considéré comme tabou s’il mène à une solution présentant certaines caracté-
ristiques.

17
Pour être concret, prenons l’exemple du voyageur de commerce symé-
trique. Un mouvement 2-opt peut être caractérisé par le couple [i, j] qui con-
siste à remplacer les arêtes [i, si ] et [j, sj ] de la solution courante s par les
arêtes [i, j] et [si , sj ] (on suppose ici que la solution s donne le « successeur »

20
de chaque ville et que la ville j vient « après » la ville i lorsque l’on parcours les
villes dans l’ordre donné par s). Si le mouvement [i, j] est réalisé à une itération,
on peut interdire le mouvement inverse [i, si ] durant les itérations suivantes. Il
s’agit là d’une interdiction directe basée sur l’inverse d’un mouvement.

e
Une autre possibilité est d’interdire de façon indirecte, après avoir effectué

br
le mouvement [i, j], les mouvements qui mèneraient à une solution comportant
à la fois les arêtes [i, si ] et [j, sj ].
em
Par abus de langage, on notera m−1 l’inverse d’un mouvement, ou les ca-
ractéristiques d’une solution que l’on ne voudrait pas retrouver après avoir ef-
fectué le mouvement m d’un voisinage caractérisé par un ensemble M de mou-
vements. Bien que l’on ait (s ⊕ m) ⊕ m−1 = s, il peut y avoir diverses manières
pt

de définir m−1 . La trame de la plus élémentaire des recherche avec tabous est
donnée par l’algorithme 8.1.
se

Algorithme 8.1 : Trame d’une recherche avec tabous élémentaire.


Entrées : Solution s, ensemble M de mouvements applicable à toute
25

solution, fonction-objectif f (·) à minimiser, paramètres Imax , d.


Résultat : Solution s∗ améliorée

1 s ← s pour Imax itérations faire
2 valeur_meilleur_voisin ← ∞;
g

3 pour ∀m ∈ M |m non marqué comme interdit faire


Al

4 si f (s ⊕ m) < valeur_meilleur_voisin alors


5 valeur_meilleur_voisin ← f (s ⊕ m);
6 m∗ ← m
T_

7 si valeur_meilleur_voisin < ∞ alors


8 s ← s ⊕ m∗ ;
9 Marquer (m∗ )−1 comme interdit pour les d prochaines itérations;
10 si f (s) < f (s∗ ) alors
11 s∗ ← s
12 sinon
13 Message d’erreur : d trop grand
176 A PPRENDRE À MODIFIER

It. Var. Solution r v Interdictions


1 s9 (0, 0, 0, 0, 0, 0, 0, 0, 1) 13 14 (0, 0, 0, 0, 0, 0, 0, 0, 4)
2 s1 (1, 0, 0, 0, 0, 0, 0, 0, 1) 25 24 (5, 0, 0, 0, 0, 0, 0, 0, 4)
3 s7 (1, 0, 0, 0, 0, 0, 1, 0, 1) 36 33 (5, 0, 0, 0, 0, 0, 6, 0, 4)
4 s2 (1, 1, 0, 0, 0, 0, 1, 0, 1) 46 45 (5, 7, 0, 0, 0, 0, 6, 0, 4)
5 s9 (1, 1, 0, 0, 0, 0, 1, 0, 0) 33 31 (5, 7, 0, 0, 0, 0, 6, 0, 8)
6 s3 (1, 1, 1, 0, 0, 0, 1, 0, 0) 42 39 (5, 7, 9, 0, 0, 0, 6, 0, 8)
7 s8 (1, 1, 1, 0, 0, 0, 1, 1, 0) 48 45 (5, 7, 9, 0, 0, 0, 6, 10, 8)
8 s2 (1, 0, 1, 0, 0, 0, 1, 1, 0) 38 33 (5, 11, 9, 0, 0, 0, 6, 10, 8)

17
9 s4 (1, 0, 1, 1, 0, 0, 1, 1, 0) 45 40 (5, 11, 9, 12, 0, 0, 6, 10, 8)
10 s5 (1, 0, 1, 1, 1, 0, 1, 1, 0) 49 45 (5, 11, 9, 12, 13, 0, 6, 10, 8)

Tableau 8.1 – Évolution sur 10 itérations d’une recherche avec tabous élémentaire

20
pour le problème du sac de montagne 8.1. La première colonne donne le numéro de
l’itération, la seconde la variable qui est modifiée, la suivante la solution, r donne le
revenu du sac, v le volume occupé et la dernière colonne donne l’état de la liste des
interdictions. Cette recherche interdit de modifier à nouveau une variable pendant 3

e
itérations.

br
Mise en œuvre de l’interdiction sur les mouvements
em
Dans la mesure où la taille du voisinage n’est pas trop importante, il est pos-
sible de mémoriser, pour chaque caractéristique de mouvements, le numéro de
l’itération de la recherche avec tabou à partir de laquelle cette caractéristique
peut à nouveau être utilisée. Donnons tout de suite un petit exemple d’une telle
pt

mise en œuvre sur le problème du sac de montagne à 10 variables suivant :


se

max r = 12s1 + 10s2 + 9s3 + 7s4 + 4s5 + 8s6 + 11s7 + 6s8 + 13s9
sous 10s1 + 12s2 + 8s3 + 7s4 + 5s5 + 13s6 + 9s7 + 6s8 + 14s9 6 45
contraintes si ∈ {0, 1} (i = 1, . . . , 9)
(8.1)
25

Une solution s de ce problème est donc un vecteur 0-1, avec si = 1 si l’objet


i est choisi et si = 0 sinon. Chaque objet occupe une certaine place dans le sac
(mesurée dans une seule dimension, par exemple son volume ou son poids) et
ce dernier dispose globalement d’une place de 45. Un voisinage élémentaire
g

pour ce problème consiste à modifier la valeur d’une seule des variables de s.


Al

Les conditions d’interdictions peuvent être représentées sous la forme d’un


vecteur t d’entiers avec ti donnant le numéro de l’itération à partir de laquelle
la variable si peut à nouveau changer de valeur. On initialise t = 0, ce qui
T_

signifie qu’à la première itération, toutes les variables peuvent être modifiées.
Pour ce petit problème, on va supposer que la durée des interdictions est de
3. La solution initiale peut également être initialisée à s = 0, ce qui constitue la
plus mauvaise des solutions admissibles du problème.
Le tableau 8.1 donne l’évolution d’une recherche avec tabous sur ce petit
exemple de problème. Sans surprise, à la première itération, on insère l’objet
9 avec le revenu le plus élevé. À la fin de l’itération 1, il sera interdit jusqu’à
l’itération t9 = 4 = 1 + 3 de poser à nouveau s9 = 0.
Tant que l’on arrive à insérer des objets dans le sac, la recherche avec
tabous se comporte comme un algorithme constructif glouton et arrive à la
solution localement optimale s = (1, 1, 0, 0, 0, 0, 1, 0, 1) de valeur 46 à l’itéra-
8.1 R ECHERCHE AVEC TABOUS 177

tion 4. À l’itération 5, il faut retirer un objet, car le sac est entièrement plein.
Seul l’objet 9 peut être retiré en raison des conditions tabous. La fonction-
objectif diminue donc de 46 à 33, mais de la place est libérée. À l’itération 6,
le meilleur mouvement consisterait à ajouter l’objet 9, mais ce mouvement est
tabou. Il correspondrait du reste à revenir à la solution visitée à l’itération 4.
Le meilleur mouvement autorisé est donc d’ajouter l’objet 3, puis à l’itération
suivante l’objet 8, menant à un nouvel optimum local s = (1, 1, 1, 0, 0, 0, 1, 1, 0)
de valeur r = 48, avec un sac à nouveau entièrement plein avec v = 45. À
l’itération 8, il faut à nouveau retirer un objet et on pose s2 = 0. La place ainsi

17
libérée permet d’ajouter les objets 4 et 5 ce qui permet d’obtenir une solution
s = (1, 0, 1, 1, 1, 0, 1, 1, 0) encore meilleure que les deux optima locaux précé-
demment obtenus.

20
Dans l’exemple du voyageur de commerce, le type d’interdictions décrites
ci-dessus peuvent être implantées au moyen d’une matrice T dont l’entrée tij
donne l’itération à partir de laquelle on peut à nouveau effectuer un mouvement
qui ferait apparaître l’arête [i, j] dans la solution. Ce principe s’étend à tout

e
problème combinatoire pour lequel on cherche une permutation optimale.

Durée des interdictions


br
em
Dans l’exemple ci-dessus, la durée des interdictions a été choisie à 3 itéra-
tions. Cette valeur peut paraître arbitraire. On peut constater que si l’on sup-
prime les interdictions (durée nulle), la recherche va tourner en rond : une fois
arrivé à un optimum local, on retire un objet que l’on ajoute à nouveau à l’itéra-
pt

tion suivante. Il est clair que la durée maximale des interdictions est limitée par
la taille du voisinage : Pour autant qu’il existe à chaque itération un mouvement
se

menant à une solution admissible, la recherche effectue tout les mouvements


du voisinage puis reste bloquée, puisqu’ils sont alors tous interdits.
Ces deux cas extrêmes, menant à des recherches inefficaces —choisir une
durée nulle des interdictions revient à ne rien apprendre ; choisir une durée très
25

élevée signifie un mauvais apprentissage— montre qu’il faut trouver un bon


compromis pour la durée des interdictions. La figure 8.1 illustre ce phénomène
pour des exemples de problèmes d’affectation quadratique de taille n = 12
avec voisinage basé sur les transpositions.
g

Il faut donc apprendre quelle est cette durée pour l’exemple de problème
Al

traité. [?] ont proposé le mécanisme d’apprentissage, sous l’appellation de


recherche tabou réactive : On mémorise toutes les solutions visitées par la
recherche ; cette mémorisation pouvant être approximative, en utilisant la tech-
T_

nique de hachage présentée en section8.1.1. On part d’une durée d’interdic-


tions faible. Si la recherche visite une nouvelle fois une solution, alors cette
durée est augmentée. Si la recherche ne revisite aucune des solutions durant
un relativement grand nombre d’itérations, alors la durée des interdictions est
diminuée.
Cette dernière condition peut paraître étrange : Pourquoi vouloir forcer la
recherche à revenir à des solutions déjà explorées ? L’explication est la sui-
vante : si la durée des interdictions est suffisante pour éviter tout phénomène
de cyclage, cela signifie également que l’on s’interdit de visiter certaines solu-
tions de bonne qualité en raison du statut tabou des mouvements. On risque
alors de manquer des solutions dont la qualité est meilleure que celle que la
178 A PPRENDRE À MODIFIER

Valeur des solutions


2675

2650

2625 Moyenne de toutes les solutions visitées

2600 Moyenne de la meilleure solution trouvée

17
2575

20
2550
0 5 10 15 20 25 30 35 40 45 50
Durée des interdictions

e
F IGURE 8.1 – Influence de la durée des interdictions d’une recherche avec tabous ap-

br
pliquée au problème de l’affectation quadratique où il faut trouver une permutation de
coût aussi faible que possible. Une faible durée permet de visiter en moyenne des solu-
tions de meilleure qualité, mais la recherche n’arrive pas à s’échapper d’optima locaux,
em
ce qui fait que la qualité de la meilleure solution trouvée n’est pas très bonne. Inver-
sement, si la durée des interdictions est très élevée, la qualité moyenne des solutions
visitée diminue, de même que celle des meilleures solutions trouvées. Dans ce cas, un
bon compromis semble être une durée d’interdictions comprise entre 15 et 20, soit un
pt

peu plus grand que la taille des problèmes traités (ou de la racine carrée de la taille du
voisinage).
se

recherche a été capable de découvrir. Il faut donc trouver une durée d’interdic-
tions suffisamment grande pour ne pas cycler, mais aussi faible que possible
25

pour ne pas s’interdire de bons mouvements. C’est précisément ce que fait la


recherche tabou réactive.
Cependant, cette technique d’apprentissage ne fait que repousser le pro-
blème : en effet, son utilisateur doit trouver un autre paramètre qui est le nom-
g

bre d’itérations sans nouvelle visite déclenchant la diminution de la durée des


Al

interdictions. De plus, elle nécessite la mise en place d’un mécanisme de mé-


morisation de toutes les solutions visitées, qui peut être très lourd à implanter.
Une autre technique permettant de choisir des durées d’interdictions faibles
T_

tout en évitant fortement le phénomène de cyclage est de choisir aléatoirement


cette durée à chaque itération. Une méthode très simple à mettre en œuvre est
de tirer la durée des interdiction aléatoirement entre une durée minimale dmin
et une durée maximale dmax = dmin +∆. Pour réaliser la figure 8.2, on a résolu
500 exemples de problèmes d’affectation quadratique de taille n = 12 dont ont
connaît les solutions optimales. Pour chacun de ces problèmes on a exécuté
des recherches avec tabous avec un grand nombre d’itérations (pour des pro-
blèmes d’aussi petite taille) avec tous les paramètres possibles pour dmin et
∆). On a ensuite comptabilisé le nombre de solutions optimales trouvées pour
chaque paramétrage, et, si la recherche a été capable de trouver l’ensemble
des 500 solutions optimale, le nombre moyen d’itérations nécessaires pour at-
8.1 R ECHERCHE AVEC TABOUS 179

25

20

15

17
10

20
5

e
0
0 5 10 15 20
br
25 30 35 40
dmin
em
F IGURE 8.2 – Technique du choix aléatoire de la durée des interdictions entre dmin et
dmin +∆ à chaque itération. Un cercle vide indique que la recherche avec tabou n’a pas
été en mesure de trouver systématiquement l’optimum de 500 exemples de problèmes
d’affectation quadratique. La dimension du cercle est proportionnelle au nombre d’op-
pt

tima trouvés. Un disque rempli indique que l’optimum a été systématiquement trouvé.
La dimension du disque est proportionnelle au nombre moyen d’itérations qu’il a fallu
se

effectuer avant d’obtenir l’optimum.


25

teindre l’optimum.
On remarque qu’avec une durée non aléatoire des interdictions (∆ = 0), il
n’a jamais été possible de trouver toutes les solutions optimales, même avec
des durées relativement importantes. Inversement, on remarque qu’avec des
g

durées minimales faibles et une variation aléatoire de l’ordre de grandeur de la


taille du problème, on obtient l’optimum de façon très systématique, en relati-
Al

vement peu d’itérations.


La figure 8.3 donne la qualité de la solution obtenue pour un petit problème
T_

de voyageur de commerce pour tout couple (dmin , ∆). On remarque des si-
militudes avec la figure 8.2 ; dans ce cas il semble également qu’une durée
d’interdiction aléatoire mais proportionnelle à la taille du problème soit un bon
compromis.

Condition d’aspiration

L’interdiction inconditionnelle d’un mouvement dans une recherche tabou


élémentaire est que l’on pourrait passer à côté d’une amélioration de la
meilleure solution trouvée. Ainsi, à la ligne 3 de la trame 8.1, on testera si
le mouvement m permet d’aboutir à une solution meilleure que s∗ , auquel cas
180 A PPRENDRE À MODIFIER


2n

3n
2 Qualité
+4%

17
+3%
n +2%

20
+1%
Optimum
n
2

e
0 br dmin
em
0 n 3n
2 n 2 2n

F IGURE 8.3 – Qualité des solutions obtenues avec une recherche tabou où la durée
des interdictions est choisie aléatoirement entre dmin et dmin + ∆ pour un problème de
pt

voyageur de commerce à n = 52 villes. La méthode effectue 10n itérations en partant


d’une solution construite de manière déterministe avec une méthode gloutonne d’inser-
tion. Pour chaque couple (dmin , ∆) variant entre 0 et 2n on a lancé une recherche et
se

représenté la qualité de la solution trouvée par une couleur.


25

il sera retenu. Dans la littérature, ceci est appelé une condition d’aspiration.
Il est possible de définir d’autres conditions d’aspiration moins triviales, no-
tamment pour mettre en œuvre une mémoire à long terme.
g

8.2 Oscillations stratégiques


Al

Le mécanisme d’interdiction de mouvements récemment effectués implante


T_

une mémoire à court terme qui peut se révéler très efficace pour des problèmes
de taille modérée. Par contre, dès que l’on s’attaque à des problèmes plus
difficiles, ce seul mécanisme n’est pas suffisant. Une stratégie de recherche
qui a été proposée dans le cadre de la recherche avec tabous est d’alterner
des phases d’intensification et de diversification. Le but de l’intensification est
d’examiner en profondeur une portion limitée de l’espace de recherche, en
conservant des solutions qui ont une structure globalement similaire. Une fois
que l’on pense avoir exploré toutes les solutions intéressantes de cette portion,
il faut aller voir ailleurs. En d’autres termes, on diversifie la recherche en brisant
la structure de la solution sur laquelle on travaille.
L’intensification de la recherche peut être faite à l’aide du simple mécanisme
8.2 O SCILLATIONS STRATÉGIQUES 181

d’interdiction de mouvements vu plus haut, en ayant une durée d’interdiction


faible. Implanter un mécanisme de diversification suppose de disposer d’une
mémoire à long terme. Plusieurs techniques ont été proposé pour réaliser cela.

8.2.1 Mémoire à long terme


Mouvements forcés
La manière la plus sûre et la plus simple à mettre en œuvre pour casser

17
la structure d’une solution est d’effectuer des modifications qui n’ont jamais
été retenues durant de nombreuses itérations. Si l’on dispose d’une recherche
avec tabous de base, où l’on a mémorisé pour chaque mouvement l’itération
à partir de laquelle il peut à nouveau être effectué, la mise en œuvre de cette

20
forme de mémoire à long terme est pratiquement gratuite : en effet si le nu-
méro d’itération mémorisé pour un mouvement est bien plus petit que celui
de l’itération courante, c’est que le mouvement en question n’a pas été effec-

e
tué pendant longtemps. On peut ainsi forcer l’utilisation de cette modification,
quelle que soit la qualité de la solution vers laquelle elle conduit.

br
Ce mécanisme requiert un nouveau paramètre, K représentant le nombre
d’itérations à partir duquel un mouvement jamais choisi sera forcé. Naturel-
lement, ce paramètre doit être plus grand que la taille du voisinage, sinon la
em
recherche dégénérera en n’effectuant plus que des mouvements forcés. Cet
type de mémoire à long terme est une autre forme de mise en œuvre des
conditions d’aspiration que l’on a introduite dans la section précédente.
pt

Pénalité sur les mouvements


se

Un des défaut de la recherche avec tabous dotée d’une mémoire à très


court terme est de n’effectuer que des modifications de faible amplitude. Pour
illustrer ce propos sur le problème du voyageur de commerce, une telle recher-
che va « tricoter » un petit nœud sur une tournée qui était localement optimale,
25

puis un autre ailleurs et ainsi de suite jusqu’à ce qu’il soit à nouveau autorisé
de défaire le premier nœud.
Pour éviter ce comportement, il faut mémoriser le nombre de fois fm qu’un
mouvement m a été choisi et en limiter son usage. Un mécanisme est de pé-
g

naliser m proportionnellement à fm lors de l’évaluation du mouvement. Le fac-


Al

teur de proportionnalité F constituant un paramètre de la technique qu’il faudra


ajuster. Naturellement, on utilisera une condition d’aspiration du mouvement en
conjonction avec ce mécanisme, pour pouvoir tout de même choisir une modi-
T_

fication fortement pénalisée mais qui mène à une amélioration de la meilleure


solution connue.
La figure 8.4 illustre l’amélioration de la qualité d’une recherche avec tabou
effectuant 10n itérations sur un problème de voyageur de commerce de n = 52
villes lorsque l’on introduit le mécanisme de pénalisation sur la fréquence d’uti-
lisation des mouvements. On remarque dans cette figure que la durée des in-
terdictions des mouvements peut être réduite et que l’on obtient plus fréquem-
ment de bonnes solutions. Ce mécanisme pourrait même être utilisé seul, sans
liste d’interdiction. En effet, on remarque dans cette figure qu’une bonne solu-
tion a pu être obtenue avec une durée minimale et maximale des interdictions
de 0. Le code 8.1 illustre comment une liste d’interdictions et un comptage de
182 A PPRENDRE À MODIFIER


2n

3n
2 Qualité
+4%

17
+3%
n +2%

20
+1%
Optimum
n
2

e
0 br dmin
em
0 n 3n
2 n 2 2n

F IGURE 8.4 – Même diagramme que pour la figure 8.3, mais la recherche avec tabous
a été dotée du mécanisme de mémoire à long terme de pénalisation des mouvements
pt

fréquemment effectués. La pénalité appliquée à un mouvement qui cherche à introduire


une nouvelle fois un arête e qui l’a déjà été ne fois durant la recherche est de F · ne ,
où F est égal à la longueur moyenne d’une arête de la tournée divisée par la taille du
se

problème.
25

chaque mouvement peut être implanté. Ici, la liste des interdictions est une
matrice dont l’entrée (i, j) donne le numéro de l’itération à partir de laquelle
on peut à nouveau utiliser l’arête [i, j] dans un mouvement. Le comptage des
mouvements est implanté de façon similaire. Le code 8.1 donne la procédure
g

permettant d’effectuer un mouvement et de mettre à jour la liste d’interdiction


et la fréquence d’utilisation des mouvements.
Al
T_
8.2 O SCILLATIONS STRATÉGIQUES 183

Listing 8.1 – perform_move_update.c Réalisation d’un mouvement 2-opt pour le pro-


blème du voyageur de commerce avec mise à jour de la liste des interdictions et du
comptage du nombre de fois qu’un trajet est impliqué dans la modification de la solu-
tion.
v o i d perform_move_update ( i n t n ,
double ∗∗d ,
int i , int j ,
i n t tabu_duration ,
i n t sol [ ] ,
double ∗ l e n g t h ,
i n t ∗∗ t a b u _ l i s t ,
i n t ∗∗ f r e q u e n c y )

17
{ / ∗ F o r b i d t o use again edges ( i , i +1) and ( j , j +1) ∗ /
t a b u _ l i s t [ s o l [ i ] ] [ s o l [ i + 1 ] ] = t a b u _ l i s t [ s o l [ j ] ] [ s o l [ ( j +1)%n ] ] =
t a b u _ l i s t [ s o l [ i + 1 ] ] [ s o l [ i ] ] = t a b u _ l i s t [ s o l [ ( j +1)%n ] ] [ s o l [ j ] ]
= tabu_duration ;

20
frequency [ s o l [ i ] ] [ sol [ j ]]++;
frequency [ s o l [ j ] ] [ sol [ i ]]++;
frequency [ s o l [ i + 1 ] ] [ s o l [ ( j +1)%n ] ] + + ;
frequency [ s o l [ ( j +1)%n ] ] [ s o l [ i + 1 ] ] + + ;

/ ∗ Update s o l u t i o n c o s t ∗ /

e
∗length = ∗length + d [ sol [ i ] ] [ sol [ j ] ] + d [ s o l [ i + 1 ] ] [ s o l [ ( j +1)%n ] ]
− d [ s o l [ i ] ] [ s o l [ i + 1 ] ] − d [ s o l [ j ] ] [ s o l [ ( j +1)%n ] ] ;

}
f o r ( i n t r = 0 ; r < ( j −i ) / 2 ; r ++)
swap(& s o l [ r + i + 1 ] , &s o l [ j −r ] ) ;
br
/ ∗ Reverse path from i + 1 t o j ∗ /
em
Le code 8.2 donne une implantation d’une recherche avec tabous pour le
problème du voyageur de commerce basé sur un voisinage de type 2-opt. Deux
types de mémoires sont utilisées : une mémoire classique à court terme qui
pt

empêche d’effectuer un mouvement qui réintroduirait dans la solution deux


arêtes qui en ont été retirées récemment et une mémoire à long terme qui
compte le nombre de fois que chaque arête a été insérée dans la solution.
se

L’évaluation des mouvements est pénalisée proportionnellement au nombre


de fois que les arêtes que l’on veut introduire dans la solution l’ont déjà été.
Une modification est interdite si les deux arêtes qu’elle veut incorporer ont été
25

récemment retirées de la solution (mais pas forcément à la même itération).


Finalement, une modification est aspirée si elle améliore la meilleure solution
trouvée jusque là.
g
Al
T_
184 A PPRENDRE À MODIFIER

Listing 8.2 – tsp_TS.c Implantation d’une recherche avec tabous pour le problème du
voyageur de commerce.
v o i d tsp_TS ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , / ∗ D i s t a n c e m a t r i x , must be s y m m e t r i c a l ∗/
i n t best_sol [ ] , / ∗ InOut S o l u t i o n p r o v i d e d and r e t u r n e d ∗/
double ∗ b e s t _ c o s t , / ∗ InOut Length o f t h e b e s t t o u r ∗/
int iterations , / ∗ Number o f TS i t e r a t i o n s ∗/
i n t min_tabu_duration , / ∗ Minimal f o r b i d d e n d u r a t i o n ∗/
i n t max_tabu_duration ,
double F )
{ int i , j , /∗ Indices ∗/
nr_iteration , /∗ I t e r a t i o n counter ∗/
i_kept , j_kept ; / ∗ Move t o perform ∗/

17
double d e l t a , / ∗ Cost o f c u r r e n t move ∗/
delta_penalty , / ∗ Cost o f move k e p t w i t h p e n a l t y ∗/
length = ∗best_cost ; / ∗ Length o f c u r r e n t s o l u t i o n ∗/
i n t ∗ s o l = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ; /∗ Current s o l u t i o n ∗/

20
i n t ∗∗ t a b u _ l i s t ; / ∗ I t e r a t i o n from which an a r c can be moved again ∗/
i n t ∗∗ f r e q u e n c y ;
double p e n a l t y ;

f o r ( i = 0 ; i < n ; i ++) s o l [ i ] = b e s t _ s o l [ i ] ;

e
/ ∗ I n i t i a l i z a t i o n o f tabu l i s t : any move i n i t i a l l y allowed ∗/
t a b u _ l i s t = ( i n t ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ∗));
f o r ( i = 0 ; i < n ; i ++)

f o r ( i = 0 ; i < n ; i ++)
br
t a b u _ l i s t [ i ] = ( i n t ∗) c a l l o c ( ( s i z e _ t ) n , s i z e o f (
f r e q u e n c y = ( i n t ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t

f r e q u e n c y [ i ] = ( i n t ∗) c a l l o c ( ( s i z e _ t ) n , s i z e o f (
int ));
∗));

int ));
em
/ ∗ Main tabu search l o o p ∗ /
f o r ( n r _ i t e r a t i o n = 1 ; n r _ i t e r a t i o n <= i t e r a t i o n s ; n r _ i t e r a t i o n ++)
{ delta_penalty = i n f i n i t e ;
i _ k e p t = j _ k e p t = −1; / ∗ Dummy v a l u e t o a v o i d c o m p i l e r warnings ∗ /
pt

/ ∗ ∗∗∗∗∗∗ Find b e s t move a l l o w e d ∗∗∗∗∗∗ ∗ /


f o r ( i = 0 ; i < n−2; i ++)
{ f o r ( j = i +2; ( j < n ) && ( i > 0 | | j < n−1); j ++)
se

{ delta = d [ sol [ i ] ] [ sol [ j ] ] + d [ s o l [ i + 1 ] ] [ s o l [ ( j +1)%n ] ]


− d [ s o l [ i ] ] [ s o l [ i + 1 ] ] − d [ s o l [ j ] ] [ s o l [ ( j +1)%n ] ] ;
p e n a l t y = F∗( f r e q u e n c y [ s o l [ i ] ] [ s o l [ j ] ] +
f r e q u e n c y [ s o l [ i + 1 ] ] [ s o l [ ( j +1)%n ] ] ) ;
i f ( ( d e l t a + p e n a l t y < d e l t a _ p e n a l t y ) && / ∗ A b e t t e r move i s found ∗ /
( t a b u _ l i s t [ s o l [ i ] ] [ s o l [ j ] ] <= n r _ i t e r a t i o n | | / ∗ Allowed ? ∗ /
25

t a b u _ l i s t [ s o l [ i + 1 ] ] [ s o l [ ( j +1)%n ] ] <= n r _ i t e r a t i o n | |
length + delta < ∗best_cost − epsilon ) ) /∗ Aspirated ? ∗/
{ delta_penalty = delta + penalty ;
i_kept = i ; j_kept = j ;
}
} ; /∗ f o r j ∗/
g

} ; /∗ f o r i ∗/
Al

/ ∗ ∗∗∗∗∗ Perform b e s t move ∗∗∗∗∗∗ ∗ /


i f ( delta_penalty < i n f i n i t e )
perform_move_update ( n , d , i _ k e p t , j _ k e p t ,
u n i f ( m i n _ t a b u _ d u r a t i o n , max_tabu_duration ) + n r _ i t e r a t i o n ,
T_

s o l , &l e n g t h , t a b u _ l i s t , f r e q u e n c y ) ;
else
p r i n t f ( " A l l moves are f o r b i d d e n : tabu l i s t t o o l o n g \ n " ) ;

i f ( length < ∗best_cost − epsilon ) / ∗ S t o r e b e s t s o l u t i o n i f improved ∗ /


{ ∗best_cost = length ;
f o r ( i = 0 ; i < n ; i ++) b e s t _ s o l [ i ] = s o l [ i ] ;
p r i n t f ( "TS %d %f \ n " , n r _ i t e r a t i o n , l e n g t h ) ;
}
} ; /∗ f o r n r _ i t e r a t i o n ∗/

f o r ( i = 0 ; i < n ; i ++) f r e e ( f r e q u e n c y [ i ] ) ;
f r e e ( frequency ) ;
f o r ( i = 0 ; i < n ; i ++) f r e e ( t a b u _ l i s t [ i ] ) ;
free ( tabu_list ) ; free ( sol ) ;
} / ∗ tsp_TS ∗ /
8.2 O SCILLATIONS STRATÉGIQUES 185

Redéparts
Une technique fréquemment employée pour intensifier une recherche avec
tabous est de repartir avec la meilleure solution trouvée jusque là si la re-
cherche semble stagner, par exemple s’il n’y a pas eu d’amélioration de cette
meilleures solution durant un relativement grand nombre d’itération. Afin de ne
pas perdre tout le travail fait depuis la dernière amélioration de la meilleure
solution, le redépart se fait en conservant les informations collectées durant
ces itérations, notamment la liste des interdictions et les statistiques sur les
fréquences d’utilisation des mouvement, si ce mécanisme a été utilisé.

17
Ainsi, les structures de données guidant la recherche étant dans un état
différent après redémarrage, la trajectoire suivie par la recherche le sera éga-
lement. Ce mécanisme peut être vu comme l’opposé de celui présenté plus

20
haut où l’on force l’utilisation d’attribut négligés pendant de nombreuses itéra-
tions. Son but est de réaliser une intensification de la recherche et non une
diversification. Naturellement, l’implantation de ce mécanisme implique l’intro-
duction de nouveaux paramètres qu’il faut ajuster, tel que le nombre d’itérations

e
à effectuer avant un redépart et une éventuelle adaptation de la valeur d’autres

br
paramètres (durée des interdictions, pénalité sur la fréquence) pour inciter la
recherche à suivre des trajectoires diversifiées.
em
pt
se
25
g
Al
T_
186 A PPRENDRE À MODIFIER

Exercices
Exercice 8.1. Recherche tabou pour une fonction explicite Une fonction
entière [−7, −6] × [6, 7] → [−10, 650] est donnée explicitement dans le tableau
suivant :
x
y -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6
-6 248 216 210 222 230 234 256 304 336 372 428 495 585 650
-5 193 175 157 166 174 181 215 249 295 329 382 454 539 597
-4 138 144 126 116 124 150 184 194 250 305 361 425 480 566
-3 123 89 85 97 105 109 129 179 209 246 302 368 458 525

17
-2 92 58 70 70 78 94 98 148 168 223 282 339 413 510
-1 68 34 46 46 54 70 74 124 144 199 258 315 388 486
0 51 17 14 25 33 38 57 107 136 174 230 296 386 454
1 18 25 5 -4 3 29 65 74 131 185 240 305 361 445
2 27 6 -10 0 8 13 46 83 126 160 213 284 371 429

20
3 33 0 -3 7 15 20 39 89 118 156 212 278 368 436
4 33 12 -4 6 14 19 52 89 132 166 219 290 377 435
5 30 37 17 7 15 41 77 86 143 197 252 317 373 457
6 69 35 32 43 51 56 75 125 154 192 248 314 404 472
7 92 58 70 70 78 94 98 148 168 223 282 339 412 510
Pour trouver le minimum de cette fonction, on considère une recherche avec

e
tabous basée sur le voisinage où l’on modifie d’une unité la valeur d’une va-

br
riable. Les conditions tabous consistent à interdire pendant d itérations d’incré-
menter (respectivement : de décrémenter) une variable qui a été décrémentée
(respectivement : incrémentée). Considérer tout d’abord une durée d’interdic-
em
tions de d = 3 et (−7, 7) comme solution de départ. Ensuite, partir de (−7, −6)
et utiliser t = 1. La recherche s’arrête s’il n’y a plus de mouvement autorisé ou
si 25 itérations ont été effectuées.
pt

Exercice 8.2. Recherche tabou pour tournée de véhicules Pour un pro-


blème d’élaboration de tournées de véhicules, on utilise un voisinage qui con-
siste soit à déplacer un client d’une tournée dans une autre, soit à échanger
se

deux clients appartenant à des tournées différentes. Proposer des critères ta-
bous pour ce voisinage.
Exercice 8.3. Application de recherche avec tabous au QAP Soit l’exemple
25

de QAP donné par la matrice de flots F et de distance D :


   
0 1 1 2 3 0 5 2 4 1
1 0 2 1 2 5 0 3 0 2
g

   
F = 1 2 0 1 2
  D= 2 3 0 0 0

2 1 1 0 1 4 0 0 0 5
Al

3 2 2 1 0 1 2 0 5 0
T_

En commençant avec la solution p = (2, 4, 1, 5, 3), effectuer 6 itérations de


recherche avec tabous avec une durée d’interdiction d = 6. À chaque itération,
donner la solution, sa valeur, celle de tous les mouvements ainsi que leur statut
tabou
Chapitre 9

17
Apprendre par les solutions

20
Avec une modélisation adéquate d’un problème d’optimisation, il est très

e
facile de construire de nombreuses solutions différentes notamment au moyen
de méthodes randomisées. Dès lors, on peut chercher à apprendre à élabo-

br
rer de nouvelles solutions à partir celles précédemment construites. Dans ce
chapitre, nous allons donc étudier comment exploiter une population de so-
lutions, ce qui nous amènera à rassembler dans une méthode de résolution
em
les diverses briques des méta-heuristiques étudiées plus haut (construction et
améliorations de solutions).
pt

9.1 Trame des algorithmes évolutionnaires


se

L’intuition à la source des algorithmes évolutionnaires vient des travaux de


biologistes du XIXe siècle, tels que Darwin et Mendel à la base de la théorie de
l’évolution des espèces vivantes. En effet, au cours des générations, un être
vivant est capable de s’adapter à des conditions extérieures en changement
25

permanent. Cela signifie que les êtres vivants peuvent optimiser leur chances
de survie, donc de résoudre des problèmes d’une extrême complexité. Dès
lors, pourquoi ne pas tenter de reproduire artificiellement cette évolution pour
résoudre des problèmes d’optimisation combinatoire.
g

Dans les années 1960-1970, différentes variantes d’exploitation de ces


Al

idées ont vu le jour. La trame générale des algorithmes évolutionnaires est


donnée par l’algorithme 9.1. On commence par générer un ensemble de µ so-
lutions au problème, généralement de façon purement aléatoire. Cet ensemble
T_

de solutions est appelé population par analogie à un groupe d’êtres vivants. De


même, une solution du problème est un individu.
Les algorithmes évolutionnaires répètent les opérations suivantes en boucle
(appelée boucle générationnelle), jusqu’à ce qu’un critère d’arrêt soit satisfait.
Ce dernier est soit fixé d’avance, par exemple le nombre de fois que la boucle
générationnelle est répétée, soit décidé sur la base de la diversité des individus
présents dans la population.
Tout d’abord, on sélectionne un certain nombre de solutions de la popula-
tion qui seront utilisés pour la reproduction. Ceci est réalisé par un opérateur
de sélection pour la reproduction. Le but de cet opérateur est de favoriser les
individus bien adaptés à leur environnement (ceux dont la fonction-objectif est
188 A PPRENDRE PAR LES SOLUTIONS

Population

Sélection pour la survie Sélection pour la reproduction

17
20
Évaluation

e
Mutation Croisement

br
F IGURE 9.1 – Boucle générationnelle dans un algorithme évolutionnaire. À partir d’une
em
population de solutions, symbolisées ici par des bâtonnets de couleur, on sélectionne
des individus qui vont se reproduire par croisement et mutation. Les solutions-filles
ainsi générées sont évaluées et incorporées à la population. Finalement, des individus
de cette dernière sont éliminés par un opérateur de sélection pour la survie afin de
pt

ramener la population à sa taille d’origine.


se
25
g

Algorithme 9.1 : Trame d’un algorithme évolutionnaire.


Al

Résultat : Meilleure solution trouvée


1 Générer une population P de µ solutions;
T_

2 répéter
3 Sélectionner des individus de P pour la reproduction;
4 Combiner ces individus et leur faire subir des mutations pour obtenir
λ nouvelle solutions;
5 Sélectionner µ individus pour la survie, parmi les µ + λ ; ces µ
individus formeront la population P de la prochaine génération
6 jusqu’à ce qu’un critère d’arrêt soit satisfait;
9.2 A LGORITHMES GÉNÉTIQUES 189

la meilleure) au détriment de ceux qui sont plus faibles, malades, mal adaptés,
à l’image de ce qui se passe dans la nature.
Les individus sélectionnés sont ensuite mélangés entre eux (par exemple
par paire) à l’aide d’un opérateur de croisement pour former λ nouvelles so-
lutions appelées solutions-enfants qui subissent au passage des modifications
aléatoires au moyen d’un opérateur de mutation. Ces deux opérateurs simulent
la reproduction sexuée des espèces vivantes, en faisant l’hypothèse qu’avec
un peu de chance les bonnes caractéristiques (les bons gènes contenus dans
l’ADN) des solutions-parents seront transmises à leurs enfants et que les mu-

17
tations aléatoires feront apparaître de nouveaux gènes favorables.
Finalement, les nouvelles solutions sont évaluées et un opérateur de sé-
lection pour la survie élimine λ solutions parmi les µ + λ disponible pour se

20
ramener à une nouvelle population de µ individus. La figure 9.1 illustre le pro-
cessus d’une boucle générationnelle.
La trame des algorithmes évolutionnaires laisse une grande liberté dans
les choix à opérer pour l’implantation des divers opérateurs et paramètres. Par

e
exemple [?] dans sa « stratégie d’évolution » n’utilise pas d’opérateur de croise-
ment entre deux solutions. Dans cette technique, les solutions de la population

br
sont modifiées avec un opérateur de mutation et entrent en compétition les
unes avec les autres, à l’instar de la reproduction parthénogénétique.
em
9.2 Algorithmes génétiques
pt

Parmi les algorithmes évolutionnaires, c’est sans conteste les algorithmes


génétiques proposés par [?] qui ont reçu le plus d’attention, ce qui peut paraître
se

paradoxal, puisque dans cette référence, le cœur de l’étude portait sur la com-
préhension des mécanismes de convergence de ces algorithmes, et non sur
leur capacité à optimiser des problèmes difficiles. Pendant longtemps, la com-
munauté gravitant dans ce domaine a continué à travailler sur la théorie de
25

la convergence des algorithmes génétiques, en étudiant des version « ortho-


doxes » des divers opérateurs mentionnés plus haut, en conjonction avec une
représentation standard des solutions sous la forme de vecteurs de booléens
de taille donnée.
g

Malheureusement, tous les problèmes d’optimisation n’ont pas des solu-


tions pouvant se représenter naturellement par des vecteurs binaires. Ayant
Al

à disposition des opérateurs standards et connaissant leurs propriétés théo-


riques, de gros efforts ont été dépensés pour trouver de bons codages des
T_

solutions sous forme de vecteurs binaires et de décodage de ces derniers vers


des solutions réalisables.
Dans cette section, nous allons passer en revue les principaux opérateurs
des algorithmes génétiques, en discutant au passage leur généralisation pour
qu’ils s’appliquent également à une représentation naturelle de solutions et non
seulement à des vecteurs binaires.

9.2.1 Opérateurs de sélection pour la reproduction


La sélection pour la reproduction a pour but de favoriser les meilleures so-
lutions, pour qu’elles puissent transmettre leur bonnes propriétés à leur des-
190 A PPRENDRE PAR LES SOLUTIONS

cendance. Il faut donc attribuer à chaque solution i une mesure de qualité fi ;


plus cette dernière est élevée, plus la probabilité de sélection doit être haute.
Si l’objectif du problème à résoudre est de maximiser une fonction prenant des
valeurs positives, cette fonction peut directement être utilisée comme mesure
de qualité. Sinon, il faut procéder à une transformation de la fonction-objectif
pour obtenir la mesure de qualité de chaque individu. Une transformation cou-
rante, ne nécessitant pas le calcul d’une fonction-objectif mais seulement la
possibilité de comparer la qualité des individus et de les trier. Le meilleur in-
dividu d’une population aura un rang de 1 et le plus mauvais de µ. Le iième

17
individu aura une mesure de qualité fi = (1 − rµi )p , où p > 0 est un paramètre
permettant de moduler la pression sélective. Une pression p = 0 implique un
tirage uniforme parmi la population (pas de pression sélective) alors que p = 2

20
représente une assez forte pression. Le code 9.1 donne une implantation de
cet opérateur pour une pression sélective p = 1.
Listing 9.1 – rank_based_selection.c Implantation d’un opérateur de sélection pour
la reproduction basé sur le rang, avec une pression sélective p = 1. Le meilleur des µ

e
individus a une probabilité de 2µ/(µ · (µ + 1))) d’être choisi, alors que le plus mauvais
a une probabilité de 2/(µ · (µ + 1))).

br
i n t r a n k _ b a s e d _ s e l e c t i o n ( i n t mu)
{ r e t u r n mu − ( i n t ) c e i l ( s q r t ( 0 . 2 5 + 2∗ u n i f ( 1 , mu∗(mu+ 1 ) / 2 ) ) − 0 . 5 ) ; }
em
Sélection proportionnelle
L’opérateur de sélection le plus simple est de tirer aléatoirement un individu
pt

proportionnellement
P à sa mesure de qualité. L’individu i aura donc une proba-
bilité fi / fi d’être choisi. En principe, on ne sélectionne pas qu’un individu à
se

chaque boucle générationnelle, mais plusieurs. La sélection se fait en général


avec remise, ce qui fait qu’un (bon) individu peut être choisi plusieurs fois dans
une génération.
Les algorithmes génétiques sont intrinsèquement parallèles : la boucle gé-
25

nérationnelle peut s’appliquer aussi bien à la production d’un seul individu


à chaque génération, comme représentée en figure 9.1, qu’à la génération
d’une multitude de solutions-enfants. Une technique fréquemment utilisée est
de sélectionner un nombre pair λ de solutions-parents à une génération, de
g

les apparier, chaque couple produisant deux solutions-enfants par croisement-


Al

mutation.
T_

Sélection naturelle
Il est également envisageable de procéder à une sélection totalement aléa-
toire et uniforme pour la reproduction, à l’image de ce qui se passe pour les
êtres vivants. La convergence de l’algorithme doit alors être guidée par l’opé-
rateur de sélection pour la survie, qui assure un biais vers les meilleures indi-
vidus.

Sélection complète
Si l’on ne choisit pas une taille de population trop grande, il est également
possible de faire participer tous les individus, de manière systématique, pour
9.2 A LGORITHMES GÉNÉTIQUES 191

17
20
e
F IGURE 9.2 – Reproduction de coccinelles. On peut imaginer que les couples du haut
vont produire des enfants très semblables à eux-mêmes, alors que ceux du bas vont

br
conserver une certaine diversité génétique dans la population, et, avec un peu de
chance, produire quelques enfants nettement mieux adaptés qu’eux à leur environne-
ment.
em
la reproduction. Comme pour la sélection naturelle, l’évolution de la popula-
tion vers de bonnes solutions dépend alors de l’opérateur de sélection pour la
pt

survie, qui doit, lui, favoriser les meilleures solutions.


se

9.2.2 Opérateurs de croisement


Un opérateur de croisement a pour but de simuler la reproduction sexuée
des espèces vivantes. Schématiquement, lors d’une reproduction sexuée,
25

l’ADN de chaque parent se sépare en deux chaînes de gènes durant le pro-


cessus de méiose, afin de produire des gamètes (contenus dans les œufs non
fécondés, les spermatozoïdes ou les grains de pollen). Lors de la fécondation
de l’œuf, se produit un brassage génétique, durant lequel la chaîne de gènes
g

de l’enfant se constitue en apondant les gènes de l’un ou l’autre parent de


Al

façon aléatoire.
Le but de cet opérateur est de créer un nouvel individu, différent de ses pa-
rents, mais ayant hérité de certaines de ses caractéristiques. Avec un peu de
T_

chance, l’enfant combinera de bonnes caractéristiques de ses parents et sera


mieux adapté qu’eux à son environnement. Avec un peu moins de chance,
l’enfant ne combinera pas que des bonnes caractéristiques, mais perpétuera
des gènes toutefois importants à conserver à l’intérieur de la population, car
source de diversité et donc d’innovation potentielle. Ceci est imagé par la fi-
gure 9.2 où l’on a photographié la reproduction de différentes coccinelles. Les
couples en haut vont vraisemblablement produire des enfant très similaires à
eux-mêmes alors que les couples du bas de la figure vont produire des enfant
génétiquement plus riches.
Il faut noter que dans certaines stratégies, l’opérateur de croisement est
absent. Ces stratégies imitent la reproduction asexuée, où un individu crée un
192 A PPRENDRE PAR LES SOLUTIONS

Parent 1
A C A G T T T G G C A G
Parent 2
C A T G C T G A G T C G

Enfant 1
C A A G T T G A G C C G
Enfant 2

17
A C T G C T T G G T A G

F IGURE 9.3 – Croisement uniforme. Production de deux enfants complémentaires re-


lativement à la provenance des gènes de deux parents. Chaque élément du premier

20
enfant est tiré aléatoirement du premier ou du second parent, le deuxième enfant rece-
vant l’élément complémentaire.

e
ou plusieurs enfants presque identique à lui-même, où seules des mutations

br
spontanées font évoluer le patrimoine génétique de la population.
em
Croisement uniforme

Le croisement uniforme consiste à prendre deux solutions-parents, repré-


pt

sentées sous la forme de vecteurs à n éléments et à en créer un troisième de


même longueur en choisissant aléatoirement ses composantes parmi l’un ou
l’autre des parents.
se

La figure 9.3 illustre la production de deux enfants « anti-jumeaux » à partir


de deux parents. Cette procédure de croisement convient lorsqu’il est facile et
naturel de représenter toute solution du problème par un vecteur de n compo-
25

sante, et qu’à tout vecteur de cette taille on peut faire correspondre une solution
admissible du problème.
Ceci n’est pas le cas pour un problème où l’on cherche une permutation
de n éléments. Une technique d’adaptation du croisement uniforme pour cette
g

situation est de procéder en deux passes : durant la première passe, on sé-


lectionne aléatoirement l’élément de la permutation chez l’un ou l’autre des
Al

parents, pour autant que l’élément en question n’ait pas encore été choisi. Si
les deux parents ont des éléments déjà choisis à la position à remplir, cette
T_

dernière reste temporairement vide chez l’enfant. La seconde passe consiste


à compléter les positions vides aléatoirement avec les éléments qui n’ont pas
été placés durant la première passe. Cet opérateur est illustré par la 9.4.

Croisement 1-point

Le croisement 1-point, ou enjambement simple, consiste à choisir aléatoi-


rement un point à l’intérieur du vecteur-solution et à copier tous les éléments
du premier parent jusqu’à ce point, puis les éléments du second parent à partir
de là. En pratique, pour un vecteur de n éléments, on tire aléatoirement un
nombre c entre 1 et n − 1 ; on copie les éléments 1 à c, compris, du premier
9.2 A LGORITHMES GÉNÉTIQUES 193

Parent 1
9 5 12 8 2
6 1 11 3 10 4 7
Parent 2
3 11 4 8 12 5 1 2 10 6 9 7

Phase 1
3 11 12 8 2 6 1 10 9 7
Enfant

17
3 11 12 8 2 6 1 5 10 4 9 7

F IGURE 9.4 – Croisement uniforme sur une permutation. Un enfant est produit en deux
passes. On choisit d’abord successivement les éléments de l’un ou l’autre des parents,

20
pour autant que ces éléments n’aient pas été choisis (auquel cas, on prend l’unique élé-
ment disponible, ou on laisse la case vide si les deux éléments des parents figurent déjà
dans l’enfant. La seconde passe complète aléatoirement l’enfant à l’aide des éléments
encore disponibles.

e
Parent 1 br
em
A C A G T T T G G C A G
Parent 2
C A T G C T G A G T C G
pt

Enfant 1
se

A C A G T T T G G T C G
Enfant 2
C A T G C T G A G C A G
25

F IGURE 9.5 – Enjambement simple ou croisement 1-point. Production de deux « anti-


jumeaux » par tirage aléatoire d’un point d’enjambement (ici, le 8), et copie des éléments
du premier parent jusqu’au point d’enjambement, et ceux du second à partir de là.
g
Al

parent et les éléments c + 1 à n du second parent. On peut produire un second


enfant complémentaire en parallèle. Cet opérateur est illustré en figure 9.5.
T_

Croisement 2-points

Le double enjambement ou croisement 2-points consiste à choisir deux


points de croisement sur les parents. L’enfant est créé par copie de la por-
tion d’un parent située entre les points de croisement et de copier la portion
avant le premier point de croisement et celle après le second de l’autre parent.
Cet opérateur est illustré en figure 9.6.
194 A PPRENDRE PAR LES SOLUTIONS

Parent 1
A C A G T T T G G C A G
Parent 2
C A T G C T G A G T C G

Enfant 1
A C A G C T G A G C A G

17
Enfant 2
C A T G T T T G G T C G

F IGURE 9.6 – Enjambement double ou croisement 2-points. Production de deux « anti-

20
jumeaux » par tirage aléatoire de deux points points de croisement (ici, 4 et 8). Copie
des éléments d’un parent jusqu’au premier point de croisement et à partir du second
point de croisement et ceux de l’autre pour la partie intermédiaire.

e
Croisement OX
br
Pour chaque problème, on peut inventer un opérateur de croisement spé-
em
cifique. Par exemple, pour celui du voyageur de commerce, on peut faire le
raisonnement que des portions de chemins devraient être copiées dans la
solution-enfant à partir des parents. Si l’on considère une solution comme étant
une permutation des villes, on se rend compte que le croisement uniforme vu
pt

plus haut et adapté au cas des permutations n’a pas vraiment de sens : la ville
de départ n’est pas déterminante, donc ce n’est pas la position d’une ville dans
se

la tournée qui est importante, mais les villes qui lui précèdent et succèdent.
Dans ce cas, on aura intérêt à adapter l’opérateur de croisement 2-points pour
les problèmes où ce sont les séquences qui sont importantes.
L’opérateur de croisement OX imaginé pour le problème du voyageur de
25

commerce commence par copier la portion intermédiaire d’un parent, à l’image


du double enjambement. On repère la dernière ville de cette portion dans
l’autre parent et l’enfant est complété en parcourant cycliquement les villes
de ce parent et en y insérant celles qui n’y figurent pas encore. L’opérateur de
g

croisement OX est illustré en 9.7


Al

Une implantation de cet opérateur en C est donné par le code 9.2.


T_
9.2 A LGORITHMES GÉNÉTIQUES 195

Parent 1
9 5 12 8 2
6 1 11 3 10 4 7
Parent 2
3 11 4 8 12 5 1 2 10 6 9 7

Enfant
2 6 1 11 4 8 12 5 10 9 7 3

17
F IGURE 9.7 – Croisement OX, spécifiquement développé pour le problème du voyageur
de commerce. On commence par tirer aléatoirement deux points de croisement. La
portion intermédiaire du premier parent est copiée chez l’enfant. Dans cet exemple
cette portion se termine par la ville 11. On repère cette ville dans le second parent

20
et on complète l’enfant à partir de là, en l’occurrence par la ville 4. Les villes figurant
déjà dans l’enfant (1, 2, puis 6) sont sautées. Lorsqu’on arrive à la « dernière » ville du
second parent (7) on revient à la première (3).

e
br
Listing 9.2 – OX_crossover.c Implantation de l’opérateur de croisement OX préservant
em
l’ordre d’une sous-séquence
v o i d OX_crossover ( i n t n , / ∗ Number o f c i t i e s ∗/
c o n s t i n t p1 [ ] , c o n s t i n t p2 [ ] , / ∗ Parent s o l u t i o n s ∗/
int child [ ] )
{ i n t i , j , temp ,
pt

point2 , point1 , / ∗ P o r t i o n o f p1 between p o i n t 1 and p o i n t 2 i s copied ∗/


nr_inserted ; / ∗ Counter o f elements i n s e r t e d i n t h e c h i l d ∗/
i n t ∗already_inserted ; / ∗ Mark o f elements a l r e a d y i n s e r t e d ∗/
se

a l r e a d y _ i n s e r t e d = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
f o r ( i = 0 ; i < n ; i ++)
already_inserted [ i ] = 0;

/ ∗ Randomly generate t h e p o r t i o n o f p1 t h a t i s copied i n c h i l d ∗ /


p o i n t 2 = u n i f ( 1 , n−2);
25

p o i n t 1 = u n i f ( 1 , n−3);
i f ( p o i n t 1 >= p o i n t 2 )
{ temp = p o i n t 2 ;
p o i n t 2 = ++ p o i n t 1 ;
p o i n t 1 = temp ;
}
g

/ ∗ Copy t h e p o r t i o n o f p1 a t t h e b e g i n n i n g o f c h i l d ∗ /
Al

f o r ( i = 0 ; i < p o i n t 2−p o i n t 1 +1; i ++)


{ c h i l d [ i ] = p1 [ i + p o i n t 1 ] ;
already_inserted [ child [ i ] ] = 1;
}
T_

/ ∗ Find i n p2 t h e l a s t element i n s e r t e d i n c h i l d ∗ /
f o r ( j = 0 ; p2 [ j ] ! = c h i l d [ p o i n t 2−p o i n t 1 ] ; j + + ) { } /∗ j u s t increment j ∗/

/ ∗ I n s e r t t h e r e m a i n i n g elements i n c h i l d , i n t h e o r d e r o f appearance i n p2 ∗ /
n r _ i n s e r t e d = p o i n t 2−p o i n t 1 + 1 ;
f o r ( i = j ; n r _ i n s e r t e d < n ; i ++)
i f ( ! a l r e a d y _ i n s e r t e d [ p2 [ i%n ] ] )
{ c h i l d [ n r _ i n s e r t e d ] = p2 [ i%n ] ;
a l r e a d y _ i n s e r t e d [ p2 [ i%n ] ] = 1 ;
n r _ i n s e r t e d ++;
}
free ( already_inserted ) ;
} / ∗ OX_crossover ∗ /
196 A PPRENDRE PAR LES SOLUTIONS

Coût
135

130 Taux de mutation de 1%


Taux de mutation de 2%
125
Taux de mutation de 5%
Pas de mutation
120

17
115

110

20
105

e
100
100 1’000 10’000 100’000

br Générations
em
F IGURE 9.8 – Influence du taux de mutation sur la qualité des solutions produites
en fonction du nombre de boucles générationnelles réalisées. Seule la valeur de la
meilleure solution de la population est représentée, en fonction du nombre d’itérations
de la boucle générationnelle. L’algorithme favorise les meilleures solutions de la po-
pulations au moyen d’opérateurs de sélection pour la reproduction et de survie. Sans
pt

mutation, la population converge relativement rapidement vers des individus tous sem-
blables et de mauvaise qualité. Plus le taux de mutation est élevé, plus la convergence
se

est lente, ce qui permet d’obtenir de meilleures solutions.

9.2.3 Opérateur de mutation


25

Les opérateurs de mutations peuvent être décrits de façon simple dans le


contexte de ce livre : il s’agit d’appliquer de façon aléatoire à la solution, une
ou plusieurs modifications locales, comme décrit dans le chapitre 4 qui y est
g

consacré.
L’opérateur de mutation a deux rôles : tout d’abord, la modification locale
Al

peut améliorer la solution, ensuite, même si cette dernière n’est pas amélio-
rée, elle ralentit la convergence globale de l’algorithme par renforcement de
T_

la diversité génétique de la population. En effet, sans cet opérateur, la popula-


tion ne peut que perdre en diversité. Par exemple, les opérateurs de croisement
présentés plus haut recopient systématiquement les parties identiques des pa-
rents chez l’enfant. Ainsi, certains gènes vont prendre le dessus par rapport à
d’autres qui disparaissent avec l’élimination de solutions par l’opérateur de sé-
lection pour la survie.
La figure 9.8 illustre l’influence du taux de mutations pour un problème où
l’on recherche une permutation de n éléments. Dans cette figure, un taux de
mutation de 5% signifie qu’il y a cette proportion d’éléments qui sont échangés
aléatoirement dans une solution.
9.2 A LGORITHMES GÉNÉTIQUES 197

Listing 9.3 – mutate.c Implantation d’un opérateur de mutation pour des problèmes
sur des permutations.
/ ∗ M u t a t i o n o p e r a t o r f o r p e r m u t a t i o n perform m u t a t i o n _ r a t e ∗n / 2 random swaps ∗/
v o i d mutate ( i n t n , /∗ Permutation size ∗/
double m u t a t i o n _ r a t e ,
int p []) / ∗ P e r m u t a t i o n t o mutate ∗ /
{ i n t i , nr_mutations ;
nr_mutations = ( i n t ) ( mutation_rate ∗ n / 2 . 0 ) ;
f o r ( i = 0 ; i < n r _ m u t a t i o n s ; i ++)
swap(&p [ u n i f ( 0 , n −1)] , & p [ u n i f ( 0 , n − 1 ) ] ) ;
}

17
Le code 9.3 donne une implantation d’un opérateur de mutation pour des
problèmes sur des permutations.

20
9.2.4 Sélection pour la survie
Le dernier opérateur-clé des algorithmes est celui de la sélection pour la

e
survie, qui a pour but de ramener la population à sa taille initiale de µ indivi-
dus, après que l’on ait généré λ nouvelles solutions. Plusieurs politiques de

br
sélection ont été imaginées, selon les valeurs choisies pour les paramètres µ
et λ.
em
Remplacement générationnel

La politique la plus simple pour sélectionner les individus qui survivront


pt

est de générer le même nombre d’enfant qu’il y a d’individus dans la popula-


tion (λ = µ). La population au début de la nouvelle boucle générationnelle est
se

constituée uniquement des enfants, la population initiale disparaissant. Avec un


tel choix, il est nécessaire de disposer d’un opérateur de sélection pour la re-
production qui favorise les meilleures solutions. Cela signifie que les meilleurs
individus pourront participer à la création de plusieurs enfants, alors que cer-
25

tains des plus mauvais seront exclus du processus de reproduction.

Stratégie d’évolution
g

La stratégie d’évolution (µ, λ) consiste à générer un grand nombre d’en-


Al

fants (λ > µ) et de ne conserver pour la génération suivante que les µ enfants


les plus performants. La population est donc intégralement changée d’une ité-
T_

ration de la boucle générationnelle à la suivante. Cette stratégie entraîne un


biais dans le choix des meilleurs individus d’une génération à l’autre, et elle est
compatible avec un opérateur de sélection pour la reproduction non discrimi-
nant.

Remplacement stationnaire

Une technique également fréquemment rencontrée est de faire évoluer pro-


gressivement la population, avec un faible nombre d’enfants la rejoignant à
chaque boucle générationnelle. Une stratégie est de générer λ = 2 enfants à
chaque génération, enfants qui vont remplacer leurs parents
198 A PPRENDRE PAR LES SOLUTIONS

140

Coût
µ=5
135

µ = 10
130

125

17
120

115
µ = 20

20
110
µ = 50

105 µ = 100

e
µ = 200
µ = 500
100
10 100
br 1’000 10’000 100’000
em
Générations

F IGURE 9.9 – Influence de la taille de la population sur la qualité des solutions. Lorsque
la population est trop petite, elle converge très rapidement avec peu de chances d’at-
pt

teindre de bonnes solutions. Inversement, une grande population convergera très len-
tement, mais vers de meilleures solutions.
se

Remplacement élitiste
25

Une autre stratégie plus agressive est de considérer l’ensemble des µ + λ


solutions disponibles en fin de boucle générationnelle et de ne conserver que
les µ meilleures pour la génération suivante. Cette stratégie a été utilisée pour
produire la figure 9.9 où l’on a représenté l’évolution de la meilleure solution de
g

la populations pour diverses valeurs de µ.


Al

Le code 9.4 implante un remplacement élitiste dans le cas où λ = 1, c’est-


à-dire lorsqu’à chaque génération on ne produit qu’un enfant qui va remplacer,
s’il n’est pas encore plus mauvais, la plus mauvaise solution de la population.
T_

Dans ce code, on a ajouté une gestion élémentaire de la population qui ne doit


comporter que des individus différents. Pour simplifier le test de l’égalité entre
deux solutions, ces dernières sont discriminées uniquement sur la base de
leur longueur : deux solutions dont les longueurs ne sont pas significativement
différentes sont considérées comme identiques.
9.3 A LGORITHMES MÉMÉTIQUES 199

Listing 9.4 – insert_child.c Implantation d’un remplacement élitiste lorsqu’à chaque


génération on ne produit qu’un enfant. Cette procédure implante une gestion élémen-
taire de la population où tous les individus doivent avoir des évaluations différentes.

int insert_child ( int n,


const i n t c h i l d [ ] , /∗ Child to i n s e r t ∗/
double l e n g t h _ c h i l d , /∗ Child f i t n e s s ∗/
i n t pop_size , /∗ Population size ∗/
i n t ∗∗ p o p u l a t i o n , / ∗ P o p u l a t i o n t o update ∗/
double l e n g t h [ ] , /∗ Fitness of i n d i v i d u a l s ∗/
i n t order [ ] ) / ∗ I n d i v i d u a l s number , from b e s t t o w o r s t ∗/
{ i n t ∗ rank = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ; / ∗ Rank o f i n d i v i d u a l s ∗/

17
i n t child_rank = 0;
int i ;

f o r ( i = 0 ; i < pop_size ; i ++)


rank [ o r d e r [ i ] ] = i ;

20
/ ∗ Find t h e rank o f t h e c h i l d ∗ /
child_rank = 0;
f o r ( i = 0 ; i < pop_size ; i ++)
i f ( length [ i ] < length_child )
c h i l d _ r a n k ++;

e
i f ( c h i l d _ r a n k < pop_size −1) / ∗ The c h i l d i s n o t dead−born ∗/

br
{ / ∗ May t h e c h i l d be i d e n t i c a l t o an i n d i v i d u a l o f t h e p o p u l a t i o n ?
i f ( f a b s ( l e n g t h [ o r d e r [ c h i l d _ r a n k ] ] − l e n g t h _ c h i l d ) > e p s i l o n &&
( c h i l d _ r a n k == 0 | |
f a b s ( l e n g t h [ o r d e r [ c h i l d _ r a n k −1]] − l e n g t h _ c h i l d ) > e p s i l o n ) )
∗/
em
{ / ∗ The c h i l d n o t p r e s e n t i n t h e p o p u l a t i o n , i t r e p l a c e w o r s t i n d i v i d u a l ∗/
f o r ( i = 0 ; i < n ; i ++)
p o p u l a t i o n [ o r d e r [ pop_size − 1 ] ] [ i ] = c h i l d [ i ] ;
l e n g t h [ o r d e r [ pop_size −1]] = l e n g t h _ c h i l d ;
f o r ( i = 0 ; i < pop_size ; i ++)
i f ( rank [ i ] >= c h i l d _ r a n k )
pt

rank [ i ] + + ;
rank [ o r d e r [ pop_size −1]] = c h i l d _ r a n k ;
f o r ( i = 0 ; i < pop_size ; i ++)
se

o r d e r [ rank [ i ] ] = i ;
}
else
c h i l d _ r a n k = pop_size ; / ∗ C h i l d a l r e a d y p r e s e n t i n p o p u l a t i o n , i g n o r e i t ∗/
}
25

return child_rank ;
}
g

9.3 Algorithmes mémétiques


Al

Les algorithmes génétiques présentent deux défauts majeurs : première-


ment, rien ne permet d’assurer que la meilleure solution trouvée ne puisse
T_

être améliorée par une simple modification locale, telle que vue au chapitre 4.
Secondement, la diversité de la population décroît au fur et à mesure des ité-
rations de la boucle générationnelle pour finalement ne comporter que des
clones du même individu.
Pour contrer ces deux inconvénients, [?] a imaginé ce qu’il a appelé les
algorithmes mémétiques. Le premier de ces défaut est résolu par l’application
d’une recherche locale après avoir produit une solution-enfant. La manière la
plus simple d’éviter la duplication d’individus dans la population est d’éliminer
immédiatement les doublons.
Le code 9.5 illustre une implantation simple d’un algorithme mémétique
pour le problème du voyageur de commerce où les enfants sont améliorés à
200 A PPRENDRE PAR LES SOLUTIONS

l’aide d’une recherche locale basée sur les chaînes d’éjections et où ils ne rem-
placent la plus mauvaise solution de la population que s’ils sont de meilleure
qualité que cette dernière et que leur évaluation est différente de toutes celles
de la population, ce qui assure de ne pas créer de doublons. Cet algorithme
n’implante qu’une version élémentaire d’un algorithme mémétique. Une ges-
tion de la population proposée par [?] est un peu plus évoluée. Ces auteurs
suggèrent de d’évaluer, pour chaque solution produite, une mesure de simila-
rité avec les solutions contenues dans la population. Les solution trop similaires
sont écartées pour maintenir une diversité suffisante, pour que l’algorithme ne

17
converge pas prématurément.

Archipels de populations D’autres techniques de gestion de la population

20
plus sophistiquées ont été imaginées, notamment celle basée sur des îlots.
L’idée est de faire évoluer plusieurs populations de faible taille indépendam-
ment pendant un nombre restreint d’itérations. Du fait de leur faible taille, la
qualité des solutions de chaque population s’améliore rapidement. Pour ne pas

e
perdre de diversité, des individus sont transférés régulièrement d’une popula-
tion à une autre, ce qui atténue les problèmes de consanguinité.

br
em
pt
se
25
g
Al
T_
9.3 A LGORITHMES MÉMÉTIQUES 201

Listing 9.5 – tsp_GA.c Implantation d’un algorithme mémétique pour le problème du


voyageur de commerce. Cet algorithme utilise un opérateur de sélection pour la repro-
duction basé sur le rang. Après génération d’un enfant, ce dernier est amélioré par une
recherche locale (méthode des chaînes d’éjections) et il remplace immédiatement la
plus mauvaise solution de la population. Cet algorithme comporte trois paramètres :
le nombre µ de solutions dans la population, le nombre de boucles générationnelles à
effectuer et le taux de mutations.
double tsp_GA ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , /∗ Distance matrix ∗/
i n t best_sol [ ] , / ∗ Out S o l u t i o n r e t u r n e d ∗/
i n t mu, / ∗ Size o f t h e p o p u l a t i o n ∗/

17
i n t generations , / ∗ Number o f c h i l d r e n generated ∗/
double m u t a t i o n _ r a t e )
{ i n t i , j , nr_generation , /∗ Indices ∗/
p1 , p2 ; / ∗ Rank o f p a r e n t s chosen ∗/
double l e n g t h _ c h i l d ; /∗ Fitness of c h i l d ∗/

20
i n t ∗ c h i l d = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ; / ∗ c h i l d −s o l u t i o n ∗/
i n t ∗ order ; / ∗ I n v e r s e o f t h e rank ∗/
double∗ l e n g t h = ( double ∗) m a l l o c ( ( s i z e _ t )mu ∗ s i z e o f ( double ) ) ; / ∗ Sol . f i t . ∗/
i n t ∗∗ p o p u l a t i o n ; /∗ Population of sol ut ion s ∗/

o r d e r = ( i n t ∗) m a l l o c ( ( s i z e _ t )mu ∗ s i z e o f ( i n t ) ) ;

e
p o p u l a t i o n = ( i n t ∗∗) m a l l o c ( ( s i z e _ t )mu ∗ s i z e o f ( i n t ∗ ) ) ;
f o r ( i = 0 ; i < mu; i ++)

/ ∗ Generate a p o p u l a t i o n o f random s o l u t i o n s ∗ /
f o r ( i =0; i < mu; i ++) br
p o p u l a t i o n [ i ] = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
em
{ generate_random_permutation ( n , p o p u l a t i o n [ i ] ) ;
length [ i ] = tsp_length (n , d , population [ i ] ) ;
}
/ ∗ Order t h e i n d i v i d u a l by d e c r e a s i n g f i t n e s s and a s s i g n them a rank ∗ /
f o r ( i = 0 ; i < mu; i ++)
order [ i ] = i ;
pt

f o r ( i = 0 ; i < mu−1; i ++)


f o r ( j = i +1; j < mu; j ++)
se

i f ( length [ order [ i ] ] > length [ order [ j ] ] )


swap(& o r d e r [ i ] , &o r d e r [ j ] ) ;
p r i n t f ( "GA i n i t i a l p o p u l a t i o n %f \ n " , l e n g t h [ o r d e r [ 0 ] ] ) ;

/ ∗ ∗∗∗∗∗∗∗∗ Main GA l o o p ∗∗∗∗∗∗∗ ∗ /


f o r ( n r _ g e n e r a t i o n = 0 ; n r _ g e n e r a t i o n < g e n e r a t i o n s ; n r _ g e n e r a t i o n ++)
25

{ / ∗ Generate a new c h i l d ∗ /
p1 = r a n k _ b a s e d _ s e l e c t i o n (mu ) ;
p2 = r a n k _ b a s e d _ s e l e c t i o n (mu ) ;
OX_crossover ( n , p o p u l a t i o n [ o r d e r [ p1 ] ] , p o p u l a t i o n [ o r d e r [ p2 ] ] , c h i l d ) ;
mutate ( n , m u t a t i o n _ r a t e , c h i l d ) ;
length_child = tsp_length (n , d , child ) ;
g

tsp_LK ( n , d , c h i l d , & l e n g t h _ c h i l d ) ;
i f ( i n s e r t _ c h i l d ( n , c h i l d , l e n g t h _ c h i l d , mu, p o p u l a t i o n , l e n g t h , o r d e r ) == 0 )
Al

p r i n t f ( "GA %d %f \ n " , n r _ g e n e r a t i o n , l e n g t h _ c h i l d ) ;
}
/ ∗ Return t h e b e s t s o l u t i o n o f t h e p o p u l a t i o n ∗ /
f o r ( i = 0 ; i < n ; i ++)
T_

best_sol [ i ] = population [ order [ 0 ] ] [ i ] ;

free ( child ) ;
free ( length ) ;
free ( order ) ;
f o r ( i =0; i < mu; i ++)
free ( population [ i ] ) ;
free ( population ) ;
return tsp_length (n , d , best_sol ) ;
}
202 A PPRENDRE PAR LES SOLUTIONS

17
F IGURE 9.10 – La recherche par dispersion brise le tabou d’une reproduction limitée au

20
croisement de deux solutions.

9.4 Recherche par dispersion

e
La recherche par dispersion est presque aussi ancienne que les algo-

br
rithmes génétiques. [?] a proposé cette technique dans le cadre de la pro-
grammation linéaire en nombres entiers. À l’époque, il brisait certains tabous,
em
comme le fait de pouvoir représenter une solution sous une forme naturelle et
non codée par un vecteur binaire ou de croiser plus de deux solutions entre
elles, comme illustré en figure 9.10.
Les principales idées de la recherche par dispersion sont les suivantes,
pt

présentées en opposition aux algorithmes génétiques traditionnels :


Population initiale dispersée Plutôt que de générer une population initiale
se

de grande taille et aléatoirement, cette dernière est générée de façon


déterministe et aussi dispersée que possible dans l’espace des solutions
potentielles. Ces dernières ne sont pas forcément réalisables, mais elles
le sont rendues par un opérateur de réparation/amélioration.
25

Représentation naturelle des solutions Les solutions sont représentées


sous un format naturel et non forcément avec des vecteurs binaires de
taille donnée.
g

Combinaison de plusieurs solutions Plus de deux solutions peuvent


concourir à la production d’une nouvelle solution potentielle. Plutôt que
Al

de reposer sur une grande population et un opérateur de sélection pour


la reproduction, la recherche par dispersion essaie toutes les combinai-
T_

sons possibles des individus de la population, qui doit donc être limitée à
quelques dizaines de solutions.
Opérateur de réparation/amélioration Du fait de la représentation naturelle
des solutions, le « croisement » simultané de combinaisons de plusieurs
individus ne produit pas forcément une solution réalisable. Un opérateur
de réparation projetant une solution potentielle irréalisable dans l’espace
des solutions admissibles est donc prévu. Cet opérateur peut également
au passage améliorer une solution réalisable, notamment à l’aide d’une
recherche locale.
Gestion de la population Une population de référence, de faible taille, est dé-
composée en un sous-ensemble de solutions-élites et d’autres solutions
9.4 R ECHERCHE PAR DISPERSION 203

aussi différentes que possible des solutions-élites.


La trame de la recherche par dispersion est donnée par l’algorithme 9.2.
L’avantage de cette trame est son faible nombre de paramètres : µ pour la taille
de la population de référence et E < µ pour l’ensemble des solutions-élites.
De plus, la valeur de µ doit être limitée à une vingtaine, puisqu’il faut combiner
un nombre de solutions potentielles croissant exponentiellement avec µ ; cela
signifie également que le nombre E de solutions-élites sera de quelques unités
à une dizaine.
En revanche, cette trame est très incomplète, car elle ne précise pas com-

17
ment générer des solutions aussi dispersées que possible, ni comment com-
biner plusieurs solutions entre elles ou encore comment implanter la répara-
tion et l’amélioration des solutions potentielles. Toutes ces choses sont dépen-

20
dantes du problème traité et doivent être adaptées au cas par cas. Le para-
graphe suivant donne un exemple d’adaptation pour le problème du sac de
montagne.

e
Algorithme 9.2 : Trame d’une recherche par dispersion.

des solutions-élites
Résultat : Meilleure solution trouvée
br
Données : Taille µ de la population complète, E taille du sous-ensemble
em
1 Générer de façon systématique une (grande) population P de solutions
potentielles aussi dispersées que possible;
2 répéter
pt

3 Réparer et améliorer les solutions de P pour les rendre admissibles


au moyen de l’opérateur de réparation/amélioration;
4 Éliminer de P les solutions identiques;
se

5 Identifier les E meilleures de la population, qui seront conservées


dans la population de référence comme solutions-élites;
6 Identifier de P les µ − E solutions qui sont les plus différentes des
25

solutions-élites, elles seront conservées dans la population de


référence;
7 Combiner de toutes les manières possible les µ solutions de la
population de référence pour obtenir 2µ − µ − 1 nouvelles solutions
g

potentielles;
8 Joindre les solutions potentielles à l’ensemble de référence pour
Al

obtenir la nouvelle population P de l’itération suivante;


9 jusqu’à ce que la population ne change plus;
T_

Illustration de la recherche par dispersion pour le sac de montagne


Pour illustrer comment les diverses options de la trame de la recherche par
dispersion peuvent être adaptées à un problème particulier, considérons un
exemple de sac de montagne :

max r = 11s1 + 10s2 + 9s3 + 12s4 + 10s5 + 6s6 + 7s7 + 5s8 + 3s9 + 8s10
sous 33s1 + 27s2 + 16s3 + 14s4 + 29s5 + 30s6 + 31s7 + 33s8 + 14s9 + 18s10 6 100
contraintes si ∈ {0, 1}(i = 1, . . . , 10)
(9.1)
204 A PPRENDRE PAR LES SOLUTIONS

Solution Val. Solution Val.


potentielle réparée/améliorée
1 (1,1,1,1,1,1,1,1,1,1) 81 (0,1,1,1,0,0,0,0,1,1) 42
2 (1,0,1,0,1,0,1,0,1,0) 40 (1,0,1,1,1,0,0,0,0,0) 42
3 (1,0,0,1,0,0,1,0,0,1) 38 (1,0,0,1,0,0,1,0,0,1) 38
4 (1,0,0,0,1,0,0,0,1,0) 24 (1,0,0,1,1,0,0,0,1,0) 36
5 (1,0,0,0,0,1,0,0,0,0) 17 (1,0,1,1,0,1,0,0,0,0) 38
6 (0,0,0,0,0,0,0,0,0,0) 0 (0,1,1,1,0,0,0,0,0,1) 39
7 (0,1,0,1,0,1,0,1,0,1) 41 (0,1,0,1,0,1,0,0,0,1) 36

17
8 (0,1,1,0,1,1,0,1,1,0) 43 (0,1,1,1,1,0,0,0,1,0) 44
9 (0,1,1,1,0,1,1,1,0,1) 57 (0,1,1,1,0,0,0,0,1,1) 42 = solution 1
10 (0,1,1,1,1,0,1,1,1,1) 64 (0,1,1,1,0,0,0,0,1,1) 42 = solution 1

20
Tableau 9.1 – Population initiale dispersée P pour le problème du sac de montagne 9.1
et résultat de l’application de l’opérateur de réparation/amélioration sur les solutions
potentielles. Celles qui ne sont pas réalisables sont mises en évidence, de même que
les E = 3 solutions-élites.

e
br
Population initiale Les solutions de ce problèmes sont donc des vecteurs bi-
naires de 10 composantes. Pour générer un ensemble de solutions potentielles
em
aussi dispersées que possible, on peut choisir de mettre tous les objets dans
le sac, ou un sur deux, ou un sur trois, etc. et, pour chaque solution potentielle
ainsi générée, la solution complémentaire. Naturellement, toutes ces solutions
ne sont pas admissibles. En particulier, la solutions comportant tous les objets
pt

ne satisfait pas la contrainte de volume du sac ; sa solution complémentaire,


de revenu nul est la plus mauvaise possible.
Il faut donc appliquer un opérateur de réparation/amélioration à ces solu-
se

tions potentielles. On peut procéder ainsi : tant que la solution n’est pas admis-
sible, retirer l’objet ayant le plus mauvais rapport revenu/volume. Une solution
admissible peut être améliorée gloutonnement, en lui ajoutant l’objet avec le
25

meilleur rapport revenu/volume tant que la capacité du sac le permet.


Ainsi, on obtient la population de solutions donnée dans le tableau 9.1

Création de l’ensemble de référence Les solutions 9 et 10 sont identiques


g

à la première solution ; elle sont donc éliminées. Si l’on choisit un ensemble de


E = 3 solutions-élites, ces dernières seront les solutions 1, 2 et 8. En suppo-
Al

sant que l’on veuille se ramener à un ensemble de référence de µ = 5 solutions


il faut ajouter deux solutions aux trois solutions-élites parmi les solutions 3 à 7.
T_

Les deux solutions qui compléteront l’ensemble de référence sont déterminées


en évaluant une mesure de dissimilarité avec les solutions-élites. Une manière
de faire est de considérer la plus petite distance de Hamming entre la solution
candidate et les solutions-élites, ce qui est illustré par le tableau 9.2.

Combinaison de solutions Finalement, il faut implanter un opérateur per-


mettant de créer une solution potentielle en combinant plusieurs solutions de
l’ensemble de référence. Supposons que l’on désire combiner les solutions 3,
7 et 8 de valeur respective 38, 36 et 44. Une possibilité est de considérer les
solutions comme des vecteurs numériques et d’en faire une combinaison li-
néaire. On est tenté d’attribuer un poids d’autant plus grand à une solutions
9.5 C HEMIN DE LIAISON 205

Solution Distance de Hamming Distance


candidate Élite 1 Élite 2 Élite 8 minimale
3 (1,0,0,1,0,0,1,0,0,1) 5 4 7 4
4 (1,0,0,1,1,0,0,0,1,0) 5 2 3 2
5 (1,0,1,1,0,1,0,0,0,0) 5 2 5 2
6 (0,1,1,1,0,0,0,0,0,1) 1 4 3 1
7 (0,1,0,1,0,1,0,0,0,1) 3 6 5 3

Tableau 9.2 – Détermination des solutions de la population qui sont aussi différentes
que possible des solutions-élites. Si l’on veut un ensemble de référence de µ = 5

17
solutions, on retiendra les solutions 3 et 7 en plus des 3 solutions-élites car ce sont
celles qui maximisent la plus petite distance avec une de ces dernières.

20
38
qu’elle est bonne. Une idée est donc d’attribuer un poids de 38+36+44 à la so-
36 44
lution 3, de 38+36+44 à la solution 7 et de 38+36+44 à la solution 8. Le vecteur
ainsi obtenu est arrondi pour le projeter vers des valeurs binaires :

e
0.322·(1, 0, 0, 1, 0, 0, 1, 0, 0, 1)+
0.305·(0, 1, 0, 1, 0, 1, 0, 0, 0, 1)+
0.373·(0, 1, 1, 1, 1, 0, 0, 0, 1, 0) br
em
=(0.322, 0.678, 0.373, 1.000, 0.373, 0.305, 0.322, 0.000, 0.373, 0.627)
Arrondi(0, 1, 0, 1, 0, 0, 0, 0, 0, 1)
pt

9.5 Chemin de liaison


se

La technique du chemin de liaison a été proposée par [?] dans le cadre


de la recherche avec tabou sous l’appellation de path relinking « chemin de
re-liaison ». L’idée est de mémoriser un certain nombre de bonnes solutions
25

trouvées par une recherche avec tabous. Parmi ces solutions, on en choisit
deux, qui ont été reliées entre elles avec la recherche tabou par un chemin
allant de solution en solution voisine et de les relier à nouveau par un nouveau
chemin, plus court.
g

Cette technique peut être implantée indépendamment d’une recherche avec


tabous puisqu’il suffit de disposer d’une population de solutions et d’une struc-
Al

ture de voisinage pour l’implanter. On choisit donc dans la population une solu-
tion de départ et une solution d’arrivée. On évalue tous les voisins de la solution
T_

de départ qui se rapprochent de la solutions d’arrivée. Parmi ces voisins, on


identifie celui qui a la meilleure évaluation et on recommence le processus à
partir de celui-ci jusqu’à ce qu’on arrive à la solution d’arrivée. Avec un peu de
chance, une des solutions intermédiaires améliore la meilleure solution trou-
vée. La technique du chemin de liaison est illustrée en figure 9.11
Il existe différentes versions de la techniques du chemin de liaison : On
peut parcourir le chemin dans les deux sens en renversant le rôle des solu-
tions de départ et d’arrivée ; on peut appliquer une méthode d’amélioration à
chaque solution intermédiaire ; finalement, on peut modifier alternativement la
solution de départ et celle d’arrivée et s’arrêter lorsqu’elles se rencontrent en
une solution intermédiaire.
206 A PPRENDRE PAR LES SOLUTIONS

17
20
Solution de départ

e
br
em
pt
se

Solution d’arrivée
25

F IGURE 9.11 – Chemin de liaison. On transforme progressivement une solution de dé-


part —ici, la permutation de 7 éléments (1, 2, 3, 4, 5, 6, 7)— en une solution d’arrivée
g

(4, 6, 3, 2, 5, 1, 7) avec une structure de voisinage. À chaque étape, on évalue l’ensemble


Al

des solutions voisines qui permettent de se rapprocher de la solution d’arrivée et on


choisit celle dont la fonction-objectif est la meilleure.
T_
9.5 C HEMIN DE LIAISON 207

Listing 9.6 – tsp_path_relinking.c Implantation d’un chemin de liaison pour le pro-


blème du voyageur de commerce. À chaque itération, on identifie un mouvement de
type 3-opt qui va incorporer au moins un arc de la solution d’arrivée à la solution cou-
rante.
void tsp_path_relinking ( i n t n , / ∗ Number o f c i t i e s ∗/
double ∗∗d , /∗ Distance matrix ∗/
const i n t t a r g e t _ s o l u t i o n [ ] , /∗ A r r i v a l s o l u t i o n ∗/
i n t sol [ ] , / ∗ S t a r t i n g s o l u t i o n −−> Best on t h e path ∗/
double ∗ b e s t _ c o s t ) / ∗ S t a r t i n g s o l u t i o n c o s t −> b e s t ∗/
{ int i , j , k, / ∗ C i t i e s t r i e d f o r 3−o p t move n o t going away from t a r g e t ∗/
i _ k e p t , j _ k e p t , k_kept ; / ∗ c i t i e s i , j , k k e p t f o r 3−o p t move ∗/
double d e l t a , b e s t _ d e l t a ; / ∗ T r i a l and r e t a i n e d c o s t d i f f e r e n c e ∗/

17
double c o s t = ∗ b e s t _ c o s t ; / ∗ Cost o f c u r r e n t s o l u t i o n ∗/
i n t ∗ s u c c _ t a r g e t , ∗succ , ∗pred ; /∗ Alternate sol ut io ns representation ∗/

s u c c _ t a r g e t = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
succ = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;

20
pred = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;

f o r ( i = 0 ; i < n ; i ++) /∗ Building a l t e r n a t e s o l u t i o n representation ∗/


{ s u c c _ t a r g e t [ t a r g e t _ s o l u t i o n [ i ] ] = t a r g e t _ s o l u t i o n [ ( i +1)%n ] ;
succ [ s o l [ i ] ] = s o l [ ( i +1)%n ] ; /∗ Current solution , i n i t i a l l y : sol ∗/
pred [ s o l [ ( i +1)%n ] ] = s o l [ i ] ;

e
}

do
{ i = 0;
best_delta = i n f i n i t e ;
do br
em
{ i f ( succ [ i ] ! = s u c c _ t a r g e t [ i ] ) / ∗ t r y i −succ [ i ] −> i −s u c c _ t a r g e t [ i ] ∗ /
{ j = pred [ s u c c _ t a r g e t [ i ] ] ; / ∗ j −succ [ j ] n o t i n t a r g e t s o l u t i o n ∗ /
f o r ( k = s u c c _ t a r g e t [ i ] ; k ! = i ; k = succ [ k ] )
i f ( succ [ k ] ! = s u c c _ t a r g e t [ k ] )
{ d e l t a = d [ i ] [ succ [ j ] ] + d [ j ] [ succ [ k ] ] + d [ k ] [ succ [ i ] ]
−d [ i ] [ succ [ i ] ] − d [ j ] [ succ [ j ] ] − d [ k ] [ succ [ k ] ] ;
pt

i f ( delta < best_delta )


{ best_delta = delta ;
i _ k e p t = i ; j _ k e p t = j ; k_kept = k ;
se

}
}
}
i = succ [ i ] ;
}
w h i l e ( b e s t _ d e l t a >= 0 . 0 && i ) ; / ∗ Impr . move found o r a l l moves e v a l u a t e d ∗ /
25

i f ( best_delta < i n f i n i t e ) / ∗ A move has been found ∗ /


{ i = i _ k e p t ; j = j _ k e p t ; k = k_kept ;
c o s t += b e s t _ d e l t a ;
pred [ succ [ i ] ] = k ; pred [ succ [ j ] ] = i ; pred [ succ [ k ] ] = j ;
succ [ j ] = succ [ k ] ; succ [ k ] = succ [ i ] ; succ [ i ] = s u c c _ t a r g e t [ i ] ;
g

i f ( cost < ∗best_cost )


{ ∗best_cost = cost ;
Al

sol [ 0 ] = 0;
f o r ( i = 0 ; i < n−1; i ++)
s o l [ i +1] = succ [ s o l [ i ] ] ;
}
T_

}
}
while ( best_delta < i n f i n i t e ) ;
f r e e ( s u c c _ t a r g e t ) ; f r e e ( succ ) ; f r e e ( pred ) ;
} /∗ tsp_path_relinking ∗/

9.5.1 GRASP-PR
Une méthode utilisant les principales composantes des méta-heuristiques
(construction, recherche locale et gestion d’une population de solution) tout en
restant relativement simple et avec peu de paramètres est la méthode GRASP-
PR (procédure de recherche gloutonne adaptative avec chemin de liaison) de
208 A PPRENDRE PAR LES SOLUTIONS

[?]. L’idée est de générer une population P de µ solutions différentes à l’aide


d’une méthode constructive gloutonne biaisée avec un paramètre α (voir l’al-
gorithme 6.6), solutions qui sont améliorées à l’aide d’une recherche locale.
Ensuite, on répète Imax fois une boucle durant laquelle on construit glouton-
nement et avec un biais une nouvelle solution qui est améliorée avec une re-
cherche locale. On tire ensuite aléatoirement une autre solution de P et on
applique un chemin de liaison entre ces deux solutions. La meilleure solution
du chemin est ajoutée à P si elle est strictement meilleure qu’une des solution
de P et qu’elle est n’y figure pas déjà. La nouvelle solution remplace la solu-

17
tion de P qui est la plus différente d’elle-même tout en étant plus mauvaise.
L’algorithme 9.3 donne la trame de GRASP-PR.

20
Algorithme 9.3 : Trame de GRASP-PR.
Données : Structure de voisinage N , paramètres Imax , 0 6 α 6 1, µ
Résultat : Meilleure solution trouvée
1 P ← ∅;

e
2 tant que |P | < µ faire
3
4
5 si s0 ∈
/ P alors br
Générer une solution s avec une méthode gloutonne biaisée avec α;
s0 ← minimum local associé à s et N ;
em
6 P ← P ∪ s0
7 pour Imax itérations faire
8 Générer une solution s avec une méthode gloutonne biaisée avec α;
pt

9 s0 ← minimum local associé à s et N ;


10 Choisir aléatoirement une solution s” ∈ P ;
Appliquer un chemin de liaison entre s0 et s” en identifiant la
se

11
meilleure solution s∗ du chemin;
12 si s∗ ∈/ P et s∗ strictement meilleur qu’une solution de P alors
13 s remplace la solutions de P la plus différente de s∗ et plus

mauvaise que s∗
25
g

9.6 Essaims particulaires


Al

Les essaims particulaires sont un peu particuliers car ils ont été conçus
T_

d’abord pour l’optimisation continue. Il s’agit de faire évoluer une population de


particules, dont la position représente une solution du problème sous la forme
d’un vecteur de nombres réels, interagissant entre elles. Chaque particule a
une vitesse en plus de sa position et est attirée ou repoussée par les autres
particules.
Ce type de méthodes, proposées par [?], simulent le comportement d’ani-
maux vivants en essaim, comme des oiseaux, des insectes ou des poissons
et qui adoptent un comportement favorisant leur survie, que ce soit pour se
nourrir, se défendre vis-à-vis de prédateurs ou encore entreprendre une migra-
tion. Chaque individu de l’essaim est influencé par ceux se trouvant dans son
voisinage, et éventuellement aussi d’un meneur.
9.6 E SSAIMS PARTICULAIRES 209

Traduit en termes d’optimisation, chaque particule représente une solution


du problème avec sa qualité mesurée par une fonction-utilité. Une particule se
déplace à une certaine vitesse dans une direction donnée, mais elle est dé-
viée par son environnement : si dans le voisinage il existe une autre particule-
solution de meilleure qualité, elle sera attirée dans sa direction. Ainsi, chaque
solution énumérée par l’algorithme peut être associée au sommet d’un graphe.
Les arêtes de ce graphe correspondent aux solutions qui s’influencent mutuel-
lement.
Il existe diverses variantes de méthodes à essaims particulaires, se diffé-

17
renciant par le graphe d’influence et les formules utilisées pour calculer les
déviations de la vitesse des particules. Dans sa version la plus simple, une
particule p d’un ensemble en comportant P est influencée par seulement deux
solutions : la meilleure solution →

20
g trouvée par l’ensemble des particules et la


meilleure solution mp qu’elle a elle-même trouvée. La nouvelle vitesse de la
particule est un vecteur dont chaque composante est modifiée avec des poids
aléatoirement tirés entre 0 et φ1 dans la direction de −m→ et tirés entre 0 et φ
p 2

e
dans la direction de g , où φ1 et φ2 sont des paramètres de la méthode. De
plus, une particule a une inertie ω également donnée en paramètre. L’algo-

br
rithme 9.4 donne une trame simple d’essaim particulaire.
em
Algorithme 9.4 : Trame d’une méthode à essaim particulaires.
Données : Fonction f : [→ −
x min , →

x max ] ∈ Rn → R à minimiser,
paramètres P, ω, φ1 , φ2 , Imax
Résultat : →−
g
pt


1 f = ∞;
2 pour p = 1 . . . P faire

− −−−→ −
sp ← unif (→ x min , →

se

3 x max );
4
−→ →

mp ← sp ;

− −−−→ −
5 vp ← unif (→ x min − → −
x max , →

x max − →−x min );
6
∗ →

si f > f ( sp ) alors
25

7 f ∗ ← f (→ −
sp );
8


g ←s ; →

p

9 pour Imax itérations faire


g

10
→←−

u
−−→ → − → −
unif ( 0 , 1 ) ;
1
− −−− → →
− →

→ ← unif ( 0 , 1 ) ;
Al

11 u2


vp ← ω → −
vp + φ 1 − →·I·− →+φ → − −

12 m p u1 2 g · I · u2 ;

− −− →
sp ← − −→ min(→ −
sp + →−
vp , →

x max ), →

T_

13 max( x min );
14

→ →

si f (mp ) > f ( sp ) alors
15

m→←→ −
sp ;
p
16 si f > f (→
∗ −
sp ) alors
17 f ← f (→
∗ −
sp );
18

−g ←s ; →

p

Certains auteurs suggèrent de ne choisir que le paramètre d’inertie ω et


2
de poser φ1 = φ2 = (1+ω)
2 . D’autres, suggèrent de ne pas multiplier les com-
posantes des meilleures solutions →−
g et −m→ par une matrice diagonale dont
p
210 A PPRENDRE PAR LES SOLUTIONS

les cœfficients sont tirés uniformément entre 0 et 1 pour dévier le vecteur de


vitesse, mais de multiplier ces solutions par une matrice de rotation aléatoire.

17
20
e
br
em
pt
se
25
g
Al
T_
9.6 E SSAIMS PARTICULAIRES 211

Exercies
Exercice 9.1. Algorithme génétique pour fonction à une dimension On
doit optimiser une fonction f d’une variable entière x, 0 6 x < 2n . Dans le
cadre d’un algorithme génétique doté d’un opérateur de croisement de deux
solutions, comment coder x sous la forme d’un vecteur binaire ?
Exercice 9.2. Séquences d’inversions Une permutation p des éléments de
1 à n peut être représentée par une séquence d’inversions s, où si compte le
nombre d’éléments de p1 , . . . , pk = i qui sont plus grand que i. Par exemple, la

17
permutation p = (2, 4, 6, 1, 5, 3) a pour séquence d’inversion s = (3, 0, 3, 0, 1, 0).
À quelles permutations correspondent les séquences d’inversions (4, 2, 3, 0, 1, 0)
et (0, 0, 3, 1, 2, 0) ? Donner des conditions nécessaires et suffisantes pour qu’un

20
vecteur s soit une séquence d’inversions d’une permutation. Est-ce que les
opérateurs de croisement standards 1-point, 2-points et uniformes peuvent être
appliqués aux séquences d’inversions ? Comment les séquences d’inversions
peuvent être utilisées dans le contexte de la recherche par dispersion ?

e
Exercice 9.3. Sélection basée sur le rang Quelle est la probabilité de la

br
fonction rank_based_selection(m) donnée dans l’algorithme 9.1 de retourner
une valeur v donnée ?
em
Exercice 9.4. Ajustement de paramètre d’un algorithme génétique Ajuster
la taille de la population et le taux de mutation de la procédure tsp_GA donnée
par le code 9.5 si cette dernière génère en tout 5n enfants.
pt

Exercice 9.5. Recherche par dispersion pour le sac de montagne On consi-


dère le problème du sac à dos 9.1 de la section 9.4. Effectuer la première
se

itération d’une recherche par dispersion pour ce problème : génération de la


nouvelle population, réparation/amélioration, mise à jour d’une population de 5
solutions comportant 3 élites.
25
g
Al
T_
212 A PPRENDRE PAR LES SOLUTIONS

17
20
e
br
em
pt
se
25
g
Al
T_
Annexe A

17
Codes

20
Cette annexe donne les codes C des quelques procédures utilitaires appa-
raissant dans divers algorithmes présentés dans ce livre.A.1 A.2

e
Listing A.1 – random_generators.c Génération de nombres pseudo-aléatoires.

br
rando() n’a pas de paramètres et retourne un double uniformément réparti entre 0
et 1 et unif retourne un entier entre deux bornes données en paramètres. Génération
em
d’un tableau de n entiers rempli avec une permutation aléatoires des nombres 0 à n − 1.
/ ∗ Random number ] 0 , 1 ] g e n e r a t o r , proposed by Lecuyer , r e p l a c e bad rand ( ) ∗/
double rando ( v o i d )
{ s t a t i c i n t x10 = 12345 , x11 = 67890 , x12 = 13579 , /∗ i n i t i a l value ∗/
x20 = 24680 , x21 = 98765 , x22 = 43210; / ∗ o f seeds ∗ /
pt

c o n s t i n t m = 2147483647; c o n s t i n t m2 = 2145483479;
c o n s t i n t a12= 63308; c o n s t i n t q12 =33921; c o n s t i n t r12 =12979;
c o n s t i n t a13=−183326; c o n s t i n t q13 =11714; c o n s t i n t r13 =2883;
c o n s t i n t a21= 86098; c o n s t i n t q21 =24919; c o n s t i n t r21= 7417;
se

c o n s t i n t a23=−539608; c o n s t i n t q23= 3976; c o n s t i n t r23 =2071;


c o n s t double invm = 4.656612873077393e−10;
i n t h , p12 , p13 , p21 , p23 ;
h = x10 / q13 ; p13 = −a13 ∗( x10−h∗q13)−h∗r13 ;
h = x11 / q12 ; p12 = a12 ∗( x11−h∗q12)−h∗r12 ;
i f ( p13 < 0 ) p13 = p13 + m; i f ( p12 < 0 ) p12 = p12 + m;
25

x10 = x11 ; x11 = x12 ; x12 = p12−p13 ; i f ( x12 < 0 ) x12 = x12 + m;
h = x20 / q23 ; p23 = −a23 ∗( x20−h∗q23)−h∗r23 ;
h = x22 / q21 ; p21 = a21 ∗( x22−h∗q21)−h∗r21 ;
i f ( p23 < 0 ) p23 = p23 + m2; i f ( p21 < 0 ) p21 = p21 + m2;
x20 = x21 ; x21 = x22 ; x22 = p21−p23 ; i f ( x22 < 0 ) x22 = x22 + m2;
i f ( x12 < x22 ) h = x12 − x22 + m; e l s e h = x12 − x22 ;
g

i f ( h == 0 ) r e t u r n ( 0 . 5 ) ;
e l s e r e t u r n ( h∗invm ) ;
Al

/ ∗ ∗∗∗∗∗∗∗∗ Returns a random i n t e g e r between low and h i g h ( i n c l u d e d ) ∗∗∗∗∗∗∗∗∗∗ ∗ /


i n t u n i f ( i n t low , i n t h i g h )
T_

{ r e t u r n low + ( i n t ) ( ( double ) ( h i g h − low + 1 ) ∗ rando ( ) ) ; }

v o i d swap ( i n t ∗ a , i n t ∗ b )
{ i n t temp = ∗a ; ∗a = ∗b ; ∗b = temp ; }

/ ∗ ∗∗∗∗∗∗ Generate a random a r r a y o f n i n t w i t h a l l elements o f [ 0 , n−1] ∗∗∗∗∗∗ ∗ /


v o i d generate_random_permutation ( i n t n , i n t p [ ] )
{ int i ;
f o r ( i = 0 ; i < n ; i = i +1) p [ i ] = i ;
f o r ( i = 0 ; i < n−1; i = i +1) swap(&p [ i ] , &p [ u n i f ( i , n − 1 ) ] ) ;
}
214 C ODES

Listing A.2 – tsp_length.c Calcul de la longueur d’une tournée d’un voyageur de com-
merce. Une solution est donnée sous la forme d’un tableau comportant l’ordre dans le-
quel les villes sont parcourues. Parfois une autre représentation d’une solution, comme
un tableau qui donne les villes qui succèdent, serait meilleure.
double t s p _ l e n g t h ( i n t n , / ∗ Number o f c i t i e s ∗ /
double ∗∗d , /∗ Distance matrix ∗/
const i n t s o l u t i o n [ ] ) / ∗ Order o f t h e c i t i e s ∗ /
{ int i ;
double sum = d [ s o l u t i o n [ n − 1 ] ] [ s o l u t i o n [ 0 ] ] ;
f o r ( i = 0 ; i < n−1; i ++)
sum += d [ s o l u t i o n [ i ] ] [ s o l u t i o n [ i + 1 ] ] ;
r e t u r n sum ;

17
}

Le code A.3 donne un exemple de programme complet permettant de tester


divers codes présentés dans ce livre pour traiter des problèmes de voyageur

20
de commerce. La méthode de résolution ici utilisée est GRASP, qui utilise elle-
même une recherche locale basée sur les listes d’éjections, ainsi que d’autres
fonctions utilitaires. Une valeur de eplsilon permettant d’éviter des problèmes
numériques est de prendre 10−14 fois la plus grande distance séparant 2 villes.

e
Le code A.4 permet quant à lui de tester l’algorithme FANT.

br
Le code A.5 permet quant à lui de tester un algorithme mémétique.
Le code A.6 permet de tester une recherche avec tabous.
Le code A.7 permet de tester une recherche locale multi-objectifs. Ces
em
codes ont été simplifiés de sorte qu’un utilisateur peu habitué à la program-
mation en C, notamment en ce qui concerne la compilation séparée, n’ait qu’à
compiler le programme de test qu’il désire pour obtenir un exécutable fonction-
nel. Leur style de programmation n’est donc pas exemplaire !
pt
se
25
g
Al
T_
215

Listing A.3 – test_tsp_GRASP.c Programme de test de quelques codes pour le voya-


geur de commerce donnés dans ce livre. Les données du problème sont générée aléa-
toirement, mais il est important de s’assurer que la matrice des distances est symé-
trique, car la recherche locale ne fonctionne correctement que pour ce type de pro-
blèmes.
/ ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
Programme f o r t e s t i n g procedures presented i n :
E . T a i l l a r d , I n t r o d u c t i o n aux m é t a h e u r i s t i q u e s , 2017
Compile : gcc −O2 t e s t _ t s p . c −lm
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ /
# i n c l u d e < s t d i o . h>
# i n c l u d e < s t d l i b . h>

17
# d e f i n e i n f i n i t e 9.99 e99
double e p s i l o n ;
# i n c l u d e <math . h>

20
# i n c l u d e " random_generators . c " /∗ Listing A.1 ∗/
#include " tsp_length . c " /∗ Listing A.2 ∗/
# i n c l u d e " tsp_LK . c " /∗ Listing 4.4 ∗/
# i n c l u d e " tsp_GRASP . c " /∗ Listing 6.3 ∗/

i n t main ( v o i d )

e
{
int n, i , j ;
int ∗solution ;
double ∗∗ d i s t a n c e ;

double ∗x , ∗y ; br
em
p r i n t f ( " Number o f c i t i e s : \ n " ) ;
s c a n f ( "%d " ,&n ) ;

s o l u t i o n = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
d i s t a n c e = ( double ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ∗ ) ) ;
pt

f o r ( i = 0 ; i < n ; i ++)
d i s t a n c e [ i ] = ( double ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ) ) ;

x = ( double ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ) ) ;
se

y = ( double ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ) ) ;

f o r ( i = 0 ; i < n ; i ++)
{ x [ i ] = rando ( ) ; y [ i ] = rando ( ) ; }

epsilon = 0.0;
25

f o r ( i = 0 ; i < n−1; i ++)


f o r ( j = i +1; j < n ; j ++) i f ( i ! = j )
{ distance [ i ] [ j ] = distance [ j ] [ i ] =
s q r t ( ( x [ i ]−x [ j ] ) ∗ ( x [ i ]−x [ j ] ) + ( y [ i ]−y [ j ] ) ∗ ( y [ i ]−y [ j ] ) ) ;
i f ( epsilon < distance [ i ] [ j ] )
epsilon = distance [ i ] [ j ] ;
g

}
e p s i l o n ∗= 1 . 0 e−14;
Al

tsp_GRASP ( n , d i s t a n c e , s o l u t i o n , 100 , 0 . 8 ) ;

f o r ( i = 0 ; i < n ; i ++)
T_

free ( distance [ i ] ) ;
free ( solution ) ;

r e t u r n EXIT_SUCCESS ;
}
216 C ODES

Listing A.4 – test_tsp_FANT.c Programme de test d’une méthode inspirée des colo-
nies de fourmi artificielles.
/ ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
Programme f o r t e s t i n g procedures presented i n :
E . T a i l l a r d , I n t r o d u c t i o n aux m é t a h e u r i s t i q u e s , 2015
Compile : gcc −O2 test_tsp_FANT . c
Example o f e x e c u t i o n r e s u l t :

Number o f c i t i e s :
30
Number o f FANT i t e r a t i o n s , FANT parameter :
50 30
FANT 0 1.761522

17
FANT 1 1.660644
FANT 2 1.646723
FANT 3 1.616719
FANT 4 1.614217

20
FANT 28 1.607204
Cost o f s o l u t i o n found w i t h FANT 1.607204e+00
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ /
# i n c l u d e < s t d i o . h>
# i n c l u d e < s t d l i b . h>
# i n c l u d e <math . h>

e
# d e f i n e i n f i n i t e 9.99 e99
double e p s i l o n ;
# i n c l u d e " random_generators . c "
#include " tsp_length . c "
# i n c l u d e " tsp_LK . c "
#include " i n i t _ u p d a t e _ t r a i l . c "
br /∗
/∗
/∗
/∗
Listing
Listing
Listing
Listing
A.1
A.2
4.4
7.1
∗/
∗/
∗/
∗/
em
#include " generate_solution_trail . c " /∗ Listing 7.2 ∗/
# i n c l u d e " tsp_FANT . c " /∗ Listing 7.3 ∗/

i n t main ( v o i d )
{
pt

i n t n , i , j , f a n t _ i t e r a t i o n s , fant_parameter ;
int ∗solution ;
double ∗∗ d i s t a n c e ;
double l e n g t h ;
se

p r i n t f ( " Number o f c i t i e s : \ n " ) ;


s c a n f ( "%d " ,&n ) ;
p r i n t f ( " Number o f FANT i t e r a t i o n s , FANT parameter : \ n " ) ;
s c a n f ( "%d%d " ,& f a n t _ i t e r a t i o n s , &f a n t _ p a r a m e t e r ) ;
25

s o l u t i o n = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
d i s t a n c e = ( double ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ∗ ) ) ;
f o r ( i = 0 ; i < n ; i ++)
d i s t a n c e [ i ] = ( double ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ) ) ;

epsilon = 0.0;
g

f o r ( i = 0 ; i < n−1; i ++)


f o r ( j = i +1; j < n ; j ++)
Al

{ d i s t a n c e [ i ] [ j ] = d i s t a n c e [ j ] [ i ] = rando ( ) ;
i f ( epsilon < distance [ i ] [ j ] )
epsilon = distance [ i ] [ j ] ;
}
T_

e p s i l o n ∗= 1 . 0 e−14;

l e n g t h = tsp_FANT ( n , d i s t a n c e , s o l u t i o n , f a n t _ p a r a m e t e r , f a n t _ i t e r a t i o n s ) ;
p r i n t f ( " Cost o f s o l u t i o n found w i t h FANT %e \ n " , l e n g t h ) ;

f o r ( i = 0 ; i < n ; i ++)
free ( distance [ i ] ) ;
free ( distance ) ;
free ( solution ) ;

r e t u r n EXIT_SUCCESS ;
}
217

Listing A.5 – test_tsp_GA.c Programme de test d’un algorithme mémétique pour pro-
blème de voyageur de commerce dont la matrice des distance est symétrique et géné-
rée aléatoirement.
/ ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
Programme f o r t e s t i n g procedures presented i n :
E . T a i l l a r d , I n t r o d u c t i o n aux m é t a h e u r i s t i q u e s , 2015
Compile : gcc −O2 test_tsp_GA . c −lm
Example o f e x e c u t i o n r e s u l t :

Number o f c i t i e s :
30
Size o f t h e p o p u l a t i o n , m u t a t i o n r a t e , number o f g e n e r a t i o n s :

17
10 0.01 60
GA i n i t i a l p o p u l a t i o n 11.592710
GA 0 1.707681
GA 2 1.696093
GA 4 1.614217

20
GA 59 1.607204
Cost o f s o l u t i o n found w i t h GA: 1.607204e+00
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ /
# i n c l u d e < s t d i o . h>
# i n c l u d e < s t d l i b . h>
# i n c l u d e <math . h>

e
# d e f i n e i n f i n i t e 9.99 e99

br
double e p s i l o n ;
# i n c l u d e " random_generators . c " /∗ Listing A.1 ∗/
#include " tsp_length . c " /∗ Listing A.2 ∗/
# i n c l u d e " tsp_LK . c " /∗ Listing 4.4 ∗/
em
# include " rank_based_selection . c " /∗ Listing 9.1 ∗/
# i n c l u d e " OX_crossover . c " /∗ Listing 9.2 ∗/
# i n c l u d e " mutate . c " /∗ Listing 9.3 ∗/
#include " insert_child . c " /∗ Listing 9.4 ∗/
# i n c l u d e " tsp_GA . c " /∗ Listing 9.5 ∗/
pt

i n t main ( v o i d )
{
i n t n , i , j , population_size , nr_generations ;
int ∗solution ;
se

double ∗∗ d i s t a n c e ;
double l e n g t h , m u t a t i o n _ r a t e ;

p r i n t f ( " Number o f c i t i e s : \ n " ) ;


s c a n f ( "%d " ,&n ) ;
25

p r i n t f ( " Size o f t h e p o p u l a t i o n , m u t a t i o n r a t e , number o f g e n e r a t i o n s : \ n " ) ;


s c a n f ( "%d%l f%d " ,& p o p u l a t i o n _ s i z e , &m u t a t i o n _ r a t e , &n r _ g e n e r a t i o n s ) ;

s o l u t i o n = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
d i s t a n c e = ( double ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ∗ ) ) ;
f o r ( i = 0 ; i < n ; i ++)
g

d i s t a n c e [ i ] = ( double ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ) ) ;

epsilon = 0.0;
Al

f o r ( i = 0 ; i < n−1; i ++)


f o r ( j = i +1; j < n ; j ++)
{ d i s t a n c e [ i ] [ j ] = d i s t a n c e [ j ] [ i ] = rando ( ) ;
T_

i f ( epsilon < distance [ i ] [ j ] )


epsilon = distance [ i ] [ j ] ;
}
e p s i l o n ∗= 1 . 0 e−14;

l e n g t h = tsp_GA ( n , d i s t a n c e , s o l u t i o n , p o p u l a t i o n _ s i z e ,
nr_generations , mutation_rate ) ;
p r i n t f ( " Cost o f s o l u t i o n found w i t h GA: %e \ n " , l e n g t h ) ;

f o r ( i = 0 ; i < n ; i ++)
free ( distance [ i ] ) ;
free ( distance ) ;
free ( solution ) ;

r e t u r n EXIT_SUCCESS ;
}
218 C ODES

Listing A.6 – test_tsp_TS.c Programme de test d’une recherche avec tabous pour
problème de voyageur de commerce dont la matrice des distance est symétrique et
générée aléatoirement.
/ ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
Programme f o r t e s t i n g procedures presented i n :
E . T a i l l a r d , I n t r o d u c t i o n aux m é t a h e u r i s t i q u e s , 2015
Compile : gcc −O2 t e s t _ t s p _ T S . c
Example o f e x e c u t i o n :
Number o f c i t i e s :
30
Number o f tabu i t e r a t i o n s , min . and max . t a b u _ d u r a t i o n , p e n a l t y :
200 4 20 0.0005

17
TS 1 11.855969
TS 2 10.474485
TS 3 8.993716
...
TS 17 1.828523

20
TS 21 1.698364
TS 26 1.650980
TS 156 1.629700
TS 157 1.610270
TS 158 1.607204
Cost o f s o l u t i o n found w i t h TS 1.607204e+00

e
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ /
# i n c l u d e < s t d i o . h>

br
# i n c l u d e < s t d l i b . h>

# d e f i n e i n f i n i t e 9.99 e99
double e p s i l o n ;
em
# i n c l u d e " random_generators . c " /∗ Listing A.1 ∗/
#include " tsp_length . c " /∗ Listing A.2 ∗/
# i n c l u d e " perform_move_update . c " /∗ Listing 8.1 ∗/
# i n c l u d e " tsp_TS . c " /∗ Listing 8.2 ∗/

i n t main ( v o i d )
pt

{
i n t n , i , j , i t e r a t i o n s , min_tabu , max_tabu ;
int ∗solution ;
double ∗∗ d i s t a n c e ;
se

double f r e q _ p e n a l t y , l e n g t h ;

p r i n t f ( " Number o f c i t i e s : \ n " ) ;


s c a n f ( "%d " ,&n ) ;
p r i n t f ( " Number o f tabu i t e r a t i o n s , min . and max . t a b u _ d u r a t i o n , p e n a l t y : \ n " ) ;
25

s c a n f ( "%d%d%d%l f " ,& i t e r a t i o n s , &min_tabu , &max_tabu , & f r e q _ p e n a l t y ) ;

s o l u t i o n = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
d i s t a n c e = ( double ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ∗ ) ) ;
f o r ( i = 0 ; i < n ; i ++)
d i s t a n c e [ i ] = ( double ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ) ) ;
g

epsilon = 0.0;
f o r ( i = 0 ; i < n−1; i ++)
Al

f o r ( j = i +1; j < n ; j ++)


{ d i s t a n c e [ i ] [ j ] = d i s t a n c e [ j ] [ i ] = rando ( ) ;
i f ( epsilon < distance [ i ] [ j ] )
T_

epsilon = distance [ i ] [ j ] ;
}
e p s i l o n ∗= 1 . 0 e−14;

generate_random_permutation ( n , s o l u t i o n ) ;
length = tsp_length ( n , distance , s o l u t i o n ) ;
tsp_TS ( n , d i s t a n c e , s o l u t i o n , &l e n g t h ,
i t e r a t i o n s , min_tabu , max_tabu , f r e q _ p e n a l t y ) ;
p r i n t f ( " Cost o f s o l u t i o n found w i t h TS %e \ n " , l e n g t h ) ;

f o r ( i = 0 ; i < n ; i ++)
free ( distance [ i ] ) ;
free ( distance ) ;
free ( solution ) ;

r e t u r n EXIT_SUCCESS ;
}
219

Listing A.7 – test_tsp_3opt_pareto.c Programme de test d’une recherche locale Pa-


reto pour problème de voyageur de commerce dont la matrice des distance est générée
aléatoirement. Pour un problème à 20 villes et 3 objectifs, ce programme génère une
approximation de l’ensemble Pareto comportant 3290 solutions. Comme l’implantation
est fortement récursive, il faut redimensionner au besoin la pile de récursion.
/ ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
Programme f o r t e s t i n g procedures presented i n :
E . T a i l l a r d , I n t r o d u c t i o n aux m é t a h e u r i s t i q u e s , 2017
Compile : gcc −O2 t e s t _ t s p _ 3 o p t _ p a r e t o . c
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ /
# i n c l u d e < s t d l i b . h>
# i n c l u d e < s t d i o . h>

17
# i n c l u d e < s t r i n g . h>
# d e f i n e i n f i n i t e 9.99 e99
#define K 3 / ∗ Number o f o b j e c t i v e s ∗ /
double e p s i l o n ;

20
# i n c l u d e " random_generators . c " / ∗ L i s t i n g A.1 ∗ /
# i n c l u d e " KD_tree_add_scan . c " / ∗ L i s t i n g 4.6 ∗ /
# i n c l u d e " KD_tree_delete . c " / ∗ L i s t i n g 4.7 ∗ /
# include " tsp_3opt_pareto . c " / ∗ L i s t i n g 4.5 ∗ /
# i n c l u d e " KD_tree_update_pareto . c " / ∗ L i s t i n g 4.8 ∗ /

e
i n t main ( v o i d )
{
int n, i , j , k;
i n t ∗succ ;
double ∗∗∗ d i s t a n c e ;
POINT l e n g t h s ; br
em
NODE ∗ p a r e t o _ f r o n t = NULL ;

p r i n t f ( " Number o f c i t i e s : \ n " ) ;


s c a n f ( "%d " ,&n ) ;

succ = ( i n t ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( i n t ) ) ;
pt

d i s t a n c e = ( double ∗∗∗) m a l l o c ( ( s i z e _ t ) K ∗ s i z e o f ( double ∗ ∗ ) ) ;


f o r ( k = 0 ; k < K ; k ++)
{ d i s t a n c e [ k ] = ( double ∗∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ∗ ) ) ;
se

f o r ( i = 0 ; i < n ; i ++)
d i s t a n c e [ k ] [ i ] = ( double ∗) m a l l o c ( ( s i z e _ t ) n ∗ s i z e o f ( double ) ) ;
}

f o r ( k = 0 ; k < K ; k ++) / ∗ Generate d i s t a n c e m a t r i c e s ∗ /


f o r ( i = 0 ; i < n ; i ++)
25

f o r ( j = 0 ; j < n ; j ++)
d i s t a n c e [ k ] [ i ] [ j ] = rando ( ) ;
e p s i l o n = 1 . 0 e−13;

f o r ( i = 0 ; i < n ; i ++) / ∗ Generate a s t a r t i n g s o l u t i o n ∗ /


succ [ i ] = ( i +1)%n ;
g

f o r ( k = 0 ; k < K ; k ++) / ∗ Compute i t s c o s t s f o r a l l o b j e c t i v e s ∗ /


{
Al

lengths [ k ] = 0;
f o r ( i = 0 ; i < n ; i ++)
l e n g t h s [ k ] += d i s t a n c e [ k ] [ i ] [ succ [ i ] ] ;
}
T_

t s p _ 3 o p t _ p a r e t o ( n , d i s t a n c e , succ , l e n g t h s , & p a r e t o _ f r o n t ) ;
KD_scan_and_delete ( p a r e t o _ f r o n t , n ) ;

f o r ( k = 0 ; k < K ; k ++)
{
f o r ( i = 0 ; i < n ; i ++)
free ( distance [ k ] [ i ] ) ;
free ( distance [ k ] ) ;
}
free ( distance ) ;
f r e e ( succ ) ;

r e t u r n EXIT_SUCCESS ;
}
T_ 220

Al
g
25
se
pt
em
br
e
20
17
C ODES

Vous aimerez peut-être aussi