Graphes orientés

publicité
Concepts et définitions
INFO0902 – Data Structures and
Algorithms
Graphes
Justus H. Piater
Graphe
Graphes orientés
Définition : Un graphe est (ici) un ensemble
de nœuds (vertices) et un ensemble de paires
d’éléments de , les arêtes (edges).
Une arête peut être orientée (directed) ou non.
Un graphe est orienté si toutes les arêtes sont
orientées.
Deux nœuds liés par une arête sont adjacents.
Une arête orientée a une origine et une destination.
Le degré d’un nœud est le nombre des arêtes
incidentes.
Un nœud peut avoir des arêtes entrantes et des
arêtes sortantes.
Exemples ?
Concepts et définitions
Exemples ?
3 / 40
Concepts et définitions
4 / 40
Propriétés basiques
Proposition : Si
alors
Proposition : Si
arêtes, alors
est un graphe avec
Graphes pondérés
arêtes,
Les arêtes sont annotées d’une étiquette numérique,
son poids.
.
Exemples ?
est un graphe orienté avec
BOS
.
2704
867
Proposition : Soit un graphe simple avec
nœuds et
arêtes. Le nombre des arêtes est
: Si
est non-orienté, alors
; si est orienté,
alors
.
187
SFO
1846
PVD
849
ORD
802
1464
337
144
740
JFK
621
1258
184
1235
DFW
1391
BWI
1121
LAX
964
1090
2342
MIA
Concepts et définitions
5 / 40
Concepts et définitions
6 / 40
TDA graphe
TDA, SDD et algorithmes basiques
Vertices vertices(void);
Edges edges(void);
Edges incidentEdges(Vertex v);
Vertex opposite(Vertex v, Edge e);
Array endVertices(Edge e);
Boolean areAdjacent(Vertex v, Vertex w);
Object replace(Vertex v, Object o);
Object replace(Edge e, Object o);
Vertex insertVertex(Object o);
TDA, SDD et algorithmes basiques
8 / 40
TDA graphe (suite)
Structure de liste des arêtes
Deux conteneurs
Nœud :
Edge insertEdge(Vertex v, Vertex w, Object o);
Object removeVertex(Vertex v);
et :
• une référence vers sa propre position (ou entrée)
dans
• une référence vers les données
Arête :
Object removeEdge(Edge e);
• une référence vers sa propre position (ou entrée)
dans
• une référence vers les données
• deux références vers les nœuds connectés
Regardons un exemple…
Complexité en espace ?
Complexité en temps des méthodes ?
TDA, SDD et algorithmes basiques
9 / 40
Structure de liste des adjacences
Pour éviter le parcours de toutes les arêtes, on
représente les incidences explicitement :
10 / 40
Structure de matrice des adjacences
Pour déterminer les adjacences entre deux nœuds en
temps constant, on ajoute à la structure de liste des
arêtes une matrice des adjacences :
Incidence :
Matrice des adjacences :
• une référence vers l’arête incidente
Au nœud on ajoute une référence vers le conteneur
des incidences sur .
À l’arête connectant et on ajoute deux références
vers les incidences associées à dans
et
.
Regardons un exemple…
• une matrice
dont l’élément
contient une
référence vers l’arête correspondante (ou nulle si elle
n’existe pas).
À chaque nœud on ajoute un indice (clé) entre
et
.
Regardons un exemple…
Complexité en espace ?
Complexité en espace ?
Complexité en temps des méthodes ?
Complexité en temps des méthodes ?
TDA, SDD et algorithmes basiques
TDA, SDD et algorithmes basiques
11 / 40
TDA, SDD et algorithmes basiques
12 / 40
Parcours en profondeur
Un exemple
• un fil (comme l’utilisa Thésée pour sortir du
labyrinthe)
• de la peinture (comme Thésée aurait pû l’utiliser
pour trouver le Minotaure plus vite)
Algorithm DFS( , ):
Input: A graph and a vertex of .
Output: A labeling of the edges in the connected component
of as discovery edges and back edges.
label as visited
foreach in .incidentEdges( ) do
if is unvisited then
.opposite( , )
if is unexplored then
label as a discovery edge
DFS( , )
else
label as a back edge
TDA, SDD et algorithmes basiques
13 / 40
Parcours en profondeur : propriétés
Proposition : Les arêtes de découverte forment un
arbre couvrant.
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
TDA, SDD et algorithmes basiques
14 / 40
Parcours en largeur
Avancer par « couches » de distance constante du
nœud de départ
À prouver :
Regardons un exemple…
• Tous les nœuds sont atteints.
• Les arêtes de découverte ne forment aucun cycle.
Temps de calcul ? Exigences aux structures de
données ?
TDA, SDD et algorithmes basiques
15 / 40
TDA, SDD et algorithmes basiques
16 / 40
Parcours en largeur (suite)
Parcours en largeur : propriétés
Proposition : Les arêtes de découverte forment un
arbre couvrant.
Algorithm BFS( , ):
Input: A graph and a vertex of .
Output: A labeling of the edges in the connected component
of as discovery edges and cross edges.
label as visited; insert it into container
Les conteneurs contiennent les nœuds des plus
courts chemins de longueur à partir de .
Temps de calcul ? Exigences aux structures de
données ?
while is not empty do
create empty container
foreach in do
foreach in .incidentEdges( ) do
if is unexplored then
.opposite( , )
if is unexplored then
label as a discovery edge
label as visited; insert it into
else
label as a cross edge
TDA, SDD et algorithmes basiques
17 / 40
Implémentation
Plus courts chemins – Dijkstra
Comment attacher des attributs (visited, discovery
edge, back edge, cross edge) aux nœuds et arêtes :
• Prévoir un champ explored ?
• Table de hashage externe ?
Le design pattern décorable : attacher une application
à (ici) la position.
Object element(void);
Object get(Object key);
Object put(Object key, Object value);
Object remove(Object key);
Entries entries(void);
TDA, SDD et algorithmes basiques
TDA, SDD et algorithmes basiques
19 / 40
18 / 40
Plus courts chemins (shortest paths)
La longueur ou le poids d’un chemin
des poids des arêtes de :
est la somme
L’algorithme de Dijkstra
Pour trouver les plus courts chemins (ici non orientés)
d’un nœud désigné vers tous les autres nœuds d’un
graphe (arbre des plus courts chemins) – single-source
shortest paths (shortest-path tree)
.
La distance
d’un nœud à un nœud est la
longueur d’un plus court chemin (chemin de poids
minimal) de à , ou
.
•
• méthode gloutonne : recherche « pondérée » en
largeur
Note
Attention aux poids négatifs – un plus court chemin
n’est pas défini pour un cycle de poids négatif !
Comment trouver les plus courts chemins d’un
nœud désigné vers tous les autres nœuds si
pour tous les ?
Plus courts chemins – Dijkstra
21 / 40
Plus courts chemins – Dijkstra
Survol
Algorithme
dénote la longueur du plus court chemin de
trouvé jusqu’à présent.
1.
2.
3.
, et
pour
« nuage » de nœuds
Répéter :
a.
b.
Choisir
de
à
Algorithm DijkstraShortestPaths( , ):
Input: A simple, undirected, weighted graph
with nonnegative edge weights, and
a distinguished vertex of .
Output: A label
for each vertex of
that gives the distance from to in .
.
foreach vertex
minimale, et l’ajouter à
Relaxation : pour tous les
mettre à jour
.
.
of
do
Let be a PQ containing all
using the
while is not empty do
.removeMin()
foreach vertex
adjacent to do
if
then
voisins de ,
Regardons un exemple…
Plus courts chemins – Dijkstra
22 / 40
Update
23 / 40
as keys.
accordingly
Plus courts chemins – Dijkstra
24 / 40
Correction
Proposition : Quand un nœud
insertion dans ,
.
Correction (suite)
est choisi pour
Puisque est le prochain nœud choisi,
Puisque est dans ,
implique que
Preuve (par contradiction) : Soit
•
le premier nœud choisi avec
(l’impossibilité de
est facilement prouvée
par construction),
• le plus court chemin de à ,
• le dernier nœud de dans ,
• son successeur (le premier nœud de pas dans ).
Alors,
Plus courts chemins – Dijkstra
.
, ce qui
ce qui contredit notre définition de .
25 / 40
Plus courts chemins – Dijkstra
Temps d’exécution
26 / 40
Remarques
Pour l’algorithme, il faut préciser les structures de
données et leurs implémentations.
• L’algorithme de Dijkstra s’adapte facilement aux
graphes orientés.
• L’algorithme de Bellman-Ford est
et fonctionne
en présence de poids négatifs (orientés) dans le
graphe.
PQ adaptable avec localisateur basée
tas : Temps total de la boucle while :
d’après notre proposition.
PQ basée séquence non triée : puisque est simple.
Plus courts chemins – Dijkstra
27 / 40
Plus courts chemins – Dijkstra
28 / 40
Arbres couvrants minimaux
(minimum spanning trees)
Arbres couvrants minimaux
P.ex., pour connecter un ensemble d’ordinateurs entre
eux avec un minimum de cablage :
Pour un graphe
minimise
, trouver un arbre
qui
.
Arbres couvrants minimaux
Une propriété clé des ACMs
Une propriété clé des ACMs (suite)
Proposition : Soient
•
•
Note
Cette proposition est vraie même en présence de
poids négatifs.
un graphe pondéré et connexe,
et
une partition de
disjoints et non vides,
30 / 40
en deux ensembles
•
une arête de poids minimal parmi celles connectant
et .
Alors fait partie d’un arbre couvrant minimal.
Preuve (par construction) : Soit un ACM ne
comportant pas . On l’ajoute alors à , ce qui crée
un cycle dont et une arête connectent
et .
Puisque (par le choix de )
, on peut recréer
un ACM en supprimant .
Arbres couvrants minimaux
31 / 40
Arbres couvrants minimaux
32 / 40
L’algorithme de Kruskal
L’algorithme de Kruskal (suite)
Regardons un exemple.
Note
Sa correction est une conséquence de la proposition
précédente.
Algorithm KruskalMST( ):
Input: A simple, connected, weighted graph
with vertices and
edges.
Output: A minimum spanning tree for .
foreach
do
define an elementary cluster
Initialize a PQ containing all
with weights as keys.
while
has fewer than
edges do
.removeMin()
Let
,
be the clusters containing , .
if
then
Add
to .
Merge
and
.
Arbres couvrants minimaux
33 / 40
Temps d’exécution
Proposition : Pour un graphe avec nœuds,
l’algorithme de Kruskal prend un temps total de
pour fusionner tous les groupes.
• Arêtes dans une file de priorité basé tas : prochaine
arête en
• Nœuds d’un groupe dans une liste non triée stockés
avec une référence vers son propre groupe ; fusion
par l’ajout du plus petit groupe au plus grand :
en
, temps total de
pour les
fusions (voir le transparent prochain)
Arbres couvrants minimaux
34 / 40
Fusion des groupes des nœuds
Pour l’algorithme, il faut préciser les structures de
données et leurs implémentations :
Le temps total de Kruskal est
Arbres couvrants minimaux
Preuve : À chaque fusion, la taille du cluster ajouté
est multipliée par deux au moins. Soit
le nombre
de fois un nœud est ajouté à un autre groupe. Alors,
. Le temps maximal total pour tous les nœuds
est donc proportionnel à
.
.
35 / 40
Arbres couvrants minimaux
36 / 40
L’algorithme de Prim-Jarník
Prim-Jarník : remarques
Regardons un exemple.
Algorithm PrimJarníkMST( ):
Input: A simple, connected, weighted graph
with vertices and
edges.
Output: A minimum spanning tree for .
Pick any vertex of
foreach vertex
Temps d’exécution ?
do
Initialize a PQ with keys
, elements
while is not empty do
.removeMin()
Add vertex , edge to
foreach vertex
adjacent to do
if
then
Change to
Change to
Il s’agit d’une variation simple de l’algorithme de
Dijkstra ; son implémentation est un peu plus simple
que celui de Kruskal.
the element of
the key of in
null
in
Arbres couvrants minimaux
37 / 40
Arbres couvrants minimaux
38 / 40
Graphes
Résumé
• Structures de données : liste des arêtes, liste des
adjacences, matrice des adjacences
• Parcours en profondeur et en largeur
• Plus courts chemins : Dijkstra
• Arbres couvrants minimaux : Kruskal et Prim-Jarník
Résumé
40 / 40
Téléchargement