From a2e0cbb2a39177891c6ba42be0171410094e17e7 Mon Sep 17 00:00:00 2001 From: Orestis <orestis.malaspinas@pm.me> Date: Tue, 21 May 2024 07:44:45 +0200 Subject: [PATCH] added 2024 --- slides/cours_25.md | 1425 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1425 insertions(+) create mode 100644 slides/cours_25.md diff --git a/slides/cours_25.md b/slides/cours_25.md new file mode 100644 index 0000000..da306e1 --- /dev/null +++ b/slides/cours_25.md @@ -0,0 +1,1425 @@ +--- +title: "Théorie des graphes" +date: "2024-05-21" +--- + +# Les graphes + +\Huge + +Les graphes + +# Les graphes! Historique + +**Un mini-peu d'histoire...** + +## L. Euler et les 7 ponts de Koenigsberg: + +* Existe-t-il une promenade sympa, passant **une seule fois** par les 7 ponts et revenant au point de départ? + +{width=50%} + +. . . + +* Réponse: ben non! + +# Utilisation quotidienne + +## Réseau social + +{width=40%} + +* Chaque sommet est un individu. +* Chaque trait une relation d'amitié. +* Miam, Miam, Facebook. + +# Utilisation quotidienne + +## Moteurs de recherche + +{width=40%} + +* Sommet est un site. +* Liens sortants; +* Liens entrants; +* Notion d'importance d'un site: combien de liens entrants, pondérés par l'importance du site. +* Miam, Miam, Google (PageRank). + +# Introduction + +## Définition, plus ou moins + +* Un graphe est un ensemble de sommets, reliés par des lignes ou des flèches. + + + +* Des sommets (numérotés 1 à 6); +* Connectés ou pas par des traits ou des flèches! + +# Généralités + +## Définitions + +* Un **graphe** $G(V, E)$ est constitué + * $V$: un ensemble de sommets; + * $E$: un ensemble d'arêtes. +* Une **arête** relie une **paire** de sommets de $V$. + +## Remarques + +* Il y a **au plus** une arête $E$ par paire de sommets de $V$. +* La **complexité** d'un algorithme dans un graphe se mesure en terme de $|E|$ et $|V|$, le nombre d'éléments de $E$ et $V$ respectivement. + +# Généralités + +## Notations + +* Une arête d'un graphe **non-orienté** est représentée par une paire **non-ordonnée** $(u,v)=(v,u)$, avec $u,v\in V$. +* Les arêtes ne sont pas orientées dans un graphe non-orienté (elles sont bi-directionnelles, peuvent être parcourues dans n'importe quel ordre). + +## Exemple + + +::: columns + +:::: column + + + + +:::: + +:::: column + +## Que valent $V$, $|V|$, $E$, et $|E|$? + +. . . + +\begin{align*} +V&=\{1, 2, 3, 4\},\\ +|V|&=4,\\ +E&=\{(1,2),(2,3),(2,4),(4,1)\},\\ +|E|&=4. +\end{align*} + +:::: + +::: + +# Généralités + +## Notations + +* Une arête d'un graphe **orienté** est représentée par une paire **ordonnée** $(u,v)\neq(v,u)$, avec $u,v\in V$. +* Les arêtes sont orientées dans un graphe orienté (étonnant non?). + +## Exemple + + +::: columns + +:::: column + + + + +:::: + +:::: column + +## Que valent $V$, $|V|$, $E$, et $|E|$? + +. . . + +\begin{align*} +V&=\{1, 2, 3, 4\},\\ +|V|&=4,\\ +E&=\{(1,2),(2,3),(2,4),(4,1),(4,2)\},\\ +|E|&=5. +\end{align*} + +:::: + +::: + +# Généralités + +## Définition + +* Le somme $v$ est **adjacent** au sommet $u$, si et seulement si $(u,v)\in E$; +* Si un graphe non-orienté contient une arête $(u,v)$, $v$ est adjacent à $u$ et $u$ et adjacent à $v$. + +## Exemple + +::: columns + +:::: column + +{width=80%} + +:::: + +:::: column + +{width=80%} + +:::: + +::: + +# Généralités + +## Définition + +* Un **graphe pondéré** ou **valué** est un graphe dont chaque arête a un + poids associé, habituellement donné par une fonction de pondération $w:E\rightarrow\mathbb{R}$. + +## Exemples + +{width=80%} + + +# Généralités + +## Définition + +* Dans un graphe $G(V,E)$, une **chaîne** reliant un sommet $u$ à un sommet $v$ est une suite d'arêtes entre les sommets, $w_0$, $w_1$, ..., $w_k$, telles que +$$ +(w_i, w_{i+1})\in E,\quad u=w_0,\quad v=w_k,\quad \mbox{pour }0\leq i< k, +$$ +avec $k$ la longueur de la chaîne (le nombre d'arêtes du chemin). + +## Exemples + +{width=80%} + +# Généralités + +## Définition + +* Une **chaîne élémentaire** est une chaîne dont tous les sommets sont distincts, sauf les extrémités qui peuvent être égales + +## Exemples + +{width=80%} + +# Généralités + +## Définition + +* Une **boucle** est une arête $(v,v)$ d'un sommet vers lui-même. + +## Exemples + +{width=40%} + +# Généralités + +## Définition + +* Un graphe non-orienté est dit **connexe**, s'il existe un chemin reliant n'importe quelle paire de sommets distincts. + +## Exemples + +\ + +::: columns + +:::: column + +{width=80%} + +:::: + +:::: column +{width=60%} + +:::: + +::: + +# Généralités + +## Définition + +* Un graphe orienté est dit **fortement connexe**, s'il existe un chemin reliant n'importe quelle paire de sommets distincts. + +## Exemples + +\ + +::: columns + +:::: column + +{width=60%} + +:::: + +:::: column + +{width=100%} + +:::: + +::: + +# Généralités + +## Définition + +* Un **cycle** dans un graphe *non-orienté* est une chaîne de longueur $\geq 3$ telle que le 1er sommet de la chaîne est le même que le dernier, et dont les arêtes sont distinctes. +* Pour un graphe *orienté* on parle de **circuit**. +* Un graphe sans cycles est dit **acyclique**. + +## Exemples + +{width=100%} + +# Question de la mort + +* Qu'est-ce qu'un graphe connexe acyclique? + +. . . + +* Un arbre! + +# Représentations + +* La complexité des algorithmes sur les graphes s'expriment en fonction du nombre de sommets $V$, et du nombre d'arêtes $E$: + * Si $|E|\sim |V|^2$, on dit que le graphe est **dense**. + * Si $|E|\sim |V|$, on dit que le graphe est **peu dense**. +* Selon qu'on considère des graphes denses ou peu denses, différentes structure de données peuvent être envisagées. + +## Question + +* Comment peut-on représenter un graphe informatiquement? Des idées (réflexion de quelques minutes)? + +. . . + +* Matrice/liste d'adjacence. + +# Matrice d'adjacence + +* Soit le graphe $G(V,E)$, avec $V=\{1, 2, 3, ..., n\}$; +* On peut représenter un graphe par une **matrice d'adjacence**, $A$, de dimension $n\times n$ définie par +$$ +A_{ij}=\left\{ \begin{array}{ll} + 1 & \mbox{si } i,j\in E,\\ + 0 & \mbox{sinon}. + \end{array} \right. +$$ + + +::: columns + +:::: column + +## Exemple + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 1---2; + 1---4; + 2---5; + 4---5; + 5---3; +``` + +:::: + +:::: column + +\footnotesize + +## Quelle matrice d'adjacence? + +. . . + +``` + || 1 | 2 | 3 | 4 | 5 +===||===|===|===|===|=== + 1 || 0 | 1 | 0 | 1 | 0 +---||---|---|---|---|--- + 2 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 3 || 0 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 4 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 5 || 0 | 1 | 1 | 1 | 0 +``` + +:::: + +::: + +# Matrice d'adjacence + +## Remarques + +* Zéro sur la diagonale. +* La matrice d'un graphe non-orienté est symétrique + +$$ +A_{ij}=A_{ji}, \forall i,j\in[1,n] +$$. + +::: columns + +:::: column + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 1---2; + 1---4; + 2---5; + 4---5; + 5---3; +``` + +:::: + +:::: column + +\footnotesize + +``` + || 1 | 2 | 3 | 4 | 5 +===||===|===|===|===|=== + 1 || 0 | 1 | 0 | 1 | 0 +---||---|---|---|---|--- + 2 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 3 || 0 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 4 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 5 || 0 | 1 | 1 | 1 | 0 +``` + +:::: + +::: + +# Matrice d'adjacence + +* Pour un graphe orienté (digraphe) + +::: columns + +:::: column + +## Exemple + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 2-->1; + 1-->4; + 2-->5; + 5-->2; + 4-->5; + 5-->3; +``` + +:::: + +:::: column + +\footnotesize + +## Quelle matrice d'adjacence? + +. . . + +``` + || 1 | 2 | 3 | 4 | 5 +===||===|===|===|===|=== + 1 || 0 | 0 | 0 | 1 | 0 +---||---|---|---|---|--- + 2 || 1 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 3 || 0 | 0 | 0 | 0 | 0 +---||---|---|---|---|--- + 4 || 0 | 0 | 0 | 0 | 1 +---||---|---|---|---|--- + 5 || 0 | 1 | 1 | 0 | 0 +``` + +:::: + +::: + +* La matrice d'adjacence n'est plus forcément symétrique +$$ +A_{ij}\neq A_{ji}. +$$ + +# Stockage + +* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe orienté? + +. . . + +* $\mathcal{O}(|V|^2)$. +* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe non-orienté? + +. . . + +* $\mathcal{O}(|V|-1)|V|/2$. + +# Considérations d'efficacité + +* Dans quel type de graphes la matrice d'adjacence est utile? + +. . . + +* Dans les graphes denses. +* Pourquoi? + +. . . + +* Dans les graphes peu denses, la matrice d'adjacence est essentiellement composée de `0`. + +## Remarque + +* Dans la majorité des cas, les grands graphes sont peu denses. +* Comment représenter un graphe autrement? + +# La liste d'adjacence (non-orienté) + +* Pour chaque sommet $v\in V$, stocker les sommets adjacents à $v$- +* Quelle structure de données pour la liste d'adjacence? + +. . . + +* Tableau de liste chaînée, vecteur (tableau dynamique), etc. + + +::: columns + +:::: column + +## Exemple + +{width=80%} + +:::: + +:::: column + + +## Quelle liste d'adjacence? + +. . . + + + + +:::: + +::: + +# La liste d'adjacence (orienté) + + +::: columns + +:::: column + +## Quelle liste d'adjacence pour... + +* Matrix (2min) + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 0-->1; + 0-->2; + 1-->2; + 3-->0; + 3-->1; + 3-->2; +``` + +:::: + +:::: column + +``` + + + + + + + + + + + +``` + + +:::: + +::: + +# Complexité + +## Stockage + +* Quelle espace est nécessaire pour stocker une liste d'adjacence (en fonction de $|E|$ et $|V|$)? + +. . . + +$$ +\mathcal{O}(|E|) +$$ + +* Pour les graphes *non-orientés*: $\mathcal{O}(2|E|)$. +* Pour les graphes *orientés*: $\mathcal{O}(|E|)$. + +## Définition + +* Le **degré** d'un sommet $v$, est le nombre d'arêtes incidentes du sommet (pour les graphes orientés on a un degré entrant ou sortant). +* Comment on retrouve le degré de chaque sommet avec la liste d'adjacence? + +. . . + +* C'est la longueur de la liste chaînée. + + +# Parcours + +* Beaucoup d'applications nécessitent de parcourir des graphes: + * Trouver un chemin d'un sommet à un autre; + * Trouver si le graphe est connexe; +* Il existe *deux* parcours principaux: + * en largeur (Breadth-First Search); + * en profondeur (Depth-First Search). +* Ces parcours créent *un arbre* au fil de l'exploration (si le graphe est non-connexe cela crée une *forêt*, un ensemble d'arbres). + +# Illustration: parcours en largeur + +{width=80%} + +# Exemple + +## Étape par étape (blanc non-visité) + +{width=50%} + +## Étape par étape (gris visité) + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape (vert à visiter) + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape + +{width=50%} + +# Exemple + +## Étape par étape + +{width=50%} + +## Étape par étape + +{width=50%} + +# En faisant ce parcours... + + +::: columns + +:::: column + +## Du parcours de l'arbre + +{width=100%} + +:::: + +:::: column + +## Quel arbre est créé par le parcours (2min)? + +. . . + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 0[x]-->1[w]; + 0-->2[t]; + 0-->3[y]; + 2-->9[u]; + 1-->4[s]; + 4-->5[r]; + 5-->6[v]; +``` + +:::: + +::: + +## Remarques + +* Le parcours dépend du point de départ dans le graphe. +* L'arbre sera différent en fonction du noeud de départ, et de l'ordre de parcours des voisins d'un noeud. + +# Le parcours en largeur + +## L'algorithme, idée générale (3min, matrix)? + +. . . + +```C +v = un sommet du graphe +i = 1 +pour sommet dans graphe et sommet non-visité + visiter(v, sommet, i) // marquer sommet à distance i visité + i += 1 +``` + +## Remarque + +* `i` est la distance de plus cours chemin entre `v` et les sommets en cours de visite. + + +# Le parcours en largeur + +## L'algorithme, pseudo-code (3min, matrix)? + +* Comment garder la trace de la distance? + +. . . + +* Utilisation d'une **file** + +. . . + +```C +initialiser(graphe) // tous sommets sont non-visités +file = visiter(sommet, vide) // sommet est un sommet du graphe au hasard +tant que !est_vide(file) + v = défiler(file) + file = visiter(v, file) +``` + +## Que fait visiter? + +``` +file visiter(sommet, file) + sommet = visité + pour w = chaque arête de sommet + si w != visité + file = enfiler(file, w) + retourne file +``` + +# Exercice (5min) + +## Appliquer l'algorithme sur le graphe + +{width=50%} + +* En partant de `v`, `s`, ou `u` (par colonne de classe). +* Bien mettre à chaque étape l'état de la file. + +# Complexité du parcours en largeur + +## Étape 1 + +* Extraire un sommet de la file; + +## Étape 2 + +* Traîter tous les sommets adjacents. + +## Quelle est la complexité? + +. . . + +* Étape 1: $\mathcal{O}(|V|)$, +* Étape 2: $\mathcal{O}(2|E|)$, +* Total: $\mathcal{O}(|V| + |2|E|)$. + +# Exercice + +* Établir la liste d'adjacence et appliquer l'algorithme de parcours en largeur au graphe + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 1---2; + 1---3; + 1---4; + 2---3; + 2---6; + 3---6; + 3---4; + 3---5; + 4---5; +``` + + +# Illustration: parcours en profondeur + +{width=80%} + +# Parcours en profondeur + +## Idée générale + +* Initialiser les sommets comme non-lus +* Visiter un sommet +* Pour chaque sommet visité, on visite un sommet adjacent s'il est pas encore visité récursivement. + +## Remarque + +* La récursivité est équivalent à l'utilisation d'une **pile**. + +# Parcours en profondeur + +## Pseudo-code (5min) + +. . . + +```C +initialiser(graphe) // tous sommets sont non-visités +pile = visiter(sommet, vide) // sommet est un sommet du graphe au hasard +tant que !est_vide(pile) + v = dépiler(pile) + pile = visiter(v, pile) +``` + +## Que fait visiter? + +. . . + +```C +pile visiter(sommet, pile) + sommet = visité + pour w = chaque arête de sommet + si w != visité + pile = empiler(pile, w) + retourne pile +``` + + +# Exercice + +* Établir la liste d'adjacence et appliquer l'algorithme de parcours en profondeur au graphe + +```{.mermaid format=pdf width=400 loc=figs/} +graph LR; + 1---2; + 1---3; + 1---4; + 2---3; + 2---6; + 3---6; + 3---4; + 3---5; + 4---5; +``` + +# Interprétation des parcours + +* Un graphe vu comme espace d'états (sommet: état, arête: action); + * Labyrinthe; + * Arbre des coups d'un jeu. + +. . . + +* BFS (Breadth-First) ou DFS (Depth-First) parcourent l'espace des états à la recherche du meilleur mouvement. + * Les deux parcourent *tout* l'espace; + * Mais si l'arbre est grand, l'espace est gigantesque! + +. . . + +* Quand on a un temps limité + * BFS explore beaucoup de coups dans un futur proche; + * DFS explore peu de coups dans un futur lointain. + +# Contexte: les réseaux (informatique, transport, etc.) + +* Graphe orienté; +* Source: sommet `s`; +* Destination: sommet `t`; +* Les arêtes ont des poids (coût d'utilisation, distance, etc.); +* Le coût d'un chemin est la somme des poids des arêtes d'un chemin. + +## Problème à résoudre + +* Quel est le plus court chemin entre `s` et `t`. + +# Exemples d'application de plus court chemin + +## Devenir riches! + +* On part d'un tableau de taux de change entre devises. +* Quelle est la meilleure façon de convertir l'or en dollar? + +{width=80%} + +. . . + +* 1kg d'or => 327.25 dollars +* 1kg d'or => 208.1 livres => 327 dollars +* 1kg d'or => 455.2 francs => 304.39 euros => 327.28 dollars + +# Exemples d'application de plus court chemin + +## Formulation sous forme d'un graphe: Comment (3min)? + +{width=80%} + + +# Exemples d'application de plus court chemin + +## Formulation sous forme d'un graphe: Comment (3min)? + +{width=60%} + +* Un sommet par devise; +* Une arête orientée par transaction possible avec le poids égal au taux de change; +* Trouver le chemin qui maximise le produit des poids. + +. . . + +## Problème + +* On aimerait plutôt avoir une somme... + + +# Exemples d'application de plus court chemin + +## Conversion du problème en plus court chemin + +* Soit `taux(u, v)` le taux de change entre la devise `u` et `v`. +* On pose `w(u,w)=-log(taux(u,v))` +* Trouver le chemin poids minimal pour les poids `w`. + +{width=60%} + +* Cette conversion se base sur l'idée que + +$$ +\log(u\cdot v)=\log(u)+\log(v). +$$ + +# Applications de plus courts chemins + +## Quelles applications voyez-vous? + +. . . + +* Déplacement d'un robot; +* Planificaiton de trajet / trafic urbain; +* Routage de télécommunications; +* Réseau électrique optimal; +* ... + +# Plus courts chemins à source unique + +* Soit un graphe, $G=(V, E)$, une fonction de pondération $w:E\rightarrow\mathbb{R}$, et un sommet $s\in V$ + * Trouver pour tout sommet $v\in V$, le chemin de poids minimal reliant $s$ à $v$. +* Algorithmes standards: + * Dijkstra (arêtes de poids positif seulement); + * Bellman-Ford (arêtes de poids positifs ou négatifs, mais sans cycles). +* Comment résoudre le problèmes si tous les poids sont les mêmes? + +. . . + +* Un parcours en largeur! + +# Algorithme de Dijkstra + +## Comment chercher pour un plus court chemin? + +. . . + +``` +si distance(u,v) > distance(u,w) + distance(w,v) + on passe par w plutôt qu'aller directement +``` + +# Algorithme de Dijkstra (1 à 5) + +* $D$ est le tableau des distances au sommet $1$: $D[7]$ est la distance de 1 à 7. +* Le chemin est pas forcément direct. +* $S$ est le tableau des sommets visités. + +::: columns + +:::: column + + + +:::: + +:::: column + +. . . + +![1 visité, `D[2]=1`, `D[4]=3`.](figs/dijkstra_1.png) + +:::: + +::: + +# Algorithme de Dijkstra (1 à 5) + +::: columns + +:::: column + + + + +:::: + +:::: column + +. . . + +![2 visité, `D[3]=2`, `D[7]=3`.](figs/dijkstra_2.png) + +:::: + +::: + +# Algorithme de Dijkstra (1 à 5) + +::: columns + +:::: column + + + + +:::: + +:::: column + +. . . + +![3 visité, `D[7]=3` inchangé, `D[6]=6`.](figs/dijkstra_3.png) + +:::: + +::: + +# Algorithme de Dijkstra (1 à 5) + + +::: columns + +:::: column + + + + +:::: + +:::: column + +. . . + +![4 visité, `D[7]=3` inchangé, `D[5]=9`.](figs/dijkstra_4.png) + +:::: + +::: + +# Algorithme de Dijkstra (1 à 5) + +::: columns + +:::: column + + + + +:::: + +:::: column + +. . . + +![7 visité, `D[5]=7`, `D[6]=6` inchangé.](figs/dijkstra_5.png) + +:::: + +::: + +# Algorithme de Dijkstra (1 à 5) + +::: columns + +:::: column + + + + +:::: + +:::: column + +. . . + +![`6` visité, `D[5]=7` inchangé.](figs/dijkstra_6.png) + +:::: + +::: + +# Algorithme de Dijkstra (1 à 5) + +::: columns + +:::: column + + + +:::: + +:::: column + +. . . + + + +:::: + +::: + +# Algorithme de Dijkstra + +## Idée générale + +* On assigne à chaque noeud une distance $0$ pour $s$, $\infty$ pour les autres. +* Tous les noeuds sont marqués non-visités. +* Depuis du noeud courant, on suit chaque arête du noeud vers un sommet non visité et on calcule le poids du chemin à chaque voisin et on met à jour sa distance si elle est plus petite que la distance du noeud. +* Quand tous les voisins du noeud courant ont été visités, le noeud est mis à visité (il ne sera plus jamais visité). +* Continuer avec le noeud à la distance la plus faible. +* L'algorithme est terminé losrque le noeud de destination est marqué comme visité, ou qu'on a plus de noeuds qu'on peut visiter et que leur distance est infinie. + +# Algorithme de Dijkstra + +## Pseudo-code (5min, matrix) + +\footnotesize + +. . . + +```C +tab dijkstra(graph, s, t) + pour chaque v dans graphe + distance[v] = infini + q = ajouter(q, v) + distance[s] = 0 + tant que non_vide(q) + // sélection de u t.q. la distance dans q est min + u = min(q, distance) + si u == t // on a atteint la cible + retourne distance + q = remove(q, u) + // voisin de u encore dans q + pour chaque v dans voisinage(u, q) + // on met à jour la distance du voisin en passant par u + n_distance = distance[u] + w(u, v) + si n_distance < distance[v] + distance[v] = n_distance + retourne distance +``` + +# Algorithme de Dijkstra + +* Cet algorithme, nous donne le plus court chemin mais... +* ne nous donne pas le chemin! + +## Comment modifier l'algorithme pour avoir le chemin? + +. . . + +* Pour chaque nouveau noeud à visiter, il suffit d'enregistrer d'où on est venu! +* On a besoin d'un tableau `precedent`. + +## Modifier le pseudo-code ci-dessus pour ce faire (3min matrix) + +# Algorithme de Dijkstra + +\footnotesize + +```C +tab, tab dijkstra(graph, s, t) + pour chaque v dans graphe + distance[v] = infini + precedent[v] = indéfini + q = ajouter(q, v) + distance[s] = 0 + tant que non_vide(q) + // sélection de u t.q. la distance dans q est min + u = min(q, distance) + si u == t + retourne distance + q = remove(q, u) + // voisin de u encore dans q + pour chaque v dans voisinage(u, q) + n_distance = distance[u] + w(u, v) + si n_distance < distance[v] + distance[v] = n_distance + precedent[v] = u + retourne distance, precedent +``` + +# Algorithme de Dijkstra + +## Comment reconstruire un chemin ? + +. . . + +```C +pile parcours(precedent, s, t) + sommets = vide + u = t + // on a atteint t ou on ne connait pas de chemin + si u != s && precedent[u] != indéfini + tant que vrai + sommets = empiler(sommets, u) + u = precedent[u] + si u == s // la source est atteinte + retourne sommets + retourne sommets +``` + +# Algorithme de Dijkstra amélioré + +## On peut améliorer l'algorithme + +* Avec une file de priorité! + +## Une file de priorité est + +* Une file dont chaque élément possède une priorité, +* Elle existe en deux saveurs: `min` ou `max`: + * File `min`: les éléments les plus petits sont retirés en premier. + * File `max`: les éléments les plus grands sont retirés en premier. +* On regarde l'implémentation de la `max`. + +## Comment on fait ça? + +. . . + +* On insère les éléments à haute priorité tout devant dans la file! + +# Les files de priorité + +## Trois fonction principales + +```C +booléen est_vide(element) // triviale +element enfiler(element, data, priorite) +data defiler(element) +rien changer_priorite(element, data, priorite) +nombre priorite(element) // utilitaire +``` + +## Pseudo-implémentation: structure (1min) + +. . . + +```C +struct element + data + priorite + element suivant +``` + +# Les files de priorité + +## Pseudo-implémentation: enfiler (2min) + +. . . + +```C +element enfiler(element, data, priorite) + n_element = creer_element(data, priorite) + si est_vide(element) + retourne n_element + si priorite(n_element) > priorite(element) + n_element.suivant = element + retourne n_element + sinon + tmp = element + prec = element + tant que !est_vide(tmp) && priorite < priorite(tmp) + prec = tmp + tmp = tmp.suivant + prev.suivant = n_element + n_element.suivant = tmp + retourne element +``` + +# Les files de priorité + +## Pseudo-implémentation: defiler (2min) + +. . . + +```C +data, element defiler(element) + si est_vide(element) + retourne AARGL! + sinon + tmp = element.data + n_element = element.suivant + liberer(element) + retourne tmp, n_element +``` + +# Algorithme de Dijkstra avec file de priorité min + +```C +distance, precedent dijkstra(graphe, s, t): + distance[source] = 0 + fp = file_p_vide() + pour v dans sommets(graphe) + si v != s + distance[v] = infini + precedent[v] = indéfini + fp = enfiler(fp, v, distance[v]) + tant que !est_vide(fp) + u, fp = defiler(fp) + pour v dans voisinage de u + n_distance = distance[u] + w(u, v) + si n_distance < distance[v] + distance[v] = n_distance + precedent[v] = u + fp = changer_priorite(fp, v, n_distance) + retourne distance, precedent +``` + +# Algorithme de Dijkstra avec file + +\footnotesize + +```C +distance dijkstra(graphe, s, t) +--------------------------------------------------------- + pour v dans sommets(graphe) +O(V) si v != s + distance[v] = infini +O(V) fp = enfiler(fp, v, distance[v]) // notre impl est nulle +------------------O(V * V)------------------------------- + tant que !est_vide(fp) +O(1) u, fp = defiler(fp) +--------------------------------------------------------- +O(E) pour v dans voisinage de u + n_distance = distance[u] + w(u, v) + si n_distance < distance[v] + distance[v] = n_distance +O(V) fp = changer_priorite(fp, v, n_distance) +--------------------------------------------------------- + retourne distance +``` + +* Total: $\mathcal{O}(|V|^2+|E|\cdot |V|)$: + * Graphe dense: $\mathcal{O}(|V|^3)$ + * Graphe peu dense: $\mathcal{O}(|V|^2)$ + +# Algorithme de Dijkstra avec file + +## On peut faire mieux + +* Avec une meilleure implémentation de la file de priorité: + * Tas binaire: $\mathcal{O}(|V|\log|V|+|E|\log|V|)$. + * Tas de Fibonnacci: $\mathcal{O}(|V|+|E|\log|V|)$ +* Graphe dense: $\mathcal{O}(|V|^2\log|V|)$. +* Graphe peu dense: $\mathcal{O}(|V|\log|V|)$. + +# Algorithme de Dijkstra (exercice, 5min) + +{width=60%} + +* Donner la liste de priorité, puis... + +## A chaque étape donner: + +* Le tableau des distances à `a`; +* Le tableau des prédécesseurs; +* L'état de la file de priorité. + +# Algorithme de Dijkstra (corrigé) + + + +# Algorithme de Dijkstra (corrigé) + + + +# Algorithme de Dijkstra (corrigé) + + + +# Algorithme de Dijkstra (corrigé) + + + +# Algorithme de Dijkstra (corrigé) + + + +# Algorithme de Dijkstra (corrigé) + + + +# Limitation de l'algorithme de Dijkstra + +## Que se passe-t-il pour? + +{width=50%} + +## Quel est le problème? + +. . . + +* L'algorithme n'essaiera jamais le chemin `s->x->y->v` et prendra direct `s->v`. +* Ce problème n'apparaît que s'il y a des poids négatifs. + -- GitLab