Théorie des graphes : parcours, coloration et ordonnancement
Ce que ce chapitre apporte
- Maîtriser le vocabulaire des graphes : sommets, arêtes, degré, chaîne, cycle, connexité.
- Choisir une représentation en machine et connaître le coût de chaque opération.
- Implémenter et dérouler un parcours en largeur et un parcours en profondeur.
- Définir coloration et nombre chromatique, et minorer ce dernier par la taille d'une clique.
- Appliquer l'algorithme glouton et comprendre sa dépendance à l'ordre des sommets.
- Reconnaître un graphe d'intervalles, un graphe cordal, un graphe parfait.
- Modéliser un problème d'ordonnancement par un graphe et le résoudre de façon optimale.
Si une notion résiste ici, c'est là qu'il faut aller la chercher.
Vocabulaire
Un graphe est la donnée d'un ensemble fini de sommets et d'un ensemble de paires de sommets, appelées arêtes si le graphe est non orienté, arcs s'il est orienté.
On note l'ordre du graphe et sa taille.
Un graphe est simple s'il n'a ni boucle (arête d'un sommet vers lui-même) ni arête multiple. Sauf mention contraire, tous les graphes de ce chapitre sont simples et non orientés.
Degré
Le degré d'un sommet est son nombre de voisins. Dans un graphe orienté, on distingue le degré entrant et le degré sortant.
La somme des degrés vaut deux fois le nombre d'arêtes, puisque chaque arête est comptée à ses deux extrémités.
Chemins, cycles, connexité
Une chaîne est une suite de sommets consécutivement reliés. Elle est simple si elle ne répète aucune arête, élémentaire si elle ne répète aucun sommet.
Un cycle est une chaîne qui revient à son point de départ. Dans un graphe orienté, on parle de chemin et de circuit.
Un graphe est connexe si toute paire de sommets est reliée par une chaîne. Sinon, il se décompose en composantes connexes.
Un arbre est un graphe connexe sans cycle. Il possède exactement arêtes.
Sous-graphes et cliques
Un sous-graphe induit par une partie est le graphe formé de et de toutes les arêtes de dont les deux extrémités sont dans . On ne choisit pas les arêtes : elles viennent avec les sommets.
Une clique est un ensemble de sommets deux à deux adjacents. On note la taille de la plus grande clique de .
La clique jouera un rôle central : c'est elle qui donnera la borne inférieure du nombre de couleurs nécessaires.
Représenter un graphe en machine
Trois représentations, et le choix a des conséquences mesurables.
Liste d'adjacence : pour chaque sommet, la liste de ses voisins. En Python, un dictionnaire de set. Occupe .
Matrice d'adjacence, un tableau où si l'arête existe. Occupe , quel que soit le nombre d'arêtes.
Liste d'arêtes, la simple liste des paires. Occupe , compacte mais lente à interroger.
| Opération | Liste d'adjacence | Matrice | Liste d'arêtes |
|---|---|---|---|
| et sont-ils voisins ? | avec un set | ||
| Parcourir les voisins de | |||
| Ajouter une arête | |||
| Mémoire |
m est de l'ordre de n, dense quand il approche n²/2. Les graphes réels sont presque toujours creux : réseaux, dépendances, chevauchements de tâches.Pour un graphe creux, la liste d'adjacence gagne sur tous les tableaux : mémoire et temps de parcours. La matrice ne se justifie que sur un graphe dense, ou quand on veut exploiter ses propriétés algébriques.
(i, j) de Aᵏ donne le nombre de chaînes de longueur exactement k entre les sommets i et j. Une multiplication de matrices répond ainsi à une question de dénombrement de chemins : argument classique en devoir, et impossible à formuler aussi simplement avec une liste d'adjacence.
Voici le graphe manipulé dans le bloc ci-dessous : six sommets, sept arêtes, deux triangles.
Parcourir un graphe
Le parcours en largeur (BFS) explore les sommets par distances croissantes : d'abord tous les voisins, puis les voisins des voisins. Il utilise une file (premier entré, premier sorti).
Le parcours en profondeur (DFS) s'enfonce aussi loin que possible avant de revenir en arrière. Il utilise une pile, ou la récursion.
Les deux visitent chaque sommet une fois et chaque arête deux fois : leur complexité est avec des listes d'adjacence, contre avec une matrice, puisqu'il faut alors examiner toute une ligne pour trouver les voisins d'un sommet.
DFS : détection de cycle, tri topologique, composantes fortement connexes. Il donne la structure parce qu'il suit les branches jusqu'au bout.
Dijkstra et Prim sont des variantes où la file devient une file de priorité, ce qui permet de tenir compte de poids sur les arêtes.
1.Une clique de taille 4 dans un graphe prouve que…
2.« Le problème est NP-complet » signifie…
3.Sur un graphe d'intervalles, le nombre minimal de serveurs est…
Dijkstra donnerait la même réponse, avec une file de priorité en plus, donc un facteur logarithmique payé pour rien. Le réflexe à prendre : regarder les poids avant de choisir l'algorithme. Poids identiques, BFS ; poids positifs, Dijkstra ; poids négatifs possibles, Bellman-Ford.
Coloration et nombre chromatique
Une coloration attribue une couleur à chaque sommet de sorte que deux sommets adjacents n'aient jamais la même.
Le nombre chromatique est le plus petit nombre de couleurs permettant de colorer .
Dans une clique de taille , chaque sommet est adjacent à tous les autres : il leur faut couleurs distinctes. Il en faut donc au moins autant pour le graphe entier.
1. Exhiber une clique de taille
k : cela prouve χ ≥ k ;2. Exhiber une coloration à
k couleurs : cela prouve χ ≤ k.Les deux ensemble donnent
χ = k. Une coloration seule ne prouve jamais l'optimalité : elle ne fournit qu'une majoration.
Un problème NP-complet
Déterminer pour un graphe quelconque est NP-complet : on sait vérifier rapidement qu'une coloration proposée est valide, mais on ne connaît aucun algorithme qui en trouve une optimale en temps polynomial, et si l'on en trouvait un, il résoudrait du même coup tous les problèmes de la classe NP.
L'algorithme glouton
Un algorithme glouton fait à chaque étape le choix qui paraît le meilleur localement, sans jamais revenir en arrière.
Pour la coloration : on parcourt les sommets dans un ordre donné et on attribue à chacun la plus petite couleur non utilisée par ses voisins déjà colorés.
Il est en et produit toujours une coloration valide. Mais pas forcément optimale : le résultat dépend entièrement de l'ordre choisi.
Un cas complet : planifier des tâches
Voici la modélisation. Chaque tâche devient un sommet. Deux tâches sont reliées par une arête si leurs intervalles se chevauchent, elles ne peuvent alors pas tourner sur le même serveur. Une couleur est un serveur. Le nombre minimal de serveurs est le nombre chromatique.
Pour deux intervalles et :
ils se chevauchent ⟺ max(d₁, d₂) < min(f₁, f₂)
d₁ < f₂ et d₂ < f₁ », ou pire, d'énumérer les positions relatives des deux intervalles. La forme max(début) < min(fin) dit la même chose en une ligne, sans cas particulier, et se lit directement : l'intersection est non vide si elle commence avant de finir. Utilise l'inégalité stricte : deux tâches dont l'une finit à l'instant où l'autre commence ne se chevauchent pas.
Un graphe construit ainsi s'appelle un graphe d'intervalles, et il a des propriétés remarquables.
Le graphe des chevauchements, coloré : trois couleurs, donc trois serveurs, et le triangle mis en évidence prouve qu'on ne peut pas faire mieux.
Graphes cordaux, graphes parfaits, LexBFS
Un graphe est cordal (ou triangulé) si tout cycle de longueur au moins 4 possède une corde, une arête reliant deux sommets non consécutifs du cycle. Autrement dit, ses seuls cycles sans corde sont des triangles.
Un graphe est parfait si, pour tout sous-graphe induit , on a . La borne inférieure par la clique y est donc toujours atteinte.
La chaîne d'implications qui débloque le problème :
graphe d'intervalles ⟹ graphe cordal ⟹ graphe parfait ⟹
Il suffit donc de compter le recouvrement maximal pour connaître le nombre exact de serveurs. Reste à trouver une coloration qui l'atteigne.
Le parcours en largeur lexicographique est un BFS où, à chaque étape, on choisit le sommet dont l'étiquette est la plus grande dans l'ordre lexicographique. Chaque sommet retenu ajoute son numéro à l'étiquette de ses voisins non encore traités.
Sur un graphe cordal, l'ordre produit est un ordre parfait d'élimination : l'algorithme glouton appliqué dans cet ordre donne une coloration optimale, en temps linéaire.
O(n + m). On n'a pas trouvé un meilleur algorithme général : on a identifié la structure du problème particulier. C'est le mouvement le plus rentable de toute l'algorithmique.
Et la même chose en images : les intervalles d'un côté, le graphe coloré de l'autre.
Exercices type
Un graphe a 6 sommets de degré 3. Combien d'arêtes ? Un graphe à 5 sommets de degré 3 existe-t-il ?
Par le lemme des poignées de main, , donc et .
Pour 5 sommets de degré 3 : , qui devrait valoir , or 15 est impair. Un tel graphe n'existe pas.
C'est le schéma de preuve d'impossibilité le plus court de toute la théorie des graphes : la somme des degrés est toujours paire.
Quelle structure de données pour un réseau social de 10⁹ utilisateurs ayant chacun ~200 amis ?
Liste d'adjacence, sans hésitation.
La matrice demanderait cases, soit un exaoctet même à un bit par case : matériellement impossible.
La liste stocke arêtes, soit de l'ordre de quelques téraoctets : grand, mais réel.
Le rapport de taille est de : le graphe est extrêmement creux, et c'est le cas de tous les graphes réels de grande taille.
Combien de couleurs faut-il pour un cycle à 5 sommets ? à 6 sommets ?
Cycle de longueur paire (6 sommets) : . On alterne les deux couleurs le long du cycle, et l'alternance retombe juste au bouclage.
Cycle de longueur impaire (5 sommets) : . L'alternance échoue au dernier sommet, qui se retrouve voisin de deux couleurs différentes ; une troisième est indispensable.
Résultat général : un graphe est biparti (donc 2-coloriable) si et seulement s'il ne contient aucun cycle impair. Et un BFS le détecte en , en colorant par parité de distance et en vérifiant qu'aucune arête ne relie deux sommets de même parité.
Remarque au passage : le cycle impair n'est pas parfait, puisque mais .
Cinq tâches : $(0{,}3)$, $(1{,}4)$, $(2{,}5)$, $(4{,}7)$, $(6{,}9)$. Combien de serveurs ?
Chevauchements : T1-T2 ( ✓), T1-T3 ( ✓), T2-T3 ( ✓), T3-T4 ( ✓), T4-T5 ( ✓). T2-T4 : est faux, elles ne se chevauchent pas.
À l'instant , trois tâches tournent : T1, T2, T3. C'est une clique de taille 3, donc .
Coloration : T1→0, T2→1, T3→2, T4→0, T5→1. Trois couleurs suffisent, donc : trois serveurs.
Les deux étapes sont indispensables : la clique donne la borne inférieure, la coloration la borne supérieure.
Pourquoi la coloration est-elle facile sur un graphe d'intervalles alors qu'elle est NP-complète en général ?
Parce qu'un graphe d'intervalles est cordal, donc parfait : sur lui et sur tous ses sous-graphes induits. Le nombre chromatique se lit alors directement comme le recouvrement maximal des intervalles, sans rien explorer.
Et LexBFS fournit en temps linéaire un ordre pour lequel l'algorithme glouton atteint cette borne. On obtient donc l'optimum en .
Le point de méthode, transposable : la NP-complétude est une propriété du problème général. Reconnaître que l'instance appartient à une famille structurée peut la ramener au domaine du facile, et c'est presque toujours plus rentable que d'optimiser un algorithme exponentiel.
L'algorithme glouton peut-il donner un résultat très éloigné de l'optimum ?
Oui, arbitrairement. Il existe des graphes bipartis (donc ) sur lesquels un ordre bien choisi force le glouton à utiliser couleurs.
Deux garanties partielles seulement : le glouton n'utilise jamais plus de couleurs, où est le degré maximal ; et il existe toujours un ordre pour lequel il atteint , mais le trouver est aussi difficile que le problème de départ.
D'où les heuristiques d'ordre, comme Welsh-Powell qui trie les sommets par degré décroissant : souvent bien meilleure que l'ordre arbitraire, sans aucune garantie d'optimalité. Sur les graphes cordaux, en revanche, LexBFS donne cette garantie.
La méthode
- Dis ce que sont les sommets et ce que sont les arêtes, en français, avant tout dessin. « Un sommet = une tâche ; une arête = deux tâches qui se chevauchent. »
- Décide orienté ou non en testant si la relation est symétrique.
- Choisis la représentation selon la densité : liste d'adjacence pour un graphe creux, matrice pour un graphe dense ou un calcul de chemins.
- Vérifie le lemme des poignées de main : la somme des degrés doit valoir .
- Pour colorer, cherche d'abord une clique : elle donne la borne inférieure, et souvent la réponse.
- Encadre : une clique de taille puis une coloration à couleurs. Les deux, sinon rien n'est prouvé.
- Repère la famille du graphe. Intervalles, cordal, biparti, arbre : chacune a un algorithme exact rapide.
- Contrôle la coloration en parcourant les arêtes : aucune ne doit relier deux sommets de même couleur.
En résumé
- , sommets, arêtes. Orienté si la relation n'est pas symétrique.
- Lemme des poignées de main : , donc le nombre de sommets de degré impair est pair.
- Chaîne, cycle, connexité. Un arbre est connexe sans cycle et a arêtes.
- Un sous-graphe induit emporte toutes les arêtes entre les sommets retenus.
- Clique : sommets deux à deux adjacents. est la taille de la plus grande.
- Représentations : liste d'adjacence pour un graphe creux, matrice pour un graphe dense.
Aᵏcompte les chaînes de longueur . - BFS (file) donne les distances ; DFS (pile) donne la structure. Les deux en .
- Coloration : deux voisins de couleurs différentes. est le minimum de couleurs.
- : la clique minore toujours. Pour prouver l'optimalité, exhiber une clique et une coloration.
- Déterminer est NP-complet en général, mais pas sur des familles structurées.
- Glouton : , toujours valide, optimal seulement pour un bon ordre.
- Intervalles ⟹ cordal ⟹ parfait ⟹ . LexBFS donne l'ordre qui rend le glouton optimal.
- Ordonnancement : une tâche = un sommet, un chevauchement = une arête, une couleur = un serveur.
max(début) < min(fin).
Et ensuite ? Le bloc est bouclé. Six problèmes, six outils : la théorie des jeux pour décider face à quelqu'un, les probabilités pour chiffrer un risque, les statistiques pour lire des données, la complexité pour choisir un algorithme, l'arithmétique pour protéger un message, les graphes pour modéliser des relations. Ce qui se répète d'un chapitre à l'autre, et qui est en réalité le vrai objet du bloc, c'est le passage de l'énoncé en français au modèle mathématique, puis au programme qui le résout.