Download - Flot maximal par l'algorithme d'Edmonds-Karp

Transcript
Page 1: Flot maximal par l'algorithme d'Edmonds-Karp
Page 2: Flot maximal par l'algorithme d'Edmonds-Karp

Ecole nationale des sciences appliquées khouribga - Université Hassan 1er

Flot maximal par l'algorithme d'Edmonds-

Karp

01 janvier 2012

Mohammed Cheddad Imad Lamtouni Yacine abdessalam Amkassou

Encadré par : Mr. Imad hafidi

Page 3: Flot maximal par l'algorithme d'Edmonds-Karp

Table des matièresINTRODUTION :

CHAPITRE I : BIBLIOGRAPHIE DE L’ALGORITHME D’EDMONDS-KARP

1 Problème du Flot maximal :1.1 Introduction au problème du flot maximale

1.2 Algorithme d’Edmonds-Karp

1.2.1 Etapes de l’Algorithme

1.2.2 Pseudo code

1.2.3 Etude de complexité

1.2.4 Exemple d’application de l’algorithme d’Edmond-Karp

CHAPITRE II : PROGRAMMATION DE L’ALGORITHME D’EDMONDS-KARP

1 Génération aléatoire du graphe :1.1 Introduction1.2 Description du programme1.3 Les fonctions utilisées1.4 Fonction principal de création de graphe

2 Chemin Augmentant

2.1 Méthode de Marquage2.2 Fonction de Parcours2.3 Exemple de Parcours

3 L’algorithme d’augmentation de flot3.1 Démarrage de l’Algorithme3.2 La recherche de la capacité minimale3.3 La mise à jour des capacités et des flots

4 Exemple d’exécution

CONCLUSION

INTRODUTION :

Page 4: Flot maximal par l'algorithme d'Edmonds-Karp

Dans le cadre du module d’algorithme avancée, nous avons été amené à étudier l’algorithme d’ Edmonds-Karp. Ce même algorithme est devenu le sujet de notre projet dans ce module.

Nous présenterons dans un premier temps, l’algorithme d’ Edmonds-Karp plus en détails. Dans un deuxième temps nous passerons en revue les différentes phases de la réalisation de ce projet et pour terminer nous allons exécuter notre programme.

Le but est de créer un programme appliquant un algorithme de flot maximum. L’algorithme devant être appliqué est l’algorithme d’ Edmonds-Karp.

CHAPITRE I :

BIBLIOGRAPHIE DE L’ALGORITHME D’EDMONDS-KARP

1 Problème du Flot maximal :

Page 5: Flot maximal par l'algorithme d'Edmonds-Karp

La théorie des graphes est née en 1736 quand Léonard Euler démontra de manière rigoureuse qu’il était impossible de

traverser chacun des sept ponts de la ville de Konigsberg une fois exactement et de revenir à son point de départ.

Un graphe est un ensemble de points appelés sommets, reliés par des flèches ou des traits. C’est un outil qui sert à modéliser de nombreux problémes,

1.1 Introduction au problème du flot maximale

Le problème de flot maximum consiste à trouver un flot réalisable depuis une source unique et vers un puits unique. Quelquefois le problème répond simplement à la question de trouver la valeur de ce flot. Le problème du flot maximum peut être vu comme un cas particulier de plusieurs autres problèmes de flots dans les réseaux. Le s→t flot maximum (depuis la source s vers le puits t) est égal a la s→t coupe minimale du graphe.1

Définition : Un flot est une fonction entière positive ou nulle f définie sur les arcs satisfaisant : Contrainte de capacité : f (a)≤ c(a) ; Conservation du flot : pour tout sommet autre que s et t, la somme des flots sur les arcs entrants et la somme des flots sur les arcs sortants sont égales.

Figure 1 exemple de réseau du flot

1.2 Algorithme d’Edmonds-Karp 

Définition : Un réseau de transport R=(S , A , s , p , c) est un graphe orienté G=(S , A )sans circuit :

Muni d’une source : un sommet s ∈ S tel que d−¿ (s )=0¿, Muni d’un puits : un sommet p ∈S tel que d+¿+(p )=0 ,¿

Dont chaque arc u ∈ A est valué par une capacité : un nombre positif ou nul noté c (u) , Et tel qu’il existe au moins un chemin de s vers p.

L'algorithme de Edmonds-Karp construit un flot maximal en partant d'un flot nul ∀a∈ A f (a )=0et en augmentant son débit le long de chemins s=s1 , s2 …… .. sn−1 , sn=t de s à t acceptables, c'est à dire tels que

∀ i ; (s i ;s i+1)∈ A et que le débit maximum max ic (si ;si+1) soit strictement positif.

1 Wikipedia http://fr.wikipedia.org/wiki/Probl%C3%A8me_de_flot_maximum

Page 6: Flot maximal par l'algorithme d'Edmonds-Karp

La particularité de l'algorithme de Edmonds-Karp est de toujours choisir un chemin acceptable don’t la longueur (en nombre d'arêtes) est minimale. Dès qu'un nouveau chemin L acceptable de longueur minimale est trouvé, son débit est ajouté à f et, parallélement, les capacités c de G sont mises à jour.2

Figure 2 exemple de réseaux de transport

Cette methode était crée par Jack Edmonds et Richard Karp en 1971 3 elle s’agit d’une modification de l’algorithime de Ford-Fulkerson , cette derniére consiste a calculer de debit maximal dans un réseau de transport . La différance entre les deux c’est que la premiére utilise le plus court chemin dans l’augmentation du flot .

1.2.1 Etapes de l’Algorithme

L’algorithme repose sur 2 etape principeaux . Dabord il faut chercher un chemin de s vers p ,cette étape est fait par le parcours par Largeure ce qui garentie que le chemin suivant soit minimal en nombe de arêtes ( sans utiliser aucun methode de plus court chemin) . Arpes qu’on a trouvé ce chemin, l’etape suivante consiste à augmenter ce chemin en quantité de flot qui le traverse . Ceci nécessite de trouver le maximal flot qui peut traverser ce chemin , ce dernier est determine par l’équation suivante :

e=minx∈ A(c ( x )−f (x ))Donc le chemin C(s,p) est dit augmentant si e>0 .Alors on peut dire que l’algorithme d’Edmond-Karp est :

initialiser le flot f avec la valeur 0 sur chaque arc tant qu’il existe un chemin augmentant s à p, augmenter le flot de e jusqu’à l’obtention d’un flot complet, tant qu’il existe une châıne augmentante de s à p, augmenter le flot de e jusqu’à l’obtention d’un flot maximal, retourner f

1.2.2 Pseudo code

Parcours() Edmonds−Karp()

2 Thomas H. Cormen, Cliôrd Stein, Ronald L. Rivest, and Charles E. Leiserson. Introduction à l'algorithmique. Dunod, 2nd edition, 2001.3 Puplier pour la premier fois dans Journal of the Association for Computing Machinery, Vol. 19, No. 2, Apri| 1972. pp. 248-264

Page 7: Flot maximal par l'algorithme d'Edmonds-Karp

∀u∈S , p [u ]=−1Q=[s ] Tant queQ ≠∅ u=dépiler Q pour chaque v telque (u , v )∈ A , c (u , v )>0 et p [ u ]=−1 p[v ]=u si v=t , alors retourner 0 ajouter và la fin deQ fin pour fintant queretourner

∀ (u , v )∈ A , f (u , v )=0Tant que (parcours ()=¿0) min=∞ x=t tant que x ≠ s min=min(m , c ( p[ x ] , x )) x=p[ x ] Fintant que x=t Tant que x≠ s f ( p[ x ] , x )=f (p [ x] , u)+min c ( p [ x ] , x )=c ( p [ x ] , x )−min c (x , p [x ])=c (x , p [x ])+min x=p[ x ] f ∈tant quefintant queretourner f

1.2.3 Etude de complexité

Le temps de fonctionnement de O(|S|.|A2|) est trouvé en prouvant que chaque chemin augmentant peut être trouvé dedans O(A) temps, celui chaque fois au moins un de A le bord devient saturé, ce la distance du bord saturé à la source le long du chemin augmentant doit être plus long que la fois passée qu'il a été saturé, et ce la distance est au plus S long.

Remarque : la longueur du chemin augmentant le plus court augmente monotoniquement. Il y a une preuve accessible dedans4

1.2.4 Exemple d’application de l’algorithme d’Edmond-Karp

Soit le graphe suivant tel que la source est l et le puits est 5 et ∀ (u , v )∈ A , f (u , v )=0 :

Le premier chemin augmentant est : 1 →2 →5

On va calculer e le minimal des (c (x )−f (x))

→ e=min (9−0,19−0 )=9

4 Thomas H. Cormen, Cliôrd Stein, Ronald L. Rivest, and Charles E. Leiserson. Introduction à l'algorithmique. Dunod, 2nd edition, 2001.

Page 8: Flot maximal par l'algorithme d'Edmonds-Karp

Donc on augmente tout les flots de 1 →2 →5 par e=9

L’arête 1→ 2devient saturé

On cherche le chemin augmentant suivant tel que l’arête 1→ 2 est éliminé

Alors on a: 1 →3 → 4 → 5

On va calculer e le minimal des (c (x )−f (x))

→ e=min (7−0,5−0,12−0 )=5

Donc on augmente tout les flots de 1 →3 → 4 → 5par e=5 . L’arête 3→ 4 est saturé

Quand il ne reste aucun chemin augmentant on calcule le flot maximal par une coupe minimal .Alors le flot maximal est f =9+5=14

CHAPITRE II :

PROGRAMMATION DE L’ALGORITHME D’EDMONDS-KARP

La première étape du projet fut la compréhension de l’algorithme. Cette étape est sans doute la plus importante du projet car elle permet de partir dans la bonne direction dès le début pour les étapes suivantes.

1 Génération aléatoire du graphe :

1.1 Introduction

C'est très important de savoir à la fin que le programme réalisé fonctionne correctement et atteint l'objectif, mais pour vérifier ça nous devons le tester pas seulement une fois ou deux mais plusieurs et sur des cas différents, pour éviter que notre programme marche pour certains cas et non pas pour tout. Alors nous devons créer un sous programme qui génère des graphes juste et de manière aléatoire, pour pouvoir tester le programme principal sur différents cas.

Page 9: Flot maximal par l'algorithme d'Edmonds-Karp

Donc on peut dire que le générateur aléatoire des graphes est la matière première de notre projet.

Ce qui fait la création de ce générateur doit être avec vigilance et prudence pour ne pas se baser sur quelques choses de faux.

On a adopté pour le graphe un structure de données particulières et intelligente qui nous permettra de travailler sur le graphe avec souplesse, cette structure utilise seulement les listes chainés pour leurs efficacité (mais difficile à coder) la structure de donnée adoptée est illustrée dans la figure suivante:

Figure: Structure de graphe

4 typedef struct graph graph ;5 struct graph6 {7 int val ;8 CHaine adj ;9 graph * suiv ;10 };1112 typedef graph * GRaph ;

Cette structure est composée de trois attributs ;

Valeur. un pointeur de type chaine pointant vers la liste chainée contenant les adjacents de

ce sommet. un pointeur de type graph pointant vers le sommet suivant.

Voici la structure de base pour la liste chainée :

typedef struct chaine chaine;5 struct chaine6 {7 int valeur;8 int capacity;9 int flot;10 chaine *suivant;11 };12 typedef chaine* CHaine;

Page 10: Flot maximal par l'algorithme d'Edmonds-Karp

Figure 3 : chaine

Pendant la réalisation de ce sous programme on a rencontré tant de problèmes certains sont résolus (comme les problèmes de programmation) et d'autres non c'est du au complexité du problème.

1.2 Description du programme:

L'utilisateur nous fournit seulement le nombre des sommets et aussi le nombre des arrêts et le programme génère le graphe correspondant.

Dans un réseau de transport deux sommets sont particuliers sont: la source et le puit, le puit ne doit pas avoir des successeurs et la source aussi ne doit pas posséder des prédécesseurs.

On a utilisé les nombres entiers comme étiquettes des nœuds (1,2,..., S) et nous avons pris que toujours 1 est la source et S le puit car ça nous aidera un peu à simplifier les tâches.

EXEMPLE Si S=6, on a: 1 et la source et 6 le puits.

L'algorithme de génération des graphes aura recours à des fonctions supplémentaires, donc il est préférable de les détailler avant de passer pour détailler l'algorithme principal.

1.3 Les fonctions utilisées:

void repartirArrets(int S, int A, int t[])Cette fonction sert à repartir le nombre d'arrêts que chaque nœud doit faire, cette répartition se fait aléatoirement en se

servant de la fonction rand.

void repartirArret(int S,int A,int t[]){ int som=0,i,a; srand(time(NULL)); for(i=0;i<S-1;i++) { t[i]=1; som++; } t[S-1]=0; while(som<A) // chaque fois on ajoute 1 pour une case tiré au hasard jusqu'à on obtient som=1 { a=rand()%(S-1); // on choisit aléatoirement entre 0 et S-1 a=c'est l'indice de la case . if(t[a]<(S-1)) // Chaque nœud peut avoir au max S-1 arrêts. { t[a]=t[a]+1;

Chaque nœud doit obligatoirement avoir au moins un arrêt sauf le puits.

Page 11: Flot maximal par l'algorithme d'Edmonds-Karp

som++; } }}

void selectionerParmi(int t[],int n,int Tab[],int m,int k);Cette fonction à comme travaille est de sélectionner m nombres parmi des valeurs contenues dans le tableau t(de taille

n),et les rangés dans le tableau Tab.

Cette sélectionne se fait d'une manière aussi aléatoire comme précédant mais en imposant les contraintes suivantes:

Elle ne doit pas sélectionner du tableau t la valeur donnée K pour une simple raison c'est que si on autorise ça il risque de créer un arrêt entre un nœud et lui-même. La fonction ne doit pas tirer du tableau deux fois la même valeur et pour ne pas tomber dans ce cas on a imposé, si la fonction a choisi un nombre du tableau, elle doit le permuter avec la dernière case et décrémentant la taille.

void selectionerParmi(int t[],int n, int Tab[], int m,int k){ srand(time(NULL)); int i=0,a; for(i=0;i<m;i++) { a=rand()%n; while(t[a]==k) { a=rand()%n; } Tab[i]=t[a]; permuter(t+a,t+(n-1)); n=n-1; } }

chaine *ajouterFin(chaine* C,int n,int cap,int flot)Cette fonction ajoute un nouveau élément à la fin d'une liste chainée.

CHaine ajouterFin(CHaine C,int n,int cap,int flot){ CHaine nouv=malloc(sizeof(chaine)); nouv->valeur=n; nouv->capacity=cap; nouv->suivant=NULL; nouv->flot=flot; if(C==NULL) { return nouv; } else { CHaine aux=C; while((aux->suivant)!=NULL) { aux=aux->suivant; } aux->suivant=nouv; return C;

Page 12: Flot maximal par l'algorithme d'Edmonds-Karp

}}

chaine* createChaine(int taille, int t[],int cap[],int flo)Cette fonction transforme un tableau donné de taille n en liste chainée, cette fonction à comme paramètres un tableau des

capacités pour chaque nœud et une variable flo c'est le flot initial (0).

chaine* createChaine(int taille, int t[],int cap[],int flo){ Chaine *ch=NULL; ch=ajouterFin(ch,t[0],cap[0],flo); int i=0; Chaine *aux=ch; for(i=1;i<taille;i++) { chaine* nouv=malloc(sizeof(chaine)); nouv->valeur=t[i]; nouv->capacity=cap[i]; nouv->flot=flo; nouv->suivant=NULL; aux->suivant=nouv; aux=nouv; } return ch; }

graph* ajoute(graph *G, chaine *H, int k)Cette fonction ajoute un nouvel élément au graphe et lui affecte la valeur k et le chaines H qui contient les nœuds adjacents.

graph *ajoute(graph *G, chaine *C, int n){ graph *nouv= malloc(sizeof(graph)); nouv->val=n; nouv->adj=C; nouv->suiv=NULL; if(G==NULL) { return nouv; } else { graph* aux=G; while(aux->suiv !=NULL) { aux=aux->suiv; } aux->suiv=nouv; return G; }}

1.4 Fonction principal de création de graphe:

graph* creeGraph(int S, int A);input=S,A.output= pointeur de graphe.

Demarche de la fonction: Dans un premier temps cette fonction repartit fait la répartition des arrêts et stocke les résultats dans un tableau T.

Page 13: Flot maximal par l'algorithme d'Edmonds-Karp

Remplir un tableau par les étiquettes des nœuds (ce tableau ne doit pas contenir l'étiquette de la source c-à-d 1 donc le tableau commence de 2 à S)

On boucle un compteur de 0 à S-1 et dans chaque itération Il y a :- création d'un tableau de taille n= T[i], ce tableau contiendra les adjacents après l'appellation de la fonction

selectionerParmi.- Création de la liste chainée en transformant le tableau des adjacents en liste chainée H.- insérer dans le graphe un nouvel élément de valeur : i+1 (car le compteur commence par 0), adj=H.

à la fin on ajoute au graphe un nouvel élément (puit) de val=S,H=NULL.

graph* creeGraphe(int S,int A){ graph *G=NULL; int T[S]; int i=0; repartirArret(S,A,T); int ta[S-1]; for(i=0;i<S-1;i++) { ta[i]=i+2; } for(i=0;i<S-1;i++) { CHaine H=NULL; int ti[T[i]]; selectionerParmi(ta,S-1,ti,T[i],i+1); H=createChaine(T[i],ti); G=ajoute(G,H,i+1); } G=ajoute(G,NULL,S); return G;}Figure 4 Exécution: avec S=6 et A=9. Le graphe correspondant:

En premier temps le sous-programme semble fonctionne correctement, il génère des graphes aléatoirement sans erreurs et sans bugs nous étions satisfait. Mais après des tests successifs nous avons observé que le générateur se trompe parfois car il génère des réseaux étranges non connexes, nous avons essayé de détecter la faille et la corriger mais en vain cela demande un temps de plus c'est qui nous a pousser à créer une fonction qui génère des réseaux de notre choix pour avancer dans le projet et ne pas rester achopper par cette contrainte.

graph* teste(int taille, int tab[], int Tab[]) Input: tab, taille, Tab.Output: pointeur de graphe.Cette fonction a trois paramètres : tab, Tab, taille.

tab: un tableau qui contient la répartition des arrêts pour chaque sommet Tab: un tableau qui contient les sommets adjacents pour chaque nœud

Page 14: Flot maximal par l'algorithme d'Edmonds-Karp

taille: nombre des nœuds.EXEMPLE: Si tab[6]={2,2,2,1,1}, Tab[8]={2,3,5,4,2,4,6,6}, taille=6. Le graphe sera:

GRaph teste(int taille, int tab[], int Tab[]){ GRaph G=NULL; srand(time(NULL)); int i=0,k=0,j; int ta[taille-1]; int cap[taille-1]; for(i=0;i<taille-1;i++) { ta[i]=i+2; cap[i]=rand()%30; } for(i=0;i<taille-1;i++) { CHaine H=NULL; int ti[tab[i]]; for(j=0;j<tab[i];j++) { ti[j]=Tab[k]; k++; } H=createChaine(tab[i],ti,cap,0); G=ajoute(G,H,i+1); } G=ajoute(G,NULL,taille); return G; }

2 Chemin Augmentant

Dans cette partie on va présenter la methode qui sert à trouver le chemin augmentant . L’algorithme de parcours par largeure

nous donne ce chemin avec la condition principale l’algorithme d’edmonds-Karp c-à-d le chemin suivant est le plus petit en

nombre d‘arcs5 .

2.1 Méthode de Marquage

Dans l’algorithme d’Edmond-Karp le marquage est utilisé pour stocker le chemin choisi dans le parcous dans un table pre[s] .

On va marquer tout les adjacents v∈d (u) par la valeur du sommet . pre[x] est le predecesseur de x , donc si on démarre un

int x avec le puit p et on incremente x par pre[x] l’ indice x terminera avec la valeur du source s . Ce dernier va parcourir

éxactement le chemin que la fonction parcours détermine .

5 Thomas H. Cormen, Cliôrd Stein, Ronald L. Rivest, and Charles E. Leiserson. Introduction à l'algorithmique. Dunod, 2nd edition, 2001.

Page 15: Flot maximal par l'algorithme d'Edmonds-Karp

2.2 Fonction de Parcours

Pour le but de choisir le chemin augmentant en utilusant le parcours par Largeur (voir Pseudo code parcours) .

165 int parcour(GRaph G, int p[], int S) La fonction parcour() prend comme paramètres : GRaph G un pointeur sur notre graph , int p[] un tableau qui stocker les predecesseurs des sommets ∈ au chemin choisi , int S le nombre des sommets pour utiliser comme la taille de tableau p[].

166 {167 File Q=NULL; On déclare un file Q pour stocker les adjaccents des sommets en cours

168 int i,u;169 for(i=0;i<S;i++)170 {171 p[i]=-1;172 } p est initialisé par -1 c-à-d non marqué

173 Q=enfiler(Q,G->val); On enfiler la source dans la file Q

174 GRaph GH=G; GH est un GHaph auxiliere pour parcourer dans le graphe

175 while(Q!=NULL) 176 {177178 Q=extraire(Q,&u); La fonction extraire6 défile Q aprés avoir stocker la valeur defilé dans u

181 GH=search(G,u); La fonction search cherche dans le graphe G la valeur u et pointer GH sur la case de valeur u

183 CHaine H=G->adj; H est la chaine des adjacents de u.

187 int n=taillecChaine(H); La fonction taillecChaine donne la taille de la liste chainée H

190 for(i=0;i<n;i++)191 {192 if(H!=NULL && H->capacity>0 && p[(H->valeur)-1]==-1)193 { La condition H->capacity>0 détermine si l’arête est saturé ou non , p[(H->valeur)-1]==-1 il faut que v n’est pas encore visiter .

194 p[(H->valeur)-1]=GH->val; On marque v par u (sont prédécesseure).

6

Page 16: Flot maximal par l'algorithme d'Edmonds-Karp

195 Q=enfiler(Q,H->valeur);200 if((H->valeur)==S)201 {202 return 0;203 } Si on arrive à p la fonction retourner 0 , Notre chemin est trouvé !

206 }207 H=H->suivant; Incrémenter H pour passer à l’adjacents suivant

208 }209 }210 return 1; Retourner 1 si on ne peut pas arriver au puits211 }

2.3 Exemple de Parcours

Soit le graph suivant : S={S,A,B,P}

On n’a pour tout les arêtes c(u)>0 (le premier parcours)

Et aussi p(u)=-1 (le premier parcours)

La fonction recoit G un pointeur sur s

s enfilé dans Q et on entre dans la 1er while, Puis s est

defilé après avoir stocker dans u alors u=s

Les adjacents de s sont enfilés dans Q

Q= {A,B}

P[A]=S P[B]=S

U=A depiler Q Q= {A,B}

Empilé P Q= {B}

P[P]=A

v=P alors retourne 1

Donc on obtient notre chemin depuis le tableau P[] S → A → P

Exemple de programme de parcours

Page 17: Flot maximal par l'algorithme d'Edmonds-Karp

3 L’algorithme d’augmentation de

flot :

La particularité de l’algorithme d’augmentation de flot, est de toujours choisir un chemin acceptable déjà fournie par l’algorithme du parcours de graphe, dont la longueur (en nombre d'arêtes) est minimale, faire un retour en ariére depuis le puits jusqu’à la source et dés que la capacité minimale est trouvée, son débit est ajoutée à f et parallèlement, les capacités c du graphe sont mises à jour. Dans cette algorithme on aura besoin de trois fonctions, qu’on a choisit les détaillés séparément.

La fonction GRaph search :GRaph search(GRaph G,int valeur){ GRaph aux=G; while(aux!=NULL) { if(aux->val==valeur) { return aux; } aux=aux->suiv; } return NULL; }

La fonction GRaph search aura comme paramètres d’entrée la valeur recherchée int valeur et le pointeur initial de la liste chainée GRaph G. Cette fonction a pour but de chercher une valeur précise dans une liste chainée appelée GRaph composée de tous les sommets du graphe, elle parcoure toute la liste jusqu’à trouver la valeur recherché puis elle retourne son pointeur, sinon elle retourne la valeur NULL.

La fonction  searchChaine :CHaine searchChaine(CHaine C, int n){ if(C==NULL) { return NULL;

Page 18: Flot maximal par l'algorithme d'Edmonds-Karp

} CHaine aux=C; while(aux != NULL) { if(aux->valeur == n) { return aux; } aux=aux->suivant; } return NULL; } La fonction searchChaine aura comme paramètres d’entrée la valeur recherchée int valeur et le pointeur de la liste chainée CHaine C. Cette fonction va nous permettre de trouver une valeur précise dans une liste chainée appelée CHaine composée de tous les sommets adjacents d’un sommet déjà déterminé. Elle parcoure toute la liste en commençant du pointeur initial C jusqu’à trouver la valeur recherché et retourne son pointeur, sinon elle retourne la valeur NULL.

La fonction Min :int Min(int m1,int m2) { if (m1<m2) return m1; else return m2; }

Cette fonction a comme paramètres d’entrées deux valeurs m1 et m2 de types entiers, son but est de les comparer et retourner la valeur du plus minimale.

3.1 Démarrage de l’Algorithme L’algorithme d’augmentation du flot sera composé de deux principales étapes, la première consiste à trouver la capacité la plus minimale m le long d’un chemin, et pour la deuxième sera la mise à jour des capacités et des flots de tous les arcs qui composent ce chemin. Dans c’est deux étapes, on aura recours aux variables suivants :

m : la valeur de la capacité minimale. U :un pointeur initialement pointé sur le puits Uaug : un pointeur initialement pointé sur le puits GH :pointeur sur le prédécesseur de U H : pointeur sur la liste des adjacents de GH

3.2 La recherche de la capacité minimale :

Pour faire cette recherche, on a tout d’abord initialisé la capacité minimale m à l’infini et on a pointé le pointeur U premièrement sur le puits.

int m=99999;GRaph U=search(g,6);

Page 19: Flot maximal par l'algorithme d'Edmonds-Karp

Puis on a utilisé une boucle while() qui se répète tant qu’on a pas encore trouver la source qui a pour valeur 1. La boucle While va permettre de faire une recherche en arrière en largeur à partir du puits pour obtenir les capacités des arcs qui composent ce chemin. La fonction GRaph search déjà mentionné au début va nous aider à chaque fois de trouver le prédécesseur GH du sommet U->val. La fonction  searchChaine a pour but de chercher la position de U dans la liste des adjacents de GH .

Après chaque itération on compare la valeur de la capacité d’un arc avec m à l’aide de la fonction min, on conserve la valeur la plus minimale et pour finir cette, étape on incrémente à U la valeur GH pour mettre à jour la boucle While().

while(U->val!=1) {

GRaph GH=search(g,pre[U->val-1]); CHaine H=searchChaine(GH->adj,U->val); m=Min(m,H->capacity); U=GH; //Incrementation de sommet/graph H }

3.3 La mise à jour des capacités et des flots : Maintenant qu’on a trouvé la capacité minimale d’un chemin, on doit l’ajouter à la valeur du flot des arcs qui composent ce chemin, et aussi trancher cette valeur de toutes les capacités. Pour faire cette étape on doit avant tout initialiser le nouveau pointeur Uaug sur le puits :

GRaph Uaug=search(g,6);

Puis utiliser une boucle while() qui se répète tant qu’on a pas encore trouvé la valeur de la source qui égale à 1. La fonction GRaph search va nous permettre à chaque fois de trouver le prédécesseur GH du sommet Uaug->val.

D’autre part, le pointeur H va être utilisé pour pointer sur la valeur Uaug dans la liste des adjacents de GH à l’aide de la fonction CHaine H.

Maintenant qu’on a détecté le prédécesseur de Uaug, on va augmenter le flot et diminuer la capacité de l’arc qui relie GH avec Uaug dans un même temps :

Cette boucle sera répétée tant de fois jusqu’à retrouver la source.

GRaph Uaug=search(g,6); while(Uaug->val!=1) { GRaph GH=search(g,pre[Uaug->val-1]); // pointer GH sur predecesseure de U CHaine H=searchChaine(GH->adj,Uaug->val); // pointer H sur le list des adjacents de GH

Page 20: Flot maximal par l'algorithme d'Edmonds-Karp

H->flot+=m; H->capacity-=m; Uaug=GH; }

4 Exemple d’exécution

Page 21: Flot maximal par l'algorithme d'Edmonds-Karp

Conclusion Le bilan est que nous avons atteint présquement les objectifs fixés en début de projet. Pour conclure, on peut dire que ce projet à été particulièrement intéressant. D’un point de vue pédagogique, le fait de devoir créer un logiciel nous a permis de comprendre encore mieux le fonctionnement de l’algorithme de flot maximum. En ce qui concerne l’aspect programmation, même s’il ne s’agit pas du but principal, il s’avère que ce projet nous a permis de mettre en application un certain nombre de connaissances apprises dans des semestres précédentes y compris la programmation en langage C.