polycopié

Transcription

polycopié
RECHERCHE OPERATIONNELLE
PLUS COURTS CHEMINS
DANS DES GRAPHES VALUES
I INTRODUCTION
(1) Notations, Problèmes
(2) Quelques résultats fondamentaux
(3) Structures de données
II PLUS COURTS CHEMINS D’UN SOMMET A TOUS LES AUTRES
(1) Algorithme de DIJKSTRA
(2) Algorithme de BELLMAN-FORD
III PLUS COURTS CHEMINS ENTRE TOUS LES COUPLES DE
SOMMETS
(1) Algorithme de DANTZIG
(2) Algorithme de FLOYD
I - INTRODUCTION
Tout le monde connaît la boutade : « Quel est le plus court chemin pour aller d’un
point A à un point B ? – Ben, la ligne droite … – Mais non, c’est le raccourci ! » Ce que
confirment les êtres infiniment plats, en fait chacun réduit à un point, vivant sur S2, la surface
de la sphère usuelle, qui savent tous dès leur plus jeune age (mais est-ce aussi le cas des
chauffeurs de taxi ?) que pour aller de A à B il faut utiliser un arc de grand cercle, en bref
suivre la géodésique locale
Et oui, si Ulysse l’avait su Pénélope eût été ravie
Ou alors, comme dit le Chat : « Le plus court chemin d’un point à un autre c’est de ne
pas y aller » … Certes, mais allons y tout de même
De fait de nombreux problèmes de RO reviennent à déterminer l’existence de chemins,
ou les meilleurs chemins, en un sens à préciser, entre certains ou tous les sommets d’un
graphe. On les rencontre dès qu’il s’agit d’acheminer par exemple des marchandises entre
deux points d’un réseau ou d’un entrepôt à des centres de vente, de façon à minimiser un coût,
une durée, etc. Ils apparaissent aussi en sous problèmes de nombreux problèmes
combinatoires comme les flots et les ordonnancements
(1)
Notations, Problèmes
Nous nous plaçons dans le cadre général suivant
Soit G = (X, U, v) un graphe simple orienté valué : tout arc xy est muni d’une
valuation v(x, y) (coût, temps, distance, capacité, …) réelle quelconque
On utilise aussi les mots pondéré et pondération à la place de valué et valuation
Si C = (x1, x2, … , xk) est un chemin de G de x1 à xk sa longueur est :
k −1
v(C) = v(x1, x2, … , xk) = ∑ v(xi xi +1) = d(x1, xk)
i =1
Si x1 est un sommet fixé à l’avance on pourra noter plus simplement d(xk) la
« distance » de x1 à tout sommet xk, bien sûr d(x1) = 0
Les problèmes étudiés ici sont :
(P1) Recherche des plus courts chemins reliant un sommet à tous les autres
(P2) Recherche de tous les plus courts chemins entre tous les couples de sommets
Notons qu’il n’y a pas de solution spécifique au problème consistant à chercher un plus
court chemin entre deux sommets x et y particuliers d’un graphe, il se résout en résolvant (P1) :
partant de x on s’arrête arrivé en y
1
Les algorithmes étudiés ici sont ceux de DIJKSTRA et de BELLMAN – FORD qui
résolvent (P1) respectivement lorsque v ≥ 0 puis lorsque v est quelconque, et les algorithmes
de DANTZIG et de FLOYD qui résolvent (P2)
L’algorithme de DIJKSTRA est sans doute le plus utilisé car il est aisé à mettre en
œuvre, efficace en temps d’exécution et bien adapté aux situations courantes, c’est pourquoi
nous en donnerons une écriture détaillée
Nous détaillerons aussi l’algorithme de DANTZIG car il est matriciel, donc facile à
mettre en œuvre, et plus efficace que l’algorithme de BELLMAN – FORD appliqué à tous
les sommets lorsque v est quelconque. Puis nous présentons succinctement l’algorithme de
FLOYD dont les détails sont laissés en exercice
Pour simplifier nous écrirons « PC2 » pour « Plus Court(s) Chemin(s) »
Conventionnellement : | X | = n, X = {1, 2, …, n}, les sommets sont numérotés de 1 à
n, et | U | = m (et | E | = m, si le graphe est non orienté)
Considérons par exemple le graphe orienté valué suivant ayant 6 sommets (1, 2, …, 6)
et 11 arcs où tous les couples de chemins existent et dont les valuations sont indiquées sur les
arcs :
1
5
2
6
3
3
3
2
1
1
4
2
2
1
6
Les deux arcs 34 et 43 existent et v(3, 4) = 1 et v(4, 3) = 3
Nous utiliserons cet exemple pour illustrer chacun des algorithmes étudiés
(2)
Quelques résultats fondamentaux
Un circuit absorbant de G est un circuit de longueur négative
Les trois Théorèmes suivants donnent les conditions d’existence des PC2 ainsi que
leurs structures
Théorème 1
(P1) a une solution à partir de s ∈ X si et seulement si s est racine (ie il y a un chemin
de s à tous les autres sommets) et G est sans circuit absorbant
Donc si G = (X, E, v) est un graphe simple non orienté connexe valué où v ≥ 0 alors
(P1), donc (P2), a toujours une solution à partir de tout sommet de G, mais cette solution n’est
pas nécessairement unique
2
Théorème 2 (Principe d’optimalité)
Tout sous-chemin xi, … , xj d’un chemin optimal x1, …, xi, … , xj, … , xk de x1 à xk est un
chemin optimal de xi à xj
Nous retrouverons ce Principe dans un cadre plus général, celui de la Programmation
Dynamique
Le théorème suivant concrétise davantage les choses
Théorème 3
La suite d(1), d(2), … , d(n) représente les plus courtes distances de 1 à 2, … , n
respectivement si et seulement si d(1) = 0, d(y) ≤ d(x) + v(x, y) ∀ xy ∈ U et le graphe partiel des
PC2 de 1 aux autres sommets, G’ = (X, U’) où U’ = { xy ∈ U | d(y) = d(x) + v(x, y) }, admet 1
comme racine (c’est une arborescence si chaque PC2 est unique)
(3)
Structures des données et des résultats
Répétons-le, quel que soit le problème, pour le résoudre effectivement, il faut toujours
savoir définir, d’une façon ou d’une autre, tant que c’est possible, quelles sont précisément ses
données (en gros d’où part-on ?) et quelles structures doivent avoir, ou souhaiterions nous, pour
les résultats (où va t’on ? que cherche t’on exactement ?), ceux-ci peuvent en effet à leur tour
faire l’objet de traitements ultérieurs. Cela participe de la modélisation du problème
Nous supposerons ici que le graphe G = (X, U, v) où X = {1, 2, … , n} est donné par sa
matrice d’adjacence M, de taille n.n, définie par M(i, j) = v(i, j) si et seulement si ij ∈ U,
sinon M(i, j) = ∞, pour simplifier on note ∞ pour + ∞, avec bien sûr M(i, i) = 0
(P1) consistera à chercher les PC2 du sommet 1 aux autres sommets
Pour le calcul des PC2 de 1 aux autres sommets il faut déterminer le tableau d(1),
d(2), … , d(n) des distances (d(i) = ∞ si un tel chemin n’existe pas) et le tableau p(1), p(2), …
, p(n) des prédécesseurs défini par : p(1) = 1 et p(i) = j ⇔ j est le prédécesseur de i sur un PC2
de 1 à i, s’il existe, 0 sinon. Nous aurons ainsi au plus un PC2 par sommet
Le tableau p permet, à la demande et s’il existe, de construire effectivement un PC2 de 1
à un sommet donné ainsi que l’arborescence des PC2
Pour le calcul des PC2 entre tous les couples de sommets il faut déterminer la matrice
D des distances, D(i, j) = longueur d’un PC2 de i à j s’il existe, ∞ sinon, bien sûr D(i, i) = 0, et
la matrice P des prédécesseurs, P(i, j) = prédécesseur immédiat de j sur un PC2 de i à j s’il
existe, 0 sinon. Là aussi il y aura au plus un PC2 pour chaque couple de sommets
Comme dans le cas précédent P permet de construire effectivement un PC2 entre tout
couple de sommets ainsi que le sous graphe des PC2, si nécessaire
Remarquons enfin que l’étude faite dans le cadre général des graphes orientés reste
bien sûr valable pour les graphes non orientés
3
II - PLUS COURTS CHEMINS D’UN SOMMET A TOUS LES AUTRES
(1) Algorithme de DIJKSTRA
L’algorithme de DIJKSTRA (1959) résout (P1) lorsque v ≥ 0
Principe et squelette de l’algorithme
A chaque étape l’ensemble des sommets est divisé en trois parties disjointes :
V = {sommets visités} est l’ensemble des sommets x pour lesquels d(x) est connue, 1 ∈ V et
d(1) = 0
A = {sommets atteints} est l’ensemble des successeurs immédiats et non visités des sommets
visités, pour ces sommets on a une estimation de la distance
X – (V ∪ A) pour lesquels d(y) = ∞
L’algorithme consiste tout simplement alors à prendre dans A le sommet ayant la plus
petite distance estimée
Initialement :
V = {1}, d(1) = 0 et p(1) = 1
A = {successeurs immédiats de 1} et d(x) = M(1, x), p(x) = 1 si x ∈ A
d (y) = ∞ pour tout y dans X – (V ∪ A)
Etape courante (jusqu’à visiter tous les sommets) :
choix de x dans A tel d(x) soit minimal
V = V ∪ {x}
A = A - {x} ∪ {y | y successeur de x ni visité ni atteint}
pour chaque successeur non visité y de x on calcule d(y) = min {d(y), d(x) + M(x, y)}, on aura
alors p(y) = x si le minimum change
Si nous appliquons l’algorithme sur notre exemple, il y a 6 étapes qui sont :
Etape initiale : V = {1}, d(1) = 0, p(1) = 1, A = {3, 4} (ce sont les successeurs de 1) avec d(3)
= 6, d(4) = 2 et p(3) = 1, d(4) = 1, tous les autres sommets ont une distance infinie et leurs
prédécesseurs sont à 0
Première étape : 4 est choisi donc V = {1, 4} et sa distance (définitive) est d(4) = 2, on a
maintenant A = {2, 3}, d(2) = 4, d(3) = 5, p(2) = 4, p(3) = 4, les autres sommets ont une
distance infinie et sont sans prédécesseur, dans la suite nous ne mentionnerons plus ces
sommets, seuls seront mentionnés les sommets de V et A
Deuxième étape : 2 est choisi donc V = {1, 2, 4} et sa distance est d(2) = 4, d’où A = {3}, d(3)
= 5 et p(3) = 4
Troisième étape : 3 est choisi donc V = {1, 2, 3, 4} et sa distance est d(3) = 5, d’où A = {5, 6},
d(5) = 8, d(6) = 6 et p(5) = 3, p(6) = 3
Quatrième étape : 6 est choisi donc V = {1, 2, 3, 4, 6} et sa distance est d(6) = 6 et p(6) = 3,
d’où A = {5}, d(5) = 7 et p(5) = 6
4
Cinquième et dernière étape (car à l’issue de cette étape tous les sommets sont visités) : 5
est choisi donc V = {1, 2, 3, 4, 5, 6}, sa distance est d(5) = 7 et p(5) = 6
On peut illustrer avantageusement la suite des calculs par la tableau suivant :
2
3
4
5
6
V = {1}
∞
6, 1
2, 1
∞
∞
V = {1, 4}
4, 4
5, 4
-
∞
∞
V = {1, 2, 4}
-
5, 4
-
∞
∞
V = {1, 2, 3, 4}
-
-
-
8, 3
6, 3
V = {1, 2, 3, 4, 6}
-
-
-
7, 6
-
V = {1, 2, …, 6}
4, 4
5, 4
2, 1
7, 6
6, 3
Chaque ligne contient V, les distances estimées ou définitives (en gras) de 1 à chaque
sommet ainsi que le prédécesseur courant. Par exemple en ligne 2 : V = {1, 4}, 4 a été choisi, sa
distance est 2, elle est définitive, son prédécesseur est 1 (inutile donc de mentionner à nouveau
ces renseignements dans les lignes suivantes) et les distances estimées sont celles des sommets
2 et 3, notées avec les prédécesseurs courants respectifs
La dernière ligne correspondant à la dernière étape contient les résultats définitifs
Le graphe partiel des plus courts chemins trouvés correspond à l’arborescence suivante :
1
5
3
2
1
1
3
2
4
6
2
Ce graphe partiel est bien entendu construit à partir du tableau p des prédécesseurs
5
A titre d’exemple, nous donnons ci dessous une écriture détaillée possible de
l’algorithme
Précisons tout d’abord les structures de données choisies, rappelons que les sommets
sont numérotés 1, 2, … , n :
- Matrice d’adjacence du graphe : M (M(i, j) = v(i, j))
- Tableau des distances : d
- Tableau des prédécesseurs : p
- Tableaux binaires (en vrai/faux ou 0/1) de marque des visités et des atteints : visité et
atteint
- Tableau stockant (entre les indices 1 et k) les sommets atteints : A
- Divers entiers de gestion de boucles, de comptage, de désignation de sommets, …
Sachant que les trois parties entre guillemets demandent bien sûr à être précisées, les
lecteurs curieux les traduiront aisément dans leur langage préféré, l’algorithme peut alors
s’écrire :
/* initialisations */
d(1) = 0 ; p(1) = 1
visité(1) = vrai
s=1
pour i = 2 à n faire
visité(i) = faux
atteint(i) = faux
d(i) = + ∞
k=0
pour « chaque successeur i de 1 » faire
k=k+1
A(k) = i
atteint(i) = vrai
d(i) = M(1, i) ; p(i) = 1
/* corps de l’algorithme */
tant que s < n faire
x = « élément de A, entre 1 et k, tel que d(x) soit minimal, soit i son indice »
« échanger A(i) et A(k) »
k=k–1
visité(x) = vrai
s=s+1
pour « chaque successeur y de x » faire
si visité(y) = faux alors
si atteint(y) = faux alors atteint(y) = vrai ; k = k + 1 ; A(k) = y
D = d(x) + M(x, y)
si D < d(y) alors d(y) = D ; p(y) = x
6
Estimation des coûts (complexités)
En espace : O(n2), car utilisation d’une matrice d’adjacence de taille n2, de cinq
tableaux tous de taille au plus n et d’un nombre constant de variables auxiliaires
En temps : O(n2), car initialisations en O(n) et corps de l’algorithme en n – 1 étapes,
chacune utilisant O(n) opérations élémentaires (la recherche des successeurs d’un sommet x
nécessite le parcours de la ligne x de la matrice et le calcul de l’élément minimum de A(1), … ,
A(k) se fait en O(k), k ≤ n)
On peut démontrer
Théorème
L’algorithme de DIJKSTRA calcule au plus un PC2 de 1 à tous les autres sommets du
graphe en O(n2) en temps et en espace
Attention, hormis les estimations des coûts, pour établir ce théorème il reste à justifier
que l’algorithme calcule effectivement les PC2 cherchés. En gros on peut procéder par
récurrence : la valuation étant positive la propriété est vraie pour le premier sommet choisi, il
suffit alors de montrer qu’étant vraie pour les k premiers sommets choisi elle le reste pour le
sommet suivant (exercice)
Remarques
Si l’on veut uniquement chercher un PC2 de 1 à un sommet particulier x0 il suffit
d’arrêter l’algorithme dès que x0 devient visité
La seule différence entre la version orientée vue ici et la version non orientée consiste
pour cette dernière à remplacer la recherche des successeurs par celles des voisins
Il existe des implémentations plus efficaces de l’algorithme quand le graphe est peu
dense, c’est à dire quand m << n2, si le graphe est représenté par un tableau de listes de
successeurs et si A est géré en tas (heap) la complexité en espace est en O(n + m) et la
complexité en temps en O(mlogn)
Quelques sujets de réflexion
• Montrer que l’algorithme de DIJKSTRA est faux s’il existe des valuations négatives
• Ecrire un algorithme permettant de construire effectivement, quand il existe, un PC2 du
sommet 1 à un sommet donné i, ou de construire l’arborescence des PC2
• Montrer qu’on peut simplifier cet algorithme lorsque
(i)
les valuations sont constantes
(ii)
le graphe est sans circuit
(iii) le graphe est un réseau routier représenté à une certaine échelle
7
Exercice
Un réseau aérien relie 8 villes A, B, C, D, E, F, G et H. Les durées (en heures) des
trajets existant entre ces villes sont données par la matrice M suivante :
A
B
C
D
E
F
G
H
A
0
6
∞
2
∞
∞
8
∞
B
6
0
4
1
2
∞
2
∞
C
∞
4
0
∞
8
1
3
∞
D
2
1
∞
0
1
∞
∞
∞
E
∞
2
8
1
0
9
∞
∞
F
∞
∞
1
∞
9
0
∞
2
G
8
2
3
∞
∞
∞
0
7
H
∞
∞
∞
∞
∞
2
7
0
M(i,j) = ∞ lorsque i ≠ j signifie bien sûr qu’il n’existe pas de liaison entre i et j
(1) Dessiner le graphe non orienté correspondant. Une représentation planaire, c’est-àdire sans intersection d’arêtes, est possible
(2) Une entreprise de livraison située dans la ville A souhaitant satisfaire au mieux ses
clients désire déterminer les meilleurs itinéraires c’est-à-dire les chemins de livraison les plus
rapides de la ville A aux autres villes. Déterminer ces itinéraires en utilisant l’algorithme de
DIJKSTRA, puis déterminer et représenter le graphe partiel de ces itinéraires
(3) La compagnie aérienne gérant le réseau veut déterminer les meilleurs itinéraires
entre toutes les villes. Calculer ces itinéraires
(4) On fait l’hypothèse que le coût de gestion d’u ne liaison est proportionnel à sa
longueur (donc à la durée du trajet). Déterminer un sous-réseau (graphe partiel) permettant de
relier toute ville à toute autre ville (via éventuellement des villes intermédiaires) et qui soit le
plus économique possible
Éléments de réponses :
(1) Placer les sommets A, D, E, F, H et G, dans cet ordre, comme sommets d’un hexagone
régulier
(2) d(A) = 0, d(B) = 3, d(C) = 7, d(D) = 2, d(E) = 3, d(F) = 8, d(G) = 5 et d(G) = 10. Les
arêtes du graphe partiel de ces itinéraires sont : AD, BC, BD, BG, CF, DE, et FH
(3) Appliquer l’algorithme de DIJKSTRA à partir de chacun des sommets du graphe
(4) La solution du problème est un arbre recouvrant minimal, il suffit d’appliquer
l’Algorithme de KRUSKAL ou de PRIM (voir poly sur ce problème). L’arbre obtenu a
un coût égal à 12, il est unique
8
(2) Algorithme de BELLMAN-FORD
L’algorithme de BELLMAN-FORD (1956) permet de résoudre (P1) pour des
valuations quelconques
Principe
A partir de d(1) = 0 et d(x) = +∞ ∀ x ≠ 1, on parcourt séquentiellement tous les arcs du
graphe : pour chaque arc xy on teste si d(y) ≤ d(x) + M(x, y) si ce n’est pas le cas d(y) prend
la valeur d(x) + M(x, y), puis on teste l’arc suivant. Si, à l’issue d’un deuxième parcours, d
n’est pas modifié, il représente les distances cherchées sinon un parcours supplémentaire est
nécessaire et cela jusqu’à stabilisation de d
Squelette de l’algorithme
d(1) = 0
p(1) = 1
pour i = 2 à n faire
d(i) = +∞
p(i) = 0
tant que ∃ xy ∈ U tel que d(y) > d(x) + M(x, y) faire
d(y) = d(x) + M(x, y)
p(y) = x
Appliquons l’algorithme sur notre exemple
On initialise le tableau des distances à : d(1) = 0 et d(2) = … = d(6) = ∞ et le tableau des
prédécesseurs à p(1) = 1 et p(2) = … = p(6) = 0 (0 signifiant ici non déterminé). L’algorithme
consiste à faire plusieurs parcours (faire un parcours du graphe c’est parcourir un à un tous ses
arcs) et si, dans un parcours, on a un arc xy vérifiant d(y) > d(x) + M(x, y) (ce qui montre que le
chemin allant de 1 à y en passant par x est plus court le chemin déjà connu de longueur d(y))
alors d(y) devient d(y) = d(x) + M(x, y) et p(y) = x.
L’algorithme ne s’arrête que si, dans un parcours, aucune modification n’est faite.
Pour chaque parcours considérons les arcs dans l’ordre lexicographique (ce n’est pas
obligatoire, tout ordre convient, mais c’est plus simple à gérer) c’est à dire 13, 14, 21, 34, 35,
36, 42, 43, 51, 64 et 65. Nous ne détaillerons pas toutes les étapes de l’algorithme, examinons
tout de même le premier parcours en détail
13 : d(3) = ∞ > d(1) + M(1, 3) = 0 + 6 = 6, d’où les modifications d(3) = 6 et p(3) = 1
14 : d(4) = ∞ > d(1) + M(1, 4) = 0 + 2 = 2, d’où les modifications d(4) = 2 et p(4) = 1
21 : aucune modification puisque d(1) = 0 ≤ d(2) + M(2, 1) = ∞ + 3 = ∞
34 : aucune modification puisque d(4) = 2 ≤ d(3) + M(3, 4) = 6 + 1 = 7
35 : d(5) = ∞ > d(3) + M(3, 5) = 6 + 3 = 9, d’où les modifications d(5) = 9 et p(5) = 3
36 : d(6) = ∞ > d(3) + M(3, 6) = 6 + 1 = 7, d’où les modifications d(6) = 7 et p(6) = 3
9
42 : d((2) = ∞ > d(4) + M(4, 2) = 2 + 2 = 4, d’où les modifications d(2) = 4 et p(2) = 4
43 : d(3) = 6 > d(4) + M(4, 3) = 2 + 3 = 5, d’où les modifications d(3) = 5 et p(3) = 4
51 : aucune modification puisque d(1) = 0 ≤ d(5) + M(5, 1) = 9 + 2 = 11
64 : aucune modification puisque d(4) = 2 ≤ d(6) + M(6, 4) = 7 + 1 = 8
65 : d(5) = 9 > d(6) + M(6, 5) = 7 + 1 = 8, d’où les modifications d(5) = 8 et p(5) = 6
Dans le deuxième parcours (tous les arcs du graphe sont à nouveau passés en revue,
toujours dans le même ordre : 13, 14, … , 65) les deux seules modifications sont (et dans cet
ordre) :
36 : d((6) = 7 > d(3) + M(3, 6) = 5 + 1 = 6, d’où la modification d(6) = 6 et p(6) = 3
65 : d(5) = 8 > d(6) + M(6, 5) = 6 + 1 = 7, d’où la modification d(5) = 7 et p(5) = 6
Un troisième parcours est donc nécessaire, celui-ci n’apporte rien, l’algorithme est donc
terminé. Les tableaux définitifs des distances de 1 à tous les autres sommets et des
prédécesseurs sont donc respectivement : d(2) = 4, d(3) = 5, d(4) = 2, d(5) = 7, d(6) = 6 et p(2)
= 4, p(3) = 4, p(4) = 1, p(5) = 6, p(6) = 3
On retrouve le graphe partiel des PC2 obtenu avec l’algorithme de DIJKSTRA
Remarquons pour terminer que cet exemple met bien en évidence la différence
d’efficacité en temps de ces deux algorithmes : l’algorithme de DIJKSTRA est bien plus rapide
et clair que celui de BELLMAN – FORD
On peut montrer
Théorème
Si G n’a pas de circuit absorbant l’algorithme de BELLMAN-FORD résout (P1) en au
plus n – 1 parcours du graphe
Exercices
• Reprendre l’exemple précédent en échangeant les sommets 3 et 4, en quoi l’algorithme
se comporte t’il différemment ?
• En s’inspirant de l’exemple donner une écriture détaillée de l’algorithme et montrer
que si G est donné par sa matrice d’adjacence il est implémentable O(n3) en temps et
en O(n2) en espace
• Montrer que si le nième parcours modifie encore les distances alors le graphe contient
nécessairement un circuit absorbant. Comment alors construire celui-ci ?
10
III - PLUS COURTS CHEMINS ENTRE TOUS LES SOMMETS
Dans le cas où v ≥ 0 il suffit d’appliquer l’algorithme de DIJKSTRA à partir de
chacun des sommets du graphe, le calcul de tous les PC2 se fait donc alors en O(n3)
Les algorithmes de DANTZIG (1966) et de FLOYD (1962), essentiellement matriciels,
permettent de résoudre directement (P2) pour une valuation quelconque
(1) Algorithme de DANTZIG
Principe et squelette de l’algorithme
L’idée est de calculer de proche en proche, les matrices D et P sur des sous graphes de
plus en plus gros allant du sous graphe réduit au sommet 1 jusqu’au graphe tout entier
Pour k ∈ {1, 2, … , n} notons Gk le sous-graphe engendré par les sommets 1, 2, … , k et
Dk la matrice des distances des PC2 entre tous les couples de sommets de Gk
Il faut donc calculer D = Dn tout en actualisant à chaque étape la matrice des
prédécesseurs P
On a D1(1, 1) = 0
Pour k variant de 1 à n – 1 la construction de la matrice Dk+1 à partir de la matrice
Dk se fait de la façon suivante :
- pour tout i variant de 1 à k
Dk+1(i, k+1) = min {Dk(i, j) + M(j, k+1) | 1 ≤ j ≤ k}
P(i, k +1) = j, pour « le j » réalisant le minimum, ci celui-ci est fini
- pour tout i variant de 1 à k
Dk+1(k+1, i) = min {M(k+1, j) + Dk(j, i) | 1 ≤ j ≤ k}
P(k + 1, i) = soit k + 1 soit P(j, i) selon que le minimum est réalisé par j = i ou non
- pour tous les i et j variant de 1 à k (i ≠ j)
Dk+1(i, j) = min {Dk(i, j), Dk+1(i, k+1) + Dk+1(k+1, j)}
P(i, j) = P(k + 1, j) si le minimum change
Explicitons l’algorithme sur notre exemple
Initialement D(i, i) = 0 et P(i, i) = i, D(i, j) = ∞ et P(i, j) = 0 pour tout i ≠ j
Il y a 5 étapes, k variant de 1 à 5 ; examinons-les successivement (pour ne pas trop
surcharger le déroulement de l’algorithme seules certaines étapes sont détaillées)
-
pour k =1 : D(1, 2) = D(1, 1) + M(1, 2) = 0 + ∞ = ∞ et D(2, 1) = M(2, 1) + D(1, 1) = 3
+ 0 = 3, donc P(2, 1) = 2
-
pour k = 2 : D(1, 3) = min (D(1, 1) + M(1, 3), D(1, 2) + M(2, 3)) = min (0 + 6, ∞ + ∞)
= 6, donc P(1, 3) = 1 ; D(2, 3) = min (D(2, 1) + M(1, 3), D(2, 2) + M(2, 3)) = min (3 +
6, 0 + ∞) = 9, donc P(2, 3) = 1 ; D(3, 1) = min (M(3, 1) + D(1, 1), M(3, 2) + D(2, 1)) =
min (∞ + 0, ∞ + 3) = ∞ ; D(3, 2) = min (M(3, 1) + D(1, 2), M(3, 2) + D(2, 2)) = min
(∞ + 3, ∞ + 0) = ∞; enfin D(1, 2) = min (D(1, 2), D(1, 3) + D(3, 1)) = min (∞, 6 + ∞)
= ∞ et D(2, 1) = min (D(2, 1), D(2, 3) + D(3, 1)) = min (3, 9 + ∞) = 3
11
-
pour k = 3 : il faut calculer D(1, 4), D(2, 4) et D(3, 4), par exemple D(1, 4) = min (
D(1, 1) + M(1, 4), D(1, 2) + M(2, 4), D(1, 3) + M(3, 4)) = min (0 + 2, ∞ + ∞, 6 + 1) =
2, donc P(1, 4) = 1 ; il faut ensuite calculer D(4, 1), D(4, 2) et D(4, 3) puis finalement
D(1, 2), D(1, 3), D(2, 1), D(2, 3), D(3, 1) et D(3, 2). Nous obtenons : D(2, 4) = 5 (P(2,
4) = 1), D(3, 4) = 1 (P(3, 4) = 3) ; D(4, 1) = 5 (P(4, 1) = 2), D(4, 2) = 2 (P(4, 2) = 2),
D(4, 3) = 3 (P(4, 3) = 4) ; D(1, 2) = 4 (P(1, 2) = 4), D(1, 3) = 5 (P(1, 3) = 4), D(2, 3) =
8 (P(2, 3) = 4), D(3, 1) = 6 (P(3, 1) = 2) et D(3, 2) = 3 (P(3, 2) = 4)
-
pour k = 4 : nous obtenons D(1, 5) = 8 (P(1, 5) = 3), D(2, 5) = 11 (P(2, 5) = 3), D(3, 5)
= 3 (P(3, 5) = 3), D(4, 5) = 6 (P(4, 5) = 3) ; D(5, 1) = 2 (P(5, 1) = 5), D(5, 2) = 6 (P(5,
2) = 4), D(5, 3) = 7 (P(5, 3) = 4), D(5, 4) = 4 (P(5, 4) = 1) ; enfin, seul changement :
D(3, 1) = 5 (P(3, 1) = 5)
-
pour k = 5 : nous obtenons D(1, 6) = 6 (P(1, 6) = 3, D(2, 6) = 9 (P(2, 6) = 3), D(3, 6) =
1 (P(3, 6) = 3), D(4, 6) = 4 (P(4, 6) = 3), D(5, 6) = 8 (P(5, 6) = 3) ; D(6, 1) = 3 (P(6, 1)
= 5), D(6, 2) = 2 (P(6, 2) = 4), D(6, 3) = 4 (P(6, 3) = 4), D(6, 4) = 1 (P(6, 4) = 6), D(6,
5) = 1 (P(6, 5) = 6) ; enfin, les derniers changements sont : D(1, 5) =7 (P(1, 5) = 6),
D(2, 5) = 10 (P(2, 5) =6), D(3, 1) = 4 (P(3, 1) = 5), D(3, 5) = 2 (P(3, 5) = 6), D(4, 5) =
5 (P(4, 5) = 6)
Il est facile d’établir
Théorème
Si G est sans circuit absorbant l’algorithme de DANTZIG calcule au plus un PC2
entre tous les couples de sommets du graphe en O(n3) en temps et en O(n2) en espace
Comme pour l’algorithme de DIJKSTRA, nous donnons ci dessous quelques éléments
précisant chacune des étapes de l’algorithme de DANTZIG et permettant d’en faire plus
facilement l’estimation des coûts
Les structures de données nécessaires sont :
- La matrice d’adjacence du graphe M (M(i, j) = v(i, j))
- La matrice des distances D
- La matrice des prédécesseurs P
- Divers entiers de gestion de boucles, de comptage, de désignation de sommets, …
/* initialisations */
pour i = 1 à n faire
pour j = 1 à n faire
si i ≠ j alors P(i, j) = 0
D(i, j) = ∞
sinon P(i, j) = i
D(i, j) = 0
12
/* corps de l’algorithme */
pour k = 1 à n – 1 faire
pour i = 1 à k faire
pour j = 1 à k faire
d = D(i, j) + M(j, k+1)
si d < D(i, k+1) alors D(i, k+1) = d; P(i,k+1) = j
d = M(k+1, j) + D(j, i)
si d < D(k+1, i) alors D(k+1, i) = d
si i = j alors P(k+1, i) = k + 1
sinon P(k+1, i) = P(j, i)
pour i = 1 à k faire
pour j = 1 à k faire
d = D(i, k+1) + D(k+1, j)
si d < D(i, j) alors D(i, j) = d ; P(i, j) = P(k+1, j)
Estimation des coûts (complexités)
En espace cet algorithme est en O(n2) (matrices d’adjacence du graphe, des plus
courtes distances et des prédécesseurs)
En temps il est en O(n3) (car pour k variant de 1 à n – 1, i et j varient de 1 à k)
Remarquons que la stratégie sous jacente à l’algorithme de DANTZIG est du type
Programmation Dynamique, voir suite du cours, car il résout le problème global à partir de
solutions de sous problèmes de tailles croissantes
Quelques questions supplémentaires
• L’algorithme de DANTZIG résout (P2) pour toute valuation, comment peut-on le
modifier pour tester s’il existe un circuit absorbant ?
• Ecrire un algorithme permettant de construire effectivement, quand il existe et à partir
de la matrice P, un PC2 entre deux sommets fixés i et j, puis un algorithme construisant
le graphe des PC2
• Quelles simplifications peut-on apporter à l’algorithme lorsque le graphe est non
orienté ? Comment est alors D ?
13
(2) Algorithme de FLOYD
Nous présentons maintenant rapidement l’algorithme de FLOYD dont certains détails
sont laissés en exercice
Formellement, l’algorithme considère une suite de matrices n.n : F0, F1, …, Fn, définies
pour tous les couples de sommets (x, y) de X par :
F0 (x, y) = M(x, y) si xy ∈ U, ∞ sinon, et F0 (x, x) = 0
Fk (x, y) = longueur d’un PC2 reliant x à y dans G dont les sommets
intermédiaires sont dans {1, 2, …, k} ou ∞ si un tel chemin n’existe pas
Remarquons que Fk (x, x) sera la longueur minimale d’un circuit passant par x et
n’utilisant que des sommets de {1, 2, …, k} ∪ {x}, si un tel circuit existe
Nous avons alors :
Propriété
Fk (x, y) = min { Fk-1 (x, y), Fk-1 (x, k) + Fk-1 (k, y) }
Principe de l’algorithme
Partant de F = F0, qui correspond en fait à M, la matrice du graphe, on calcule
successivement F = F1, F = F2, … jusqu’à F = Fn qui est la matrice des distances cherchées
À chaque étape, par le test « Fk (x, x) < 0 ? », on peut détecter l’existence d’un circuit
absorbant et arrêter l’algorithme
La preuve de cet algorithme est immédiate par définition des matrices Fk et d’après la
propriété mentionnée
Exercice
• Prouver la propriété précédente et préciser comment évolue P, la matrice des
prédécesseurs suivant les cas
• Appliquer l’algorithme à l’exemple choisi
• Donner une écriture détaillée de l’algorithme
• Estimer ses complexités en espace et en temps
14

Documents pareils

Programmation Effective – TD 03 : Détections de cycles de

Programmation Effective – TD 03 : Détections de cycles de Arcs de poids négatifs : La fonction de pondération est à valeurs dans R, rien n’empêche donc les arcs d’avoir des poids strictement négatifs. De fait, s’il y a un circuit de poids total strictemen...

Plus en détail