Algorithme de Prim 1 File de priorité 2 Travail demandé

publicité
Algorithmique et Programmation
Projet : Algorithme de Prim
Ecole normale supérieure, Département d’informatique
[email protected] ∗
2013-2014
Dans un graphe connexe non-orienté avec arêtes pondérées G = (V, E, w), un arbre couvrant minimal
P est un ensemble d’arêtes de G qui est un arbre, touche tous les sommets de G, et est de poids
{u,v}∈A w(u, v) minimal. L’algorithme de Prim (voir [?, §24.2]) construit un arbre couvrant minimal
de manière “gloutonne”. Il part d’un sommet r arbitraire et de A = ∅ puis fait grossir A en y adjoignant
une arête de poids minimal qui laisse l’ensemble des arêtes de A connectées à r et sans cycle. On note
u ∼ v pour dire que {u, v} ∈ E. Voici l’algorithme de Prim :
1: function ACM-Prim(G)
2:
choisir r ∈ V , A ← ∅ et S ← {r}.
3:
while S 6= V do
4:
choisir s ∈
/ S tel que minx∈S,x∼s w(x, s) soit minimum.
5:
A ← A ∪ {{x, s}} et S ← S ∪ {s}
6:
end while
7:
return A
8: end function
1
File de priorité
Pour une implémentation efficace, l’algorithme de Prim utilise une file de priorité pour les éléments
de V \ S avec clé Clef(u) ∈ R ∪ {+∞} égale au poids de la plus petite arête de G reliant u aux sommets
de S. Voici le pseudo-code :
1: function ACM-Prim(G)
2:
A←∅
3:
choisir r ∈ V
4:
for all t ∼ r do Insertion(P, t, w(s, t))
5:
for all t 6= r et t 6∼ r do Insertion(P, t, +∞)
6:
while P 6= ∅ do
7:
s ← Extraire-Min(P )
8:
u ← choisir un sommet tel que u ∼ s, u ∈
/ P , et w(s, u) = Clef(s)
9:
A ← A ∪ {{s, u}}
10:
for all t ∼ s do
11:
if t ∈ P et w(s, t) < Clef(t) then
12:
Diminuer-Clef(P, t, w(s, t))
13:
end if
14:
end for
15:
end while
16:
return A
17: end function
Si la file de priorité est implantée à l’aide des tas de Fibonacci (voir [?, §21]), les fonctions ExtraireMin et Diminuer-clef se font respectivement en temps amorti O (log |V |) et O (1). On obtient un coût
total O (|E| + |V | log |V |), qui est meilleur que celui de Kruskal.
2
Travail demandé
Vous écrirez et testerez une fonction qui calcule un arbre couvrant minimal par l’algorithme de Prim
avec tas de Fibonacci. La fonction prend en entrée un graphe connexe pondéré de taille arbitraire donné
∗ Conception
: Charles Bouillaguet. Révisé par Claire Mathieu 9/2013.
1
sous forme de listes d’adjacence. Les poids sont de type entier. La sortie sur écran est la liste des arêtes qui
forment l’arbre (dans un ordre quelconque) suivie du poids de l’arbre. Ainsi, votre travail se décompose
en les étapes suivantes.
1. Implémentation d’une fonction pour tester si un graphe est connexe. La fonction prend en entrée
un graphe de taille arbitraire donné sous forme de listes d’adjacence, et donne en sortie une valeur
binaire, vrai ou faux.
2. Implementation d’une fonction qui prend en entrée deux entiers n et m ∈ [n − 1, n(n − 1)/2] et
donne en sortie un graphe connexe à n sommets et m arêtes donné sous forme de listes d’adjacence.
Vous pourrez utiliser la méthode de rejet : faire de manière répétée une génération aléatoire d’un
graphe à n sommets et m arêtes, jusqu’à ce que le graphe obtenu soit connexe.
3. Implémentation naı̈ve de l’algorithme de Prim. Tests sur des graphes connexes aléatoires dont les
arêtes ont des poids aléatoires uniformes entre 1 et 1000.
4. Implémentation d’une file de priorité avec un tableau. Implémentation de l’algorithme de Prim avec
une file de priorité. Tests.
5. Implémentation d’une file de priorité avec un tas de Fibonacci. Implémentation de l’algorithme de
Prim avec une file de priorité. Tests.
6. Comparaison entre la complexité en temps des diverses implémentations de l’algorithme de Prim.
Quelles sont, selon les implémentations, les plus grandes valeurs de (n, m) pour lesquelles le problème puisse être résolu en un temps raisonnable (de l’ordre de quelques secondes) ?
3
Bonus
Cette partie est optionnelle.
On peut utiliser l’arbre couvrant minimum pour obtenir un tour qui donne une solution approchée
au problème du voyageur de commerce, comme suit.
Soit G = (V, E, w) un graphe complet (E est l’ensemble de toutes les paires de sommets de V ),
pondéré, non orienté et dont les poids sont positifs ou nuls et vérifient l’inégalité triangulaire : ∀s, t, u ∈
V, w({s, u}) ≤ w({s, t}) + w({t, u}). On cherche à trouver un tour, c’est à dire un chemin s1 , . . . , sn ∈ V
Pn−1
passant une et une seule fois par chaque sommet, et qui soit de poids i=1 w({si , si+1 }) + w({sn , s1 })
minimal. Il est connu (voir [?, §37.2.1]) que le parcours préfixe d’un arbre couvrant minimal de G est un
tour de poids au plus double du poids minimal.
Vous écrirez une fonction qui prend en argument un graphe complet de taille arbitraire, dont les poids
sont positifs ou nuls et vérifient l’inégalité triangulaire, et qui calcule un circuit grâce à cette heuristique.
La sortie sur écran sera la liste, dans l’ordre, des sommets à visiter suivie du poids du circuit. Les poids
seront de type flottant double.
Vous écrirez également un programme de démonstration qui teste votre fonction sur des graphes
aléatoires. Le programme prendra en argument en ligne de commande le nombre de sommets des graphes
à générer. Les graphes seront générés de la manière suivante (afin de s’assurer que l’inégalité triangulaire
est vérifiée) : pour chaque sommet si ∈ S, on choisit une position aléatoire uniforme (xi , yi ) ∈ [0, 1]2
dans le carré unité ; chaque arête a alors pour poids la distance euclidienne entre ses extrémités :
q
w({si , sj }) = (xi − xj )2 + (yi − yj )2
2
Téléchargement