8.1 Arbre couvrant de poids minimum

publicité
8.1
8.1.1
Arbre couvrant de poids minimum
Le problème
Le problème est le suivant :
— entrée : un graphe connexe, non orienté, pondéré (pas forcément positivement) non
orienté G = (S , A) ;
— sortie : un arbre couvrant de poids minimal E ⊆ A, c’est à dire un ensemble d’arêtes E,
X
qui connecte tous les sommets, et tel que
poids(a, b) est minimal.
(a,b)∈E
Remarquez que si le graphe initial est pondéré positivement, un sous-graphe couvrant de
poids minimal est forcément... un arbre couvrant.
Applications :
• Circuits électroniques
• Réseaux
Exemple 35. Dessinez un graphe. Le graphe représente une ville dans laquelle il n’y a malheureusement pas encore de pistes cyclables. Les nœuds sont des maisons et les arcs représentent
les routes. Le poids d’un arc est la longueur de la route. Le maire souhaite placer des pistes
cyclables entre les maisons de façon à ce qu’il est possible d’aller d’une maison à une autre en
prenant une piste. L’arbre couvrant donne une solution la moins chère.
A
1
1
3
B
1
1
1
D
1
H
8.1.2
C
E
1
4
F
1
G
25
I
Algorithme de Kruskal
L’algorithme date de 1956. Kruskal (1928-2010) a aussi travaillé dans d’autres domaines :
statistique et linguistique notamment. Mais il reste vraiment célèbre pour son algorithme de
calcul d’un arbre couvrant minimal, qui est devenu un classique des cours d’algorithmique.
Principe
Le principe est on ne peut plus glouton : on débute avec E = ∅ et tant que E n’est pas un
arbre, on ajoute à E l’arête la plus légère parmi les arêtes non traités si elle ne crée pas de cycles
dans E.
Cela ne vous rappelle rien ? L’algorithme de Kruskal est une généralisation de l’algorithme
de génération de labyrinthe vu en section 5.1.
Au début, comme E = ∅, le sous-graphe en construction n’a pas d’arcs et a donc autant de
composantes connexes que de sommets. Puis lorsque l’on traite une arête {x, y}, on regarde si x
est y ne sont pas déjà relié, ie. si x et y ne sont pas dans la même composante connexe.
Pour cela, on va utiliser une structure de données abstraite pour représenter une partition
d’un ensemble fini. Il s’agit de union-find vu au chapitre 5 et ses opérations sont :
François Schwarzentruber
Page 98
ALGO1 - ENS Rennes
• créer_union_find : crée la partition
[
{{s}} :
s∈S
• find : Trouve la composante de x
• union : fusionne les composantes de x et y.
Algorithme
Le pseudo-code de l’algorithme de Kruskal est l’algorithme 28.
Algorithme 28 : Algorithme de Kruskal
Entrées : Un graphe G = (S , A) pondéré non orienté
Sorties : Un ACM (arbre couvrant minimal) de G
CC := créer_union_find(S )
E := ∅
L := tri(A) par ordre croissant des poids.
pour {x, y} ∈ L (dans l’ordre) faire
si CC. f ind(x) , CC. f ind(y) alors
E := E ∪ {{x, y}}
CC.union(x, y)
retourner E
Théorème. À la fin, E contient les arêtes d’un ACM.
Démonstration.
On va démontrer l’invariant suivant I :
1. il existe T ACM tel que E ⊆ T
2. et pour tout x, y ∈ S
x et y sont reliés pas des arêtes dans E ssi x et y sont dans la même composante
dans CC.
— Initialisation : E = ∅, et il existe un ACM (qui trivialement contient les arêtes de E). Par
ailleurs :
x et y sont reliés par des arêtes de E
ssi (car E est vide)
x=y
ssi (car CC est la partition composée de singletons)
x et y sont dans la même classe dans CC
— Conservation : Supposons que l’invariant I est vraie avant un tour de boucle en (*).
Montrons qu’il reste vraie après le tour de boucle en (∆).
(∗)
if CC. f ind(x) , CC. f ind(y) then
E := E ∪ {{x, y}}
CC.union(x, y)
endIf
(∆)
1. Occupons nous du point 1. On a ajouté une arête {x, y} à E. On a il existe T ACM tel
que E \ {x, y} ⊆ T et on veut montrer que que le point 1 de l’invariant est conservée,
c’est à dire qu’il existe bien un T 0 ACM tel que E ⊆ T 0 .
François Schwarzentruber
Page 99
ALGO1 - ENS Rennes
— Si (par chance !) {x, y} ∈ T , alors la première partie de l’invariant est conservée
en prenant T 0 = T .
— Sinon, on construit un ACM T 0 qui contient E. La construction de T 0 s’appuie
sur la donnée de T . Voici la situation actuelle :
— en noir fin : T
— en vert gros : E
y
x
a
rête
té
jou
ar
On rappelle la caractérisation des arbres :
arbre ⇔ connexe et |S | − 1 arcs
Comme T est un arbre, il est connexe et x et y sont reliés par un chemin c dans T .
Par le point 2 de I en (*), comme CC. f ind(x) , CC. f ind(y), x et y ne peuvent
pas être reliés par uniquement des arêtes de E \ {x, y}. Donc une des arêtes du
chemin c n’est pas dans E. Soit {u, v} une telle arête de T \ E (reporté en trait
bleu sur le dessin d’avant).
On construit T 0 à partir de T en supprimant cette arête bleu et en ajoutant {x, y}.
Formellement, on définit T 0 par T 0 = T ∪ {{x, y}} \ {{u, v}}. Ainsi E ⊆ T 0 . Voici
T 0 dessiné en trait noir fin :
y
x
Montrons que T 0 est un ACM. En effet,
— T 0 est connexe, T 0 et T ont même nombre d’arêtes (|S | − 1) donc c’est un
arbre.
— Comme {u, v} n’a pas encore été choisie mais que {x, y} a été choisi et que
les arêtes sont triées, on a poids({x, y}) ≤ poids({u, v}). Ainsi : poids(T 0 ) =
poids(T ) + poids({x, y}) − poids({u, v}) 6 poids(T ). Donc le poids de T 0 est
minimal.
— Montrons le point 2 de l’invariant. Soit {x, y} l’arête ajouté à E. Montrons que x0 et y0
sont reliés pas des arêtes dans E ssi x0 et y0 sont dans la même composante dans CC. On
s’intéresse à deux cas clefs.
Cas où x0 était la classe de x ety0 dans la classe y en (∗)
François Schwarzentruber
Page 100
ALGO1 - ENS Rennes
D’une part, par l’invariant en (∗), il existe un chemin c x dans E \ {{x, y}} de x0 à x et un
chemin de cy dans E \ {{x, y}} de y à y0 . On construit alors un chemin de E en concaténant
c x , x ↔ y et cy .On a x0 et y0 sont reliés pas des arêtes dans E.
D’autre part, les classes de x et y sont fusionnées par CC.union(x, y). Donc x0 et y0 sont
dans la même composante dans CC.
Cas où x0 est dans la classe x et y0 dans une autre classe que x ou y en (∗)
D’une part, montrons qu’il n’y a pas de chemin dans E de x0 à y0 . Par l’absurde, supposons qu’il existe un tel chemin. Si ce chemin est intégralement dans E \ {{x, y}}, alors
par l’invariant, x0 et y0 devraient être dans la même classe en (∗) ce qui n’est pas le cas.
Donc le chemin dans E de x0 à y0 passe par l’arête {x, y}. Mais alors soit y0 est dans la
classe de x ou y... Non.
D’autre part, les classes de x0 et y0 ne sont pas fusionnées par CC.
À présent, montrons que E est un ACM.
— D’une part, (S , E) est un arbre.
— D’une part (S , E) est connexe. Cela resulte de la connexité de G et du traitement
systématique de toute les arêtes de G. En effet, si x, y ∈ S , on sait que x et y sont
reliés dans G : x = x1 ↔ x2 ↔ · · · ↔ xn ↔ y.
On construit alors un chemin de x à y avec des arêtes de E de la manière suivante.
Pour tout i, si {xi , xi+1 } ∈ E, on prend cette arête dans le chemin. Sinon, si {xi , xi+1 } <
E, lorsque l’algorithme a traité {xi , xi+1 }, {xi , xi+1 } n’a pas été ajouté à E. On avait xi et
xi+1 dans la même composante CC. Donc, l’invariant nous dit qu’il y avait un chemin
de xi à xi+1 dans E (il est toujours intégralement composé d’arêtes de E puisque E
est croissant lors de l’algorithme). Donc on prend ce chemin pour aller de xi à xi+1 .
On a ainsi construit un chemin de x à y avec des arêtes de E.
— D’autre part, il est acyclique. S’il contenait un cycle, regardons la dernière arête
{x, y} ajouté de ce cycle. Par l’invariant, il existait un chemin de x à y donc l’arête
n’aurait pas dû être ajoutée. Contradiction.
— D’autre part, il est minimal. En effet, par l’invariant, il existe T 0 ACM tel que E ⊆ T 0 .
(S , E) est un arbre donc il contient |S | − 1 arêtes. De même pour T 0 . Donc E = T 0 .
Complexité
Théorème. L’algorithme de Kruskal s’exécute en
|creer_union_ f ind| + O(A ln(A)) + O(A(| f ind| + |union|)).
Démonstration.
Il y a la création de la structure union find, puis le tri, puis une boucle, dont chaque passage
de boucle appelle f ind et union. Autrement dit pour des arbres de type union-find :
— |creer_union_ f ind| : O(S ) ;
— f ind et union en O(ln S ).
Bilan : Comme |S | − 1 ≤ |A|, on a dans le pire des cas une complexité en O(A ln(A)). Cela
peut se réécrire en O(A ln(S )) car |A| ≤ |S |2 et donc ln A = 2 ln S . Si le tri de A a déjà été fait
alors la complexité peut être en O(A ln∗ (S )) avec la structure union find avec compression de
chemin.
François Schwarzentruber
Page 101
ALGO1 - ENS Rennes
8.1.3
Algorithme de Prim
L’algorithme date de 1957... Kruskal a aussi participé à son élaboration. Attention ! Il ressemble comme deux gouttes d’eau à l’algorithme Dijkstra ! Ce n’est pas sans raison : Dijkstra
s’en inspiré en 1959. On utilise une stratégie gloutonne : on ajoute à E (arbre qui grossit pendant
l’algorithme) un arc u ∈ E → t < E de poids minimum.
Algorithme 29 : Algorithme de Prim
Entrées : Un graphe G = (S , A)
Sorties : Un ACM de G
pour s ∈ S faire
cout[s] :=+∞
pred[s] :=∅
u0 := un sommet de G
cout[u0 ] :=0
F := filedepriorité (S ,cout)
tant que F , ∅ faire
t := F.défilemin
pour tout u tel que t → u ∈ A faire
si cout[u]> poids(t → u) alors
cout[u] :=poids(t → u)
F.notifierDiminution(u)
pred[u] :=t
retourner pred
Au niveau de la complexité, cela se passe comme pour l’algorithme de Djikstra :
Théorème.
L’algorithme effectue O(|S | + |S ||défiler_min| + |file_créer| + |A||MàJ|).
Remarque.
Avec une implémentation sous forme de tableau, on a une complexité en O(|S |2 ).
Sous forme d’un tas, c’est O((|S | + |A|) log(|S |)).
Sous forme d’un tas de Fibonacci, c’est O(|S | log(|S |) + |A|).
8.1.4
Kruskal VS Prim
On note les complexités (avec les structures de données qui donnent les meilleures complexités) et les avantages des deux algorithmes.
Kruskal
O(A ln S )
graphe creux
rapide si déjà les arcs sont déjà triés
8.2
Prim
O(S ln S + A)
graphe dense
on a toujours une solution partielle
Formules de Horn
[DPV06], p. 157 Dans cette section, on veut faire du raisonnement automatique. Alfred
Horn (1918-2001) est un mathématicien, logicien américain décrit en 1951 les clauses de Horn
comme fondement de la programmation logique. Les clauses de Horn sont un fragment logique
qui permettent d’exprimer des règles qui sont sous la forme suivante :
— Des implications comme a ∧ b ∧ c → d. Cette expression signifie ‘Si a, b, c sont vraies
alors d est vraie’ ;
François Schwarzentruber
Page 102
ALGO1 - ENS Rennes
Téléchargement