Intoduction
Très Illustres et très chevalresques champions, gentilshommes, IA autonomes et autres, bienvenue dans ce livre des interwebs qui reprend certains des éléments les plus notoires de la théorie des graphes.
Ce livre a été créé dans le but d'avoir un document de reference qui ne fait pas saigner des yeux, accessible de partout et facile d'utilisation pour la partie qui concerne la théorie des graphes du cours LEPL1108 à l'UCLouvain. Il contient également certains ajouts personnels que je trouve pertinents/interessants et qui ne sont pas vus dans le cours. Le but final est d'avoir un livre de référence le plus complet possible sur la théorie des graphes.
Donc si vous trouvez qu'un certain sujet devrait être inclus dans le libre, n'hésitez pas à contribuer au repositoire github de ce livre. Il ne faut pas s'y connaître en Rust/mdBook/développement web pour contribuer, il suffit d'avoir un éditeur markdown/Latex (je recommande Obsidian avec l'extension Latex Suite) et de savoir utiliser git.
Pour le moment le livre contien deux grand chapitres :
- Bases et définitions : qui donne les bases de la théorie des graphes et définit les termes utiles de façon rigoureuse.
- Algorithmes : qui présente les algorithmes les plus importants de la théorie des graphes, les explique, propose une implémentation et démontre qu'ils sont corrects.
Conseil(s) :
- Si vous cherchez un terme spécifique utilisez la petite loupe en haut à gauche pour faire une recherche rapide
Bases et Définitions
Cette section reprend les définitions rigoureuses (enfin je l'espère) et propriétés qui forment la base de la théorie des graphes vue dans le cours LEPL1108 à l'UCLouvain.
Il est divisé en 4 chapitres :
Notions de Base :
Nœud/Sommet/Point :
Unité fondamentale d'un graphe
Propriétés/Théorèmes :
- Deux sommets sont voisins s'ils sont reliés par une arête.
- Deux sommets sont indépendants s'ils ne sont pas voisins.
- Le degré d'un sommet est le nombre d'arêtes incidentes à ce sommet les boucles comptant double.
Graphe :
Un graphe est un triple :
- ensemble fini nœuds notés
- ensemble fini d'arêtes notées ()
- une relation d'incidence telle que toute arête est incidente à 1 ou 2 nœuds (cette relation est généralement sous-entendue pour un graphe donné)
Propriétés/Théorèmes :
- Un graphe est dit d'ordre si
Arête/Lien/Ligne :
liaison entre deux sommets d'un graphe
Propriétés/Théorèmes :
- Une arrête est une boucle si :
- : Indique que la paire est un élément de l'ensemble .
- : Désigne l'ensemble des tels que ce trouve dans l'ensemble des relations d'incidence c'est à dire l'ensemble des connexions arête nœud.
- Désigne la taille de l'ensemble susmentionné.
Notions Dérivées :
Parcours/Chaîne :
Un parcours de longueur dans est une suite alternée de nœuds et arêtes de .
Propriétés/Théorèmes :
- Un parcours est dit fermé si et ouvert sinon.
Piste/Chaîne simple :
Une piste est un parcours dont les arêtes sont distinctes
Chemin/Chaîne élémentaire (Définition de chemin de LEPL1108)) :
Un chemin est un parcours ouvert dont tous les nœuds sont distincts.
Cycle/Circuit (Définition d'un cycle plus répandue dans la littérature et plus utile à mon avis) :
Un cycle est une suite d'arêtes consécutives distinctes (chaine simple) dont les deux sommets extrémités sont identiques.
Cycle (Définition donnée dans LEPL1108) :
Un parcours dont tous les nœuds et arêtes sont distincts, à l’exception du premier et du dernier nœud.
Isthme :
Considérons un graphe connexe . Une arête est appelée un isthme de si la présence de est indispensable à la connexité, c’est-à-dire si le graphe partiel n’est pas connexe.
Graphe Simple :
Un graphe est simple si il n’a ni boucle ni nœuds reliés par des arêtes multiples. identifie alors l'unique arête telle que et
Propriétés/Théorèmes :
- Un graphe simple est biparti si et seulement s'il ne possède aucun cycle de longueur impaire (explication de la partie nécessaire de cette équivalence : Si on imagine un cycle de longueur 3, on place un nœud dans et dans , où place-t-on le troisième nœud ? Dans les 2 cas on aura une arête avec ses extrémités dans un même ensemble )
- Un graphe simple non orienté d'ordre a au maximum arêtes
Graphe Connexe :
Un graphe est connexe si il existe un parcours reliant toute paire de nœuds.
Graphe Biparti :
Un graphe est dit biparti si son ensemble de sommets peut être divisé en deux sous-ensembles disjoints et tels que chaque arête ait une extrémité dans et l'autre dans .
Parcours/Chaine eulérien(ne) :
Un parcours qui passe par toutes les arêtes, une seule fois.
Propriétés/Théorèmes :
- Un graphe connexe a un parcours eulérien si il possède 0 ou 2 arêtes de degré impair.
Cycle/Circuit/Tournée Eulérien(ne) :
Parcours eulérien qui revient au sommet/nœud de départ (ici on parle de cycle définit comme une chaîne simple/piste fermée).
Graphe Eulérien :
Graphe possédant au moins un cycle eulérien (ici on parle de cycle définit comme une chaîne simple/piste fermée).
Exemple(s) :
Propriétés/Théorèmes :
- Un graphe connexe dont les nœuds sont tous de degré pair est un graphe eulérien et inversement.
Piste/Parcours/Chaîne Eulérien(ne) :
Piste qui passe par toutes les arêtes.
Propriétés/Théorèmes :
- Le graphe sans nœud isolé possède une piste eulérienne si est sans nœud isolé est connexe et contient soit 0 soit 2 nœuds de degré impair.
Chemin Hamiltonien :
Un parcours passant par tous les nœuds du graphe une et une seule fois.
Cycle Hamiltonien :
Un cycle passant par tous les nœuds du graphe une et une seule fois.
Graphe Hamiltonien :
Graphe simple possédant un cycle hamiltonien.
Isomorphisme :
Les graphes simples et sont isomorphes si :
- Il existe une bijection
Propriétés/Théorèmes :
1 : La relation d'isomorphisme est une relation d'équivalence sur les graphes 2 : Il est facile de vérifier si définit un isomorphisme Il reste difficile de décider si deux graphes sont isomorphes
Matrice d'incidence :
La matrice d’incidence d’un graphe est la matrice de genre dont chaque entrée vaut :
- si l’arête est une boucle sur le nœud ,
- si relie à un autre nœud,
- si n’est pas incidente à i.
Exemple(s) :
Matrice d'Adjacence :
La matrice d’adjacence est de genre :
- nombre d’arêtes reliant et si
- deux fois le nombre de boucles sur
Exemple(s) :
Propriétés/Théorèmes :
- Soient 2 graphes et avec comme matrices d'adjacence et . et sont isomorphes si et seulement si il existe une matrice de permutation tel que : et sont donc semblables. Dit autrement: si on peut permuter les noms des nœuds de telle sorte que que devient alors les graphes sont isomorphes et la permutation des noms est équivalent à permuter les lignes et les colonnes de la matrice ce qui correspond à la formule ci-dessus.
- La somme des termes sur une lignes ou une colonne correspond au degré du nœud associé à cette ligne/colonne.
- La somme de tous les éléments de la matrice est égal au double du nombre d'arêtes dans le graphe.
- La somme des degrés des nœuds d'une graphe est égal au double du nombre d'arêtes dans le graphe.
- Si est un graphe simple, le nombre de parcours de longueur entre ses nœuds et est donné par
Graphe Orienté :
Un graphe orienté est un graphe dont les arêtes sont associées à une direction.
Graphe Pondéré :
Un graphe pondéré est un graphe , où est une fonction affectant à chaque arête un poids réel.
Arbre :
Un arbre est un graphe connexe qui ne possède pas de cycle.
Propriétés/Théorèmes : Les Propriétés suivantes sont équivalentes (elles définissent des arbres) :
- est connexe et sans cycle.
- est connexe et
- est sans cycle et
- est sans cycle et lui ajouter une arête crée un et un seul cycle.
- est connexe et supprimer une arête quelconque le déconnecte.
- Deux nœuds distincts de sont reliés par un et un seul chemin (et est sans boucle)
Feuille :
Soit un arbre. On dit qu’un nœud est une feuille de si .
Propriétés/Théorèmes :
- Les extrémités du chemin le plus long dans un arbre sont des feuilles de degré 1. Preuve : Soit un chemin de longueur maximale dans (ce chemin n’est pas nécessairement unique, mais il en existe au moins un). On voit que puisque est adjacent à . Si était de degré strictement supérieur à , il devrait exister un nœud adjacent à et distinct de . Si se trouve sur le chemin défini plus haut, alors possède un cycle, ce qui contredit le fait que est un arbre. Si ne se trouve pas sur le chemin défini plus haut, alors peut être étendu en le préfixant par , ce qui contredit l’hypothèse que est un chemin de longueur maximale. On en conclut que . Le même raisonnement s’applique à , et on a donc identifié deux nœuds de degré .
Arbre sous-tendant
L’arbre est un arbre sous-tendant le graphe si et
Propriétés/Théorèmes :
- est connexe possède un arbre sous-tendant
Arbre sous-tendant de poids minimum
est un arbre sous-tendant de poids minimum de ssi sous-tend et tout arbre sous-tendant est tel que .
Exemple(s)
Algorithmes
Cette section reprend les descriptions mathématique, implémentations et preuve d'exactitude de certains des algorithmes les plus importants de la théorie des graphes.
Il est divisé en 4 chapitres :
Algorithme de Bellman-Ford
Maths
In : un graphe orienté pondéré sans cycle négatif et
Out : Une liste de taille contenant les distances minimales séparant de tous les autres nœuds.
Init : et . On créé une liste de distances séparant des autres nœuds. On initialise les distance à une valeur de pour que les comparaisons qui suivent puissent rapidement remplacer cette valeur et la distance séparant de est .
Loop : Répète fois :
-
- si alors
Description
- On créé la liste
- Ensuite on répète fois la procédure suivante
- Pour chaque arête reliant à on regarde si la distance à l'arête peut être raccourcie en prenant la distance à l'arête plus le poids de l'arête qui les sépare.
- contient les valeurs recherchées.
Implémentation Python
# Cette fonction admet qu'il n'y a pas de cycle négatif dans le graphe.
def bellman_ford(graph, source):
distance = {vertex: float('infinity') for vertex in graph}
distance[source] = 0
for i in range(len(graph) - 1):
for u, v, weight in graph.edges():
if distance[u] + weight < distance[v]:
distance[v] = distance[u] + weight
return distance
Complexité
Spatiale :
Temporelle :
Preuve de validité
Preuve par induction
Observations :
Après répétitions :
- Si , alors est le coût d'un chemin de vers (pas forcément le plus court)
- Si un chemin de vers d'au plus arêtes, alors est au coût du plus court chemin de vers comptant au plus arêtes
Si on arrive à démontrer ces observations on aura démontré que l'algorithme est correct.
Cas initial :
On a et
Cas général :
Si a été mis à jour selon la formule alors est la longueur du chemin allant de à qui suit le chemin allant de à et ensuite vers . Ce qui prouve la première observation.
Pour la seconde observation, si on considère un chemin de longueur minimale (il peut y en avoir plusieurs) allant de à avec au plus arêtes. Soit le dernier nœud avant . Alors, le chemin allant de à dans (qu'on peut noter ) est un chemin de longueur minimale avec au plus arêtes parce que sinon il y aurait un chemin plus court avec au plus allant de à que ce qui est une contradiction.
Nous faisons maintenant l'hypothèse inductive que ( étant la fonction qui donne la somme des poids des arêtes d'un parcours).
À l'itération on calcule On sait que on a donc que ce qui démontre la seconde observation.
Comme il n'y a pas de cycle négatif le chemin le plus court ne passera pas plus d'une fois par chacun des nœuds et donc après cycles nous auront toujours le chemin le plus court.
Preuves externes :
Algorithme de Dijkstra
Maths
In : un graphe orienté pondéré avec des poids positifs et
Out : Une liste de taille contenant les distances minimales séparant de tous les autres nœuds.
Init : Soit et, ( si il n'y a pas d'arête entre et ). (où est le poids de l'arête reliant et ).
Loop : Tant que :
- un élément de qui minimise
- (et )
Description
- On créé la liste de taille qu'on initialise à 0 pour , pour les nœuds adjacents à et pour les autres nœuds. On créé également l'ensemble qui contient les nœuds dont on connait la distance minimale ainsi que l'ensemble qui contient les nœuds restants.
- Tant que n'est pas vide ou tant que on répète la procédure suivante :
- On prends l'élément de qui est le plus proche de , on le retire de et on le place dans . Ensuite on regarde pour tous les nœuds restants dans si la valeur de leur distance dans peut être raccourcie en prenant plus le poids associé à l'arête séparant et le nœud en question
- contient les valeurs recherchées.
Implémentation Python
def dijkstra(graph, source):
dist = {vertex: float('infinity') for vertex in graph.vertices}
dist[source] = 0
Q = set(graph.vertices)
while Q:
u = float('infinity')
for vertex in Q:
u = min(u, dist(vertex))
Q.remove(u)
for v, weight in graph.edges.get(u, {}).items():
if v in Q:
alt = dist[u] + weight
if alt < dist[v]:
dist[v] = alt
return dist
Complexité
Implémentation naïve :
Spatiale :
Temporelle :
Meilleure Implémentation
Temporelle : Voir : Tas de Fibonacci
Preuve de validité
Todo
Algorithme de Kruskal
Maths/Description
In : un graphe connexe pondéré
Out : un arbre sous-tendant de poids minimum
Init : On définit l'ensemble trié des arêtes pondérées venant de ainsi que
Loop : Tant que :
- (on retire la première arête de l'ensemble trié )
- Si est sans cycle, alors (une condition équivalente est : Si l'arête relie 2 arbres distincts alors...)
Implémentation Python
# Cette fonction admet l'existance de certaines
# méthodes et classes qui permettent de rendre
# le code plus lisible.
def kruskal(graph, rPrime):
graph.sortByWeight()
for edge in graph.edges():
weight, u, v = edge
if hasCycle(rPrime.union(edge)) == false:
rPrime = rPrime.union(edge)
return rPrime
Complexité
Spatiale :
Temporelle : dépend surtout de l'algorithme de triage mais dans le meilleur des cas :
Preuve de validité
Todo