Vous êtes sur la page 1sur 69

INSTITUT NATIONAL POLYTECHNIQUE DE LORRAINE

Ecole Nationale Supérieure d’Electricité et de Mécanique

Eléments de Théorie des Graphes


et
Programmation Linéaire
Didier Maquin
Professeur à l’INPL

Version initiale, mai 2003.


Première révision augmentée, mai 2008.
Table des matières
Avant propos 5

1 Un bref historique de la théorie des graphes 5

2 Introduction 7
2.1 Qu’est-ce qu’un graphe ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Graphes et applications multivoques . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Principales définitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3 Modes de représentation d’un graphe 10


3.1 Listes de succession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2 Matrice d’adjacence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 Matrice d’incidence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

4 Etude de la connexité 12
4.1 Chaı̂nes et cycles, élémentaires et simples . . . . . . . . . . . . . . . . . . . . . . 12
4.2 Chemins et circuits, élémentaires et simples . . . . . . . . . . . . . . . . . . . . . 12
4.3 Graphes et sous-graphes connexes . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.4 Graphes et sous-graphes fortement connexes . . . . . . . . . . . . . . . . . . . . . 13
4.5 Cycles et nombre cyclomatique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

5 Parcours eulériens et hamiltoniens 15


5.1 Chaı̂nes et cycles eulériens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.2 Chaı̂nes et cycles hamiltoniens . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

6 Méthode de recherche de chemins 18


6.1 Rappel sur les opérations booléennes sur les matrices . . . . . . . . . . . . . . . . 18
6.2 Recherche de chemins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
6.3 Le problème du plus court chemin . . . . . . . . . . . . . . . . . . . . . . . . . . 20

7 Arbres et arborescences 23
7.1 Définitions et propriétés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
7.2 Arbres couvrants de poids minimum . . . . . . . . . . . . . . . . . . . . . . . . . 24

8 Réseaux, réseaux de transport et problèmes de flots 25


8.1 Définitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
8.2 Recherche d’un flot complet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
8.3 Amélioration du flot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
8.4 Recherche d’un flot maximal : algorithme de Ford et Fulkerson . . . . . . . . . . 28
8.5 Exemple traité manuellement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
8.6 Recherche d’un flot maximal à coût minimal . . . . . . . . . . . . . . . . . . . . . 31

9 Couplages 31
9.1 Le problème du couplage maximal . . . . . . . . . . . . . . . . . . . . . . . . . . 32
9.2 Couplage maximal et flot maximal . . . . . . . . . . . . . . . . . . . . . . . . . . 34
9.3 Couplage de poids maximal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
9.4 Problèmes d’affectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

3
10 Problèmes d’ordonnancement 39
10.1 Le graphe potentiels-tâches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
10.2 Le graphe potentiels-étapes ou graphe PERT . . . . . . . . . . . . . . . . . . . . 40
10.3 Résolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
10.4 Compléments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

11 Programmation linéaire 43
11.1 La méthode du simplexe à propos d’un exemple . . . . . . . . . . . . . . . . . . . 45
11.2 Position du problème général . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
11.3 Algorithme de résolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

Annexe A - Implémentation de l’algorithme de Moore-Dijkstra 56

Annexe B - Implémentation de l’algorithme de Floyd 60

Annexe C - Implémentation de l’algorithme de Prim 62

Annexe A - Implémentation de l’algorithme du simplexe 64

Références 66

4
Avant propos
”Faut t’faire un dessin ?”. La représentation d’un problème par un dessin, un plan, une
esquisse contribue souvent à sa compréhension. Le langage des graphes est construit, à l’ori-
gine, sur ce principe. Nombres de méthodes, de propriétés, de procédures ont été pensées ou
trouvées à partir d’un schéma pour être ensuite formalisées et développées. Chacun d’entre nous
a, au moins une fois, vu ou utilisé un plan de métro, une carte de lignes ferroviaires, un plan
électrique, un arbre généalogique ou un organigramme d’entreprise ; ainsi, tout le monde sait
plus ou moins intuitivement ce qu’est un graphe. Toutefois, entre cette notion vague où des
points, représentant des individus, des objets, des lieux ou des situations, sont reliés par des
flèches, il y a une longue élaboration des concepts. La première difficulté à laquelle on peut être
confronté concerne la terminologie (très abondante en théorie des graphes). Nous avons donc
choisi d’isoler les principales définitions du reste du cours en utilisant une mise en page différente.

La théorie des graphes constitue aujourd’hui un corpus de connaissances très important.


Comme son nom l’indique, ce cours ne constituera donc qu’une introduction à cette théorie. Nous
le préciserons ultérieurement, le développement de cette théorie doit beaucoup à celui des calcu-
lateurs. Il nous a donc semblé incontournable d’exposer quelques algorithmes de base (recherche
de chemin, d’arbre, de flots, etc.). Cependant, ceci ne constitue pas le corps de cet enseignement
même si les problèmes pratiques de mise en œuvre sont importants. Nous n’évoquerons pas, par
exemple, l’optimalité de telle ou telle représentation d’un graphe au regard du traitement que
l’on souhaite effectuer, ni la complexité (au sens nombre d’opérations élémentaires) des algo-
rithmes. De manière à permettre au lecteur intéressé de juger des difficultés de mise en œuvre
des algorithmes “littéraux”, plus clairs pour la compréhension, décrits dans le corps du texte,
quelques implémentations à l’aide du langage Matlab R
sont donnés en annexe. Ces fonctions ne
prétendent nullement à être efficaces ou efficientes sur des données quelconques ; elles ne sont
données qu’à titre d’illustration. De même, nous nous sommes efforcés ce citer, au moment de
l’introduction des méthodes de base, les fonctions de la boı̂te à outils de manipulation de graphes
c
Metanet du logiciel Scilab qui leur correspondent.

1 Un bref historique de la théorie des graphes


Tout le monde s’accorde à considérer que la théorie des graphes est née en 1736 avec la
communication d’Euler (1707-1783) dans laquelle il proposait une solution au célèbre problème
des ponts de Königsberg (Euler, 1736). Le problème posé était le suivant. Deux ı̂les A et D
sur la rivière Pregel à Königsberg (alors capitale de la Prusse de l’Est, aujourd’hui rebaptisée
Kaliningrad) étaient reliées entre elles ainsi qu’aux rivages B et C à l’aide de sept ponts (désignés
par des lettres minuscules) comme le montre la figure 1.

Fig. 1 – La rivière Pregel et l’ı̂le de Kneiphof

5
Le problème posé consistait, à partir d’une terre quelconque A, B, C, ou D, à traverser chacun
des ponts une fois et une seule et à revenir à son point de départ (sans traverser la rivière à la
nage !). Euler représenta cette situation à l’aide d’un “dessin” où les sommets représentent les
terres et les arêtes, les ponts comme le montre la figure 2.

A D

Fig. 2 – Graphe associé au problème des ponts de Königsberg

Comme nous le montrerons ultérieurement, Euler démontra que ce problème n’a pas de so-
lution. Le problème des ponts de Königsberg est identique à celui consistant à tracer une figure
géométrique sans lever le crayon et sans repasser plusieurs fois sur un même trait.

Pendant les cent années qui suivirent, rien ne fut fait dans ce domaine de recherche. En
1847, Kirchhoff (1824-1887) développa la théorie des arbres pour l’appliquer à l’analyse de cir-
cuits électriques. Dix ans plus tard, Cayley (1821-1895) découvrit la notion d’arbre alors qu’il
essayait d’énumérer les isomères saturés des hydrocarbures de type Cn H2n+2 . A cette époque,
deux autres problèmes d’importance pour la théorie des graphes furent également proposés et
partiellement résolus.

Le premier est la conjecture des quatre couleurs qui affirme que quatre couleurs suffisent
pour colorier n’importe quelle carte plane telle que les “pays” ayant une frontière commune
soient de couleurs différentes. C’est sans doute Möbius (1790-1868) qui présenta le premier ce
problème dans l’un de ses cours en 1840. Environ dix ans après, de Morgan (1806-1871) essaya de
résoudre ce problème. Les lettres de de Morgan à ses divers collègues mathématiciens constituent
les premières références à la conjecture des quatre couleurs. Le problème devint célèbre après sa
publication, par Cayley en 1879, dans le premier volume des Proceedings of the Royal Geographic
Society. Ce problème est resté très longtemps sans solution. Il fallut attendre jusqu’en 1976 pour
que Appel et Haken prouvent ce théorème en réduisant le problème à un nombre fini de situa-
tions particulières et en trouvant une solution pour chacune d’entre elles à l’aide d’un ordinateur.

Le second problème est dû à Sir Hamilton (1805-1865). En 1859, il inventa un casse-tête
qu’il vendit pour 25 guinées à un fabricant de jouet de Dublin. Ce jeu consiste en un dodécaèdre
régulier en bois (un polyèdre à 12 faces et 20 sommets), chaque face étant un pentagone régulier
comme le montre la figure 3.

Trois arêtes sont donc issues de chaque sommet. Un clou est fiché sur chaque sommet marqué
du nom de vingt grandes villes mondiales. Le casse-tête consiste à enrouler une ficelle passant
une fois et une seule fois par chacune des villes (sommets). Bien que la solution de ce problème
soit aisée à obtenir, personne n’a encore trouvé de condition nécessaire et suffisante de l’existence
d’un tel chemin (appelé chemin Hamiltonien) dans un graphe quelconque.

Cette période fertile fut suivie d’un demi-siècle de relative inactivité. Les années 1920 virent

6
Fig. 3 – Un dodécaèdre régulier

la résurgence de l’intérêt pour les graphes. L’un des pionniers de cette période fut König à qui
l’on doit le premier ouvrage consacré entièrement à la théorie des graphes (König, 1936). Il est
sans doute à l’origine de l’utilisation du terme “graphe” pour désigner ce qui était préalablement
considéré comme un ensemble de “points et de flèches”.

A partir de 1946, la théorie des graphes a connu un développement intense sous l’impul-
sion de chercheurs motivés par la résolution de problèmes concrets. Parmi ceux-ci, citons de
manière privilégiée Kuhn (1955), Ford et Fulkerson (1956) et Roy (1959). Parallèlement, un
important effort de synthèse a été opéré en particulier par Claude Berge. Son ouvrage “Théorie
des graphes et ses applications” publié en 1958 (Berge, 1958) marque sans doute l’avènement
de l’ère moderne de la théorie des graphes par l’introduction d’une théorie des graphes unifiée
et abstraite rassemblant de nombreux résultats épars dans la littérature. Depuis, cette théorie
a pris sa place, en subissant de très nombreux développement essentiellement dus à l’appari-
tion des calculateurs, au sein d’un ensemble plus vaste d’outils et de méthodes généralement
regroupées sous l’appellation “recherche opérationnelle” ou “mathématiques discrètes”.

2 Introduction
2.1 Qu’est-ce qu’un graphe ?
Définition 1
On appelle graphe G = (X, A) la donnée d’un ensemble X dont les éléments sont
appelés sommets et d’une partie de A symétrique ( (x, y) ∈ A ⇔ (y, x) ∈ A) dont
les éléments sont appelés arêtes.
En présence d’une arête a = (x, y) qui peut être notée simplement xy, on dit que
x et y sont les extrémités de a, que a est incidente en x et en y, et que y est un
successeur ou voisin de x (et vice versa).
On dit qu’un graphe est sans boucle si A ne contient pas d’arête de la forme (x, x),
c’est-à-dire joignant un sommet à lui-même.
Le nombre de sommets est appelé ordre du graphe.

Un graphe ne possédant pas de boucle ni d’arêtes parallèles (deux arêtes distinctes joignant
la même paire de sommets) est appelé graphe simple ou 1-graphe. En revanche un p-graphe ou
graphe généralisé est un graphe pour lequel il n’existe jamais plus de p arêtes de la forme (x, x).

Graphiquement, les sommets peuvent être représentés par des points et l’arête a = (x, y)
par un trait reliant x à y. On notera que la disposition des points et la longueur ou la forme

7
(rectiligne ou incurvée) des traits n’a aucune importance. Seule l’incidence des différentes arêtes
et sommets compte. A titre d’exemple, les deux graphes de la figure 4 sont identiques.

1
1

2 2 4
4

3
3

Fig. 4 – Deux représentations graphiques d’un même graphe

Dans le tracé graphique d’un graphe, deux arêtes peuvent sembler avoir une intersection en
un point qui n’est pas un sommet. C’est le cas, par exemple, des arêtes e et f du graphe de
la figure 5. De telles arêtes peuvent être vues comme étant placées dans des plans différents et
n’ayant donc aucun point commun.

d b

Fig. 5 – Les arêtes e et f n’ont pas de point commun

Les graphes ainsi définis sont dits “graphes non orientés”. Dans certaines situations cepen-
dant, l’orientation des arêtes est importante.

Définition 2
On appelle graphe orienté ou digraphe G = (X, A) la donnée d’un ensemble X dont
les éléments sont appelés sommets et d’une partie A de X × X dont les éléments
sont appelés arcs ou arêtes.
En présence d’un arc a = (x, y) qui peut être noté simplement xy, on dit que x est
l’origine (ou extrémité initiale) et y l’extrémité (terminale) de a, que a est sortant en
x et incident en y, et que y est un successeur de x tandis que x est un prédécesseur
de y. On dit aussi que x et y sont adjacents.

2.2 Graphes et applications multivoques


L’ensemble des successeurs d’un sommet x ∈ X est noté Γ(x). L’application Γ qui, à tout
élément de X, fait correspondre une partie de X (un élément de P(X)) est appelée une applica-
tion multivoque. L’ensemble des prédécesseurs d’un sommet x ∈ X peut alors être noté Γ−1 (x)

8
où Γ−1 est l’application (multivoque) réciproque de Γ.

Si le graphe G est un 1-graphe, on constate qu’il est parfaitement déterminé par la donnée
de l’ensemble X et de l’application multivoque Γ de X → P(X). Un tel graphe peut donc aussi
être noté : G = (X, Γ).

2.3 Principales définitions


Les définitions qui suivent sont énoncées dans le cadre des graphes orientés. Le lecteur trans-
posera aisément ces définitions (si elles ont un sens) au cas des graphes non orientés.

Définition 3
On appelle degré sortant ou demi-degré extérieur d’un sommet x le nombre d’arcs
de la forme a = (x, y) avec y 6= x, c’est-à-dire le nombre d’éléments de Γ(x)\ {x}.
On note ds (x) ce degré.
On appelle degré entrant ou demi-degré intérieur d’un sommet x le nombre d’arcs
de la forme a = (y, x) avec y 6= x, c’est-à-dire le nombre d’éléments de Γ−1 (x)\ {x}.
On note de (x) ce degré.
On appelle degré de x (ou valence) la somme du degré entrant et du degré sortant.

Un sommet de degré entrant non nul et de degré sortant nul est appelé puits, tandis qu’un
sommet de degré entrant nul et de degré sortant non nul est appelé source.

Un sommet n’ayant pas d’arcs incidents est appelé sommet isolé ; ces sommets ont un degré
nul. Deux arcs adjacents sont dits ”en série” si leur sommet commun est de degré égal à deux.
Dans la définition d’un graphe, l’ensemble des arcs A peut être vide ; dans ce cas, on a affaire
à un graphe nul. Tous les sommets d’un graphe nul sont donc des sommets isolés. En revanche,
l’ensemble des sommets X ne peut être vide sinon le graphe correspondant n’existe pas. Cela
signifie donc qu’un graphe comporte au moins un sommet.

Définition 4
On appelle graphe réflexif un graphe possédant une boucle sur chaque sommet.
Un graphe est symétrique si, pour tout arc a1 = (x, y) appartenant à A, l’arc
a2 = (y, x) appartient également à A.
Un graphe est antisymétrique si, pour tout arc a1 = (x, y) appartenant à A, l’arc
a2 = (y, x) n’appartient pas à A.
Enfin, un graphe est transitif si, quelque soit deux arcs adjacents a1 = (x, y) et
a2 = (y, z) appartenant à A, alors l’arc a3 = (x, z) appartient également à A.

Le concept de graphe symétrique est très proche de celui des graphes non orientés. En
fait, à tout graphe symétrique, on peut associer un graphe non orienté en substituant aux arcs
a1 = (x, y) et a2 = (y, x), une arête a = (y, x).

9
Définition 5
Un graphe G = (X, A) est dit complet si, pour toute paire de sommets (x, y), il existe
au moins un arc de la forme (x, y) ou (y, x).
Un graphe simple complet d’ordre n est noté Kn . Un sous-ensemble de sommets
C ⊂ X tel que deux sommets quelconques de C sont reliés par une arête est appelé
une clique.

Définition 6
Soit un graphe G = (X, A) et X ′ ⊂ X. Le sous-graphe engendré par X ′ est G′ = (X ′ , A′ ),
A′ étant formé des arêtes dont les deux extrémités sont dans X ′ .
Si l’on se donne un sous-ensemble A1 de A, le graphe partiel engendré par A1 est
G1 = (X, A1 ).

Dans certaines situations, les sommets de G1 ayant un degré nul (sommets isolés n’ayant
aucune arête incidente appartenant à A1 ) peuvent être supprimés du graphe partiel.

D’après la définition précédente, une clique d’un graphe G est donc un sous-graphe complet
de G.

3 Modes de représentation d’un graphe


Comme nous l’avons mentionné précédemment, l’essor de la théorie des graphes est essen-
tiellement dû à l’avènement de puissants calculateurs. Il est donc légitime de s’intéresser à la
manière de représenter les graphes au sein d’un ordinateur. Plusieurs modes de représentation
peuvent être envisagés selon la nature des traitements que l’on souhaite appliquer au graphe
considéré.

3.1 Listes de succession


Un graphe peut être représenté à l’aide d’un dictionnaire ; il s’agit d’une table à simple entrée
où chaque ligne correspond à un sommet et comporte la liste des successeurs ou des prédécesseurs
de ce sommet. Considérons le graphe de la figure 6.

1 7

6
5
1
5 8
3

2 4
2
4

Fig. 6 – Un graphe élémentaire

Celui-ci peut être représenté par les deux tables suivantes :

10
1 2, 3, 4, 5 1 5
2 3 2 1
3 4 3 1, 2
4 - 4 1,3,5
5 1, 4 5 1

Dans la mesure où, pour une table donnée, le nombre de successeurs ou de prédécesseurs n’est
pas le même pour chaque sommet, il est préférable de représenter le dictionnaire sous forme de
deux tableaux : le premier comprenant autant d’éléments que de sommets, ces éléments pointant,
dans un second tableau, les débuts de listes de successeurs (ou de prédécesseurs). La figure 7
montre cette organisation en ce qui concerne la table des successeurs.

1
5
2 3 4 5 3 4 1 4
6
0
7

Fig. 7 – Codage d’une liste de successeurs

Cette représentation est un peu redondante dans le cas des graphes non orientés ; elle est
cependant assez commode pour parcourir le graphe. L’encombrement de cette représentation est
minimal puisqu’il correspond exactement à la quantité d’information fournie par le graphe.

3.2 Matrice d’adjacence


Les outils classiques d’algèbre linéaire peuvent également être utilisés pour coder les graphes.
La première idée consiste à considérer chaque arc comme un lien entre deux sommets.

Définition 7
Considérons un graphe G = (X, A) comportant n sommets. La matrice d’adjacence
de G est égale à la matrice U = (uij ) de dimension n × n telle que

1 si (i, j) ∈ A (c’est-à-dire (i, j) est une arête)
uij =
0 sinon
Une telle matrice, ne contenant que des ”0” et des ”1” est appelée, de manière
générale, une matrice booléenne.

Un graphe orienté quelconque a une matrice d’adjacence quelconque, alors qu’un graphe non
orienté possède une matrice d’adjacence symétrique. L’absence de boucle se traduit par une
diagonale nulle. La matrice d’adjacence du graphe de la figure 6 est la suivante :
 
0 1 1 1 1
 0 0 1 0 0 
 
U =  0 0 0 1 0 

 0 0 0 0 0 
1 0 0 1 0

11
Ce mode de représentation engendre des matrices très creuses (i.e. comprenant beaucoup
de zéros). Cependant la recherche de chemins ou de chaı̂nes s’effectue aisément avec une telle
représentation (cf § 6.2). De plus, la matrice d’adjacence possède quelques propriétés qui peuvent
être exploitées. Considérons un graphe G et sa matrice d’adjacence associée U :

– la somme des éléments de la ieme ligne de U est égale au degré sortant ds (xi ) du sommet
xi de G.
– la somme des éléments de la j eme colonne de U est égale au degré entrant de (xj ) du sommet
xj de G.
– U est symétrique si, et seulement si, le graphe G est symétrique.

3.3 Matrice d’incidence


La seconde idée permettant une représentation matricielle d’un graphe exploite la relation
d’incidence entre arêtes et sommets.

Définition 8
Considérons un graphe orienté sans boucle G = (X, A) comportant n sommets
x1 , . . . , xn et m arêtes a1 , . . . , am . On appelle matrice d’incidence (aux arcs) de
G la matrice M = (mij ) de dimension n × m telle que :

 1 si xi est l’extrémité initiale de aj
mij = −1 si xi est l’extrémité terminale de aj
0 si xi n’est pas une extrémité de aj

Pour un graphe non orienté sans boucle, la matrice d’incidence (aux arêtes) est
définie par :

1 si xi est une extrémité de aj
mij =
0 sinon

La matrice d’incidence du graphe de la figure 6 s’écrit sous la forme suivante :


 
1 0 1 0 1 1 −1 0
 −1 1 0 0 0 0 0 0 
 
M =  0 −1 −1
 1 0 0 0 0 
 0 0 0 −1 −1 0 0 −1 
0 0 0 0 0 −1 1 1

4 Etude de la connexité
4.1 Chaı̂nes et cycles, élémentaires et simples
Définition 9
Une chaı̂ne est une séquence finie et alternée de sommets et d’arêtes, débutant et
finissant par des sommets, telle que chaque arête est incidente avec les sommets qui
l’encadre dans la séquence.

Le premier et le dernier sommet sont appelés (sommets) extrémités de la chaı̂ne.


La longueur de la chaı̂ne est égale au nombre d’arêtes qui la composent.

12
Si aucun des sommets composant la séquence n’apparaı̂t plus d’une fois, la chaı̂ne
est dite chaı̂ne élémentaire.
Si aucune des arêtes composant la séquence n’apparaı̂t plus d’une fois, la chaı̂ne est
dite chaı̂ne simple.
Un cycle est une chaı̂ne dont les extrémités coı̈ncident.
Un cycle élémentaire (tel que l’on ne rencontre pas deux fois le même sommet en le
parcourant) est un cycle minimal pour l’inclusion, c’est-à-dire ne contenant stricte-
ment aucun autre cycle.

4.2 Chemins et circuits, élémentaires et simples


Toutes les définitions précédentes, s’appliquant au cas des graphes non orientés, peuvent être
transposées au cas des graphes orientés.

Définition 10
Un chemin est une séquence finie et alternée de sommets et d’arcs, débutant et
finissant par des sommets, telle que chaque arc est sortant d’un sommet et incident au
sommet suivant dans la séquence (cela correspond à la notion de chaı̂ne ”orientée”).
Si aucun des sommets composant la séquence n’apparaı̂t plus d’une fois, le chemin
est dit chemin élémentaire.
Si aucune des arêtes composant la séquence n’apparaı̂t plus d’une fois, le chemin est
dit chemin simple.
Un circuit est un chemin dont les extrémités coı̈ncident.
En parcourant un circuit élémentaire, on ne rencontre pas deux fois le même sommet.

4.3 Graphes et sous-graphes connexes


De manière intuitive, la notion de connexité est triviale. Un graphe est connexe si l’on peut
atteindre n’importe quel sommet à partir d’un sommet quelconque en parcourant différentes
arêtes. De manière plus formelle, on a :

Définition 11
Un graphe G est connexe s’il existe au moins une chaı̂ne entre une paire quelconque
de sommets de G.

La relation :

soit xi = xj
xi R xj ⇔
soit il existe une chaı̂ne joignant xi à xj

est une relation d’équivalence (réflexivité, symétrie, transitivité). Les classes d’équivalence in-
duites sur X par cette relation forment une partition de X en X1 , X2 , . . . , Xp .

Le nombre p de classes d’équivalence distinctes est appelé nombre de connexité du graphe.

13
On peut alors donner une autre définition concernant la connexité d’un graphe. Un graphe
est dit connexe si et seulement si son nombre de connexité est égal à 1.

Les sous-graphes G1 , G2 , . . . , Gp engendrés par les sous-ensembles X1 , X2 , . . . , Xp sont ap-


pelés les composantes connexes du graphe. Chaque composante connexe est un graphe connexe.

La vérification de la connexité d’un graphe est un des premiers problèmes de la théorie des
graphes. Nous décrirons ultérieurement des algorithmes permettant d’établir cette connexité.

Définition 12
Un point d’articulation d’un graphe est un sommet dont la suppression augmente le
nombre de composantes connexes.
Un isthme est une arête dont la suppression a le même effet.
Un ensemble d’articulation E ⊂ X d’un graphe connexe G est un ensemble de
sommets tel que le sous-graphe G′ déduit de G par suppression des sommets de E,
ne soit plus connexe.

4.4 Graphes et sous-graphes fortement connexes


Définition 13
Un graphe orienté est dit fortement connexe s’il existe un chemin joignant deux som-
mets quelconques.

La relation :

 soit xi = xj
xi R x j ⇔ soit il existe à la fois un chemin joignant xi à xj
et un chemin joignant xj à xi

est une relation d’équivalence et les classes d’équivalence induites sur X par cette relation forment
une partition de X en X1 , X2 , . . . , Xq . Les sous-graphes G1 , G2 , . . . , Gq engendrés par les sous-
ensembles X1 , X2 , . . . , Xq sont appelés les composantes fortement connexes du graphe.

Pour le graphe de la figure 8, les différentes composantes fortement connexes sont :

C1 = {1, 2, 3, 4, 5} C2 = {6, 7} C3 = {8}

Définition 14
On appelle graphe réduit Gr le quotient du graphe G par la relation de forte connexité
Gr = G/R ; les sommets de Gr sont donc les composantes fortement connexes et il
existe un arc entre Ci et Cj si et seulement s’il existe au moins un arc entre un
sommet de Ci et un sommet de Cj dans le graphe G. On vérifie que le graphe Gr est
sans circuit.

Le graphe réduit correspondant au graphe de la figure 8 est donné figure 9. La recherche


des composantes fortement connexes et la détermination du graphe réduit revêtent une grande
importance pour l’analyse structurale d’un système.

14
1 3 5

2 4 7 6

Fig. 8 – Graphe orienté

C3

C1

C2

Fig. 9 – Graphe réduit du graphe de la figure 8

4.5 Cycles et nombre cyclomatique


Les notions de cycle et de cycle élémentaire ont déjà été définies au paragraphe 4.1. Pour un
cycle µ donné, on désigne par µ+ l’ensemble des arcs du cycle orientés dans le sens de parcours
et par µ− l’ensemble des arcs orientés en sens contraire. Si le graphe possède m arcs désignés
par a1 , . . . , am , on peut faire correspondre à tout cycle µ un vecteur µ = (µ1 , µ2 , . . . , µm ) tel
que :
 1 si ai ∈ µ+

µi = −1 si ai ∈ µ−
0 si ai ∈ / µ+ ∪ µ−

On remarque que −µ est aussi un vecteur associé au cycle µ (obtenu en choisissant l’autre
sens de parcours). Au signe près, on pourra donc identifier le cycle µ au vecteur µ.

Définition 15
On dit que p cycles µ1 , µ2 , . . . , µp sont dépendants s’il existe, entre leurs vecteurs
associés, une relation vectorielle de la forme :

λ1 µ1 + λ2 µ2 + . . . + λp µp = 0
avec les λi non tous nuls.
Si la satisfaction de la relation précédente implique λi = 0, ∀i = 1, . . . , p, les p cycles
sont dits indépendants.

15
Une base de cycles est un ensemble minimal de cycles indépendants tel que tout
vecteur représentatif d’un cycle puisse s’exprimer comme combinaison linéaire des
cycles de la base.
On appelle nombre cyclomatique d’un graphe G, la dimension de la base de cycles.

On peut noter que le nombre cyclomatique v(G) d’un graphe à n sommets, m arcs et p
composantes connexes est égal à v(G) = m − n + p.

5 Parcours eulériens et hamiltoniens


L’étude des problèmes eulériens – ou hamiltoniens – (recherche d’une chaı̂ne ou d’un cycle
passant exactement une fois par chaque arête – ou par chaque sommet –) remonte aux origines
de la théorie des graphes.

L’intérêt porté aujourd’hui à ces problèmes s’explique par leurs nombreuses applications :
tournées de distribution, tracé automatique sur ordinateur, problèmes d’ordonnancement d’ate-
lier, etc.

5.1 Chaı̂nes et cycles eulériens


Il s’agit là d’une généralisation du jeu bien connu consistant à dessiner toutes les arêtes d’un
graphe avec un crayon sans jamais le soulever, ni passer deux fois sur la même arête.

Définition 16
Soit G = (X, A) un graphe orienté.
Une chaı̂ne eulérienne est une chaı̂ne empruntant une fois et une fois seulement
chaque arête de G.
Un cycle eulérien est une chaı̂ne eulérienne dont les extrémités coı̈ncident.
Un graphe possédant un cycle eulérien est appelé graphe eulérien.

Le problème de l’existence et de la détermination d’un cycle eulérien (d’une chaı̂ne eulérienne)


dans un graphe non orienté a été posé la première fois et résolu par Euler en 1736 à propos du
célèbre problème des ponts de Königsberg évoqué au premier paragraphe. Euler prouva l’impos-
sibilité de l’obtention d’une solution en démontrant le théorème suivant :

Théorème 1
Un graphe non orienté connexe possède une chaı̂ne eulérienne si et seulement si le
nombre de sommets de degré impair est égal à 0 ou 2.
Il admet un cycle eulérien si et seulement si tous ses sommets ont un degré pair.

Montrons que la condition est nécessaire. Si le cycle eulérien existe, on peut l’orienter de
manière arbitraire. En chaque sommet, le nombre d’arcs incidents doit être égal au nombre
d’arcs sortants, les sommets doivent donc être de degré pair. Dans le cas d’une chaı̂ne, les deux
extrémités font exception ; on part ou l’on arrive une fois de plus, d’où un degré impair pour ces

16
deux sommets extrémités.

Montrons maintenant que la condition est suffisante. Raisonnons par récurrence en supposant
que le théorème est vérifié pour des graphes connexes ayant moins de m arêtes. Soit G = (X, A)
un graphe de m arêtes vérifiant la condition du théorème. Si G possède deux sommets de degré
impair, soient a et b ces sommets (si tous les sommets de G sont de degré pair, on choisit a quel-
conque et b confondu avec a). Soit L la chaı̂ne parcourue par un “voyageur” partant de a dans
une direction quelconque et seulement soumis à l’interdiction d’emprunter deux fois la même
arête. Si, à un instant donné, il arrive en un sommet x 6= b, il aura utilisé un nombre impair
d’arêtes incidentes à x et il pourra donc repartir par une arête non déjà utilisée. Quand il ne
peut plus bouger, c’est donc qu’il est en b. Si toutes les arêtes ont été utilisées, L est une chaı̂ne
eulérienne et le théorème est vrai. Dans le cas contraire, le graphe partiel, défini par les arêtes
non utilisées, a tous ses sommets de degré pair (de part la nature des suppressions effectuées).
Soient G′1 , G′2 , ..., G′p les composantes connexes de G qui comportent au moins une arête. Chacun
des sous graphes G′i possède moins de m arêtes et d’après l’hypothèse de récurrence, il admet
un cycle eulérien µi . Comme G est connexe, L rencontre successivement G′1 , G′2 , ..., G′p en les
sommets x1 , x2 , . . . , xp . Le parcours alors constitué par :

– la chaı̂ne L entre a et x1 ,
– le cycle µ1 entre x1 et x1 ,
– la chaı̂ne L entre x1 et x2 ,
– le cycle µ2 entre x2 et x2 ,
– ...
– la chaı̂ne L entre xp et b.

constitue bien une chaı̂ne eulérienne entre a et b dans G. Le théorème est donc vrai à l’ordre m.
Comme il est vrai à l’ordre 1, il est démontré pour tout m.

Le problème d’Euler peut aussi être considéré avec des “sens uniques”.

Définition 17
Un chemin dans un graphe orienté est dit eulérien s’il passe exactement une fois par
chaque arête.
Un graphe orienté est dit eulérien s’il admet un circuit eulérien.

La démonstration précédente peut aisément être adaptée à cette nouvelle situation.

Théorème 2
Un graphe orienté connexe admet un chemin eulérien (mais pas de circuit eulérien)
si, et seulement si, pour tout sommet sauf deux (a et b), le degré entrant est égal au
degré sortant et
de (a) = ds (a) − 1 et de (b) = ds (b) + 1
Un graphe orienté connexe admet un circuit eulérien si, et seulement si, pour tout
sommet, le degré entrant est égal au degré sortant.

Parmi les problèmes “prototypes” classiques des formulations précédentes, citons le problème
du “postier chinois” (non orienté) qui consiste à parcourir les rues d’une ville en passant au moins

17
une fois dans chaque rue, le graphe n’étant pas nécessairement eulérien ; on cherche bien sûr à
minimiser la longueur totale du parcours.

On rencontre ce genre de problème dans les organisations de tournées de distribution de


courrier, de ramassage d’ordures, d’inspection de réseaux de distribution. Dans le cas orienté
où chaque arc doit être emprunté dans un sens privilégié, le problème se ramène à la recherche
d’un flot à coût minimum (cf. § 8.4).

Il s’agit d’abord de savoir si le “parcours chinois” a au moins une solution. Nous énonçons
ici sans démonstration les résultats suivants.

Théorème 3
Un graphe non orienté admet un cycle chinois si, et seulement si, il est connexe.
Un graphe orienté admet un circuit chinois si, et seulement si, il est fortement
connexe.

La résolution du problème du postier chinois peut s’inspirer des méthodes de recherche de


chaı̂nes ou cycles eulériens. Cependant, on préfèrera formuler le problème en termes de couplage
parfait de poids minimum (cf. § 9.3)

5.2 Chaı̂nes et cycles hamiltoniens


Soit G = (X, A) un graphe connexe d’ordre n.

Définition 18
On appelle chemin hamiltonien (chaı̂ne hamiltonienne) un chemin (une chaı̂ne) pas-
sant une fois, et une fois seulement, par chacun des sommets de G.
Un chemin hamiltonien (une chaı̂ne hamiltonienne) est donc un chemin (une chaı̂ne)
élémentaire de longueur n − 1.
Un circuit hamiltonien (un cycle hamiltonien) est un circuit (un cycle) qui passe une
fois, et une seule fois, par chacun des sommets de G.
On dit qu’un graphe G est hamiltonien s’il contient un cycle hamiltonien (cas non
orienté) ou un circuit hamiltonien (cas orienté).

La notion de cycle hamiltonien trouve son origine dans le jeu inventé par Hamilton que nous
avons évoqué au premier paragraphe. De nombreux problèmes concrets peuvent être formulés
en termes de recherche de parcours hamiltoniens.

On peut en particulier citer le problème du voyageur de commerce. Un représentant de com-


merce doit rendre visite à n clients x1 , x2 , . . . , xn en partant d’une ville x0 et revenir à son
point de départ. Il connaı̂t les distances d0j qui séparent le dépôt x0 de chacun de ses clients xj ,
ainsi que la distance dij entre deux clients quelconques xi et xj .

Dans quel ordre doit-il rendre visiste à ses clients pour que la distance totale parcourue soit
minimale ? Ce problème revient à chercher un cycle hamiltonien de longueur totale minimale
dans le graphe complet G construit sur l’ensemble des sommets X = {x0 , x1 , . . . , xn }, les

18
arêtes étant munies des longueurs dij .

Lorsque le point d’arrivée est différent du point de départ, le problème revient à rechercher
une chaı̂ne hamiltonienne de longueur totale minimale.

Un autre problème classique concerne l’ordonancement de tâches. On cherche un ordre dans


lequel on peut effectuer n tâches données (deux tâches quelconques ne pouvant être effectuées si-
multanément) tout en respectant un certain nombre de contraintes d’antériorité. Si l’on construit
le graphe G dont l’ensemble des sommets correspond à l’ensemble des tâches, et où il existe un
arc (i, j) si la tâche i peut être effectuée avant la tâche j, le problème revient à déterminer un
chemin hamiltonien de G.

D’autres problèmes concrets peuvent se ramener également à la problématique précédente.


On appelle cycle (circuit) préhamiltonien d’un graphe G, un cycle (un circuit) passant au moins
une fois par chaque sommet de G. Un graphe G qui admet un tel cycle (ou circuit) est appelé
graphe préhamiltonien et une condition nécessaire et suffisante pour qu’il en soit ainsi est que
G soit connexe (fortement connexe).

La recherche d’un cycle (circuit) préhamiltonien de longueur minimale dans un graphe G


où les arêtes (arcs) ont des longueurs données se ramène à un problème de recherche de cycle
(circuit) hamiltonien dans le graphe complet G′ construit sur le même ensemble de sommets, la
longueur d’une arête (arc) (i, j) de G′ étant égale à la longueur de la plus courte chaı̂ne (chemin)
entre i et j.

De nombreux problèmes du type “voyageur de commerce” sont en réalité des problèmes


préhamiltoniens et, pour les résoudre, on commencera par calculer la matrice des plus courts
chemins (des plus courtes chaı̂nes).

Notons que l’on ne connaı̂t pas de condition nécessaire et suffisante d’existence de cycles ou
de circuits hamiltoniens.

6 Méthode de recherche de chemins


6.1 Rappel sur les opérations booléennes sur les matrices
Rappelons brièvement les deux opérations d’addition et de multiplication booléenne notées
⊕ et ⊗. Les variables A et B sont booléennes et prennent donc leur valeur dans {0, 1}

A B A⊕B A⊗B
0 0 0 0
0 1 1 0
1 0 1 0
1 1 1 1
Avant de procéder à la recherche systématique de chemins, examinons, de façon générale, la
signification des opérations sur les matrices d’adjacence en termes de graphes.

19
Addition booléenne des matrices
Soient deux graphes G1 et G2 , possédant les mêmes sommets, et leurs matrices d’adjacence
associées U1 et U2 de dimension n × n. Calculons U3 = U1 ⊕ U2 telle que :
(U3 )ij = (U1 )ij ⊕ (U2 )ij
Chaque élément non nul de U3 représente, par définition, un arc de G3 décrit par la matrice
U3 . Pour qu’un élément de U3 soit non nul, il faut que l’un au moins des éléments correspondants
de U1 ou U2 soit non nul. On conclut donc que cette opération revient à construire un graphe
G3 comportant à la fois les arcs de G1 et ceux de G2 .

Multiplication booléenne des matrices


Considérons de nouveau les deux graphes G1 et G2 précédents et calculons U4 = U1 ⊗ U2
telle que :
(U4 )ij = (U1 )i1 ⊗ (U2 )1j ⊕ (U1 )i2 ⊗ (U2 )2j ⊕ . . . (U1 )in ⊗ (U2 )nj
Pour que (U4 )ij soit égal à 1, il faut qu’il existe au moins un indice k tel que simultanément
les éléments (U1 )ik et (U2 )kj soit égaux à 1.

Cela revient à construire un graphe G4 dans lequel un arc (i, j) existe si et seulement s’il
existe un sommet k tel que (i, k) soit un arc de G1 et (k, j) un arc de G2 .

6.2 Recherche de chemins


Soit U la matrice d’adjacence associée au graphe G. Par définition, Uij = 1 indique l’exis-
tence d’un chemin de longueur 1 entre les sommets i et j. Multiplions U par elle-même, soit
U 2 = U ⊗ U et considérons le graphe G′ associé à U 2 . Chaque arc (i, j) de G′ exprime l’exis-
tence d’un chemin de longueur 2 du sommet i au sommet j. En effet, d’après l’interprétation
précédente, (i, j) existe si et seulement s’il existe un sommet k tel que (i, k) et (k, j) sont des
arcs de G.

Démontrons par récurrence que, plus généralement, U p donne l’existence des chemins de lon-
gueur p. Soit un graphe possédant n sommets et U sa matrice d’adjacence associée. Admettons
la propriété pour p − 1 et démontrons la pour p.

Un chemin de longueur p entre les sommets i et j peut se décomposer en un chemin de


longueur p − 1 entre les sommets i et k auquel on ajoute l’arc (k, j). L’existence du chemin entre
les sommets i et k est donnée, par hypothèse, par l’élément (U p−1 )ik , celle de l’arc (k, j) par Ukj .

L’existence d’un chemin joignant les sommets i et j et passant par le sommet k est donc
donnée par (U p−1 )ik ⊗ Ukj . Or, le sommet k est quelconque et peut être l’un des n sommets du
graphe. L’existence d’un chemin entre les sommets i et j s’écrit donc :
Cij = U p−1 i1 ⊗ U1j ⊕ U p−1 i2 ⊗ U2j ⊕ . . . U p−1 in ⊗ Unj
  

L’expression de Cij est, par définition, celle donnée pour calculer l’élément (U p )ij . Comme
nous l’avons vérifiée pour p = 2, la propriété est vraie quel que soit p.

Remarquons que pour un graphe à n sommets, un chemin élémentaire comprend au plus


n − 1 arcs. Il suffit donc, pour avoir l’existence de tous les chemins, d’élever successivement
la matrice U jusqu’à la puissance n. De plus, si deux matrices successives ainsi calculées sont
identiques, il est inutile de poursuivre le calcul jusqu’à la puissance n.

20
6.3 Le problème du plus court chemin
Le problème de la recherche du plus court chemin dans un graphe se rencontre dans de
nombreuses applications. On peut citer entre autres :

– les problèmes de tournées,


– certains problèmes d’investissement et de gestion de stocks,
– les problèmes de programmation dynamique à états discrets et temps discret,
– les problèmes d’optimisation de réseaux (routiers, télécommunications),
– certaines méthodes de traitement numérique du signal, de codage et de décodage de l’in-
formation,
– les problèmes de labyrinthe et de récréations mathématiques.

Le problème considéré se formule ainsi. Etant donné un graphe orienté G = (X, A), on asso-
cie à chaque arc a ∈ A un nombre l(a) ∈ R appelé “longueur” de l’arc. On dit alors que G est
valué par les longueurs l(a). Si a = (i, j), on utilisera également la notation lij pour la longueur
de l’arc a.

Le problème du plus court chemin entre deuxP sommets i et j sera de trouver un chemin
µ(i, j) de i et j dont la longueur totale l(µ) = a∈µ(i,j) l(a) soit minimum.

Ce problème a de nombreuses applications pratiques car la “longueur” l(a) peut s’interpréter


aussi bien comme un coût de transport sur l’arc a, comme les dépenses de construction de l’arc
a, comme le temps nécessaire pour parcourir l’arc a, etc.

Selon les propriétés du graphe traité (les longueurs sont quelconques, positives ou toutes
égales, le graphe est quelconque ou sans circuit) et selon le problème considéré (recherche du
plus court chemin d’un sommet à un autre, ou d’un sommet à tous les autres, ou entre tous
les couples de sommets) il existe de nombreux algorithmes permettant l’obtention d’une solution.

Nous nous contenterons simplement ici de décrire les algorithmes les plus classiques, sans
explorer toutes les situations.

Dans beaucoup de situations, les longueurs sont positives. On utilisera alors l’algorithme
de Moore-Dijkstra pour calculer le plus court chemin d’un sommet (arbitrairement le sommet
numéro 1) à tous les autres.

Posons X = {1, 2, . . . , n}. Soit lij la longueur de l’arc (i, j) si (i, j) ∈ A. Définissons π ∗ (i)
comme la longueur minimum des chemins du sommet 1 au sommet i ; en particulier π ∗ (1) = 0.

L’algorithme procède en n − 1 itérations. Au début de chacune des itérations, l’ensemble des


sommets est partitionné en deux sous-ensembles S et S̄ = X\S. Le sous-ensemble S (initialisé
à {1}) contient les sommets définitivement marqués, c’est-à-dire les sommets pour lesquels la
marque π(i) représente effectivement la longueur du plus court chemin entre le sommet 1 et le
sommet i. Le complémentaire S̄ contient tous les sommets ayant une marque provisoire définie
par :
∀k ∈ S̄ : π(k) = min (π(i) + lik )
i∈S∩Γ−1
k

On démontre alors aisément qu’à une étape quelconque si j est le sommet de marque provi-
soire π(j) minimale c’est-à-dire :
π(j) = min (π(k))
k∈S̄

21
alors π(j) = π ∗ (j), c’est-à-dire que le sommet j peut être inclus dans l’ensemble S des sommets
définitivement marqués (et, bien sûr, enlevé de S̄).

On mettra donc à jour l’ensemble S en incluant j (S ← S ∪ {j}) ainsi que les marques provi-
soires des sommets k de S̄ reliés par un arc (j, k). Ceci se fera en considérant successivement tous
les sommets k ∈ Γ(j) ∩ S̄ et en remplaçant π(k) par π(j) + ljk chaque fois que π(j) + ljk < π(k).
Si l’on souhaite déterminer explicitement le plus court chemin, et non pas seulement sa longueur,
on conservera, dans un tableau de prédécesseurs, l’information selon laquelle le prédécesseur de
k est j.

Algorithme 1 (Moore-Dijkstra)
Recherche du plus court chemin entre deux sommets dans un graphe à longueurs positives.

(a) - Initialisations
S̄ = {2, 3, . . . , n}
π(1) = 0

l1i si i ∈ Γ(1)
π(i) =
+∞ sinon

(b) - Sélectionner j tel que


π(j) = min (π(k))
k∈S̄

Faire S̄ ← S̄\{j}
Si S̄ = ∅ alors FIN

(c) - Faire pour tout i ∈ S̄ ∩ Γ(j)


π(i) ← min (π(i), π(j) + lji )
Retourner en (b)

On trouvera en annexe A, un programme Matlab R


implémentant cet algorithme. Sous
c

Scilab , la commande relative à la recherche du plus court chemin entre deux sommets se
nomme shortest path.

Considérons, à titre d’exemple, le graphe de la figure 10. Les itérations de l’algorithme


précédent sont les suivantes :
(a) S̄ = {2, 3, 4, 5, 6}, π(1) = 0, π(2) = 7, π(3) = 1, π(4) = π(5) = π(6) = ∞
(b) j = 3, S̄ = {2, 4, 5, 6}
(c) S̄ ∩ Γ(3) = {2, 5, 6}, π(2) = min(7, 1 + 5) = 6, π(5) = min(∞, 1 + 2) = 3,
π(6) = min(∞, 1 + 7) = 8
(b) j = 5, S̄ = {2, 4, 6}
(c) S̄ ∩ Γ(5) = {2, 4}, π(2) = min(6, 3 + 2) = 5, π(5) = min(∞, 3 + 5) = 8
(b) j = 2, S̄ = {4, 6}
(c) S̄ ∩ Γ(2) = {4, 6}, π(4) = min(8, 5 + 4) = 8, π(6) = min(8, 5 + 1) = 6
(b) j = 6, S̄ = {4}
(c) S̄ ∩ Γ(6) = ∅
(b) j = 4, S̄ = ∅

22
4
4 5

2
2 5
7
1
1 5 3
2
1
7
3 6

Fig. 10 – Graphe orienté

Les longueurs des plus courts chemins seront donc :

π(1) = 0, π(2) = 5, π(3) = 1, π(4) = 8, π(5) = 3 et π(6) = 6

On peut également s’intéresser à la détermination des plus courts chemins entre toutes les
paires de sommets (on se place toujours dans la situation où les longueurs sont toutes positives).
On peut, bien sûr, utiliser l’algorithme précédent, mais son efficacité est faible devant ce type
de problème. On préfèrera un algorithme se rattachant aux méthodes matricielles. L’algorithme
de Floyd que nous allons présenter est particulièrement simple dans sa mise en œuvre.

Notons L = (lij ) la matrice n × n dont le terme (i, j) est égal à la longueur de l’arc (i, j) si
(i, j) ∈ A et +∞ sinon (pour les termes diagonaux, on pose lii = 0).
(k)
Pour 1 ≤ k ≤ n, notons L(k) = (lij ) la matrice dont le terme (i, j) représente la longueur
minimale d’un chemin d’origine i et d’extrémité j, et astreint à la condition que tous les sommets
intermédiaires appartiennent au sous-ensemble {1, 2, . . . , k}.

Pour k = 0, on a L(0) = L, puisque lij est la longueur du chemin direct (unique) entre i et j
(sans sommet intermédiaire). On remarque alors que les matrices L(k) sont liées par la relation
de récurrence :  
(k) (k−1) (k−1) (k−1)
lij = min lij , lik + lkj

En effet, deux situations peuvent se produire suivant que le plus court chemin de i à j à
sommets intermédiaires dans {1, 2, . . . , k} emprunte le sommet k ou non.

Dans le premier cas, ce chemin est formé d’un sous-chemin entre i et k, suivi d’un sous-chemin
entre k et j, chacun ne pouvant utiliser comme sommets intermédiaires que des sommets de
(k) (k−1) (k−1)
{1, 2, . . . , k − 1} et devant être de longueur minimale. On doit donc avoir lij = lik + lkj .
(k) (k−1)
Dans le second cas, on doit évidemment avoir lij = lij .

La matrice L(n) , donnant l’ensemble des valeurs des plus courts chemins dans le graphe,
pourra donc être déterminée en n étapes de récurrence à partir de la relation précédente.

23
Algorithme 2 (Floyd)
Recherche de la matrice des plus courts chemins dans un graphe à longueurs positives.

Pour k de 1 à n
Pour tout i et j de 1 à n faire
lij = min (lij , lik + lkj )

Comme pour l’algorithme précédent, si l’on souhaite, en plus de la longueur des chemins,
exhiber explicitement le chemin, on mettra à jour, au fûr et à mesure de l’introduction d’un
nouveau sommet k, une matrice de prédécesseurs.

Un programme Matlab
R
implémentant cet algorithme est donné en annexe B.

7 Arbres et arborescences
7.1 Définitions et propriétés
Définition 19
Un arbre est un graphe connexe sans cycles.
Un graphe sans cycle qui n’est pas connexe est appelé une forêt (chaque composante
connexe est un arbre).

Par définition même, un arbre est donc un graphe simple. On constate également que
T = (X, T ) est un arbre si et seulement s’il existe une chaı̂ne et une seule entre deux som-
mets quelconques.

Etant donné un graphe quelconque G = (X, A) un arbre de G est un graphe partiel connexe
et sans cycles. Si ce graphe partiel inclut tous les sommets du graphe G, l’arbre est appelé
arbre maximum ou arbre couvrant. Une forêt de G est un graphe partiel sans cycle de G (non
nécessairement connexe). Une forêt maximale de G est une forêt de G maximale pour l’inclusion
(l’ajout d’une seule arête supplémentaire du graphe à cette forêt crée un cycle).

Considérons un graphe G = (X, A) comportant n sommets, m arcs et p composantes


connexes ; l’algorithme suivant permet de construire une forêt maximale de G.

Initialement, tous les arcs du graphe sont “incolores”. La méthode consiste à examiner suc-
cessivement tous les arcs du graphe (dans n’importe quel ordre) et à les colorer soit en “rouge”
soit en “vert”.

A une étape quelconque, Gc est le graphe partiel engendré par les arcs colorés (rouges ou
verts) et Gr le graphe partiel engendré par les arcs rouges.

Chaque fois qu’un nouvel arc a incolore est examiné :


– soit il passe par a un cycle élémentaire µ dont tous les arcs (autres que a) sont rouges ; on
colore alors l’arc en vert, le nombre de connexité de Gc et de Gr reste constant,
– soit un tel cycle n’existe pas, auquel cas l’arc a permet de connecter deux sommets qui
n’étaient pas encore connectés dans Gc ; on colore l’arc a en rouge, le nombre de connexité
de Gc et de Gr décroı̂t de 1.

24
Pour montrer que le graphe partiel Gr obtenu est bien une forêt maximale de G, il suffit
d’observer qu’à tout instant, le graphe Gr est sans cycle (c’est donc bien une forêt de G) ; à la fin
de la procédure, elle est bien maximale pour l’inclusion car, en ajoutant un arc vert quelconque
à Gr , on crée un cycle.

On peut également facilement démontrer les propriétés suivantes :

Si G possède n sommets et p composantes connexes, une forêt maximale de G comporte


exactement n − p arcs.

Soit T = (X, T ) une forêt maximale de G = (X, A). Alors T et G ont le même nombre de
connexité.

Soit T = (X, T ) une forêt maximale de G = (X, A). Alors, par tout arc a ∈ T̄ = A − T , il
passe un cycle et un seul µa dont tous les arcs (autres que a) appartiennent à T .

Cette dernière propriété est importante car elle permet de construire une base de cycles d’un
graphe G (voir § 4.5).

Soit un graphe G = (X, A) comportant n sommets, m arcs et p composantes connexes. Soit


T = (X, T ) une forêt maximale de G = (X, A) et pour a ∈ T̄ = A − T , notons µa le cycle
(unique) contenu dans T + {a}. Les cycles {µa } forment une base de cycles du graphe G, dont
la dimension est le nombre cyclomatique de G.

La notion d’arborescense est l’adaptation de la structure d’arbre aux 1-graphes orientés.

Définition 20
Un graphe G est une arborescence s’il existe un sommet R appelé racine de G tel
que, pour tout sommet S de G, il existe un chemin et un seul de R vers S.

La notion d’arborescence couvrante se définit comme celle d’arbre couvrant, mais elle est
plus délicate car il faut trouver une racine (qui n’existe pas toujours).

7.2 Arbres couvrants de poids minimum


Considérons le problème qui consiste à relier n villes par un réseau cablé de la manière la plus
économique possible. On suppose connue la longueur lij = l(aij ) la longueur de câble nécessaire
pour relier les villes i et j. Le réseau doit évidemment être connexe et il ne doit pas admettre de
cycles pour être de coût minimal ; c’est donc un arbre et ce doit être l’arbre maximum le plus
économique.

Le problème à résoudre se pose donc dans les termes suivants :

Définition 21
Soit un graphe non orienté G, connexe, pondéré par une fonction positive l attachée
aux arêtes. Soit un arbre couvrant T = (X, B) défini comme graphe partiel de G
avec un ensemble d’arêtes B. Son poids (ou coût) total est :

25
X
l(T ) = l(a)
a∈B

On dit que T est un arbre couvrant de poids minimal de G si l(T ) est minimal parmi
les poids de tous les arbres couvrants possibles de G.

On peut montrer que si toutes les arêtes sont de “poids” différents, l’arbre couvrant de poids
minimal est unique. Plusieurs algorithmes ont été proposés pour résoudre ce problème. Les plus
simples sont les algorithmes de Prim et de Kruskal.

L’algorithme de Prim consiste à bâtir progressivement un arbre à partir d’un sommet quel-
conque (arbitrairement le sommet numéro 1) et en y greffant, à chaque étape, l’arête de poids
minimal parmi celles qui permettent de maintenir un graphe partiel qui soit un arbre. Si le
graphe est connexe, le processus s’arrête avec un arbre couvrant. Sinon, il aboutit à un arbre
couvrant pour une composante connexe ; on poursuit avec les autres composantes connexes pour
obtenir une forêt couvrante.

Plus précisément, on construit progressivement, à partir du sommet numéro 1, un sous-


ensemble de sommet S ⊂ X contenant {1} et un sous-ensemble T ⊂ A tel que le graphe partiel
(S, T ) soit un arbre de poids minimal du sous-graphe engendré par S. Pour cela, à chaque étape,
on sélectionne dans le cocycle :

ω(S) = {(k, l) | (k, l) ∈ A, k ∈ S, l ∈ X\S}

l’arête de poids minimal, soit a = (i, j). Les sous-ensembles S et T sont alors augmentés en leur
ajoutant le sommet j et l’arête a respectivement : S ← S ∪ {j}, T ← T ∪ {a}.

La mise en œuvre de cet algorithme peut se faire aisément à l’aide d’une procédure de mar-
quage de la façon suivante. On associe, à chaque sommet i, un nombre réel π(i) appelé marque du
sommet i. A une étape quelconque, la marque π(i) d’un sommet i ∈ X\S représente le poids de
l’arête de poids minimal dans l’ensemble des arêtes joignant i à S. D’autre part, on conserve dans
un tableau α l’indice α(i) de l’arête ayant permis d’attribuer au sommet i, la marque π(i). Ces
informations permettent aisément d’obtenir, à l’étape courante, l’arête de poids minimal dans le
cocycle ω(S) : il suffit en effet de déterminer le sommet i ∈ X\S ayant une marque minimale et
l’arête cherchée est α(i). Par ailleurs, lorsque le sous-ensemble S est augmenté du sommet i, les
marques sont mises à jour en examinant toutes les arêtes issues de i et dont l’autre extrémité j ne
fait pas encore partie de l’arbre (j ∈ X\S) et en effectuant la substitution π(j) ← min(π(j), lij ).
Chaque fois qu’une marque est améliorée, le tableau α est mis à jour. Si le graphe est connexe,
l’algorithme s’arrête lorsque S = X (tous les sommets ont été intégrés à l’arbre). Les éléments du
tableau α représentent alors les indices des arêtes constituant l’arbre couvrant de poids minimal.

Algorithme 3 (Prim)
Recherche d’un arbre couvrant de poids minimal.

(a) - Initialisations
π(1) = 0
π(i) = ∞, ∀i ∈ {2, 3, . . . , n}
α(i) = ∞, ∀i ∈ {1, 2, . . . , n}
S=∅

26
(b) - Sélectionner i tel que π(i) = min (π(j))
j∈X\S

Si π(i) = ∞ ou S = X alors FIN


S ← S ∪ {i}
(c) - Pour toutes les arêtes a = (i, j) telles que j ∈ X\S faire
Si lij < π(j) alors π(j) = lij , α(j) = a
Retourner en (b)

L’annexe C présente une implémentation Matlab


R
de cet algorithme et les résultats obtenus
sur un exemple.

Le problème de l’optimisation du choix d’une arborescence couvrante est plus difficile que
pour les arbres couvrants parce qu’il faut vérifier que le sommet choisi au départ est bien racine
de l’arbre. Plusieurs algorithmes ont été développés pour résoudre ce problème ; nous ne les
décrirons pas ici.

8 Réseaux, réseaux de transport et problèmes de flots


8.1 Définitions
Définition 22
Un graphe fortement connexe, sans boucle et ayant plus d’un sommet, est appelé un
réseau.
On appelle nœud d’un réseau un sommet qui a plus de deux arcs incidents. Les autres
sommets sont appelés antinœuds.
On appelle branche tout chemin pour lequel seuls les premiers et derniers sommets
sont des nœuds.

Dans un graphe orienté G, un flot est l’affectation d’une valeur réelle à chaque arc de G,
représentant une quantité transportée sur cet arc, de telle sorte que, en chaque sommet, la
somme des flots entrants soit égale à la somme des flots sortants (loi de Kirchhoff : conservation
des flux en chaque sommet).

Parmi les problèmes les plus classiques, on peut citer celui de la recherche d’un flot maxi-
mal. On se donne une capacité maximale sur chaque arc qui sera une borne supérieure du flot
autorisé sur cet arc. Le problème du flot maximal consiste à déterminer un flot dont la valeur
en un certain lieu est maximale. On peut, de plus, se donner un coût de transport d’une unité
de flot sur chaque arc et chercher le flot maximal de coût minimal.

Définition 23
On appelle réseau de transport un graphe orienté antisymétrique valué G = (X, A, C),
sans boucle et dans lequel il existe :
– un sommet x1 sans prédécesseur (c’est-à-dire Γ−1 (x1 ) = ∅) nommé entrée ou
source du réseau,
– un sommet xn sans successeur (c’est-à-dire Γ(xn ) = ∅) nommé sortie ou puits du
réseau,

27
et tel qu’au moins un chemin unisse x1 à xn dans G.
La fonction de pondération C est supposée positive et l’on nomme capacité de l’arc
a le nombre C(a).

Définition 24
Si l’on désigne par A− +
x l’ensemble des arcs sortants du sommet x et Ax l’ensemble
des arcs entrants de ce même sommet x, on dit qu’une fonction ϕ(a) définie sur A
et à valeurs réelles est un flot pour le réseau de transport si :
– il est positif : ϕ(a) ≥ 0, ∀a ∈ A,
– il vérifie la loi des nœuds de Kirchhoff :
X X
ϕ(a) − ϕ(a) = 0, ∀x 6= x1 et x 6= xn
a∈A−
x a∈A+
x

– il ne dépasse pas la capacité des arcs : ϕ(a) ≤ C(a), ∀a ∈ A.

Si x n’est ni x1 ni xn , la quantité entrante en x doit être égale à la quantité sortante que


nous désignons par ϕx : X X
ϕx = ϕ(a) = ϕ(a)
a∈A−
x a∈A+
x

Si ϕ est un flot sur un réseau de transport G, alors on a ϕx1 = ϕxn ; cette quantité s’appelle
la valeur du flot.

La principale question qui se pose pour un réseau de transport donné est de déterminer un
flot de valeur maximale ainsi que les flots le long de chaque arc. Il arrive fréquemment également
que l’on doive considérer des réseaux avec des capacités localisées non seulement sur les arêtes
mais également sur les sommets. C’est notamment le cas pour les réseaux téléphoniques pour les-
quels la limite de capacité est autant due aux lignes qu’aux centraux. On peut ramener aisément
ce problème au précédent ; il suffit de dédoubler chaque sommet en une entrée et une sortie liées
par un arc ayant pour capacité celle qu’on attribuait précédemment au sommet.

Dans ce qui suit, les valeurs des flots et des capacités sont considérées comme entières. Si
l’on ne peut pas se ramener directement à cette situation, on approche les valeurs réelles par
des rationnels, on réduit ces nombres au même dénominateur commun d et l’on choisit comme
unité de référence 1/d.

8.2 Recherche d’un flot complet


Définition 25
Pour un flot ϕ dans un réseau de transport G = (X, A, C), on dit qu’un arc est
saturé si on a ϕ(a) = C(a).
Le flot est dit complet si tout chemin allant de x1 à xn contient au moins un arc saturé.

Si l’on considère le graphe partiel engendré par les arcs non saturés par le flot et si le flot n’est
pas complet, il existe nécessairement un chemin µ allant de l’entrée à la sortie. On peut alors
définir un nouveau flot pour le réseau en augmentant de 1 le flot de chacun des arcs constituant le
chemin µ ; la valeur du flot est alors également augmentée de 1. On peut donc progressivement

28
augmenter la valeur d’un flot incomplet jusqu’à ce qu’il soit complet. En tenant compte des
différences entre les capacités et la valeur du flot sur les arcs de µ, on peut connaı̂tre d’avance
l’augmentation possible du flot. Cependant, le flot complet ainsi obtenu n’est pas, en général, le
flot maximal.

8.3 Amélioration du flot


Soit ϕ un flot complet. On va utiliser une procédure itérative pour identifier et marquer tous
les sommets du graphe où il est possible de faire transiter une unité de flot supplémentaire.

On définit un processus d’étiquetage de certains sommets du graphe. En x1 , on place une


étiquette + . Soit x un sommet déjà marqué :

– on marque avec une étiquette +x tout successeur y non marqué de x pour lequel le flot
n’est pas à son maximum ((x, y) ∈ A et ϕ(x, y) < C(x, y)).
– on marque avec une étiquette −x tout prédécesseur y non marqué de x pour lequel le
flot n’est pas nul ((x, y) ∈ A et ϕ(y, x) > 0).

L’étiquette a pour rôle de donner le nom d’un prédécesseur ou d’un successeur d’un sommet
donné en indiquant si le flot peut être augmenté dans le sens de parcours (étiquette +x ) ou
diminué s’il est dans le sens contraire (étiquette −x ).

Si l’on parvient jusqu’au marquage du sommet xn avec cette procédure, c’est qu’il existe une
chaı̂ne µ de x1 à xn dont tous les sommets sont marqués avec l’indice du sommet précédent au
signe près. Notons que l’on est pas obligé de marquer tous les sommets (tous les successeurs ou
prédécesseurs d’un sommet donné) ; l’objectif étant simplement d’élaborer une chaı̂ne marquée
de x1 à xn .

Soit alors :
 ′
 ϕ (a) = ϕ(a) si a ∈

ϕ′ (a) = ϕ(a) + 1 si a ∈ µ et si a est orientée dans le sens de µ
 ′
ϕ (a) = ϕ(a) − 1 si a ∈ µ et si a est orientée dans le sens contraire de µ

On vérifie aisément que ϕ′ est encore un flot. Comme ϕxn = ϕxn + 1, la valeur du flot ϕ est
supérieure, donc meilleure que celle de ϕ.

On peut alors systématiser l’idée précédente en introduisant la notion de graphe d’écart ou


réseau résiduel.

Définition 26
Soit un réseau de transport G = (X, A, C) possédant un flot complet ϕ. On appelle
graphe d’écart ou réseau résiduel, le réseau Ḡ(ϕ) = (X, Ā, C̄) tel que :

– si a ∈ A et ϕ(a) < C(a) alors a ∈ A et C̄(a) = C(a) − ϕ(a)


– si a = (x, y) ∈ A et ϕ(a) > 0 alors a−1 = (y, x) ∈ Ā et C̄(a−1 ) = ϕ(a)

Le réseau résiduel indique le long de quels arcs on peut augmenter ou diminuer le flot.
L’intérêt du graphe d’écart apparaı̂t dans le théorème suivant.

29
Théorème 4
Soit ϕ un flot de G (de x1 à xn ) et Ḡ(ϕ) le réseau résiduel associé à ϕ. Une condi-
tion nécessaire et suffisante pour que le flot ϕ soit maximal est qu’il n’existe pas de
chemin de x1 à xn dans Ḡ(ϕ).

La démonstration de ce théorème s’appuie sur le lemme des arcs colorés de Minty que nous
ne détaillerons pas ici.

8.4 Recherche d’un flot maximal : algorithme de Ford et Fulkerson


A partir des résultats précédents, on peut maintenant proposer une méthode constructive de
recherche d’un flot maximal.

Algorithme 4 (Ford et Fulkerson)


Recherche d’un flot maximum.

(a) - Itération k = 0
Partir d’un flot initial ϕ0 (compatible avec les contraintes de capacité),
par exemple ϕ0 = (0, 0, . . . , 0).
(b) - A l’itération k, soit ϕk le flot courant.
Rechercher un chemin µk de x1 à xn dans le graphe d’écart Ḡ(ϕk ).
S’il n’en existe pas, FIN : le flot ϕk est maximal.
(c) - Soit εk la capacité résiduelle du chemin µk
(minimum des capacités résiduelles des arcs du chemin).
Définir le flot ϕk+1 par :
 k+1
ϕa = ϕka + εk si a ∈ µ et si a est orientée dans le sens de µ
ϕk+1
a = ϕka − εk si a ∈ µ et si a est orientée dans le sens contraire de µ
Faire k ← k + 1 et retourner en (b).

Par définition du graphe d’écart, les flots ϕk sont tous compatibles avec les capacités. Par
ailleurs, εk est positif à chaque itération et, par suite, l’algorithme produit une séquence de flots
compatibles de valeurs strictement croissantes.

A chaque étape, la méthode consiste donc à rechercher une chaı̂ne joignant x1 à xn . Il


est évident que le choix d’une telle chaı̂ne n’est pas unique. Plusieurs travaux ont tenté de
systématiser ce choix afin d’améliorer les performances moyennes de l’algorithme.

8.5 Exemple traité manuellement


On considère le graphe de la figure 11 (les nombres associés aux arcs représentent les capa-
cités), pour lequel on cherche à déterminer un flot maximal entre le sommet 1 et le sommet 7.

Toutes les composantes du flot initial sont considérées nulles ϕ0 = (0, 0, . . . , 0) (figure
12a) ; le graphe d’écart Ḡ(ϕ0 ) est représenté figure 12b.

Le chemin choisi est tracé en pointillés, sa capacité résiduelle vaut ε1 = min(5, 4, 7) = 4.


On augmente donc de quatre le flot sur les arcs composant le chemin (ils sont tous orientés

30
4
4
2 7
5 2
3
1 5 7
8 5

3 2 3
6

Fig. 11 – Graphe orienté élémentaire

4 4
0 4
2 0 2 7
0 0 5 2
0 3
1 5 7 1 5 7
0 0 8 5

3 0 0 3 2 3
6 6

Fig. 12 – Flot initial et graphe d’écart

positivement). On obtient un nouveau flot ϕ1 , ainsi que son graphe d’écart Ḡ(ϕ1 ), tous deux
représentés aux figures 13a et 13b.

4
4 4
4 4
4 4
2 2
4 0 2 3
0 1 3
1 5 7 1 5 7
0 0 8 5

3 0 0 3 2 3
6 6

Fig. 13 – Flot à l’itération numéro 1 et graphe d’écart

Le nouveau chemin est toujours représenté en traits pointillés. Cette fois, sa capacité résiduelle
vaut ε2 = min(1, 2, 3) = 1. Le nouveau flot ϕ2 et le graphe d’écart correspondant sont donnés à
la figure 14.

En poursuivant ainsi l’algorithme, on obtient les situations décrites aux figures 15 et 16.
Après l’itération numéro 4, on constate qu’il n’existe plus de chemin joignant le sommet 1 au
sommet 7 dans le graphe d’écart. L’algorithme s’achève donc et le flot maximal est celui obtenu
lors de cette dernière étape ϕ1 = ϕ7 = 9.

31
4
4 4
4 4
4 5 1
2 2
5 1 3
1 1 2
1 5 7 1 5 7
0 0 8 5
1
3 0 0 3 2 3
6 6

Fig. 14 – Flot à l’itération numéro 2 et graphe d’écart

4
4 4
4 4
4 5 1
2 2
5 1 3
3 1
1 5 7 1 5 3 7
2 2 6 3

3 0 0 3 2 3
2
2
6 6

Fig. 15 – Flot à l’itération numéro 3 et graphe d’écart

4
4 4
4 4
4 5 1
2 2
5 1 3
3 1
1 5 7 1 5 3 7
4 2 4 3

3 2 2 3 2 1
2 2
2
6 6

Fig. 16 – Flot à l’itération numéro 4 et graphe d’écart

Notons également que l’algorithme peut être adapté au cas où les capacités des arcs ont
des bornes inférieures non nulles (positives, voire même négatives). En pratique, on associe à la
plupart des réseaux de transport, une notion de coût unitaire du transport qui se traduit par
l’association, à chaque arc a du réseau, d’un nombre réel w(a) représentant ce coût unitaire. Le
coût total d’un flot ϕ est défini comme la somme des coûts associés aux flots élémentaires :
X
W (ϕ) = w(a)ϕ(a)
a∈A

On peut alors se poser le problème consistant à rechercher, parmi les flots à valeur maximale,
celui qui est à coût minimal. L’algorithme de Ford et Fulkerson peut également être adapté à
cette situation.

32
8.6 Recherche d’un flot maximal à coût minimal
La recherche d’un flot maximal à coût minimal peut être résolue à l’aide de l’algorithme de
Busacker-Gowen qui permet de déterminer la famille complète de tous les flots de coût minimal
d’un sommet x1 à un sommet xn et de valeur ϕ = 1, 2, ..., v. Nous énonçons ici cet algorithme
itératif sous forme littérale et laissons le soin au lecteur d’en effectuer une description plus “in-
formatique”.

A l’itération numéro k, le flot courant ϕk est supposé être un flot de valeur ϕk0 et de coût
minimal parmi l’ensemble de tous les flots de valeur ϕk0 .

Soit Ḡ(ϕk ) le graphe d’écart relatif à ϕk ; on attribue aux arcs de Ḡ(ϕk ) les coûts w̄ et les
capacités c̄ suivantes :
– si a = (xi , xj ) ∈ A et ϕ(a) < c(a), l’arc a+ = (xi , xj ) a un coût w̄(a) = w(a) et une
capacité c̄(a) = c(a) − ϕ(a) > 0,
– si a = (xi , xj ) ∈ A et ϕ(a) > 0, l’arc a− = (xj , xi ) a un coût w̄(a) = −w(a) et une capacité
c̄(a) = ϕ(a).
Soit alors µk un chemin de coût minimal relativement aux coûts w̄ entre x1 et xn sur le
graphe d’écart Ḡ(ϕk ) ; on note ǫk la capacité résiduelle de ce chemin. On définit alors le flot
ϕk+1 comme dans l’algorithme de Ford-Kulkerson. Si µ est le vecteur associé au chemin µk
(c’est-à-dire tel que µa = 1 si a+ ∈ µk et µa = −1 si a− ∈ µk ), on a ϕk+1 = ϕk + ǫk µ et le flot
ϕk+1 est un flot de coût minimal de valeur ϕk0 + ǫk .

On notera qu’à chaque itération, on doit rechercher le plus court chemin (au sens du chemin
de coût minimal) de x1 à xn dans un graphe où la longueur (le coût) des arcs peut être négative ;
il conviendra donc d’employer un algorithme adapté à cette situation (l’algorithme de Dijkstra
ne convient pas). Il existe cependant une amélioration de cet algorithme proposée par Edmonds
et Karp et basée sur une technique de modification des coûts permettant de les rendre tous
positifs en conservant cependant la même hiérarchie de chemin sur le graphe d’écart ; dans cette
situation l’algorithme de Dijkstra peut être utilisé.

9 Couplages
Les problèmes de couplage dans les graphes quelconques (ou dans les graphes bipartis) ont
un double intérêt. Le premier, le plus évident, vient de leurs applications : ils généralisent di-
rectement les problèmes d’affectation et ils interviennent dans certains problèmes importants
de la théorie de graphes : problèmes de tournées, détermination de plus courtes chaı̂nes dans
un graphe non orienté, etc. Le second, d’ordre théorique, vient de ce qu’ils se rattachent à une
classe de problèmes de programmation linéaire en nombres entiers.

Définition 27
Etant donné un graphe simple non orienté G = (X, A), un couplage est un sous-
ensemble d’arêtes K ⊂ A tel que deux arêtes quelconques de K ne sont pas adja-
centes.
Un sommet i ∈ X est dit saturé par le couplage K ⊂ A s’il existe une arête de K
incidente à i.
Un couplage K qui sature tous les sommets du graphe est appelé couplage parfait.
Un couplage maximal est un couplage de cardinalité maximale.

33
9.1 Le problème du couplage maximal
Définition 28
Si K ⊂ A est un couplage de G = (X, A), on appelle chaı̂ne alternée (relativement à
K) une chaı̂ne élémentaire de G dont les arêtes appartiennent alternativement à K
et K̄ = A − K.
Une chaı̂ne alternée augmentante ou chaı̂ne améliorante est une chaı̂ne alternée joi-
gnant deux sommets insaturés.

En convenant de dessiner les arêtes d’un couplage par des traits épais, les arêtes de K̄ = A−K
restant en traits fins, une chaı̂ne alternée est une chaı̂ne élémentaire dont les arêtes sont alter-
nativement fines et épaisses.

Définition 29
Etant donné un couplage K ⊂ A, considérons une chaı̂ne alternée L dont chaque
extrémité est un sommet insaturé ou est telle que l’unique arête de K qui lui est
incidente soit dans L. Alors le couplage K ′ obtenu en échangeant le rôle des arêtes
fines et épaisses le long de la chaı̂ne L est encore un couplage de G. Cette opération
qui fait passer du couplage K au couplage K ′ est appelée transfert le long de la
chaı̂ne alternée L.

Une opération de transfert le long d’une chaı̂ne alternée augmentante, augmente la cardina-
lité du couplage d’une unité.

Par exemple, sur le graphe de la figure 17, les arêtes (2, 3) et (5, 6), dessinées en traits épais,
forment un couplage K de cardinalité égale à 2. La chaı̂ne L = {1, 2, 3, 4} est une chaı̂ne alternée
dont les extrémités sont des sommets insaturés. C’est donc une chaı̂ne alternée augmentante.
Un transfert le long de cette chaı̂ne produit le nouveau couplage K ′ = {(1, 2), (3, 4), (5, 6)} de
cardinalité égale à 3.

2 5 2 5

1 4 1 4

3 6 3 6

Fig. 17 – Couplages initial et final

Pour cet exemple particulier, ce couplage est maximal, car, pour un graphe d’ordre n, la
cardinalité d’un couplage maximal est égale à la partie entière de n/2.

Le théorème suivant permet de caractériser un couplage maximal.

Théorème 5
Un couplage K est maximal si et seulement s’il n’existe pas de chaı̂ne alternée aug-
mentante relativement à K.

34
Ce théorème montre que pour rechercher un couplage maximal, il suffit donc de savoir trouver
une chaı̂ne alternée augmentante (s’il en existe) relativement à un couplage K ⊂ A quelconque.
La procédure pour construire un couplage maximal K pour G = (X, A) est la suivante :

1. Initialiser K = ∅
2. Trouver un chaı̂ne améliorante Ka de K, effectuer le transfert le long de cette chaı̂ne
et remplacer le couplage K par celui ainsi obtenu (dont la cardinalité a nécessairement
augmenté de un).
3. Répéter l’étape 2 jusqu’à ce qu’il ne soit plus possible de créer une nouvelle chaı̂ne
améliorante ; K est alors un couplage maximal.

Le problème qui se pose alors est de savoir construire, pour un couplage donné, une chaı̂ne
alternée augmentante. Pour rechercher des chaı̂nes alternées d’origine fixée i0 , on construit un
arbre alterné T de racine i0 tel que :

– T = (Y, T ) est un sous-graphe partiel connexe et sans cycle de G,


– pour tout j ∈ Y , la chaı̂ne (unique) LT (j) de l’arbre entre i0 et j est une chaı̂ne alternée,
– les chaı̂nes reliant i0 aux sommets pendants ont un nombre pair d’arêtes.

Nous ne détaillerons pas ici les multiples situations particulières auxquelles on peut être
confrontés dans la construction de cet arbre. Nous nous contenterons de décrire la situation la
plus courante.

On choisit tout d’abord comme racine de l’arbre (niveau 0) un sommet insaturé relativement
au couplage courant. Au niveau i impair, on insère dans l’arbre un sommet adjacent à l’un des
sommets insérés au niveau i − 1 par le biais d’une arête n’appartenant pas au couplage cou-
rant, ainsi que cette arête. Au niveau i pair, on insère dans l’arbre alterné, un sommet adjacent à
l’un des sommets insérés au niveau i−1 par le biais d’une arête appartenant au couplage, ainsi
que cette arête. On continue à construire progressivement cet arbre jusqu’à l’insertion, à un ni-
veau impair, d’un sommet insaturé, ou bien jusqu’à ce que l’on ne puisse plus insérer de sommet.

S’il existe une chaı̂ne alternée augmentante du couplage courant, on finit nécessairement par
insérer un sommet insaturé s. La chaı̂ne reliant s à la racine de l’arbre est alors une chaı̂ne
alternée augmentante.

Considérons le graphe biparti de la figure 18 où l’on a matérialisé, à l’aide d’arêtes “épaisses”,
le couplage obtenu après une étape déterminée de l’algorithme précédent.

f f5 f4 f3 f2 f1

x x5 x4 x3 x2 x1

Fig. 18 – Couplage courant

35
Choisissons de construire un arbre alterné dont la racine est le sommet x1 insaturé par ce
couplage.

f4 x3

x1 f5 x5 f1

f3 x2

f2

Fig. 19 – Arbre alterné de racine x1

Au niveau 1 de l’arbre, la seule possibilité est d’insérer l’arête (x1 , f5 ) et le sommet f5 . Au


niveau 2, on insère l’arête (f5 , x5 ) appartenant au couplage (c’est encore la seule possibilité). Au
niveau 3, les deux arêtes (x5 , f3 ) et (x5 , f4 ) n’appartenant pas au couplage peuvent être insérées.
On insère ensuite les arêtes (f4 , x3 ) et (f3 , x2 ), ainsi que les sommets (saturés) correspondants.
Le sommet x3 est alors un sommet pendant de l’arbre, en revanche, on peut insérer, au niveau
5, les arêtes (x2 , f1 ) et (x2 , f2 ) conduisant à l’arbre alterné de la figure 19.

Comme les sommets f1 et f2 sont tous deux insaturés, on a ainsi créé deux chaı̂nes améliorantes
qui permettent d’augmenter, en effectuant un transfert, la cardinalité du couplage. Si l’on choisit
par exemple, la chaı̂ne f1 , x2 , f3 , x5 , f5 , x1 ), le nouveau couplage est représenté figure 20.

f f5 f4 f3 f2 f1

x x5 x4 x3 x2 x1

Fig. 20 – Couplage “augmenté”

Pour cet exemple particulier, on observe qu’il suffit d’ajouter à ce dernier couplage l’arête
(x4 , f2 ), reliant les deux seuls sommets insaturés, pour obtenir un couplage parfait qui est, bien
sûr, un couplage maximal du graphe.

9.2 Couplage maximal et flot maximal


Pour déterminer un couplage maximal sur un graphe biparti G = (X, Y, Γ), on peut recou-
rir à l’artifice suivant. On construit un réseau de transport (voir définition 23) en ajoutant au
graphe une origine S liée à tous les sommets de X et une destination P liée à tous les sommets
de Y (voir figure 21). On fixe à 1 les capacités de tous les arcs de ce réseau.

Un couplage permet de sélectionner un certain nombre d’arêtes du graphe biparti. Si l’on fait
passer une unité de flot par ces arêtes et sur les arêtes correspondantes vers S et P (en faisant
passer un flot nul sur les autres arêtes), on obtient bien un flot sur le réseau. En effet, la loi de

36
Kirchhoff en un sommet quelconque de X ou de Y exprime ici qu’il y a au plus une arête du
couplage y parvenant. Réciproquement, un flot sur ce réseau ne peut transporter au plus qu’une
unité de flot sur chaque arête et l’ensemble des arêtes transportant une unité de flot entre X et
Y détermine un couplage sur G. En effet, si deux arêtes retenues étaient adjacentes en x ∈ X,
la loi de Kirchhoff en x imposerait un flot de deux unités au moins sur l’arc entre S et x, ce qui
dépasse la capacité imposée. La valeur du flot est donc égale au nombre d’arêtes constituant le
couplage.

Le problème du couplage maximal se ramène ainsi à un problème de flot maximal dans un


réseau de transport, qui peut être résolu à l’aide de l’algorithme de Ford-Fulkerson. La figure
21 (partie gauche) montre un flot complet et non maximal qui peut être amélioré en un flot
maximal (partie droite).

x1 y1 x1 y1

x2 y2 x2 y2

S x3 y3 P S x3 y3 P

x4 y4 x4 y4

x5 y5 x5 y5

Fig. 21 – Flot complet et maximal

9.3 Couplage de poids maximal


A chaque arête a ∈ A du graphe G(X, A), on associe maintenant un nombre réel w(a) ap-
P d’un couplage K ⊂ A est la somme des poids des arêtes qui
pelé poids de l’arête a. Le poids
le constituent, soit w(K) = a∈K w(a). Le problème du couplage de poids maximal est la re-
cherche d’un couplage tel que son poids soit maximal sur l’ensemble de tous les couplages de G.
On remarquera qu’un couplage de poids maximal n’est pas nécessairement un couplage maximal
(couplage de cardinalité maximale).

Définition 30
Soit K ⊂ A un couplage de G = (X, A), on rappelle qu’une chaı̂ne alternée augmen-
tante est une chaı̂ne alternée joignant deux sommets insaturés.
Une chaı̂ne alternée réductrice est une chaı̂ne alternée impaire dont les arêtes extrêmes
sont dans K.
Une chaı̂ne alternée conservative est une chaı̂ne alternée paire dont une extrémité
est un sommet isolé.

On remarquera de manière évidente que le transfert le long d’une chaı̂ne alternée augmen-
tante augmente la cardinalité du couplage d’une unité ; le long d’une chaı̂ne réductrice, il la
réduit d’une unité et le long d’une chaı̂ne conservative, il ne la change pas.

37
Définition 31
Le coût réduit d’une chaı̂ne alternée L (augmentante, réductrice ou conservative)
relative au couplage K vaut :

δ(L) = w(L ∩ K̄) − w(L ∩ K)

Un cycle alterné pair est une chaı̂ne alternée paire dont les extrémités coı̈ncident.
Un transfert le long d’un cycle alterné pair conserve la cardinalité du couplage.
Le coût réduit du cycle µ est :

δ(L) = w(µ ∩ K̄) − w(µ ∩ K)

Le résultat suivant caractérise un couplage de poids maximal en termes d’existence de chaı̂nes


alternées.

Théorème 6
Un couplage K est de poids maximal si et seulement s’il n’existe pas de chaı̂ne al-
ternée, ni de cycle alterné pair de coût réduit strictement positif relativement à K.

Le théorème ci-dessous montre que l’on peut construire, de proche en proche, des couplages
K1 , K2 , ..., Kp de cardinalité 1, 2, ..., p et de poids maximal, par des transferts successifs le long
de chaı̂nes alternées augmentantes et de coût réduit maximal. On généralise ainsi le résultat de
Busacker-Gowen sur la recherche de flot maximal de coût minimal.

Théorème 7
Soit K un couplage de cardinalité p de poids maximal (sur l’ensemble des couplages
de cardinalité p) et soit L une chaı̂ne alternée augmentante (relativement à K) de
coût réduit maximal. Le couplage K ′ obtenu à partir de K par transfert le long de
L est de poids maximal parmi tous les couplages de cardinalité p + 1.

9.4 Problèmes d’affectation


La formulation générale d’un problème d’affectation est la suivante. Etant donné n tâches à
réaliser et n machines pour les réaliser et sachant que l’on connaı̂t le coût de réalisation Cij de
la tâche ti par la machine mj (pour tous les couples (ti , mj ) possibles, si la tâche ti ne peut être
effectuée par la machine mj , on pose Cij = ∞), on cherche une permutation σ de {1, 2, . . . , n}
conduisant à un coût total :
Xn
Ci,σ(i)
i=1

minimum (sur l’ensemble de toutes les n! permutations σ possibles).

Le problème d’affectation est un cas particulier du problème de transport (sans capacité).


Il peut également être vu comme un problème de couplage parfait de poids minimum dans un
graphe biparti.

Cependant, compte-tenu de l’importance de ce type de problème, un algorithme spécifique


a été proposé par Kuhn ; il s’agit de l’algorithme Hongrois.

38
Cet algorithme repose essentiellement sur la constatation suivante. On ne change pas la ou
les solutions optimales en augmentant ou en diminuant d’une même quantité λ tous les éléments
d’une même ligne (ou d’une même colonne) de la matrice des Cij (les valeurs infinies restant
infinies). Après une telle opération, la valeur totale est augmentée ou diminuée de λ.

Par conséquent, si l’on fait apparaı̂tre, par des transformations de ce type, suffisamment de
zéros dans le tableau, mais pas de coûts négatifs, et qu’il existe n zéros “indépendants” (c’est-
à-dire un seul zéro dans chaque ligne et dans chaque colonne), on aura alors trouvé l’affectation
optimale.

L’algorithme procède en trois phases successives. Afin d’expliquer la démarche suivie, considé-
rons l’exemple décrit par la matrice des coûts suivante :
1 2 3 4 5
A 7 3 5 7 10
B 6 ∞ ∞ 8 7
C 6 5 1 5 ∞
D 11 4 ∞ 11 15
E ∞ 4 5 2 10

Première phase : obtention de valeurs nulles


A tous les éléments de chacune des colonnes, on enlève le plus petit élément de cette colonne,
puis, dans la matrice ainsi obtenue, on enlève, à tous les éléments d’une même ligne, le plus petit
élément de la ligne. On obtient de la sorte une matrice (C1,ij ) ayant au moins un zéro par ligne
et par colonne.

Pour l’exemple précédent, on obtient, après traitement des colonnes puis des lignes, les deux
matrices suivantes :

1 2 3 4 5 1 2 3 4 5
A 1 0 4 5 3 A 1 0 4 5 3
B 0 ∞ ∞ 6 0 B 0 ∞ ∞ 6 0
C 0 2 0 3 ∞ C 0 2 0 3 ∞
D 5 1 ∞ 9 8 D 4 0 ∞ 8 7
E ∞ 1 4 0 3 E ∞ 1 4 0 3

Deuxième phase : recherche du maximum d’affectations possibles


A partir de la matrice (C1,ij ), on cherche à former une solution de coût nul (un seul zéro dans
chaque ligne et dans chaque colonne). Si c’est le cas, on a la solution optimale, sinon on cherche
un ensemble maximum de zéros “indépendants” : ceci revient à chercher un flot maximal sur le
graphe G′ constitué par les arcs de coût (réduit) nul. Sur la matrice C1,ij , cela correspond au
traitement suivant. On considère la ligne ayant un nombre minimal de zéros (pour l’exemple,
cela peut être la première). On encadre l’un des zéros de cette ligne (ici, C1,A2 ), puis on barre les
zéros qui se trouvent sur la même ligne ou la même colonne que le zéros encadré (ici, C1,D2 ). On
procède de même pour toutes les lignes, en tenant compte des étapes précédentes. On obtient,
pour l’exemple, la matrice suivante :

39
1 2 3 4 5
A 1 0 4 5 3
B 0 ∞ ∞ 6 0
C 0 2 0 3 ∞
D 4 0 ∞ 8 7
E ∞ 1 4 0 3

Troisième phase : détermination des affectations “intéressantes”


Pour déterminer ces affectations, on procède la manière suivante :
– On marque (d’une astérisque) toutes les lignes qui ne contiennent aucun zéro encadré –
sommet non affecté – (ligne D de l’exemple) ;
– On marque les lignes qui ont un zéro encadré dans une colonne marquée (ligne A de
l’exemple) ;
– On marque les colonnes qui ont un ou plusieurs zéros barrés dans une ligne marquée –
possibilité non exploitée – (colonne 2 de l’exemple).

On répète ces trois marquages successifs jusqu’à ce que l’on ne puisse plus effectuer de nou-
veaux marquages (pour l’exemple, une seule “passe” suffit).

Les affectations intéressantes à considérer sont celles issues des sommets correspondant aux
lignes marquées ; on barre donc les lignes non marquées. Les sommets correspondant aux colonnes
marquées ne sont pas intéressants car ils ne peuvent être réaffectés ; on barre donc les colonnes
marquées.
1 2 3 4 5
A 1 0 4 5 3 *
B 0 ∞ ∞ 6 0
C 0 2 0 3 ∞
D 4 0 ∞ 8 7 *
E ∞ 1 4 0 3
*

Dans le tableau réduit ainsi obtenu (cases non barrées), on recherche ensuite l’élément le plus
petit, nécessairement non nul par construction (pour l’exemple, il s’agit de l’élément C1,A1 ) ; on
retranche sa valeur aux colonnes non barrées et on l’ajoute aux lignes barrées. On obtient les
tableaux successifs suivants :
1 2 3 4 5 1 2 3 4 5
A 0 0 3 4 2 A 0 0 3 4 2
B -1 ∞ ∞ 5 -1 B 0 ∞ ∞ 6 0
C -1 2 -1 2 ∞ C 0 3 0 3 ∞
D 3 0 ∞ 7 6 D 3 0 ∞ 7 6
E ∞ 1 3 -1 2 E ∞ 2 4 0 3

40
On note (C2,ij ) la matrice ainsi obtenue et l’on poursuit la procédure de traitement en re-
prenant à la seconde phase. Lorsqu’une solution optimale est obtenue (un zéro par ligne et
par colonne), on arrête ; sinon on recommence et on définit successivement les matrices (C3,ij ),
(C4,ij ), . . . , (Cn,ij ).

Sur le tableau (C2,ij ) de l’exemple, on est amené à encadrer C2,D2 et barrer C2,A2 , encadrer
C2,E4 , encadrer C2,A1 et barrer C2,B1 et C2,C1 , encadrer C2,B5 et enfin encadrer C2,C3 :
1 2 3 4 5
A 0 0 3 4 2
B 0 ∞ ∞ 6 0
C 0 3 0 3 ∞
D 3 0 ∞ 7 6
E ∞ 2 4 0 3

La solution optimale est alors obtenue grâce aux éléments :

C2,A1 = C2,B5 = C2,C3 = C2,D2 = C2,E4 = 0


 
A B C D E
et à la permutation σ = .
1 5 3 2 4
Si l’on revient aux données initiales, on obtient :

CA1 = CB5 = CC3 = CD2 = CE4 = 7 + 7 + 1 + 4 + 2 = 21


La figure 22 visualise en trait fort le couplage optimal obtenu.

2 B

C 1

3 A

D 5

4 E

Fig. 22 – Affectation optimale

10 Problèmes d’ordonnancement
L’objet d’un problème d’ordonnancement est de faciliter la mise en œuvre et de guider
l’exécution d’un ensemble complexe de tâches (programme de recherche ou de production, lan-
cement d’un produit, construction d’un édifice ...). La technique d’analyse la plus connue, appelée
méthode PERT (Program Evaluation and Review Technique) a été introduite aux Etats-Unis en
1958 pour la conduite du programme de recherche et de construction des fusées Polaris. Cette

41
méthode tient une place dominante par sa simplicité, son efficacité et la variété d’extensions qui
ont pu être développées.

En toute généralité, les problèmes d’ordonnancement se posent sous la forme suivante. Etant
donné un objectif qu’on se propose d’atteindre et dont la réalisation suppose l’exécution préalable
de multiples tâches, soumises à de nombreuses contraintes, déterminer l’ordre et le calendrier
d’exécution des diverses tâches.

Le critère d’optimalité peut porter sur la minimisation de la durée et/ou du coût de la


réalisation du projet. Nous supposerons que le projet est décomposable en un nombre fini de
tâches, caractérisées par leur durée d’exécution (généralement fixe, parfois aléatoire), éventuel-
lement aussi par leur coût d’exécution, et soumises à des contraintes de postériorité stricte (une
tâche ne peut commencer que si certaines autres tâches sont complètement terminées). Ce type
de problème se nomme problème central de l’ordonnancement. Des cas plus complexes peuvent
également être envisagés comme par exemple le cas des contraintes disjonctives, c’est-à-dire le
cas où, en plus des contraintes de succession, on impose la réalisation non simultanée de certaines
paires de tâches.

La représentation par un graphe d’un problème d’ordonnancement permet une bonne appré-
hension globale du problème. L’étude de ce graphe conduit à l’identification des tâches priori-
taires et la détection des retards ou des dépassements de moyens afin de prendre les mesures
correctives nécessaires.

Le problème central de l’ordonnancement s’énonce comme suit : étant donné un projet


constitué de n tâches de durées d’exécution fixes et soumises à des contraintes de postériorité
stricte, déterminer un “calendrier d’exécution” ou ordonnancement qui minimise la durée de
réalisation totale du projet.

En pratique, le travail préliminaire à accomplir sera donc de dresser une liste des différentes
opérations à mener que l’on décomposera plus ou moins finement selon la précision souhaitée.
Généralement, les tâches sont définies pour que leurs durées d’exécution soient du même ordre
de grandeur ; de plus, les contraintes de postériorité entre les tâches doivent pouvoir être établies
avec précision. Ce travail important est souvent long et nécessite une collaboration étroite entre
les différents acteurs du projet.

10.1 Le graphe potentiels-tâches


A partir de la description des tâches du projet, on construit le graphe suivant :
– A chaque tâche i (i de 1 à n), on associe un sommet i du graphe,
– On définit un arc entre i et j de longueur di (la durée de la tâche i) si la tâche i doit
précéder la tâche j.
– On introduit deux sommets correspondant à deux tâches fictives de durée nulle, la tâche
de début des travaux α, antérieure à toutes les tâches (il suffit de relier le sommet α aux
sommets sans prédécesseurs du graphe) et la tâche de fin des travaux ω, postérieure à
toutes les autres tâches (tous les sommets sans successeur du graphe seront reliés au som-
met ω).

Le graphe ainsi défini doit être sans circuit ; en effet, dans le cas contraire, une opération
devrait se succéder à elle-même. Le travail commençant à la date 0, on cherche un ordonnance-
ment qui minimise la durée totale du projet, donc la date de fin des travaux. Pour qu’une tâche

42
puisse commencer, il est nécessaire que toutes les tâches qui la relient à la tâche début du projet
soient réalisées.

Définition 32
La date au plus tôt, ti de début de la tâche i est égale à ti = maxj∈Γ−1 (tj + dj ),
i
c’est-à-dire que ti est égale à la longueur du plus long chemin l(α, i) de α à i.
La durée minimale du projet tω est donc la longueur du plus long chemin de α à ω.
Si la durée minimale du projet est égale à tω , la date au plus tard pour commencer
la tâche i est égale à Ti = minj∈Γi (Tj − di ) avec Tω = tω , ce qui montre que Ti =
tω − l(i, ω) où l(i, ω) est la longueur du plus long chemin de i à ω.
La marge totale Mi de la tâche i est définie comme la différence entre la date au plus
tôt et au plus tard (Mi = Ti − ti ).
Les tâches dont la marge est nulle sont appelées tâches critiques. Si un quelconque
retard est pris sur la réalisation de l’une de ces tâches, la durée minimale du projet
sera augmentée d’autant.
La marge libre mi de la tâche i est le délai dont on peut retarder cette tâche sans affec-
ter les dates de début au plus tôt des tâches postérieures, mi = minj∈Γi (tj − ti − di )).

On observe donc qu’à chaque tâche i est associé un nombre ti qui peut être considéré comme
un potentiel d’où la dénomination de graphe potentiels-tâches.

10.2 Le graphe potentiels-étapes ou graphe PERT


Dans cette représentation, les tâches sont matérialisées par les arcs du graphe. La longueur
de chaque arc est égale à la durée di de la tâche correspondante. Le début et la fin d’une tâche
constituent les étapes du projet. Comme précédemment, on introduit les deux étapes de début
(α) et de fin (ω) du projet.

Chaque étape est donc définie par un ensemble de tâches déjà effectuées. Si une tâche j doit
succéder à une tâche i, on confondra l’extrémité initiale de l’arc aj (correspondant à la tâche
j) et l’extrémité terminale de l’arc ai (correspondant à la tâche i), via éventuellement un arc fictif.

Le graphe ainsi défini doit être sans circuit. Dans cette formulation, les sommets s’interprètent
comme des étapes, c’est pourquoi l’on utilise l’appellation graphe potentiels-étapes (connu plus
communément sous le nom de graphe PERT).

La construction d’un tel graphe est un peu plus complexe que celle du graphe potentiels-
tâches car elle demande la définition des étapes qui peuvent correspondre au début où à la fin
de plusieurs tâches. Si l’on se donne, pour chaque tâche i, l’ensemble Γ−1 i des tâches qui doivent
la précéder, les différentes étapes du projet correspondent aux différents ensembles Γ−1
i .

Soulignons aussi que pour pouvoir exprimer certaines contraintes de postériorité stricte, il
est parfois nécessaire d’introduire des tâches fictives et donc des arcs fictifs de durée nulle. A
titre d’exemple, considérons le sous-graphe partiel de la figure 23.

Ce graphe indique que les tâches 3 et 4 doivent succéder aux tâches 1 et 2. Supposons que
suite à une modification de conditions techniques, l’exécution de la tâche 4 puisse commencer

43
Tâche 1 Tâche 3

Tâche 2 Tâche 4

Fig. 23 – Elément de graphe PERT

avant que ne soit achevée la tâche 1. Pour adapter le graphe à ce changement, on ajoute un arc
fictif comme sur la figure 24.

Tâche 1 Tâche 3

Tâche fictive

Tâche 2 Tâche 4

Fig. 24 – Elément de graphe PERT

10.3 Résolution
Un ordonnancement est un programme d’exécution qui fixe la date ti de début d’exécution
de chacune des tâches (dans la méthode du potentiel) ou de début de réalisation de chacune des
étapes (dans la méthode PERT). Un ordonnancement est optimal s’il est réalisable c’est-à-dire
si tj − ti ≥ di et s’il minimise la durée de réalisation tω du projet.

La durée minimale du projet est égale à la longueur du plus long chemin de α à ω. En


effet, pour qu’une tâche puisse commencer, il faut que toutes les tâches précédentes aient été
exécutées, de sorte que la durée du projet ne peut être inférieure à la somme des durées des
tâches composant le chemin le plus long de α à ω. Ce chemin, appelé chemin critique, n’est pas
nécessairement unique. Comme le graphe est sans circuit,on a :

tj = max (ti + di ), 1≤j≤n


i∈Γ−1
j

Chaque ti ainsi obtenu est la longueur du chemin le plus long du sommet α au sommet i et
représente la date au plus tôt de début d’exécution de la tâche ou de l’étape i.

La durée minimum tω du projet ayant été déterminée, il est bien sûr possible de retarder
l’exécution de certaines tâches ou étapes sans pour autant accroı̂tre tω . Il est dès lors intéressant
de déterminer les dates au plus tard Ti de début d’exécution des différentes tâches ou étapes i
sous la condition que la durée minimale du projet ne soit pas modifiée. Ces dates se calculent de
même manière que pour les dates au plus tôt mais à partir du graphe inverse obtenu en inversant
le sens de tous les arcs. Il vient Tω = tω et :

Tj = min(Ti − di ), 0≤j ≤n−1


i∈Γj

44
Chaque quantité Tω − Ti ainsi obtenue est la longueur du chemin le plus long du sommet i
au sommet ω.

10.4 Compléments
Pour comparer l’intérêt des deux graphes précédemment décrits, il faut se placer dans un
cadre plus général que le problème central de l’ordonnancement et examiner un ensemble de
contraintes que l’on doit pratiquement prendre en compte dans les problèmes d’ordonnancement.
Ces contraintes sont essentiellement de trois types :
Type potentiel : la tâche j doit commencer après la fin de i ou bien après la moitié de la
réalisation de i, ou bien un certain temps après la fin de i, etc.
Type disjonctif : les tâches i et j ne peuvent être réalisées en même temps (car c’est le même
ouvrier qui les réalise par exemple).
Type cumulatif : les moyens nécessaires à l’exécution d’un certain nombre de tâches sont,
à chaque instant, limités ; par exemple, le nombre de camions utilisables ou la somme
dépensée pour les travaux réalisés à l’instant t ne doit pas dépasser un certain seuil, etc.

Les contraintes de type potentiel autres que les contraintes d’antériorité du problème central
sont difficiles à prendre en compte dans le graphe potentiels-étapes. On est en effet amené
à ajouter des sommets et des arcs fictifs en très grand nombre dans le graphe. En revanche,
dans le graphe potentiels-tâches, chaque contrainte supplémentaire de type potentiel s’introduit
simplement par l’adjonction d’un arc dans le graphe. Par exemple :
– la contrainte : j ne doit pas commencer avant la moitié de la réalisation de la tâche i se
représente par un arc (i, j) de longueur di /2.
– la contrainte : j ne peut commencer qu’un temps t après la fin de i se représente par un
arc (i, j) de longueur di + t.
– la contrainte : j ne peut commencer qu’après la date bj se représente par un arc (α, j) de
longueur bj .
– la contrainte : j doit commencer avant la date cj se représente par un arc (j, α) de longueur
−cj .
– enfin la contrainte : j doit suivre immédiatement la tâche i s’écrit ti + di = tj et se
représente par un arc (i, j) de longueur di et un arc (j, i) de longueur −di .

Les deux derniers cas introduisent des circuits et des arcs de longueurs négatives. La condi-
tion d’existence d’un ordonnancement devient alors : “il n’existe pas de circuit de longueur
strictement positive”. Comme l’on peut introduire des arcs de longueur différentes partant d’un
sommet i quelconque, il est préférable de noter dij la longueur de l’arc allant de i à j. Les
formules de détermination des dates au plus tôt et au plus tard deviennent alors :

tj = max (ti + dij ) au lieu de tj = max (ti + di )


i∈Γ−1
j i∈Γ−1
j

Tj = min(Ti − dij ) au lieu de Tj = min(Ti − di )


i∈Γj i∈Γj

Les contraintes de type disjonctif ou cumulatif sont impossibles à prendre en compte dans
le graphe PERT. Certains aménagements permettent leur prise en compte dans le graphe
potentiels-tâches. On préférera donc la représentation potentiels-tâches dès que le problème
ne se réduit pas au problème central.

45
Pour terminer cette présentation succincte des problèmes d’ordonnancement, examinons
quelques exemples pouvant se formuler en termes du “problème du voyageur de commerce”
ou de ses nombreuses variantes.

Exemple 1 : Dans un système d’exploitation automatisé, une machine doit régulièrement effec-
tuer n types de tâches différentes x1 , x2 , . . . , xn . On connaı̂t de plus des durées de commutations
entre deux tâches xi et xj quelconques. Le problème est de trouver une séquence de xi qui mini-
mise le temps total des commutations. Si l’on considère le graphe de sommets {xi }i=1,...,n dont
l’arc (xi , xj ) a une longueur égale au temps de commutation entre xi et xj , le problème revient
à déterminer un circuit hamiltonien de longueur minimum.

Dans beaucoup de situations, on cherche un chemin hamiltonien dans un graphe qui mini-
mise une autre fonction économique que la longueur totale du chemin.

Exemple 2 : Etant données n tâches i = 1, . . . , n de durée ai , soit di la date où la tâche i


doit être terminée (date souhaitée). Déterminer la séquence de tâches sur une machine unique
de façon à minimiser le retard maximum, c’est-à-dire minimiser maxi=1,...,n (ti − di ) où ti est la
date où la tâche i est effectivement terminée. La solution optimale est obtenue en ordonnant les
tâches i selon l’ordre croissant des dates souhaitées di .

Exemple 3 : Etant donné un graphe orienté G = (X, A) et des poids Ca = Ci,j sur chaque arc
a = (i, j), déterminer une chaı̂ne hamiltonienne qui minimise :
 
X X
f (σ) =  Cσ(i)σ(j) 
i=1,...,n j>i

où σ(i) représente le iième sommet de la chaı̂ne hamiltonienne.

Cela revient à déterminer, sur une matrice carrée d’ordre n, C = (Cij ), une permutation
σ des lignes et des colonnes (la même pour les lignes et les colonnes) telle que la somme des
éléments de la matrice triangulaire supérieure soit minimale.

Ce problème a de nombreuses applications. La plus classique correspond à l’analyse des


préférences : étant donné N objets, on demande à k personnes de les comparer par paires (on
pose Cij , le nombre de personnes ayant préférées i à j). L’optimum de f (σ) est obtenu si la
chaı̂ne hamiltonienne est constituée de la succession des sommets pris dans un ordre minimisant
le nombre de désaccords.

11 Programmation linéaire
La programmation linéaire constitue un cas particulier de problèmes d’optimisation sous
contraintes pour lequel la fonction objectif et les contraintes sont linéaires (par rapport aux
variables inconnues). La formulation la plus générale est donc la suivante :

max M = cT x
x
sous les contraintes Ax ≤ b (1)
x≥0
avec x ∈ IRn , A ∈ IRm×n , b ∈ IRm et m < n. On recherchera indifféremment à maximiser ou à
minimiser une fonction objectif déterminée. En général, la matrice A est non-inversible sinon le

46
problème est trivial. On est souvent confronté à ce type de problèmes qui consiste à maximiser
(ou à minimiser) une quantité qui représente, par exemple, une mesure de l’efficacité d’une ac-
tivité non seulement dans un contexte scientifique mais aussi en économie, en politique, ou en
sciences humaines pour ne citer que ces activités.

Exemple 1 – Problème de transport

Le problème de transport se présente de la manière suivante : on désire acheminer des marchandises


de n dépôts à m points de vente, connaissant cij , i = 1, . . . , n et j = 1, . . . , m, le coût de transport entre
tous les couples (i, j), Xi , i = 1, . . . , n, les stocks des dépôts et Dj , j = 1, . . . , m, les niveaux de demande
aux points de vente. On recherche, pour chaque couple (i, j), la quantité (positive) xij à transporter du
dépôt Xi au point de vente Dj , c’est-à-dire la solution du problème de programmation linéaire :
n X
X m
min cij xij
xij ≥0
i=1 j=1
Xn
sous les contraintes xij = Dj j = 1, . . . , m (2)
i=1
Xm
xij = Xi i = 1, . . . , n
j=1

Le critère représente le coût total de transport. Les contraintes expriment l’égalité de l’offre et de la
demande pour chaque point de vente et chaque P dépôt.
P Lorsque cette condition de doit pas être réalisée,
il suffit d’ajouter un point de vente fictif si i Xi ≥ j Dj ou un dépôt fictif dans la situation contraire.
Dans ce cas, le coût de transport associé à cette unité supplémentaire est fixé à une valeur très élevée
afin de ne pas perturber la solution du problème.

Le problème du transport a été à l’origine des premières recherches sur la programmation linéaire. Il
est maintenant résolu le plus souvent par des méthodes issues de la théorie des graphes.

Exemple 2 – Problème de la ration alimentaire

Il s’agit d’un problème d’intendance où l’on désire nourrir au moindre coût une collectivité tout en
assurant une fourniture minimale de vitamines, sels minéraux, protéı̈nes, glucides, etc. Soit Ai le vecteur
de composition du produit i, ci le coût pour 100 grammes (par exemple) de l’aliment i et b le vecteur des
quantités minimales requises pour le consommateur. Le problème à résoudre, si l’on dispose de n aliments
de base est :

n
X
min ci xi
xi
i=1
n
X (3)
sous les contraintes Ai xi ≥ b
i=1
xi ≥ 0
Il s’agit d’une problème de programmation linéaire tout à fait classique. Ce type de problème in-
tervient fréquemment en agriculture (rations pour animaux) ou dans l’industrie (mélanges de produits
pétroliers ayant des caractéristiques minimales – volatilité, indices d’octanes, etc –).

Nous allons décrire une méthode systématique de résolution de ce type de problème, la


méthode du simplexe, mais, pour commencer, examinons la résolution à partir d’un exemple.

47
11.1 La méthode du simplexe à propos d’un exemple
Considérons le problème de programmation linéaire suivant :

max M = 40x1 + 60x2 (4a)


x

sous les contraintes 2x1 + x2 ≤ 70


x1 + x2 ≤ 40
x1 + 3x2 ≤ 90 (4b)
x1 ≥ 0
x2 ≥ 0

Pour cet exemple très simple, une résolution graphique peut être proposée. Chaque couple
de variables inconnues peut être matérialisé comme un point dans un plan. Il suffit de tracer les
zones correspondant à la satisfaction de chacune des contraintes, puis d’en calculer l’intersec-
tion. Comme les contraintes sont linéaires en les variables inconnues, la satisfaction de chaque
contrainte entraı̂ne l’élimination d’un demi-plan. L’intersection de tous les demi-plans satisfai-
sant les contraintes se présente donc nécessairement sous la forme d’un polytope convexe1 . Il
suffit ensuite de recherche le sommet du polytope pour lequel la valeur de la fonction objectif
est maximale.

x2

2x1 + x2 = 70

25
x1 + 3x2 = 90

M = 2100
x2 = 0 x1
15
x1 + x2 = 40
x1 = 0
M=0 M = 900

Fig. 25 – Résolution graphique

Sur la figure 25, on a représenté les 5 droites définissant les frontières des contraintes. Le
polytope défini par ces contraintes est représenté en grisé. Les droites définies à partir de la fonc-
tion objectif, x2 = (M − 40x1 )/60, sont tracées en pointillés. La valeur de la fonction objectif est
maximale lorsqu’elle “tangente” le polytope au sommet de coordonnées (15, 25). Dans des situa-
tions plus complexes (plus grand nombre de variables ne permettant pas une représentation dans
le plan), ce type de résolution n’est pas praticable. Il faut donc mettre au point une procédure
plus systématique : c’est la méthode du simplexe.

1
On suppose ici que le problème ne comporte pas de contraintes contradictoires, i.e. le polytope n’est pas
réduit à l’ensemble vide

48
La première idée consiste à transformer les contraintes inégalité, portant sur des combinaisons
de variables, en contraintes égalité en utilisant des variables supplémentaires appelées variables
d’écart (slack variables). Introduisons donc les variables x3 , x4 et x5 pour obtenir les égalités :

2x1 + x2 + x3 = 70
x1 + x2 + x4 = 40 (5)
x1 + 3x2 + x5 = 90

Compte tenu du sens des inégalités initiales, les variables d’écart, comme les variables d’ori-
gine, doivent être positives :
xj ≥ 0, ∀j = 1, . . . , 5 (6)
Le problème consiste maintenant à déterminer des variables xj , ∀j = 1, . . . , 5 satisfaisant les
contraintes (5) et (6) et maximisant M défini en (4a).

Le système (5) comporte trois équations à cinq inconnues ; les équations sont indépendantes
et le rang de la matrice du système est égal à 3. Si l’on impose arbitrairement la valeur de deux
des variables, les trois variables restantes peuvent être déduites. Une façon simple d’imposer des
valeurs à ces deux variables est de les fixer à zéro. La solution qui en résulte est appelée solution
de base et les variables dont on n’a pas directement imposé la valeur sont les variables de base.
Ainsi, si l’on pose x1 = x2 = 0 dans (5) on obtient la solution de base :

x3 = 70, x4 = 40 x5 = 90 (7)

Introduisons alors la terminologie suivante :


– Toute solution de (5) qui satisfait (6) est appelée solution admissible
– Une solution admissible qui maximise la fonction critère est une solution admissible opti-
male.

On peut montrer que dès lors qu’il existe une solution admissible optimale alors il en existe
une qui est également une solution de base. Ce résultat justifie la méthode du simplexe que nous
allons décrire sur l’exemple considéré.

Démarrons avec la solution de base (7) qui est également très clairement une solution ad-
missible. Les variables hors base x1 et x2 sont toutes deux nulles. La valeur du critère M
correspondant à cette solution de base vaut M = 0. Afin d’augmenter la valeur de M , nous
pouvons attribuer une valeur positive à x1 ou x2 . Nous choisissons x2 , car si x2 augmente d’une
unité, le critère M augmente de 60, alors qu’il n’augmente que de 40 si x1 augmente d’une unité.
Nous augmentons donc x2 en conservant x1 égal à 0. L’augmentation de x2 permet celle de M
mais implique la diminution de x3 , x4 et x5 afin de respecter (5). Comme x1 = 0, on a :

x3 = 70 − x2
x4 = 40 − x2 (8)
x5 = 90 − 3x2

Comme x3 , x4 et x5 doivent être positifs, x2 ne peut être augmenté indéfiniment. La première


équation impose x2 ≤ 70, la seconde x2 ≤ 40 et la troisième x2 ≤ 30. La valeur maximale
admissible est bien sûr la plus petite, c’est-à-dire x2 = 30. On obtient alors, à partir de (8) une
nouvelle solution admissible :

x1 = 0, x2 = 30, x3 = 40, x4 = 10 x5 = 0 (9)

49
dont les nouvelles variables de base (variables non nulles) sont x2 , x3 et x4 .

Le critère M vaut alors :


M = 40x1 + 60x2 = 1800 (10)
Remarquons que l’on a pu facilement écrire le système (8) car une et une seule variable de
base, x3 , x4 ou x5 , intervient dans chaque équation de (5). Il faut donc s’assurer que chaque
nouvelle variable de base x2 , x3 et x4 n’intervient que dans une seule équation. Pour cela, il
suffit d’extraire la valeur de x2 de la troisième équation de (5) et de substituer son expression
dans les deux premières. On obtient :
5 1
x1 + x3 − x5 = 40
3 3
2 1
x1 + x4 − x5 = 10 (11)
3 3
1 1
x1 + x2 + x5 = 30
3 3
De même, M peut être exprimé en fonction des variables hors base x1 et x5 :

M = 1800 + 20x1 − 20x5 (12)

Nous continuons à travailler avec la solution de base (9) ; le système (11) met maintenant en
évidence l’effet de l’augmentation de x1 ou x5 . D’après (10), nous choisissons d’augmenter x1 en
conservant x5 = 0 ; on obtient alors :
5
x3 = 40 − x1
3
2
x4 = 10 − x1 (13)
3
1
x5 = 30 − x1
3
Comme x2 , x3 et x4 ne peuvent être négatifs, x1 ne peut être plus grand que 24, 15 et
90 respectivement. Nous devons donc choisir x1 = 15, ce qui conduit à la nouvelle solution
admissible :
x1 = 15, x2 = 25, x3 = 15, x4 = 0 x5 = 0 (14)
Les nouvelles variables de base sont x1 , x2 et x3 . En utilisant la même démarche que
précédemment, on peut transformer le système (11) de manière à ne les faire apparaı̂tre que
dans une seule équation. Il suffit pour cela d’éliminer x1 de la première et de la troisième
équation en utilisant la seconde.
5 1
+ x3 − x4 + x5 = 15
2 2
3 1
x1 + x4 − x5 = 15 (15)
2 2
1 1
+ x2 − x4 + x5 = 25
2 2
L’élimination de cette nouvelle variable de base x1 de l’équation (12) permet d’exprimer M
en fonction uniquement des variables hors base :

M = 2100 − 30x4 − 10x5 (16)

50
La seule manière de modifier x4 et x5 consiste à les rendre positives en les augmentant, mais
cela diminuera alors la valeur du critère M . Il n’existe donc plus d’amélioration possible et la
solution (14) est la solution optimale. La valeur du critère, déduite de (16), est alors égale à
2100. C’est bien évidemment la solution obtenue en termes graphiques (cf. figure 25).

En fait, on peut interpréter géométriquement l’algorithme du simplexe. On peut tout d’abord


remarquer que la solution optimale (x∗1 , x∗2 ) ne peut pas être strictement à l’intérieur du polytope
des contraintes, c’est-à-dire qu’au moins une des inégalités (4b) sera saturée (satisfaite en tant
qu’égalité). Si cela n’était pas le cas, on pourrait ajouter un petit multiple positif de la paire de
coefficient définissant le critère (40, 60) à la solution (x∗1 , x∗2 ) de manière à obtenir une nouvelle
solution (x∗1 + 40ε, x∗2 + 60ε) conduisant à une valeur de critère M = 40(x∗1 + ε) + 60(x∗2 + ε)
supérieure à la valeur M ∗ = 40x∗1 + 60x∗2 supposée initialement optimale ce qui conduit à une
contradiction.

Ainsi, la solution optimale (x∗1 , x∗2 ) doit se trouver sur la frontière du polytope de la figure
25 que l’on a redessiné figure 26.

x2

V2 (0, 30) :1800

V3 (15, 25) :2100

V4 (30, 10) :1800

x1
V1 (0, 0) : 0 V5 (35, 0) :1400

Fig. 26 – Polytope des contraintes

On peut conduire le même raisonnement sur les arêtes du polytope et donc affirmer que la
solution optimale doit être un sommet du polytope. Pour l’exemple considéré, il n’y en a que
cinq qui ont été désignés par Vi , i = 1, . . . , 5 ; la valeur du critère M en ces points est également
indiquée sur la figure 26. Au lieu d’examiner de manière aléatoire la valeur du critère en chaque
sommet, la méthode du simplexe se “déplace” de sommet en sommet le long des arêtes de
manière à augmenter le plus possible, à chaque étape, la valeur du critère. Par exemple, partant
du sommet V1 , on a choisi de se déplacer vers V2 plutôt que vers V5 .

Il est intéressant d’examiner plus en détails la procédure proposée en termes d’opérations


sur des lignes de matrices. Ecrivons tout d’abord (4a) et (5) sous la forme d’un tableau :

M x1 x2 x3 x4 x5 b
0 2 1 1 0 0 70
0 1 1 0 1 0 40 (17)
0 1 3 0 0 1 90
1 −40 −60 0 0 0 0

La dernière ligne doit être interprétée comme M − 40x1 − 60x2 = 0. Comme la colonne

51
relative à M ne sera pas modifiée ultérieurement, nous ne l’écrirons plus.

Nous avons débuté l’analyse précédente en modifiant x2 , car son accroissement d’une unité
produisait la plus grande augmentation du critère (par rapport à une augmentation comparable
de x1 ). Cela revient à choisir, dans la matrice (17), la colonne ayant la valeur la plus négative dans
sa dernière ligne. L’étape qui suit (8) consiste à diviser les trois premiers éléments de la dernière
colonne de (17) par l’élément correspondant de la seconde colonne (colonne correspondant à
x2 ) et à choisir la ligne correspondant au plus petit des trois éléments positifs de cette seconde
colonne ; il s’agit ici de la troisième ligne. L’étape suivante consiste à éliminer x2 dans (5) et
(4a). En termes de matrices, il suffit d’utiliser une technique de pivot en choisissant l’élément
(3, 2) comme pivot et en réduisant à zéro, par combinaison linéaire, les éléments de la première,
seconde et quatrième ligne dans la seconde colonne (méthode de Gauss-Jordan pour la résolution
des systèmes linéaires). Cela donne le résultat suivant, à comparer à (11) et (12).
5
0 1 0 − 31 40
 
3
2
0 0 1 − 31 10 
 
 3

1 1
 (18)

 3 1 0 0 3 30 

−20 0 0 0 20 1800
La dernière ligne de (18) doit être lue comme :
M − 20x1 + 20x5 = 1800
D’une façon analogue, on recherche maintenant la colonne dont l’élément en dernière ligne
est le plus négatif ; ici c’est la première colonne. On divise ensuite chacun des trois premiers de
la dernière colonne de (18) par l’élément correspondant de la première colonne et l’on choisit,
parmi les résultats obtenus, le plus petit ; ici celui de la seconde ligne. On effectue ensuite une
réduction pivotale en choisissant l’élément (2, 1) comme pivot ce qui donne :

0 0 1 − 52 1
15
 
2
3
1 0 0 − 21 15 
 
2

0 1 0 − 1 1
 (19)
 2 2 25 

0 0 0 30 10 2100
Les éléments de la dernière ligne sont tous positifs ; cela signifie que la valeur de M ne peut
être augmentée et que l’on est parvenu à une solution optimale.

11.2 Position du problème général


Avant de décrire la problématique générale introduisons quelques notations utiles.
Définition 33
Une matrice P est dite supérieure à Q, et l’on note P > Q, lorsque P et Q sont de
même dimension et que chaque élément de P est plus grand que l’élément corres-
pondant de Q. Des définitions analogues peuvent être posées pour les opérateurs >,
< et 6. Si P > 0, on dit que P est positive. Si P > 0, P est non-négative.

Considérons de nouveau le problème général décrit en (1) et rappelé ci-dessous :


max M = cT x
x
sous les contraintes Ax ≤ b (20)
x≥0

52
La première étape de la résolution consiste à introduire des variables d’écart, xn+1 , . . . , xn+m
de façon à convertir les inégalités en égalités. Cela transforme le vecteur d’inconnues initial x de
dimension (n × 1) en un nouveau vecteur xe de dimension ((n + m) × 1). De la même manière,
la matrice A, initialement de dimension (m × n) est étendue en une matrice Ae de dimension
(m × (n + m)) et la matrice c (n × 1) en une matrice ce ((n + m) × 1). On substitue donc au
problème initial (20), le problème suivant :

max M = cTe xe (21a)


xe

sous les contraintes Ae xe = b


(21b)
xe ≥ 0

où xe ∈ IRq×1 , ce ∈ IRq×1 , Ae ∈ IRm×q et b ∈ IRm×1 . La dimension q permet de considérer les


problèmes généraux de la forme (21), qu’ils aient été directement posés sous cette forme ou qu’ils
proviennent de la transformation précédente. La forme (21) constituera donc la forme générale
T T

d’un problème de programmation linéaire avec Ae = (A Im ), ce = c 0 , q = m + n. Etudions
maintenant les propriétés des solutions d’un problème de programmation linéaire.

Définition 34
Tout vecteur xe satisfaisant (21b) est appelé vecteur admissible ; un vecteur admis-
sible qui maximise M (21a) est appelé vecteur admissible optimal.
L’ensemble Xad = {xe |Ae xe = b, xe ≥ 0} est l’ensemble des solutions admissibles du
problème.

Afin d’effectuer un parallèle avec l’approche géométrique, rappelons également quelques


définitions sur les ensembles et les polytopes convexes.

Définition 35
Un sous-ensemble S de IRn est dit convexe si et seulement si :

∀x ∈ S, y ∈ S, λ ∈ [0, 1] ⇒ λx + (1 − λ)y ∈ S

On vérifie aisément que le demi-espace fermé des (x1 , x2 , . . . , xn ) vérifiant :

α1 x1 + α2 x2 + . . . + αn xn ≤ β

est un ensemble convexe.


Définition 36
L’intersection d’un nombre fini de sous-ensembles convexes de IRn est un ensemble
convexe.
Un polytope convexe de IRn est l’intersection d’un nombre fini de demi-espaces fermés.
Un polyèdre convexe de IRn est un polytope borné.

D’après ce qui précède, l’ensemble S des solutions admissibles d’un problème de program-
mation linéaire est soit un polytope convexe (cas des domaines non bornés) soit un polyèdre
convexe (cas des domaines bornés). On notera cependant que l’on emploie le plus souvent la
dénomination polytope même dans le second cas.

53
Définition 37
Etant donnés k points x1 , x2 , . . . , xk de IRn , on appelle combinaison linéaire convexe
de ces k points, un point x tel que :

λ1 x1 + λ2 x2 + . . . + λk xk

avec λi ≥ 0, i = 1, . . . , k et ki=1 λi = 1.
P

On appelle points extrêmes d’un polytope ou d’un polyèdre convexe S, un point


x ∈ S qui ne peut pas être exprimé comme combinaison linéaire convexe d’autres
points y ∈ S (y 6= x). Ces points correspondent aux sommets du polytope.
Tout point x d’un polyèdre convexe S ⊂ IRn est combinaison linéaire convexe de
points extrêmes de S.

Dans la méthode du simplexe décrite à l’aide de l’exemple précédent, les opérations sur les
lignes ont effectuées sur une matrice 3 × 5. A chaque étape, 3 des colonnes de cette matrice
sont des vecteurs de la matrice identité (voir (17), (18) ou (19)). Cela implique donc que les
matrices 3 × 2 correspondantes sont non-singulières. Dans la théorie générale de résolution, il est
pratique de poser l’hypothèse que toute sous-matrice m × m extraite de la matrice augmentée
[Ae , b] est non-singulière. Cette hypothèse semble assez restrictive, mais cela facilite grandement
la solution. Des techniques particulières devront être mises en œuvre si cette hypothèse n’est pas
satisfaite. Notons que celle-ci est le plus souvent vérifiée dans les problèmes les plus fréquemment
rencontrés.
Définition 38
Un problème de programmation linéaire (21) est dit non-dégénéré si toute sous-
matrice de dimension m × m extraite de la matrice augmentée (Ae b) de dimension
m × (q + 1) est non-singulière. Si tel n’est pas le cas, le problème est dit dégénéré.

Nous allons maintenant donner une définition précise des variables de base introduites
précédemment. Une solution de l’équation Ae xe = b peut être obtenue en choisissant une matrice
B non-singulière de dimension m×m extraite de Ae , en résolvant le système Bxb = b avec xi = 0
pour les variables non sélectionnées par les colonnes de B, les autres variables constituant le vec-
teur xb . Les solutions de ce type, où au moins q − m variables sont nulles, sont particulièrement
importantes en programmation linéaire et on les désigne de manière particulière.

Définition 39
Les variables associées aux colonnes de la matrice B, matrice non-singulière de di-
mension m × m extraite de Ae sont appelées variables de base. Les autres variables
sont dites hors base. Une solution dans laquelle les variables hors base sont toutes
nulles est appelée solution de base.

Compte tenu de cette partition, une simple permutation des colonnes de la matrice Ae per-
met de l’écrire sous la forme Ae = (B N ) où N désigne les colonnes de Ae qui ne sont pas dans
T
B ; on partitionne de même les vecteurs xe en xTb xTn et cTe en cTb cTn .


Toute solution du problème vérifie Ae xe = b, c’est-à-dire :

Bxb + N xn = b

54
La solution de base x associée à la base B est la solution particulière obtenue en posant
T
xn = 0 (x = xTb xTn ). Le vecteur xb est alors déterminé de façon unique par la résolution du
système de Cramer :
Bxb = b, soit xb = B −1 b
Une solution de base est admissible si xb ≥ 0, c’est-à-dire B −1 b ≥ 0. Une solution de base
est dégénérée si le vecteur xb = B −1 b a des composantes nulles.

De façon générale, on ne modifie pas le système linéaire des contraintes Ae xe = b en le mul-


tipliant par une matrice régulière K qui effectue un changement de base. La solution précédente
a été obtenue en choisissant K = B −1 . On a en effet

Ae xe = b ⇔ Bxb + N xn = b
Ae xe = b ⇔ B −1 (Bxb + N xn ) = B −1 b
Ae xe = b ⇔ xb + B −1 N xn = B −1 b

La solution générale du système précédent s’écrit donc xb = B −1 b − B −1 N xn . De plus, le


critère initial s’écrit, selon la partition des vecteurs xe et cTe :

M = cTe xe = cTb xb + cTn xn

En substituant xb par son expression en fonction de xn , on obtient :

M = cTb B −1 b + cTn − cTb B −1 N xn




que l’on notera également :


M = M (x) + cTn xn
Le premier terme, M (x), représente la contribution des variables de base dans le critère, le
second celle des variables hors base. On peut alors énoncer le théorème suivant :

Théorème 8
Une condition nécessaire et suffisante2 pour que B soit une base admissible optimale
(au sens où la solution de base associée est admissible et optimale) est que le vecteur
des coûts réduits des variables hors base soit négatif ou nul ; cn ≤ 0.
En effet, dans ce cas, comme xn ≥ 0, le terme cTn xn est nécessairement négatif ou nul. Comme
l’on cherche à maximiser la valeur du critère, cela signifie que l’on a atteint l’optimum et qu’il
est égal à M (x).

Si l’on considère une base quelconque B i et xi la solution correspondante et s’il existe une
variable hors base xs telle que la composante de rang s du vecteur de coûts réduits cn que l’on
notera cn (s) est positive, on déduit du théorème précédent que l’on est dans l’une ou l’autre des
situations suivantes :
a) on peut augmenter indéfiniment la valeur de xs sans sortir de l’ensemble des solutions
admissibles et, dans ce cas, l’optimum du critère est non borné,
b) il existe une autre base B i+1 et une autre solution de base xi+1 telle que l’on ait
M (xi+1 ) > M (xi )

2
en l’absence de dégénérescence, c’est-à-dire xb = B −1 b > 0

55
T T
En effet, à partir de la solution xi = (xib )T (xin )T = (B −1 b)T 0 envisageons un
déplacement dans lequel la variable xs est la seule parmi les variables hors base à changer de
valeur : nulle dans la solution xi , elle va prendre une valeur xs = θ > 0.
T
La nouvelle solution x = xTb xTn obtenue vérifiera donc :

xn = θes

où es est un vecteur de la dimension de xn avec toutes ses composantes nulles sauf la composante
de rang s égale à 1 (colonne de rang s d’une matrice identité).
T
La valeur de θ doit être choisie de telle sorte que x = xTb xTn reste une solution admissible,
c’est-à-dire :
xb = B −1 b − B −1 N xn ≥ 0
Posons b = B −1 b et N = B −1 N et notons N s la colonne de rang s de N . On doit donc avoir :

xb = b − θN s ≥ 0

En regroupant les contraintes, on a :



xn = θes
xb = b − θN s

Deux cas peuvent alors se présenter :


Cas 1 : N s ≤ 0
La valeur de θ peut être aussi grande que l’on veut, on aura toujours xb ≥ 0 et l’optimum
du critère est non borné
Cas 2 : ∃ i(1 ≤ i ≤ m) | N s (i) > 0
La valeur de θ ne peut être augmentée indéfiniment ; la plus grande valeur θ̂ de θ est définie
par :  
b(i) b(r)
θ̂ = min =
i,N s (i)>0 N s (i) N s (r)
La nouvelle solution admissible obtenue a pour composante :
( i+1
xn = θ̂es
xi+1
b = b − θ̂ N s

et l’on a M (xi+1 ) = M (xi ) + θ̂ cn (s) > M (xi ).

Si le problème est non dégénéré, on remarque que cette solution a exactement m composantes
non nulles. En effet :
– la variable xs qui était nulle dans la solution xi est devenue strictement positive,
– la variable xr qui était strictement positive a maintenant pour valeur :

xr = b(r) − θ̂ N s (r) = 0

La solution xi+1 = (xi+1 T (xi+1 )T T obtenue est donc bien une solution de base. Elle

b ) n
correspond à la base B i+1 déduite de B i en remplaçant la colonne r par la colonne s. On dit
que les bases B i et B i+1 sont adjacentes et elles correspondent à des points extrêmes adjacents

56
de l’ensemble S des solutions admissibles.

Géométriquement, nous avons déjà indiqué que la méthode du simplexe s’interprète comme
un cheminement de point extrême en point extrême adjacent le long de la frontière de S (en-
semble des solutions admissibles).

Algébriquement, elle s’interprète comme la détermination d’une suite de bases adjacentes


(matrices ne différant que d’une seule colonne) B 0 , B 1 ,. . . , B p et de solutions de base x0 , x1 ,. . . ,
xp , telles que :
M (x0 ) < M (x1 ) < . . . < M (xp )

11.3 Algorithme de résolution


Algorithme primal du simple (forme révisée)
On suppose que l’on dispose d’une base admissible de départ B 0 .

(a) – Initialisations
B 0 base admissible de départ, i = 0

(b) – Calcul des coûts réduits et du second membre


b = (B i )−1 b
cTn = cTn − cTb (B i )−1 N

(c) – Test d’arrêt


Si cn ≤ 0 alors FIN ; l’optimum est atteint
sinon ∃ s | cn (s) > 0

(d) – Recherche de la variable hors base à introduire dans la base


Calculer As = (B i )−1 Ae,s où Ae,s est la colonne s de Ae
Si Ae,s ≤ 0 alors FIN ; l’optimum est non borné
Sinon, calculer
 
br b(i)
x̂s = = min
Ae,s (r) i,Ae,s (i)>0 Ae,s (i)

(e) – Mise à jour de la base


Soit xt la variable correspondant à la r ième colonne de la base, c’est-à-dire telle
que (B i )−1 At = er (colonne r de la matrice identité)
La variable xs prend alors la valeur x̂s > 0 (elle entre dans la base) et la
variable xt s’annule (elle sort de la base)
En considérant les bases comme des ensembles de colonnes, on a :
B i+1 = B i + {Ae,t } − {Ae,s }

(f) – Gestion compteur


i = i + 1, retour en (b).

Remarque 1 : Lorsqu’il y a plusieurs variables xs telles que cn (s) > 0, le choix en (c) est
indifférent.

Remarque 2 : Si la matrice de  base B est


 formée par les m premières colonnes de la matrice
Ae , on a B −1 Ae = I B −1 N = I N . Dans ce cas, la variable xt qui sort de la base à
l’étape (e) est la variable xr (t = r). Cependant, avec les changements de bases successifs, ce
57
n’est généralement pas le cas et il faut établir la correspondance entre le numéro d’ordre d’une
variable dans la base et son indice.

Matrices de changement de base

Comme les bases B i et B i+1 sont adjacentes, il est aisé de calculer (B i )−1 à partir de B −1 . Il
suffit pour cela de prémultiplier l’inverse de l’ancienne base B −1 par la matrice de changement
de base suivante :  
1 0 · · · −A e ,s(1)
Ae ,s(r)
· · · 0
 
 
0 1 · · · − Ae ,s(2) · · · 0

 Ae ,s(r) 

. . . . 
. . .. ..
. . · · · 0

η=
 
0 0 · · · 1
· · ·

 Ae ,s(r)
0

 .. .. ..
 
. . 
. . · · ·
 . . 0

 
0 0 · · · − AAe ,s(m) · · · 1
 
e ,s(r)

La matrice η est formée d’une matrice identité m × m dans laquelle la colonne r a été
remplacée par un vecteur de dimension m de composantes :

 − Ae ,s(i) pour les composantes i 6= r
A ,s(r)
e
1

Ae ,s(r)
pour la composante r

58
Annexe A - Implémentation de l’algorithme de Moore-Dijkstra
Le programme Matlab R
ci-dessous est une implémentation de l’algorithme de Moore-Dijkstra
décrit au paragraphe 6.3 et permettant l’obtention du plus court chemin entre deux sommets.
Les trois paramètres d’appel de la fonction moore sont les suivants :

L : matrice des longueurs (s’il n’y a pas d’arc entre le sommet i et le sommet j, alors
lij = ∞ et conventionnellement lii = 0).
dep : numéro du sommet de départ du chemin recherché.
arv : numéro du sommet d’arrivée du chemin recherché.

En sortie, on récupère :

s : la longueur du plus court chemin (s = ∞ s’il n’existe pas de chemin).


m : le vecteur des longueurs des plus courts chemins entre dep et tous les autres
sommets.

function [s,mark]=moore(L,dep,arv)
%MOORE Recherche du plus court chemin entre deux sommets d’un graphe
%
% S=MOORE(L,DEP,ARV) calcule la longueur du plus court chemin entre
% les sommets de numéro DEP et ARV.
%
% [S,M]=MOORE(L,DEP,ARV) renvoie également le vecteur des longueurs
% des plus courts chemins entre le sommet DEP et tous les autres sommets.
%
% Voir aussi MOORE1

% Copyright (c) 2003 by Didier MAQUIN


% $Revision: 0.1 $Date: 05/01/03 $

n=size(L,1);
% Initialisation
Sb=1:n;
Sb(dep)=[];
mark=L(dep,:);
while 1
[v,indj]=min(mark(Sb));
j=Sb(indj); % j sommet de marque provisoire minimale
Sb(indj)=[]; % on retire j de Sb
if isempty(Sb),break,end % si Sb est vide on ar^ete
succ=find(L(j,:)~=inf & L(j,:)~=0); % liste des successeurs de j
A=intersect(succ,Sb); % intersection entre cette liste et Sb
if ~isempty(A) % si cette liste n’est pas vide
mark(A)=min(mark(A),mark(j)+L(j,A)); % on remet à jour les marques
end
end
s=mark(arv);

59
Considérons le graphe de la figure 27 :

4
4 5

2
2 5
7
1
1 5 3
2
1
7
3 6

Fig. 27 – Graphe orienté

Voilà ci-dessous un exemple de programme d’appel pour calculer les longueurs des plus courts
chemins joignant le sommet 1 à tous les autres :
clear
% Matrice de distance
D=[ 0 7 1 inf inf inf
inf 0 inf 4 inf 1
inf 5 0 inf 2 7
inf inf inf 0 inf inf
inf 2 inf 5 0 inf
inf inf inf inf 3 0 ];
%
dep=input(’Sommet de départ : ’);
arv=input(’Sommet d’’arrivée : ’);
[s,m]=moore(D,dep,arv)
Pour dep = 1 et arv = 6, on obtient :

Sommet de départ : 1
Sommet d’arrivée : 6
s =
6
m =
0 5 1 8 3 6

La fonction précédente peut être modifiée de manière à mémoriser, en plus de la longueur


du chemin, la succession des sommets par lesquels il passe. Il suffit pour cela de maintenir à jour
une table de prédécesseurs. Celle-ci peut ensuite être exploitée pour reconstituer le chemin suivi.

Le programme Matlab R
ci-dessous réalise cette fonction. Les trois paramètres d’appel de la
fonction moore1 sont identiques à ceux de la fonction précédente. En sortie, on obtient :

s : la longueur du plus court chemin (s = ∞ s’il n’existe pas de chemin).


chemin : le vecteur des numéros de sommets décrivant le chemin.

60
function [s,chemin]=moore1(L,dep,arv)
%MOORE1 Recherche du plus court chemin entre deux sommets d’un graphe
%
% S=MOORE1(L,DEP,ARV) calcule la longueur du plus court chemin entre
% les sommets de numéro DEP et ARV.
%
% [S,CHEMIN]=MOORE1(L,DEP,ARV) renvoie également le chemin emprunté
% (séquence de numéro de sommets).
%
% Voir aussi MOORE

% Copyright (c) 2003 by Didier MAQUIN


% $Revision: 0.1 $Date: 05/01/03 $

n=size(L,1);
% Initialisation
Sb=1:n;
Sb(dep)=[];
mark=L(dep,:);
p=ones(1,n)*inf;
succ=find(L(dep,:)~=inf & L(dep,:)~=0);
p(succ)=dep;
while 1
[v,indj]=min(mark(Sb));
j=Sb(indj); % j sommet de marque provisoire minimale.
Sb(indj)=[]; % on retire j de Sb.
if isempty(Sb),break,end % si Sb est vide on ar^ ete.
succ=find(L(j,:)~=inf & L(j,:)~=0);% on cherche la liste des successeurs de j.
A=intersect(succ,Sb); % intersection entre cette liste et Sb.
if ~isempty(A) % si cette liste n’est pas vide
oldmark=mark(A); % on mémorise l’ancienne marque
mark(A)=min(mark(A),mark(j)+L(j,A)); % et on remet à jour les marques.
id=find(oldmark~=mark(A)); % pour les sommets dont les marques ont
p(A(id))=j; % changé on mémorise le prédécesseur.
end
end
s=mark(arv);
chemin=[];
if isfinite(p(arv))
chemin=[arv]; % on construit le chemin
while chemin(end)~=dep % à l’aide de la table des prédécesseurs
k=chemin(end); % à partir de la fin.
chemin=[p(k) chemin];
end
end

Ci-dessous un exemple de programme d’appel correspondant au graphe de la figure 27 :

clear
% Matrice de distance
D=[ 0 7 1 inf inf inf

61
inf 0 inf 4 inf 1
inf 5 0 inf 2 7
inf inf inf 0 inf inf
inf 2 inf 5 0 inf
inf inf inf inf 3 0 ];
%
dep=input(’Sommet de départ : ’);
arv=input(’Sommet d’’arrivée : ’);
[s,chemin]=moore1(D,dep,arv);
if isfinite(s)
fprintf(’Le chemin ’)
fprintf(’%i ’,chemin)
fprintf(’de longueur %f ’,s)
fprintf(’est le chemin de longueur minimale\n’)
else
fprintf(’Il n’’existe pas de chemin !\n’)
end

Pour dep = 1 et arv = 6, on obtient :

Sommet de départ : 1
Sommet d’arrivée : 6
Le chemin 1 3 5 2 6 de longueur 6.000000 est le chemin de longueur minimale

Pour dep = 4 et arv = 3, on obtient :

Sommet de départ : 4
Sommet d’arrivée : 3
Il n’existe pas de chemin !

62
Annexe B - Implémentation de l’algorithme de Floyd
Le programme Matlab R
ci-après est une implémentation de l’algorithme de Floyd décrit au
paragraphe 6.3 et permettant l’obtention de la matrice des plus courts chemins dans un graphe
dont les arcs sont valuées positivement. Le seul paramètre d’appel de la fonction floyd est le
suivant :

L : matrice des longueurs (s’il n’y a pas d’arc entre le sommet i et le sommet j, alors
lij = ∞ et conventionnellement lii = 0).
En sortie, on récupère :

A : la matrice des plus courts chemins entre tous les sommets.


P : la matrice des prédécesseurs (pij représente le numéro du sommet prédécesseur
immédiat de j sur le plus court chemin entre i et j).

function [A,P]=floyd(L)
%FLOYD Recherche de la matrice des plus courts chemins entre sommets
%
% [A]=FLOYD(L) calcule a matrice des plus courts chemins entre sommets
%
% [A,P]=FLOYD(L) renvoie également la matrice des prédécesseurs
%

% Copyright (c) 2003 by Didier MAQUIN


% $Revision: 0.1 $Date: 05/04/03 $

[n,m]=size(L);
if n ~= m error(’La matrice des distance n’’est pas carrée’);end
A=L;
for i=1:n
P(i,:)=i*ones(1,m);
end
for k=1:n
for i=1:n
for j=1:n
if A(i,k) + A(k,j) < A(i,j)
A(i,j) = A(i,k) + A(k,j);
P(i,j) = P(k,j);
end
end
end
end

Considérons de nouveau le graphe de la figure 27. Le programme ci-après permet de calculer


la matrice des plus courts chemins et d’éditer, en exploitant la matrice des prédécesseurs, le
chemin reliant un sommet initial à un sommet terminal quelconques sous la forme d’une liste de
sommets.

63
clear;
% Matrice de distance
C=[ 0 7 1 inf inf inf
inf 0 inf 4 inf 1
inf 5 0 inf 2 7
inf inf inf 0 inf inf
inf 2 inf 5 0 inf
inf inf inf inf 3 0 ];
%
[A,P]=floyd(C)
initial=input(’Sommet initial : ’);
terminal=input(’Sommet terminal : ’);
%
if ~isfinite(A(initial,terminal))
fprintf(’Il n’’existe pas de chemin entre les sommets %d et %d\n\n’,initial,terminal);
else
j=terminal;
chemin=[j];
while j ~= initial
j=P(initial,j);
chemin=[j chemin];
end
fprintf(’Plus court chemin entre les sommets %d et %d\n\n’,initial,terminal)
fprintf(’%d ’,chemin);
fprintf(’\n\n’)
end

Pour initial = 1 et terminal = 6, on obtient :

Plus court chemin entre 1 et 6

1 3 5 2 6

Alors que pour initial = 6 et terminal = 1, le résultat est le suivant :

Il n’existe pas de chemin entre 6 et 1

64
Annexe C - Implémentation de l’algorithme de Prim
Le programme Matlab R
ci-après est une implémentation de l’algorithme de Prim décrit au
paragraphe 7.2 et permettant l’obtention d’un arbre couvrant de poids minimal. Les deux pa-
ramètres d’appel de la fonction prim sont les suivants :

L : matrice des longueurs (s’il n’y a pas d’arc entre le sommet i et le sommet j, alors
lij = ∞ et conventionnellement lii = 0).
dep : numéro du sommet de départ pour la construction de l’arbre recherché.

En sortie, on récupère :

alpha : un tableau de chaı̂nes de caractères désignant les arêtes constituant l’arbre.

function [alpha]=prim(L)
%PRIM Recherche d’un arbre couvrant de poids minimal
%
% ALPHA=PRIM(L) détermine un arbre couvrant de poids minimal
% ALPHA est un tableau de cha^ınes de caractères désignant les
% ar^
etes de l’arbre.

% Copyright (c) 2003 by Didier MAQUIN


% $Revision: 0.1 $Date: 05/01/03 $

n=size(L,1);
mark=ones(1,n)*inf;
alpha=ones(n,3)*abs(’-’); % liste des ar^etes de l’arbre
dep=1; % sommet de départ (fixé à 1)
mark(dep)=0;
A=[];
S=1:n;
while 1
S=setdiff(S,A); % ensemble X\A
[val,l]=min(mark(S)); % recherche du sommet ayant la plus petite marque
i=S(l); % numéro du sommet
if isempty(setxor(A,1:n)),break, end % si A=X alors FIN
A=[A i]; % ajout du sommet à l’arbre
succ=find(L(i,:)~=inf & L(i,:)~=0); % successeurs du sommet i
E=setdiff(succ,A); % liste des successeurs moins les sommets déjà dans S
for k=1:length(E) % mise à jour des marques
if L(i,E(k))<mark(E(k))
mark(E(k))=L(i,E(k));
alpha(E(k),:)=[num2str(i) ’-’ num2str(E(k))]; % mémorisation ar^etes
end
end
end

Considérons le graphe de la figure 28. Le programme ci-après permet de déterminer un arbre


couvrant de ce graphe.

65
2
1 4
7 2 1 2

2
2 3 5 7 10

1 4 4 7
3
3 6

Fig. 28 – Graphe simple

clear
% 1 2 3 4 5 6 7
D=[ 0 7 3 2 2 inf inf
7 0 1 inf inf inf inf
3 1 0 inf 4 3 inf
2 inf inf 0 1 10 2
2 inf 4 1 0 4 2
inf inf 3 10 4 0 7
inf inf inf 2 2 7 0 ]
%
alpha=prim(D);
setstr(alpha)

Le résultat obtenu est :

ans =
---
3-2
1-3
1-4
4-5
3-6
4-7

Cela correspond à l’arbre suivant :

2
1 4
1 2

2 3 5 7

1
3
3 6

Fig. 29 – Arbre couvrant de poids minimal

66
Annexe D - Implémentation de l’algorithme du simplexe
Le programme Matlab R
ci-dessous est une implémentation de l’algorithme du simplexe per-
mettant de résoudre les problèmes de programmation linéaire. Il est adapté au cas non dégénéré.
Un nombre maximal d’itérations peut cependant être fixé pour éviter d’entrer dans une boucle
infinie en cas de problème dégénéré. Les quatre paramètres d’appel de la fonction simplex sont
les suivants :

A : matrice décrivant les contraintes inégalité.


b : vecteur second membre des contraintes inégalité.
C : vecteur de poids des variables dans le critère à maximiser.

nbiter : paramètre optionnel fixant le nombre maximal d’itération de recherche de l’algo-


rithme (traitement du cas dégénéré).

En sortie, on récupère :

x : vecteur des valeurs des variables maximisant la valeur du critère.


F : valeur optimale du critère.

function [x,F] = simplex(A,b,C,nbiter)


%SIMPLEX Méthode du simplexe
%
% [x,F] = simplex(A,b,C) rend le vecteur x qui maximise C*x sous les
% contraintes A*x <= b et x >= 0, ainsi que la valeur F du critère à l’optimum
%
% [x,F] = simplex(A,b,C,nbiter) permet de limiter le nombre
% d’itérations dans la recherche de la solution optimale

% Copyright (c) 2004 by Didier MAQUIN


% $Revision: 0.1 $Date: 05/04/89$
% $Revision: 0.2 $Date: 16/05/04$

% References:
% Cooper, Steinberg Introduction to methods of optimization
% Saunders Comp. 1970, Chapter 6, Linear Programming
%
% Noble, Daniel Applied linear algebra
% Prentice Hall 1977, Chapter 7, Linear Programming
%
% Boudarel, Delmas, Commande optimale des processus, Tome 2, 1968
% Guichet Chapitre V, Paragraphe 4, Programmation linéaire
%
if nargin < 4
nbiter = inf;
end
nb = nbiter;
[nl,nc] = size(A);
M = [ A eye(nl,nl) b];

67
M = [ M;-C zeros(1,nl+1)];
[v,c] = min(M(nl+1,:));
while v < 0 & nbiter ~= 0
NZ = find(M(1:nl,c)>0);
T = ones(1,nl)*inf;
T(NZ) = M(NZ,nc+nl+1) ./ M(NZ,c);
[i,l] = min(T);
M(l,:) = M(l,:) ./ M(l,c);
for i = 1:nl+1
if i ~= l
M(i,:) = M(i,:) - M(l,:)*M(i,c);
end
end
[v,c] = min(M(nl+1,:));
nbiter = nbiter - 1;
end
%M % Décommentez cette ligne pour visualiser le "tableau"
if nbiter ~= 0 % Le nombre maxi d’itérations est-il-atteint ?
x = zeros(nc,1);
for i=1:nc
l = find(M(:,i)==1);
if l & (sum(abs(M(:,i))) - 1) == 0;
x(i) = M(l,nc+nl+1);
end
end
F = M(nl+1,nc+nl+1);
if ~all(A*x <= b) % La solution satisfait-elle les contraintes ?
x = [];F = [];
fprintf([’\nPas de solution\n\n’ 7]);
end
else
x = [];F = [];
fprintf([’\nPas de solution trouvée après ’ num2str(nb) ’ itérations\n\n’ 7]);
end

68
Références
[1] A.V. Aho, J.E. Hopcroft et J.D. Ullman, The design and analysis of computer algorithms,
ISBN 0-201-00029-6, Addison Wesley, Reading (Mass.), 1974.
[2] M.L. Assas, Analyse de la tolérance aux fautes : approches fonctionnelle et structurelle.
Thèse de doctorat de l’Université des Sciences et Technologies de Lille, 2002.
[3] K. Appel et W. Haken, Every planar map is 4-colorable, Bulletin of the AMS, Volume 82,
711-712, 1976.
[4] C. Berge, Graphes, ISBN 2-04-15555-4, Gauthiers-Villars, Bordas, Paris, 1983.
[5] H. Bestougeff, C. Guilpin et M. Jacques, La technique informatique, Tome 2 : algorithmes
numériques et non numériques, ISBN 2-225-40337-6, Masson, Paris, 1975.
[6] N. Biggs, E. Lloyd et R. Wilson, Graph Theory 1736-1936, ISBN 0-19-853901-0, Clarendon
Press Oxford, 1976.
[7] R. Cabane, Théorie des graphes, Techniques de l’Ingénieur, Traité Sciences fondamentales,
document AF205.
[8] H. Coilland, Polycopié d’exercices de recherche opérationnelle, IUT Informatique Nancy 2
et Ecole des Mines de Nancy, juillet 1999.
[9] R. Diestel, Graph theory, Graduate Texts in Mathematics Series, vol. 173, electronic
edition, http ://www.math.uni-hambourg.de/home/diestel/books/graph.theory, Springer-
Verlag, New York 1997, 2000,
[10] F. Droesbeke, M. Hallin et C. Lefevre, Les graphes par l’exemple, ISBN 2-7298-8730-X,
Ellipses, 1987.
[11] N. Deo, Graph theory with applications to engineering and computer science, Prentice-Hall,
Englewood cliffs (N.J.),1975.
[12] L. Euler, Solutio Problematis Ad geometriam Situs Pertinentis, Commenrarii Academiae
Scientiarum Imperialis Petropolitanae, 8, pp. 128-140, 1736.
[13] M. Gondran et M. Minoux,Graphes et algorithmes, 2ème ed., Collection de la Direction des
Etudes et Recherches d’Electricité de France, Eyrolles 1985.
[14] M. Minoux et G. Bartnik, Graphes, algorithmes, logiciels, Dunod Informatique, ISBN 2-04-
016470-7, Bordas Paris, 1986.
[15] Roseaux, Exercices et problèmes résolus de recherche opérationnelle. Tome 1. Graphes :
leurs usages, leurs algorithmes, ISBN 2-10-003935-0, Dunod, Paris, 1998.

69