• Aucun résultat trouvé

Structure de l’algorithme parall`ele du “Branch and Cut”

Pool contrainte de Pool de contrainte Solveur n Solveur 1

...

Initialise le programme local local

Maintient la liste des noeuds

FIG. 6.2 – Structure de l’algorithme parall`ele du “Branch and Cut”

de nœuds. Le nombre de processus utilis´e lors de la parall´elisation du “Branch and Cut” reste assez petit. Les risques de goulot d’´etranglement autour d’un pro-cessus maˆıtre sont moindres `a cause de l’espacement des requˆetes des propro-cessus solveurs.

Dans notre impl´ementation, nous utilisons une architecture centralis´ee type maˆıtre-esclave qui g`ere la construction et le parcours de l’arbre du “Branch and Cut”. La figure 6.2 montre la structure de notre algorithme. Nous d´efinissons dans la suite les fonctionnalit´es des processus maˆıtre et esclaves.

Le processus maˆıtre

Le processus maˆıtre initialise le calcul, g`ere le parcours de l’arbre du “Branch and Cut” et le partage du travail entre les processus solveurs. Il maintient aussi la valeur de la borne sup´erieure. Et g`ere la terminaison de l’algorithme.

Les processus solveurs

Le processus solveur s’occupe de l’´evaluation du nœud de l’arbre qui lui est affect´e. Il s´electionne la contrainte ou la variable de branchement. Il g´en`ere des nouveaux nœuds fils, les ´evalue puis les communique au processus maˆıtre. Quand le solveur ne poss`ede plus de nœud `a traiter, il envoie une requˆete au maˆıtre pour lui demander du travail. L’´evaluation d’un nœud de l’arbre est effectu´ee comme l’indique l’algorithme 4.

Dans notre algorithme s´equentiel nous utilisons un pool de contraintes pour g´en´erer des contraintes viol´ees par la solution courante du programme lin´eaire. Cette technique de s´eparation permet de g´en´erer facilement des contraintes sans passer par des heuristiques, tr`es coˆuteuses en temps de calcul. Dans notre impl´e-mentation parall`ele, nous utilisons des pools locaux de contraintes, au lieu d’un pool unique centralis´e. En effet sachant que la g´en´eration de contraintes par le pool est assez fr´equente, cr´eer un pool centralis´e induit des goulots d’´etrangle-ment in´evitables autour du processus qui s’occupe de gestion du pool (en g´en´eral, ce rˆole est affect´e au processus maˆıtre).

D’autre part, pour ´eviter la redondance de contraintes dans le programme li-n´eaire qui induit sa d´eg´en´erescence, on v´erifie si une contrainte voulant entrer dans le pool, n’y est pas d´ej`a. Ainsi le travail du processeur g´erant le pool centra-lis´e augmente consid´erablement puisqu’il doit s’occuper de l’ajoˆut de nouvelles contraintes arrivant des processus esclaves, de la v´erification de la non-redondance des contraintes et de la recherche de contraintes viol´ees par des solutions courantes des processus esclaves. D’o`u l’intˆeret de l’utilisation de pools locaux. On a pr´evu dans notre impl´ementation la possibilit´e d’´echanges de contraintes entre les pools locaux pour celles qui sont tr`es difficiles `a g´en´erer et dont le degr´e de violation par une solution fractionnaire est tr`es grand.

Une autre structure possible du contrˆole de la recherche arborescente consiste `a utiliser une organisation hi´erarchique de l’algorithme parall`ele. Donc outre les

6.2 Contrˆole de la recherche arborescente 93

Algorithme 4 Evaluation d’un noeud de l’arbre du Branch and Cut Continuer, nbcontr

= 1

;

Tant que (Continuer) faire

Tant que (nbcontr et vallp

<

bsg et pas-d’essoufflement()) faire

Tant que (nbcontr) faire Tant que (nbcontr) faire

R´esoudre le programme lin´eaire;

Tant que (nbsoustour = rechercher-des-sous-tour()) faire Ajouter les contraintes de sous-tour au programme lin´eaire; R´esoudre le programme lin´eaire;

Fin Tant que /* boucle sous-tour */ Si la solution est un tour alors

Mettre `a jour la valeur de la borne sup´erieure bsg; Exit;

Fin Si

nbcontr = rechercher-des-contraintes-viol´ees-dans-le-pool(); Fin Tant que /* boucle sous-tour + pool */

Si moment-du-pricing alors nouvelles-variables = pricing() ; Si nouvelles-variables alors nbcontr = rechercher-des-contraintes-viol´ees-dans-le-pool() ; Fin Si Fin Si

Fin Tant que /* boucle sous-tour + pool + pricing */ Elaguer-le-programme-lin´eaire() ;

nbcontr = Rechercher-des-contraintes-par-les-heuristiques(); Fin Tant que /* boucle recherche de contrainte */

nouvelles-variables = pricing(); /* pricing avant branchement */ Si nouvelles-variable

= 0

alors

Continuer = 0 ; Fin Si

processeurs maˆıtre et esclaves, on cr´ee des processeurs auxiliaires pour chaque processeur esclave. Les processeurs auxiliaires s’occupent de la g´en´eration des contraintes par diff´erentes m´ethodes ou de la recherche de la borne sup´erieure... Dans notre parall´elisation, cela permet par exemple, de rechercher des contraintes viol´ees par le pool et par les heuristiques de s´eparation en parall`ele en utilisant des processeurs diff´erents.

Malheureusement, dans ce type de structure hi´erarchique, l’am´elioration du temps de calcul se fait au d´etriment de l’utilisation effective des processeurs pen-dant la dur´ee totale de l’ex´ecution. Les processeurs passent une bonne partie de la dur´ee de l’ex´ecution `a ne rien faire, puisque les tˆaches qui leur sont affect´ees ne consomment pas beaucoup de temps de calcul par rapport au temps global de l’ex´ecution de l’algorithme (cf. le tableau 7.1). Ce type de strat´egie induit des acc´el´erations m´ediocres.

Un exemple d’impl´ementation avec une structure hi´erarchique est d´ecrit dans la th`ese de Th´eodore K. Ralphs [Ral95]. C’est une parall´elisation d’un code de “Branch and Cut” g´en´erique impl´ement´e pour r´esoudre le probl`eme de tourn´ee de v´ehicules. La structure de l’algorithme du “Branch and Cut” parall`ele est la suivante:

– Master: c’est le processeur maˆıtre, il joue un rˆole annexe dans l’algorithme du “Branch and Cut”. Il g`ere les entr´ees/sorties de l’algorithme, poss`ede toutes les donn´ees de l’instance r´esolue et les distribue selon les demandes des autres processeurs. Il calcule aussi la borne sup´erieure initiale, sauve-garde la meilleure solution et g`ere la terminaison de l’algorithme.

– Tree Manager: il maintient la liste des nœuds actifs. Il les distribue aux pro-cesseurs. Il maintient la valeur de la borne sup´erieure et informe les autres processeurs quand cette valeur change. Notons que ce processeur ne connaˆıt ni le type du probl`eme r´esolu, ni les donn´ees qui le concernent.

– LP Solver: c’est le processeur qui effectue le plus grand effort de calcul parmi tous les autres processeurs. Il r´esout les programmes lin´eaires du nœud courant de l’arbre du “Branch and Cut” et effectue l’op´eration de branchement. Il retourne les nouveaux nœuds au Tree Manager.

– Cut Generator: ce processeur ne s’occupe que de la g´en´eration de contraintes viol´ees par la solution courante du programme lin´eaire par les heuristiques de s´eparations.

6.3 Communication et m´emoire 95 – Cut Pool: il maintient dans le pool une liste des contraintes valides. Il g´en`ere des contraintes viol´ees par la solution courante du programme lin´eaire. Et r´eduit p´eriodiquement la taille du pool.

Les d´ependances entre chaque type de processeur sont indiqu´ees dans la figure 6.4. L’auteur rapporte des ex´ecutions sur IBM SP2 `a 16 processeurs. Il utilise la librairie PVM [GBD+

95].

6.3 Communication et m´emoire

Dans un algorithme de “Branch and Cut” parall`ele, la quantit´e et la taille de donn´ees ´echang´ees entre les processus sont importantes. Outre la valeur de la borne sup´erieure, un processus a besoin du programme lin´eaire de son nœud p`ere et la contrainte de branchement pour pouvoir ´evaluer le nœud de l’arbre du “Branch and Cut”. Notons que contrairement `a l’algorithme du “Branch and Bound”, les programmes lin´eaires r´esolus d’un nœud `a l’autre diff`erent consid´e-rablement. D’une part par les contraintes g´en´er´ees au fur et `a mesure de l’explora-tion de l’arbre et d’autre part par les variables du programme lin´eaire form´ee des arˆetes du graphe partiel courant.

En effet, on commence l’ex´ecution de l’algorithme avec un programme li-n´eaire relax´e ´ecrit sur un graphe partiel. On utilise ensuite la m´ethode de g´en´e-ration de colonnes pour ajouter de nouvelles variables dans le graphe partiel et la m´ethode des coupes poly´edrales pour g´en´erer des contraintes viol´ees. Quand on finit l’´evaluation d’un nœud, on doit sauvegarder le programme lin´eaire. Ses lignes repr´esentent l’ensemble des contraintes, et ses colonnes l’ensemble des va-riables. En g´en´eral, les notions de contrainte et de ligne du programme lin´eaire sont ´equivalentes, de mˆeme pour colonne et variable.

Dans notre impl´ementation, une contrainte et une ligne sont des objets diff´e-rents. Une contrainte est stock´ee ind´ependamment du graphe d´efinissant les va-riables courantes. Un nœud poss`ede un ensemble de contraintes actives qui ap-partiennent au programme lin´eaire courant. Quand une contrainte est ajout´ee au programme lin´eaire alors on calcule sa ligne correspondante. Plus pr´ecis´ement une ligne est une repr´esentation de la contrainte associ´ee avec un certain ensemble de variables.

Pour bien comprendre cette diff´erentiation prenons l’exemple des contraintes d’´elimination de sous-tour. Ces contraintes sont d´efinies sur un sous-ensemble

Liste des contraintes prog. linéaire Liste des contraintes de branchement

. . ValLp BBetape Profondeur Noeud Père . Fils Droit Fils Gauche Noeud Père Noeud Père

Liste des variables Fixées