Voyageur de commerce et solution exacte

publicité
Voyageur de commerce et solution exacte
Auteurs : F. Védrine, B. Monsuez
Ce projet consiste à réaliser un outil capable de trouver le plus court trajet pour un
commercial qui doit visiter n villes, les n villes étant placées sur un plan.
une solution
parmi les
plus courtes
C’est un problème bien connu en recherche opérationnelle sous le nom de « Traveling
Salesman Problem » ou TSP. Ce problème est NP-Complet. Diverses approches ont été
proposées pour les résoudre : des approches exactes (l’outil retourne effectivement le plus
court trajet) et des approches approchées (l’outil retourne un trajet proche du plus court). Ce
problème a donné lieu à beaucoup de recherches et a fourni pas mal de résultats en
algorithmique et en recherche opérationnelle.
Scénario : Vous vous trouvez dans la situation où votre supérieur vous demande :
1. Analysez le problème, sachant qu’il est souhaitable d’avoir la solution optimale
2. Réalisez un démonstrateur pour convaincre tel client que nous sommes capables de
traiter ce problème et/ou de lui fournir une première solution.
3. Si le client est convaincu, vous aurez vraisemblablement des ressources
supplémentaires pour transformer le démonstrateur en outil afin de le faire rentrer de
manière opérationnelle chez le client.
Votre objectif est d’une part d’arriver à finaliser le premier démonstrateur, tout en sachant que
les personnes qui transformeront l’outil seront des spécialistes de leur domaine et qu’ils ne
pourront pas connaître l’ensemble de l’outil pour faire leurs améliorations.
Pour le projet, vous aurez à réaliser les étapes 1 et 2 et à mettre en place et réaliser un axe
d’amélioration pour l’étape 3.
Ce projet peut alors être décomposé en 3 phases fonctionnelles :
• la première phase correspond à l’acquisition des données soit au fait de représenter n
villes dans un plan,
• la seconde phase correspond à la résolution de l’algorithmique soit la recherche du
trajet optimal,
• la troisième phase correspond à afficher le trajet optimal trouvé.
1/6
Étape 1 : Analyse du problème
Question A :
Déterminez l’architecture qui permet de faire évoluer les trois phases fonctionnelles
(acquisition, algorithmique et affichage) indépendamment les unes des autres.
Question B :
En pensant aux états dans lequel se trouve votre système (avant l’acquisition des données,
après l’acquisition et avant la résolution, après la résolution sachant que l’affichage ne
modifie pas le système), définissez l’interface exportée par chaque partie du système pour
effectuer les trois phases fonctionnelles.
Pour la question B, une des personnes du projet peut travailler à l’aide de diagrammes UML
(c’est simplement une option parmi d’autres), pendant que les autres réfléchissent à ce qui
peut bouger entre les différentes phases et comment ce sera exploité.
Il faut voir que lors de l’évolution de votre projet, l’acquisition des données pourra être
partiellement découplée de la recherche du meilleur trajet, et qu’il est assez dur d’anticiper sur
le couplage acquisition/résolution. Certaines structures de données correspondant au résultat
de l’acquisition des n villes dans le plan sont plus adéquates que d’autres pour
l’algorithmique. Ce couplage n’est pas forcément visible au niveau de l’interface que vous
définirez.
L’analyse architecturale du projet étant terminée, voici une présentation succincte
d’algorithmes de type Branch & Bound permettant une résolution exacte du problème du
voyageur de commerce. Cette présentation peut être sautée par le lecteur dans un premier
temps. Vous pouvez y revenir lorsque vous implanterez les algorithmes. Nous présentons
deux algorithmes différents. Noter que pour l’étape 2, vous pouvez implanter un algorithme
de recherche de type Branch & Bound, comme un algorithme plus approché que vous aurez
fait ou trouvé sur le Web. Dans ce dernier cas, vous pouvez consacrer l’étape 3 à remplacer
l’algorithme approché par un algorithme de recherche assez poussé parmi les deux que nous
vous présentons.
Représentation des villes
Nous représentons l’ensemble des villes placées sur un plan par une matrice de coût. Cette
matrice stocke la distance entre deux points.
C
B
E
A
D
matrice de
coût
F
I
G
H
J
A
B
C
D
...
I
J
A

2
4
7
...
7
6
B
2

2
6
...
7
7
C
4
2

4
...
5
5
D
7
6
4

...
3
5
...
...
...
...
...

...
...
I
7
7
5
3
...

2
J
6
7
5
5
...
2

La matrice de coût peut être symétrique ou non : Si elle est symétrique, cela signifie que
d(x,y) = d(y,x) quelles que soient les villes concernées.
La matrice de coût peut représenter une distance euclidienne, reflétant la propriété
d(x,y)+d(y,z) ≥ d(x,z).
2/6
L’algorithme d’insertion de nœud peut être bien optimisé pour une distance euclidienne, alors
que l’algorithme d’insertion d’arc fonctionne bien sans cette contrainte.
Algorithmes de type Branch & Bound (séparation-évaluation)
Les algorithmes de type Branch & Bound (séparation-évaluation) cherchent généralement à
minimiser une fonction de coût. La fonction de coût dans notre cas est la fonction qui à un
trajet associe sa la longueur totale.
La partie Branch ou séparation est une méthode de parcourt de l’espace des solutions. Cette
partie porte ce nom, car le parcourt est généralement un parcourt d’arbre en profondeur
d’abord pour avoir rapidement. À chaque nœud de l’arbre s’offrent alors plusieurs
possibilités. Le branchement consiste à choisir une de ces possibilités, généralement celle qui
a le plus de chance d’être choisie : l’aspect « plus de chance » est en liaison avec la partie
Bound ou évaluation.
La partie Bound ou évaluation donne une borne minimale pour le meilleur trajet (au sens de la
fonction de coût), validant les décisions (branchements ou séparations) déjà effectuées : ce
meilleur trajet aura alors une fonction de coût supérieure à cette borne.
L’algorithme effectue un certain nombre de décisions jusqu’à avoir un chemin complet. Ce
chemin a alors une fonction de coût que nous stockerons dans lmax. Nous savons que la
meilleure fonction de coût pour toutes les sous-branches d’un nœud est comprise entre
l’évaluation de la borne minimale du nœud et lmax. Ainsi si lmax est supérieur à cette borne
minimale, alors nous n’avons aucune chance de trouver une meilleure fonction de coût dans
tous les descendants du nœud. Il est inutile d’explorer dans cette partie ce qui peut faire
gagner énormément de temps.
branch1 l1min evaluation part
= lower bound
branch2 l2min
branch3 l3min = lmax
A priori l3min ≥ l2min ≥ l1min
branch1 l1min
branch2 l2min
branch3 l3min
inutile d'explorer
4
branch4 l4min si lmax ≤ l min
branch1 l1min
branch2 l2min
branch3 l3min
inutile d'explorer
si lmax ≤ l5min
branch5 l4min
exploration si lmax > l5min
lmax peut alors diminuer
exploration si lmax > l4min
lmax peut alors diminuer si une meilleure
fonction de coût est découverte
Nous concrétisons cet algorithme de deux manières différentes pour résoudre le problème du
voyageur de commerce.
3/6
Algorithme d’insertion de nœuds
L’algorithme par insertion de nœuds procède en partant d’un trajet de longueur 3 et en
insérant progressivement des nœuds dans ce trajet. La première décision (branch) consiste à
choisir le trajet initial de longueur 3. Étant donné que les points se trouveront dans cet ordre
dans le trajet optimal, il n’y a pas lieu de revenir sur cette décision. Les 3 points initiaux ont
donc tout intérêt à se trouver éloignés les uns des autres. Les décisions suivantes consistent à
choisir un nœud en même temps que son emplacement d’insertion.
La borne minimale de coût peut être la longueur du trajet déjà construit. Cette borne est bien
minimale si nous avons affaire à une distance euclidienne.
L’algorithme se comporte de la manière suivante sur un petit exemple, ne comparant que 10
trajets complets au lieu des (6-1)!/2 = 60 possibilités.
lmin = 27
lmin = 19
lmin = 27
lmin = 21
lmin = 30, abandonné si lmax ≤ 30
lmin = 26
trajet final
lmin = 24
lmin = 23
lmin = 21, trajet conservé
lmin = 25
lmin = 25
lmin = 24
finalement ces 2
possibilités et les
3 autres sont
abandonnées
lmin = 26
lmin = 28
lmin = 25
4/6
Algorithme d’insertion d’arc
Cet algorithme est généralement plus efficace que le précédent. Il détermine si des arcs
peuvent faire partie du trajet optimal. La décision (branchement ou séparation) est tel arc
appartient au trajet optimal ou tel arc n’y appartient pas. La borne minimale de coût est un peu
plus complexe à calculer. Elle contient la somme des longueurs des arcs insérés +
min({d(x,y) / y n'est pas une destination d'arc présent}) = soustrait des
∑
x non en origine d'un arc présent
lignes + ce qui reste à soustraire des colonnes.
Il est possible d’améliorer cette fonction de coût, sachant qu’elle fonctionne aussi bien pour
des distances euclidiennes que d’autres distances.
B
On soustrait de chaque ligne l'élément minimal.Idem pour les colonnes
Evaluation minimale = ce qui a été soustrait + Σ longueurs des arcs sélectionnés
D
F
matrice de
coût
E
C
A
A
B
C
D
E
F
A
B
C
D
E
F
1
1
4
3
0 (1)

1
3
3
4
0 (1)

1
3
2
0 (1)
1

4
2
2
1
 0 (1)
3
4
2
0 (1) 0 (1) 
1
1
2
0 (1) 0 (1)

AF
B
C
D
E
F
A
1
1
4
3
0
B

3
2
4
0
C
3

2
0
1
AF = AF exclus
Séparation : On essaye de choisir si un couple
n'est pas dans le chemin optimal (estimer de
combien augmentera la fonction de coût
= ce qui peut être soustrait)
Encore des
branches
lmax = lmin = 20
potentielles
avec lmax = 20
A
B
C
D
E
F
A

1
1
4
3
0
B
1

3
2
4
0
A
B
C
D
E
F
A

4
4
8
6
3
D
3
2

0
1
E
4
0
0

2
B
4

5
5
6
2
C
4
5

5
2
3
D
4
3
2

0
1
E
3
4
0
0

2
E
6
6
2
3

4
lmin = 16
F
3
2
3
4
4

A
B
C
D
E
F
lmin = 17
lmin = 17
C
1
3

2
0
1
D
8
5
5

3
4
B
C
D
E
F
A

1
4
3
0
B
1

3
2
4
0
C
1
3

2
0
1
D
4
3
2

0
1
BA
B

3
2
4
0
E
3
4
0
0

2
F
0
0
1
1
2

A
B
C
D
E
B 0 (2) 
2
2
3
C
1
3
2
0 (1)

D
4
2
2
 0 (2)
E
3
4
0 (1) 0 (1) 
F 0 (0) 0 (2)
1
1
2
lmin = 19
F

0
1
1
2

A

1
1
4
3
0
C
2

2
0
1
D
2
2

0
1
E
3
0
0

2
BA
C
D
E
F
B
3
2
4

C

2
0
1
D
2

0
1
E
0
0

2
lmin = 21
A B C D
B   2 2
C 1 3  2
D 4 2 2 
E 3 4 0 0
F 0 0 1 1
invalidé par le
2nd lmax
C D
B  0
E 0 
CA
E
3
0 DE
0

2
A
B
C
D
E
1
B 
 0 (0) 0 (0)
1
3
2
0 (1)
C

4
2
2
D
 0 (2)
3
4
0 (0) 0 (0) 
E
1
1
2
F 0 (1) 0 (2)
DE
inutile, car dans
ce cas, lmin = 22
FB
lmin = 20
C
D
A
B  0 (0) 0 (0)
1
C 0 (4) 
3
0 (0) 0 (0)
E
A
B 
C 0
E 3
C
0

0
D
0
1
0
lmin = 20
C
D
A
B
B 
 0 (0) 0 (0)
2
C 0 (1)
1

FB E
3
4
0 (0) 0 (0)
1
F 0 (0) 0 (2)
1
B
C
E
F
A

1
3
0
B

3
4
0
C
0

0
1
D
0
2
0
1
lmin = 22
B
C
D
E
C
1
2
0 (1)

D 0 (1)
2
 0 (0)
E
2
0 (0) 0 (0) 
F  0 (0) 0 (0)
1
invalidé par le
2nd lmax
CE
B C D
D 0 2 
E 2  0
F  0 
lmax = lmin = 22
5/6
Étape 2 : Réalisation du démonstrateur
Question C :
Implanter une façon d’effectuer l’acquisition des données pour un démonstrateur. Il est
possible de stocker le résultat dans une matrice de coût, mais vous pouvez utiliser tout
autre représentation.
Question D :
Définissez et implantez la notion de trajet pour le voyageur de commerce.
Question E :
Implantez un algorithme exact de type Branch & Bound ou un algorithme approché pour
la résolution du problème.
Question F :
Visualisez et estimez le temps que vous avez passé pour atteindre ce premier objectif.
Conservez l’ensemble des fichiers du projet.
Étape 3 : Amélioration de l’outil
Vous avez le choix pour améliorer votre outil, mais n’oubliez pas de conserver le résultat de
l’étape 2.
Une amélioration naturelle est de faire en sorte que l’algorithmique de recherche de trajet
Branch & Bound traite de plus en plus de villes dans votre plan.
L’implantation d’un algorithme de type exact est conseillée pour les personnes qui ont
implanté un algorithme approché à l’étape 2.
Vous pouvez également améliorer l’acquisition des données et faire en sorte qu’elle s’effectue
sur des notions plus naturelles pour un utilisateur externe au projet.
Bref, n’hésitez pas à laisser libre court à votre imagination, tout en restant dans le domaine du
réalisable dans le temps que vous avez décidé de consacrer au projet.
6/6
Téléchargement