diff --git a/slides/cours_25.md b/slides/cours_25.md new file mode 100644 index 0000000000000000000000000000000000000000..1397cfd33c93f1fdb0d439aaebcd2555d442f6b8 --- /dev/null +++ b/slides/cours_25.md @@ -0,0 +1,730 @@ +--- +title: "Arbres couvrants" +date: "2025-06-06" +--- + +# Arbres couvrants + +\Huge Les arbres couvrants + +# Trouver un réseau électrique pour + + + +# Solution: pas optimale + + + +* La longueur totale des câbles est super longue! + +# Solution: optimale + + + +# Formalisation: Les arbres couvrants + +## Application: minimisation des coûts + +* Équipement d'un lotissement avec des lignes électriques/téléphoniques, des canalisations, ... + +. . . + +* Pour réduire les coûts, on cherche à minimiser la longueur totale des câbles/tuyaux. + +. . . + +* Les lignes/tuyaux forment un *arbre couvrant*. + +. . . + +* La meilleure option est un *arbre couvrant minimal*. + + +# Formalisation: Les arbres couvrants + +* Qu'est-ce qu'un arbre couvrant? Des idées? De quel objet on part? Où va-t-on? + +. . . + +* Un arbre couvrant d'un graphe non-orienté et connexe est: + * un arbre inclus dans le graphe qui connecte tous les sommets du graphe. + +. . . + + + +# Arbres couvrants + +* Quels algorithmes que nous avons déjà vus permettent de construire des arbres couvrants? + +. . . + +* Les parcours en largeur et en profondeur! + +. . . + + + +# Arbres couvrants minimaux + +* Un *arbre couvrant minimal* est un sous-graphe d'un graphe non-orienté pondéré $G(V,E)$, tel quel: + * C'est un arbre (graphe acyclique); + * Il couvre tous les sommets de $G$ et contient $|V|-1$ arêtes; + * Le coût total associé aux arêtes de l'arbre est minimum parmi tous les arbres couvrants possibles. + +. . . + +* Est-il unique? + +. . . + +* Pas forcément. + +# Arbres couvrants minimaux + +* Comment générer un arbre couvrant minimal? + + + +# Algorithme de Prim + +::: columns + +:::: column + +## Un exemple + + + +:::: + +:::: column + +## On part de `e` (au hasard) + + + +:::: + +::: + +# Algorithme de Prim + +::: columns + +:::: column + +## On choisit comment? + + + +. . . + +* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité. + +:::: + +:::: column + +. . . + +## L'arête `e->d` + + + +:::: + +::: + +# Algorithme de Prim + +::: columns + +:::: column + +## On choisit comment? + + + +. . . + +* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité. + +:::: + +:::: column + +. . . + +## L'arête `d->a` + + + +:::: + +::: + +# Algorithme de Prim + +::: columns + +:::: column + +## On choisit comment? + + + +. . . + +* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité. + +:::: + +:::: column + +. . . + +## L'arête `d->c` + + + +:::: + +::: + +# Algorithme de Prim + +::: columns + +:::: column + +## On choisit comment? + + + +. . . + +* L'arête la plus courte sortant d'un sommet déjà visité, et entrant dans un sommet non-visité. + +:::: + +:::: column + +. . . + +## L'arête `e->b` + + + +* Game over! + +:::: + +::: + +# Exemple d'algorithme de Prim + +::: columns + +:::: {.column width="40%"} + +## Un exemple + + + +:::: + +:::: column + +``` +FP | e | d | b | c | a | +---------------------------------- +D | 0 | inf | inf | inf | inf | + + | e | d | b | c | a | +---------------------------------- +P | - | - | - | - | - | +``` + +## Devient? + +. . . + +``` +FP | d | b | c | a | +---------------------------- +D | 4 | 5 | 5 | inf | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | e | - | +``` + +:::: + +::: + +# Exemple d'algorithme de Prim + +::: columns + +:::: {.column width="40%"} + +## Un exemple + + + +:::: + +:::: column + +``` +FP | d | b | c | a | +---------------------------- +D | 4 | 5 | 5 | inf | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | e | - | +``` + +## Devient? + +. . . + +``` +FP | a | c | b | +---------------------- +D | 2 | 4 | 5 | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | d | d | +``` + +:::: + +::: + +# Exemple d'algorithme de Prim + +::: columns + +:::: {.column width="40%"} + +## Un exemple + + + +:::: + +:::: column + +``` +FP | a | c | b | +---------------------- +D | 2 | 4 | 5 | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | d | d | +``` + +## Devient? + +. . . + +``` +FP | c | b | +---------------- +D | 4 | 5 | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | d | d | +``` + +:::: + +::: + +# Exemple d'algorithme de Prim + +::: columns + +:::: {.column width="40%"} + +## Un exemple + + + +:::: + +:::: column + +``` +FP | c | b | +---------------- +D | 4 | 5 | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | d | d | +``` + +## Devient? + +. . . + +``` +FP | b | +---------- +D | 5 | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | d | d | +``` + +:::: + +::: + +# Exemple d'algorithme de Prim + +::: columns + +:::: {.column width="40%"} + +## Un exemple + + + +:::: + +:::: column + +``` +FP | b | +---------- +D | 5 | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | d | d | +``` + +## Devient? + +. . . + +``` +FP | +---- +D | + + | e | d | b | c | a | +---------------------------------- +P | - | e | e | d | d | +``` + +:::: + +::: + +# Algorithme de Prim + +## Structures de données + +* Dans quoi allons nous stocker les sommets? + +. . . + +* File de priorité min. +* Autre chose? + +. . . + +* Tableau des distances (comme pour Dijkstra). +* Autre chose? + +. . . + +* Tableau des parents (presque comme pour Dijkstra). +* Autre chose? + +. . . + +* Non. + +# Algorithme de Prim + +## Initialisation: Pseudo-code (2min) + +. . . + +```C +file_priorité, distance, parent initialisation(graphe) + s_initial = aléatoire(graphe) + distance[s_initial] = 0 + parent[s_initial] = indéfini + fp = file_p_vide() + pour s_courant dans sommets(graphe) + si s_courant != s_initial + distance[s_courant] = infini + parent[s_courant] = indéfini + fp = enfiler(fp, s_courant, distance[s_courant]) + retourne fp, distance, parent +``` + +# Algorithme de Prim + +\footnotesize + +## Algorithme: Pseudo-code (5min) + +. . . + +```C +sommets, parent prim(file_priorité, distance, parent) + sommets = vide + tant que !est_vide(fp) + s_courant, fp = défiler(fp) + sommets = insérer(sommets, s_courant) + pour s_voinsin dans voisinage(s_courant) et pas dans sommets + // ou dans fp + si poids(s_courant, s_voinsin) < distance[s_voinsin] + parent[s_voinsin] = s_courant + distance[s_voinsin] = poids(s_courant, s_voinsin) + fp = changer_priorité(fp, + s_voinsin, poids(s_courant, s_voinsin)) + retourne sommets, parent +``` + +# Exercice: algorithme de Prim + +## Appliquer l'algorithme de Prim à (15min): + + + +# Exercice: algorithme de Prim + +## Solution + + + +# Complexité de l'algorithme de Prim + +\footnotesize + +```C +file_priorité, distance, parent initialisation(graphe) + // choix r et initialisation + pour v dans sommets(graphe) +O(|V|) // initialisation distance et parent + fp = enfiler(fp, v, distance[v]) + retourne fp, distance, parent +sommets, parent prim(file_priorité, distance, parent) + sommets = vide + tant que !est_vide(file_priorité) +O(|V|) u, fp = défiler(file_priorité) + sommets = insérer(sommets, u) + pour v dans voisinage de u et pas dans sommets + O(|E|) si w(u, v) < distance[v] + // màj dista + parent + O(|V|) fp = changer_priorité(fp, w, w(u, v)) + retourne sommets, parent +``` + +* $O(|V|)+O(|E|)+O(|V|^2)=O(|E|+|V|^2)$ +* Remarque: $O(|E|)$ n'est pas mutliplié par $O(|V|)$, car les arêtes parcourues qu'une fois en **tout**. + +# Algorithme de Kruskal + +* On ajoute les arêtes de poids minimal: + * si cela ne crée pas de cycle; + * on s'arrête quand on a couvert tout le graphe. + +. . . + +* Comment on fait ça? + +. . . + +* Faisons un exemple pour voir. + +# Algorithme de Kruskal: exemple + +::: columns + +:::: column + +## Un exemple + + + +:::: + +:::: column + +## On part de `(a, d)` (poids le plus faible) + + + +:::: + +::: + +# Algorithme de Kruskal: exemple + +::: columns + +:::: column + +## On continue avec `(c, d)` + + + +:::: + +:::: column + +## Résultat + + + +:::: + +::: + +# Algorithme de Kruskal: exemple + +::: columns + +:::: column + +## On continue avec `(d, e)` + + + +:::: + +:::: column + +## Résultat + + + +:::: + +::: + +# Algorithme de Kruskal: exemple + +::: columns + +:::: column + +## On continue avec `(b, e)` + + + +:::: + +:::: column + +## Résultat + + + +:::: + +::: + +# Algorithme de Kruskal: exemple + +::: columns + +:::: column + +## Mais pourquoi pas `(c, e)`? + + + +:::: + +:::: column + +## Résultat: un cycle + + + +:::: + +::: + +* Comment faire pour empêcher l'ajout de `(c, e)` ou `(a, c)`? + +. . . + +* Si les deux sommets sont déjà couverts nous sommes sauvés (presque)! + +# Algorithme de Kruskal + +## L'initialisation + +* Créer un ensemble de sommets pour chaque de sommet du graphe ($V_1$, $V_2$, ...): + * $V_1=\{v_1\}$, $V_2=\{v_2\}$, ... + * S'il y a $n$ sommets, il y a $n$ $V_i$. +* Initialiser l'ensemble $A$ des arêtes "sûres" constituant l'arbre couvrant minimal, $A=\emptyset$. +* Initialiser l'ensemble des sommets couverts $F=\emptyset$ +* Trier les arêtes par poids croissant dans l'ensemble $E$. + +## Mise à jour + +* Tant qu'il reste plus d'un $V_i$: + * Pour $(u,v)\in E$ à poids minimal: + * Retirer $(u,v)$ de $E$, + * Si $u\in V_i$ et $v\in V_j$ avec $V_i\cap V_j=\emptyset$: + * Ajouter $(u,v)$ à $A$; + * Fusionner $u$ et $v$ dans $F$. + +# Algorithme de Kruskal: exemple + +::: columns + +:::: column + + + +:::: + +:::: column + +:::: + +::: + +# Algorithme de Kruskal: solution + + + +# Algorithme de Kruskal: exercice + +::: columns + +:::: column + + + +:::: + +:::: column + +:::: + +::: + +# Algorithme de Kruskal: solution + + diff --git a/slides/figs/kruskal_0.png b/slides/figs/kruskal_0.png new file mode 100644 index 0000000000000000000000000000000000000000..c413e3d52420a86b4323bef5baf0b4a2b987f0bb Binary files /dev/null and b/slides/figs/kruskal_0.png differ diff --git a/slides/figs/kruskal_1.png b/slides/figs/kruskal_1.png new file mode 100644 index 0000000000000000000000000000000000000000..7a0da02fa35abb08fca7770b7873f558e7938aa7 Binary files /dev/null and b/slides/figs/kruskal_1.png differ diff --git a/slides/figs/kruskal_2.png b/slides/figs/kruskal_2.png new file mode 100644 index 0000000000000000000000000000000000000000..5cfe459bea24b3a3b0146f672f191ff4d7f51e16 Binary files /dev/null and b/slides/figs/kruskal_2.png differ diff --git a/slides/figs/kruskal_3.png b/slides/figs/kruskal_3.png new file mode 100644 index 0000000000000000000000000000000000000000..66c03316704961ca8bd53ad66adac079f167891b Binary files /dev/null and b/slides/figs/kruskal_3.png differ diff --git a/slides/figs/kruskal_4.png b/slides/figs/kruskal_4.png new file mode 100644 index 0000000000000000000000000000000000000000..4c6741560c2475044005295b7b68a5cdcbf9913e Binary files /dev/null and b/slides/figs/kruskal_4.png differ diff --git a/slides/figs/kruskal_cycle.png b/slides/figs/kruskal_cycle.png new file mode 100644 index 0000000000000000000000000000000000000000..4c16b2f010793b7ff1944b6fb04da43e9863ef54 Binary files /dev/null and b/slides/figs/kruskal_cycle.png differ diff --git a/slides/figs/kruskal_enonce.png b/slides/figs/kruskal_enonce.png new file mode 100644 index 0000000000000000000000000000000000000000..294a9a388afdd8cf77d3073da007bcce6bb05b80 Binary files /dev/null and b/slides/figs/kruskal_enonce.png differ diff --git a/slides/figs/kruskal_exercice.png b/slides/figs/kruskal_exercice.png new file mode 100644 index 0000000000000000000000000000000000000000..14e76d51d3a59a7ff165433f72c834d3b76d40c3 Binary files /dev/null and b/slides/figs/kruskal_exercice.png differ diff --git a/slides/figs/kruskal_solution.png b/slides/figs/kruskal_solution.png new file mode 100644 index 0000000000000000000000000000000000000000..54e42c6b94896b27ca4017c2b1b7a1d61e32b0e1 Binary files /dev/null and b/slides/figs/kruskal_solution.png differ diff --git a/slides/figs/kruskal_solution_exercice.png b/slides/figs/kruskal_solution_exercice.png new file mode 100644 index 0000000000000000000000000000000000000000..63dc3ca82e18f05cda5b575e08e436661d577777 Binary files /dev/null and b/slides/figs/kruskal_solution_exercice.png differ diff --git a/slides/figs/prim_0.png b/slides/figs/prim_0.png new file mode 100644 index 0000000000000000000000000000000000000000..dbc6df146f83883c9aefee870fd1a4bba4164468 Binary files /dev/null and b/slides/figs/prim_0.png differ diff --git a/slides/figs/prim_1.png b/slides/figs/prim_1.png new file mode 100644 index 0000000000000000000000000000000000000000..a85adb5e4f338e67f97d89c184fe8ff4e8ab2b19 Binary files /dev/null and b/slides/figs/prim_1.png differ diff --git a/slides/figs/prim_2.png b/slides/figs/prim_2.png new file mode 100644 index 0000000000000000000000000000000000000000..81afadd299dd18af4f3ca722ccfa5e054e5380e6 Binary files /dev/null and b/slides/figs/prim_2.png differ diff --git a/slides/figs/prim_3.png b/slides/figs/prim_3.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ad120e879c247aff68a15c8bbb546d8c6fe631 Binary files /dev/null and b/slides/figs/prim_3.png differ diff --git a/slides/figs/prim_4.png b/slides/figs/prim_4.png new file mode 100644 index 0000000000000000000000000000000000000000..11aff386e69ee36435ef30c68040c8b80080cc55 Binary files /dev/null and b/slides/figs/prim_4.png differ diff --git a/slides/figs/prim_5.png b/slides/figs/prim_5.png new file mode 100644 index 0000000000000000000000000000000000000000..babfe24819fb5b7d0a82ed5f8e3b49cddc5a93eb Binary files /dev/null and b/slides/figs/prim_5.png differ diff --git a/slides/figs/prim_exercice.png b/slides/figs/prim_exercice.png new file mode 100644 index 0000000000000000000000000000000000000000..3b9995b006845743663243acc9af7641c92a8fbf Binary files /dev/null and b/slides/figs/prim_exercice.png differ diff --git a/slides/figs/prim_solution.png b/slides/figs/prim_solution.png new file mode 100644 index 0000000000000000000000000000000000000000..b8c207245814b89147c62f64b0c51d1a59840fc8 Binary files /dev/null and b/slides/figs/prim_solution.png differ