MP* Lycée Masséna
TP 5 : Graphes pondérés
Télécharger le fichier sur le site web contenant des fonctions et quelques exemples de graphes.
1 Implémentation de l’algorithme de Floyd-Warshall
Question 1. Implémentez l’algorithme de Floyd Warshall, rappelé ci-dessous. On utilisera pour cela le type zbar.
#floyd_warshall g1 ;;
- : zbar vect vect =
[|[|Z 0; Z 1; Z -3; Z 2; Z -4|]; [|Z 3; Z 0; Z -4; Z 1; Z -1|];
[|Z 7; Z 4; Z 0; Z 5; Z 3|]; [|Z 2; Z -1; Z -5; Z 0; Z -2|];
[|Z 8; Z 5; Z 1; Z 6; Z 0|]|]
#floyd_warshall gneg ;;
- : zbar vect vect =
[|[|Z -1; Z 1; Z -2; Inf; Inf|]; [|Z -3; Z -1; Z -4; Inf; Inf|];
[|Z -1; Z 1; Z -2; Inf; Inf|]; [|Z 1; Z 3; Z 0; Z 0; Z 5|];
[|Z -3; Z -1; Z -4; Inf; Z 0|]|]
Algorithme 1 : Algorithme de Floyd-Warshall
Entrée : Un graphe pondéré G= (V, E, ω)donné par sa matrice d’adjacence M
Sortie : La matrice des plus courtes (δ(i, j))0i,j<n distances entre deux sommets quelconques du graphe
Acopie(M);
pour tout kentre 0 et n1faire faire
pour tout ientre 0 et n1faire faire
pour tout jentre 0 et n1faire faire
ai,j min(ai,j , ai,k +ak,j )
Renvoyer A
1 3
40
2
8
3
-4
1
7
4
5
2
6
Figure 1: Le graphe du cours (graphe g1)
Question 2. Modifiez l’algorithme pour tester l’existence d’un circuit de poids total strictement négatif.
#floyd_warshall gneg ;;
Uncaught exception: Failure "cycle de poids strictement negatif"
Question 3. Modifier l’algorithme pour calculer en même temps la matrice de liaison Π=(πi,j )0i,j<n, définie par :
πi,j =le prédecesseur de jdans un plus court chemin de iàj, s’il en existe un
1sinon (on pourrait mettre autre chose)
Svartz Page 1/4 2015/2016
MP* Lycée Masséna
#floyd_warshall g1 ;;
- : zbar vect vect *int vect vect =
[|[|Z 0; Z 1; Z -3; Z 2; Z -4|]; [|Z 3; Z 0; Z -4; Z 1; Z -1|];
[|Z 7; Z 4; Z 0; Z 5; Z 3|]; [|Z 2; Z -1; Z -5; Z 0; Z -2|];
[|Z 8; Z 5; Z 1; Z 6; Z 0|]|],
[|[|0; 2; 3; 4; 0|]; [|3; 1; 3; 1; 0|]; [|3; 2; 2; 1; 0|];
[|3; 2; 3; 3; 0|]; [|3; 2; 3; 4; 4|]|]
Question 4. Écrire une fonction impression pi i j d’impression à l’écran d’un plus court chemin entre iet js’il
en existe un.
#imprimer_chemin pi 0 1 ;;
04321
- : unit = ()
Question 5. Pour G= (V, E)un graphe (non pondéré), on appelle fermeture transitive de Gle graphe Gf= (V, Ef)
avec (i, j)Efsi et seulement si il existe un chemin de iàjdans G. Écrire un algorithme capable de calculer la
fermeture transitive d’un graphe avec un algorithme inspiré de l’algorithme de Floyd-Warshall, mais travaillant sur
des matrices de booléens.
#warshall g2 ;;
- : int vect vect =
[|[|0; 1; 1; 0; 0; 1; 1; 1; 1; 0; 1; 1; 1; 1|];
[|0; 0; 1; 0; 0; 1; 1; 1; 1; 0; 1; 1; 1; 1|];
[|0; 0; 0; 0; 0; 0; 0; 0; 1; 0; 0; 0; 0; 0|];
[|1; 1; 1; 0; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1|];
[|1; 1; 1; 1; 0; 1; 1; 1; 1; 1; 1; 1; 1; 1|];
[|0; 1; 1; 0; 0; 0; 1; 1; 1; 0; 1; 1; 1; 1|];
[|0; 1; 1; 0; 0; 1; 0; 1; 1; 0; 1; 1; 1; 1|];
[|0; 0; 1; 0; 0; 0; 0; 0; 1; 0; 0; 0; 0; 0|];
[|0; 0; 1; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 1; 1; 0; 0; 1; 1; 1; 1; 0; 0; 1; 1; 1|];
[|0; 1; 1; 0; 0; 1; 1; 1; 1; 0; 1; 0; 1; 1|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 1|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 1; 0|]|]
2 Implémentation de l’algorithme de Dijkstra
Les graphes sous représentations creuses sont donnés sous le type (int * int) list vect, un couple (u, ω)dans
la liste d’adjacence d’un somme tsignifie qu’il y a un arc (t, u)dans le graphe, de poids ω.
Algorithme 2 : Algorithme de Dijkstra
Entrée : Un graphe pondéré G= (V, E, ω)donné par listes d’adjacences, avec ω(E)R+, un sommet s
Sortie : Les distances δ(s, t)pour tout tV
d[t]+pour tout tV;d[s]0;
E ;F← {s};
tant que F6=faire
uRetirer de Fun sommet vvérifiant d[v]minimal parmi les sommets de F;
pour tout voisin vde ufaire
si vn’est ni dans Fni dans Ealors
Ajouter vàF
d[v]min(d[v], d[u] + ω(u, v))
Ajouter uàE
Renvoyer d
Vous trouverez sur le site web une implémentation des files de priorité spécialement adaptée à l’algorithme de
Dijkstra. Le type associé est le suivant :
type fp_min = {tas: (int *int) vect ; indice: int vect ; mutable nb: int } ;;
Svartz Page 2/4 2015/2016
MP* Lycée Masséna
Les fonctions sont les suivantes :
creer_fp : int -> fp_min : prend en paramètre un entier n, et retourne une file de priorité min de capacité
n, vide.
est_vide_fp : fp_min -> bool
inserer : fp_min -> int -> int -> unit : l’appel inserer f t dt rajoute le sommet t, supposé non pré-
sent, à la file de priorité, avec priorité dt.
diminuer_cle : fp_min -> int -> int -> unit : l’appel diminuer_cle f t dt diminue la clé du sommet
t, supposé présent.
retirer_min : fp_min -> int * int : retire le minimum de la file de priorité (i.e renvoie (t, dt)avec dt
minimal).
Exceptée la création, toutes ces fonctions s’exécutent en temps constant, sauf les opérations classiques de files de priorité
qui s’exécutent en temps O(log n)) (nétant la capacité de la file). Remarquez l’utilisation d’un vecteur indice : à
tout moment indice.(v) contient l’indice dans le tas du couple associé au nœud v(s’il est dans la file). Ceci est
transparent pour l’utilisateur.
0 2
34
0
1
2 3
10
5
964
2
7
Figure 2: Un graphe pondéré à poids positifs (g3)
Question 6. Implémentez l’algorithme de Dijkstra. La fonction dijkstra g s doit renvoyer un tableau de distances
de type int vect contenant les distances entre set tous les nœuds accessibles du graphe, et 1pour les non accessibles.
(Comme les poids sont positifs, il n’y a pas ambiguïté).
# dijkstra g3 0;;
- : int vect *int vect = [|0; 8; 9; 7; 5|], [|0; 4; 1; 4; 0|]
#dijkstra g4 0 ;;
- : int vect *int vect = [|0; 5; 1; 8; 3; 6|], [|0; 4; 0; 4; 2; 1|]
#dijkstra g4 3 ;;
- : int vect *int vect =
[|-1; -1; -1; 0; -1; -1|], [|-1; -1; -1; 3; -1; -1|]
Question 7. Rajouter la production d’un tableau de prédecesseurs, comme ci-dessus.
Question 8. Profitez ensuite de l’implémentation pour réviser la structure de file de priorité.
3 Project-Euler 83
Dans la matrice ci-dessous, la somme minimale d’un chemin entre le coin en haut à gauche et le coin en bas à droite
est 2297. Un trajet correspondant est indiqué en gras (naturellement, on ne peut se déplacer qu’horizontalement et
verticalement, pas en diagonale).
131 673 234 103 18
201 96 342 965 150
630 803 746 422 111
537 699 497 121 956
805 732 524 37 331
Svartz Page 3/4 2015/2016
MP* Lycée Masséna
Sur mon site web, vous trouverez une matrice au format ml de taille 80 ×80. Déterminez la somme minimale d’un
chemin entre le coin en haut à gauche et le coin en bas à droite, et résolvez ainsi le problème 83 du site Project-Euler.
Indication : écrire une fonction permettant de construire le graphe associé à une matrice à coefficients positifs (il est
très creux !), et lancez Dijkstra depuis 0. Ne pas oublier de rajouter le coefficient en haut à gauche à votre longueur
de chemin.
Vous pouvez aussi résoudre les problèmes 81 et 82. Ils sont en fait plus simples et une solution basée sur la
programmation dynamique est possible, ce qui évite le recours aux graphes. C’est un bon exercice de révision.
Svartz Page 4/4 2015/2016
1 / 4 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !