Adloun

Graphes sans circuit et ordonnancement de projets

Cours · algorithmique (école d'ingénieur), chapitre 7 · école d'ingénieur, informatique · le début du chapitre, la suite sur Adloun

Objectifs du chapitre

  • Définir et manipuler des listes d'entiers en Java.
  • Représenter un graphe par un tableau de listes d'arcs, calculer son graphe symétrique en temps linéaire.
  • Calculer une numérotation isotone (ordre topologique) d'un graphe sans circuit.
  • Ordonnancer un projet : dates de début au plus tôt, durée minimum, chemin critique.
  • Reconnaître un problème de chemin optimal dans un graphe sans circuit derrière des énoncés variés (réseau de bus, plus longue sous-séquence croissante).

Jusqu'ici, nos sous-problèmes étaient rangés dans des tableaux : l'objet venait après l'objet , la case après les cases . Dans ce chapitre, la structure des sous-problèmes est donnée par un graphe : la tâche d'un projet ne peut commencer qu'après certaines autres tâches, ses prédécesseurs. La programmation dynamique s'applique toujours, à condition de calculer les valeurs dans un ordre où les prédécesseurs passent avant leurs successeurs.

7.1 Listes d'entiers

Définition 7.1Liste d'entiers

Une liste d'entiers est :

  • soit la liste vide, notée ;
  • soit un couple où est un entier, le premier élément de la liste, et est une liste, le reste de la liste (la liste privée de son premier élément).

La définition est récursive : la liste que nous écrivons est, pour l'ordinateur, le couple . En Java, la liste vide est représentée par null et un couple par un objet de la classe Liste :


static class Liste { int p; Liste r;    // premier et reste
    Liste(int p, Liste r) { this.p = p; this.r = r; }
}
static boolean vide(Liste l)  { return l == null; }
static int     premier(Liste l) { return l.p; }   // l non vide
static Liste   reste(Liste l)   { return l.r; }   // l non vide

La liste se construit par new Liste(0, new Liste(2, new Liste(1, new Liste(2, null)))). Ajouter un élément en tête d'une liste est en temps constant : l = new Liste(x, l). Le parcours d'une liste s'écrit avec une boucle for :


for (Liste l = L; !vide(l); l = reste(l))
    System.out.print(premier(l) + " ");

Les fonctions sur les listes s'écrivent naturellement de façon récursive, en suivant la définition : un cas pour la liste vide (base), un cas pour la liste non vide (hérédité).


static int longueur(Liste l) {
    if (vide(l)) return 0;              // la liste vide a 0 élément
    return 1 + longueur(reste(l));      // le premier, plus ceux du reste
}

7.2 Graphes orientés

Définition 7.2Graphe orienté

Un graphe orienté est formé d'un ensemble de sommets, ici , et d'un ensemble d'arcs (ou flèches) ; un arc relie le sommet au sommet . On note le nombre d'arcs et l'on appelle taille du graphe la valeur .

  • est un successeur de , et un prédécesseur de , s'il existe un arc ; on note l'ensemble des prédécesseurs de .
  • Le degré entrant d'un sommet est le nombre d'arcs qui arrivent sur lui ; une source est un sommet de degré entrant nul.
  • Un circuit est un chemin qui revient à son point de départ. Un graphe sans circuit est souvent appelé DAG (directed acyclic graph).

7.2.1 Représentation par un tableau de listes d'arcs

On représente un graphe à sommets par un tableau de listes : est la liste des successeurs de , c'est-à-dire la liste des arcs qui sortent de . L'ordre des éléments d'une liste est quelconque.

Exemple 7.3un graphe à 8 sommets

Sa représentation : , , , , , , , .


static Liste[] graphe() {   // G[i] = liste des successeurs de i
    Liste[] G = new Liste[8];
    G[0] = new Liste(1, new Liste(2, new Liste(3, null)));
    G[1] = new Liste(3, new Liste(5, null));
    G[2] = new Liste(4, new Liste(5, new Liste(6, new Liste(7, null))));
    G[3] = new Liste(7, null);
    G[4] = new Liste(6, new Liste(7, null));
    G[5] = new Liste(6, new Liste(7, null));
    G[6] = new Liste(7, null);
    G[7] = null;
    return G;
}
static void afficher(Liste[] G) {
    for (int i = 0; i < G.length; i++) {
        System.out.print(i + " :");
        for (Liste l = G[i]; !vide(l); l = reste(l))
            System.out.print(" " + premier(l));
        System.out.println();
    }
}

Cette représentation occupe une place proportionnelle à : une case de tableau par sommet, une cellule de liste par arc. Elle permet de parcourir les successeurs d'un sommet en un temps proportionnel à leur nombre.

7.2.2 Le graphe symétrique

Les récurrences de ce chapitre s'expriment avec les prédécesseurs d'un sommet, alors que donne ses successeurs. On construit donc le graphe symétrique.

Définition 7.4Graphe symétrique

Le graphe symétrique de a les mêmes sommets et les arcs inversés : est un arc de si et seulement si est un arc de . Ainsi est la liste des prédécesseurs de dans : .


static Liste[] symetrique(Liste[] G) { int n = G.length;
    Liste[] Gp = new Liste[n];                  // n listes vides
    for (int i = 0; i < n; i++)
        for (Liste l = G[i]; !vide(l); l = reste(l)) { int j = premier(l);
            Gp[j] = new Liste(i, Gp[j]);            // arc j --> i ajouté à G'
        }
    return Gp;
}

Chaque sommet est touché une fois (boucle externe), chaque arc une fois (boucle interne), et le corps de boucle est en temps constant puisque l'ajout se fait en tête de liste. Le temps de calcul est de la forme : la complexité est , linéaire en la taille du graphe. On ne peut pas faire mieux, puisqu'il faut au moins lire le graphe.


Graphe symétrique G' :
0 :
1 : 0
2 : 0
3 : 1 0
4 : 2
5 : 2 1
6 : 5 4 2
7 : 6 5 4 3 2

Attention

Les listes de sortent « à l'envers » : comme on ajoute en tête, contient alors que les arcs ont été rencontrés dans l'ordre . L'ordre des éléments d'une liste d'arcs n'a pas d'importance pour le graphe… mais il peut en avoir pour la solution retournée lorsqu'il y a plusieurs solutions optimales (voir section 7.6).

7.3 Numérotation isotone

Définition 7.5Numérotation isotone

Une numérotation des sommets d'un graphe est isotone si pour tout arc on a : les arcs vont toujours d'un numéro plus petit vers un numéro plus grand.

La suite du cours est sur Adloun

Le chapitre en entier, formules et figures comprises, avec le tuteur, les fiches, les QCM et les exercices.

Lire la suite du cours

En accès libre, sans inscription.

Exercices corrigés de ce chapitre

Lire la suite du cours →