• Aucun résultat trouvé

Analyse Syntaxique

7.6 Tri topologique

Figure 7.5 : Un exemple de graphe acyclique bon ordre les composants d'un projet.

7.6 Tri topologique

Au debut de certains livres, les auteurs indiquent les dependances chronologiques entre les chapitres en les representant par un diagramme. Celui qui gure au debut du livre de Barendregt sur lambda-calcul [4] est sans doute l'un des plus compliques. Par exemple, on voit sur ce diagramme que pour lire le chapitre 16, il faut avoir lu les chapitres 4, 8 et 15. Un lecteur courageux veut lire le strict minimum pour apprehender le chapitre 21.

Il faut donc qu'il transforme l'ordre partiel indique par les dependances du diagramme en un ordre total determinant la liste des chapitres necessaires au chapitre 21. Bien s^ur, ceci n'est pas possible si le graphe de dependance contient un cycle. L'operation qui consiste a mettre ainsi en ordre les nuds d'un graphe dirige sans circuit (souvent appeles sous leur denomination anglaise dagspour directed acyclic graphs) est appelee le tri topologique. Comme nous l'avons vu plus haut, elle est aussi bien utile dans la compilation et l'edition de liens des modules

Le tri topologique consiste donc a ordonner les sommets d'un dag en une suite dans laquelle l'origine de chaque arc apparait avant son extremite. La construction faite ici est une version particuliere du tri topologique, il s'agit pour un sommet s donne de construire une liste formee de tous les sommets origines d'un chemin d'extremite s. Cette liste doit en plus satisfaire la condition enoncee plus haut. Pour resoudre ce probleme, on applique l'algorithme de descente en profondeur d'abord (Tremaux) sur le graphe oppose. (Au lieu de considerer les successeurs succ[u,k]du sommet u, on parcourt ses predecesseurs.) Au cours de cette recherche, quand on a ni de visiter un sommet, on le met en t^ete de liste. En n de l'algorithme, on calcule l'image mirroir de la liste. Pour tester l'existence de cycles, on doit verier lorsqu'on rencontre un nud deja visite que celui-ci gure dans la liste resultat. Pour ce faire, il faut utiliser un

tableau annexe etatsur les nuds qui indique si le nud est visite, en cours de visite, ou non visite.

procedure TriTopologique (u: Sommet; var resultat: Liste);

...

procedure DFS (u: Sommet);

var k: integer;

v: Sommet;

begin

k := 1; v := pred[u, k];

while v <> Omega do begin

if etat[v] = NonVu then

begin etat[v] := EnCours; DFS (v) end else if etat[v] = EnCours then

Erreur ('Le graphe a un cycle');

k := k + 1; v := pred[u, k];

end;

etat[u] := Vu;

res := Cons (u, res);

end;

begin

for i := 1 to Nsommets do etat[i] := NonVu;

resultat := nil; resultat := Reverse (DFS (u));

end;

Nous avons omis les declarations des variablesietetatet du type enumere des elements de ce tableau. Nous avons repris les structures developpees dans les chapitres sur les graphes et les fonctions sur les listes. Nous supposons aussi que le tableau succ est remplace par preddes predecesseurs de chaque nud.

7.7 Programmes en C

Ici, il est interessant d'examiner la dierence entre Pascal et C. Les noms de fonctions sont dierents de ceux donnes dans le programme Pascal pour les les de caracteres, car nous avons copie textuellement ce code directement du noyau du systeme Unix. C'est l'occasion de constater comment la programmation en C permet certaines acrobaties, peu recommandables car on aurait pu suivre la technique d'adressage des caracteres dans les blocs de Pascal. La structure des les est legerement dierente car on adresse directement les caracteres dans un bloc au lieu du systeme base et deplacement de Pascal. Le debordement de bloc est teste en regardant si on est sur un multiple de la taille d'un bloc, car on suppose le tableau des blocs aligne sur un multiple de cette taille. Le chier interface files-de-caracteres.hest

#define NCLIST 80 /* max total clist size */

#define CBSIZE 12 /* number of chars in a clist block */

#define CROUND 0xf /* clist rounding:sizeof(int *) + CBSIZE - 1*/

/*

* A clist structure is the head

* of a linked list queue of characters.

* The characters are stored in 4-word

7.7. PROGRAMMES EN C 179

* blocks containing a link and several characters.

* The routinesFCgetandFCput

* manipulate these structures.

*/

struct clist {

int c_cc; /* character count */

char *c_cf; /* pointer to rst char */

char *c_cl; /* pointer to last char */

};

struct cblock {

struct cblock *c_next;

char c_info[CBSIZE];

};

typedef struct clist *FCtype;

int FCput(char c, FCtype p);

int FCget(FCtype p);

void FCinit(void);

Dans la partie implementation qui suit, on remarque l'emploi de la directive static qui permet de cacher a l'edition de liens des variables, procedures ou fonctions pri-vees qui ne seront pas considerees comme externes. Contrairement a Pascal, il est possible en C de cacher la representation des les, en ne declarant le type FCtype que comme un pointeur vers une structureclistnon denie. Les fonctions retournent un resultat entier qui permet de retourner des valeurs erronees comme ;1. Le chier

files-de-caracteres.cest

#include <stdlib.h>

#include <files-de-caracteres.h>

static struct cblock cfree[NCLIST];

static struct cblock *cfreelist;

int FCput(char c, FCtype p) {

struct cblock *bp;

char *cp;

register s;

if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { if ((bp = cfreelist) == NULL)

return(-1);

cfreelist = bp->c_next;

bp->c_next = NULL;

p->c_cf = cp = bp->c_info;

} else if (((int)cp & CROUND) == 0) { bp = (struct cblock *)cp - 1;

if ((bp->c_next = cfreelist) == NULL) return(-1);

bp = bp->c_next;

cfreelist = bp->c_next;

bp->c_next = NULL;

cp = bp->c_info;

}

*cp++ = c;

p->c_cc++;

p->c_cl = cp;

return(0);

}

int FCget(FCtype p) {

struct cblock *bp;

int c, s;

if (p->c_cc <= 0) { c = -1;

p->c_cc = 0;

p->c_cf = p->c_cl = NULL;

} else {

c = *p->c_cf++ & 0xff;

if (--p->c_cc<=0) {

bp = (struct cblock *)(p->c_cf-1);

bp = (struct cblock *) ((int)bp & ~CROUND);

p->c_cf = p->c_cl = NULL;

bp->c_next = cfreelist;

cfreelist = bp;

} else if (((int)p->c_cf & CROUND) == 0){

bp = (struct cblock *)(p->c_cf-1);

p->c_cf = bp->c_next->c_info;

bp->c_next = cfreelist;

cfreelist = bp;

} }

return(c);

}

void FCinit() {

int ccp;

struct cblock *cp;

ccp = (int)cfree;

ccp = (ccp+CROUND) & ~CROUND;

for(cp=(struct cblock *)ccp; cp <= &cfree[NCLIST-1]; cp++) { cp->c_next = cfreelist;

cfreelist = cp;

} }

Exploration

Dans ce chapitre, on recherche des algorithmes pour resoudre des problemes se presen-tant sous la forme suivante:

On se donne un ensembleE ni et a chaque element edeE est aectee une valeur v(e) (en general, un entier positif), on se donne de plus un predicat (une fonction a valeurs fvrai, fauxg) C sur l'ensemble des parties deE. Le probleme consiste a construire un sous ensembleF de E tel que:

C(F) est satisfait

Pe2Fv(e) soit maximal (ou minimal, dans certains cas)

Les methodes developpees pour resoudre ces problemes sont de natures tres diverses.

Pour certains exemples, il existe un algorithme tres simple consistant a initialiser F par F = ;, puis a ajouter successivement des elements suivant un certain critere, jusqu'a obtenir la solution optimale, c'est ce qu'on appelle l'algorithme glouton. Tous les problemes ne sont pas resolubles par l'algorithme glouton mais, dans le cas ou il s'applique, il est tres ecace. Pour d'autres problemes, c'est un algorithme dit de programmation dynamique qui permet d'obtenir la solution, il s'agit alors d'utiliser certaines particularites de la solution qui permettent de diviser le probleme en deux;

puis de resoudre separement chacun des deux sous-problemes, tout en conservant en table certaines informations intermediaires. Cette technique, bien que moins ecace que l'algorithme glouton, donne quand m^eme un resultat interessant car l'algorithme mis en uvre est en general polynomial. Enn, dans certains cas, aucune des deux methodes precedentes ne donne de resultat et il faut alors utiliser des procedures d'exploration systematique de l'ensemble de toutes les parties de E satisfaisant C, cette exploration systematique est souvent appeleeexploration arborescente (oubacktrackingen anglais).

Documents relatifs