• Aucun résultat trouvé

Partie II Exposés scientifiques détaillés 45

3.4 Modélisation du problème par décomposition de Benders

L’algorithme 1 présente le pseudo-code de la contrainte pour intégrer l’ordonnançabilité. Il commence par vérifier l’ordonnançabilité de l’extension du placement partiel (ligne 2). Cela est facilement réalisable en calculant le pire temps de réponse des seules tâches déjà allouées. Si l’allocation est ordonnançable, l’algortihme de filtrage supprime les valeurs inconsistantes (ligne 3 à 14) en testant l’ordonnançabilité de chaque valeur de toutes les variables restantes (ligne 8). L’élagage est ainsi propagé à travers l’ensemble des contraintes jusqu’à atteindre un point fixe (boucle while).

Algorithme 1 Algorithme de filtrage de la contrainte globale pour le placement (xi = p)

1: procédure Global constraint(a0 ← a + (xi = p)))

2: flag := checkSchedulability(a0) . flag devient vraie si a0 est ordonnançable

3: tant que flag faire

4: flag := false

5: pour each unallocated task j faire

6: pour each q in xj’s domain faire

7: a00 := a0+ (xj = q)

8: si not checkSchedulability(a00) alors

9: Remove q from domain of xj . Propagation aux autres contraintes

10: flag := true

11: fin si

12: fin pour

13: fin pour

14: fin tant que

15: fin procédure

Pour réduire le nombre d’appels à checkSchedulability et ainsi réduire le nombre de calculs de pire temps de réponse, il est possible de pré-calculer des règles de dominance entre les tâches :

Propriété 3.3.2. Si xi = pkrend la tâche i non-ordonnançable, alors k peut être supprimé du domaine des variables xj telles que πj < πi∧ ej ≥ ei∧ pj ≤ pi.

Propriété 3.3.3. Si xi = pkrend la tâche b non-ordonnançable, alors k peut être supprimé du domaine des variables xj telles que πj > πb∧ ej ≥ ei∧ pj ≤ pi.

De plus, le fonctionnement de notre algorithme de filtrage — il est important de garder en mémoire que pour un placement partiel ordonnançable a et son extension a0 ← a + (xi =

p) — seule l’ordonnançabilité des tâches placées sur p qui ont une priorité inférieure

ou égale à celle de la tâche i doit être testée. Cela réduit grandement la complexité de checkSchedulability et accroit l’efficacité de la contrainte.

3.4 Modélisation du problème par décomposition de

Ben-ders

La méthode proposée dans cette partie s’inscrit dans le cadre de la théorie Logic-Based

Benders Decomposition développée par Hooker et Ottoson (2003) dans laquelle un

pro-blème linéaire est décomposé suivant ses variables en un propro-blème maître et un propro-blème esclave. Les deux sous-problèmes sont ainsi simplifiés et découplés en problèmes plus pe-tits et donc potentiellement plus facile à traiter. Un mécanisme d’apprentissage permet ensuite de faire coopérer ces deux sous-problèmes. Dans le cadre de la décomposition de

Benders, l’apprentissage tire profit de la linéarité du problème esclave par l’intermédiaire de la résolution de son dual. À partie de cette résolution, des coupes sont produites sur le domaine de recherche du problème maître.

Les travaux de Hooker se placent dans un cadre plus général que la décomposition de Benders. Pour cela, il élargit la notion de dual à la logique en introduisant des inferences

duales pour tout type de problème. La dualité se réfère alors à la capacité de produire la

preuve logique de l’optimalité du problème esclave et de la validité de la coupe fournie. Dans le contexte d’un sous-problème discret de satisfaction de contraintes, qui est le nôtre, la preuve est celle de l’infaisabilité du sous-problème. Notre approche se situe dans ce cadre avec le problème de l’ordonnançabilité considéré comme un sous-problème logique et permettant ainsi d’intégrer la programmation par contraintes dans un schéma de dé-composition de type Benders (Thorsteinsson, 2001; Benoist et al., 2002). La formalisation de la résolution passe ensuite par la définition des coupes que nous pouvons fournir au problème maître.

La décomposition de notre problème est faite selon ses contraintes (placement et ressources d’une part, temporelles d’autre part) sans partitionnement explicite des variables. La fi-gure 3.1 illustre la stratégie que nous adoptons. Elle consiste à rechercher un placement admissible pour le problème maître à l’aide de la ppc puis à soumettre la solution trouvée à un test d’ordonnançabilité. Le problème esclave vérifie l’ordonnançabilité du placement et en cas de preuve de son infaisabilité retourne un ensemble de contraintes symboliques et d’inégalités arithmétiques (les coupes) qui identifient pourquoi cette allocation n’est pas ordonnançable et qui servent à éliminer toutes les solutions du problème maître qui partagent ces caractéristiques. Ensuite, une nouvelle solution du problème maître est re-cherchée et soumise au test d’ordonnançabilité, et ainsi de suite.

Esclave

Expression et mod´elisation

sous les contraintes de placement et de ressource Recherche d’une solution valide

Ajout du nogood au probl`eme initial

La solution est valide coupes Test d’ordonnan¸cabilit´e

de la solution produite Maˆıtre

du probl`eme

Figure 3.1 – Représentation schématique de la résolution du problème de placement L’efficacité de la résolution du problème global (recherche d’une solution valide) dépend fortement de la manière dont les problèmes coopèrent. Pour cela, nous devons retourner des coupes pertinentes pour le problème maître, mais aussi mettre en œuvre d’autres mécanismes pour améliorer la recherche : re-modélisation du problème, heuristiques de but, etc.

L’ajout de nouvelles contraintes au problème maître suite à un test d’ordonnançabilité est mise en œuvre par l’utilisation d’explications (Jussien, 2001). Une explication est un ensemble de contraintes C0 (sous-ensemble des contraintes originelles du problème initial) et d’un ensemble de décisions prises pendant la recherche (la décision i sera notée dci),

3.4. Modélisation du problème par décomposition de Benders 53

permettant ainsi d’en garder la trace. Par exemple, l’explication de pourquoi la valeur a de la variable v a été retirée suite à des décisions dci, s’écrit :

C0∧ dc1∧ dc2· · · ∧ dck⇒ v 6= a

Une contradiction survient lorsque le domaine d’une variable x se vide, ce qui est équi-valent à ne trouver aucune solution au problème. L’explication de cette contradiction est calculée par l’union de toutes les explications de chaque valeur de x. Dans le cas d’une contradiction, les algorithmes de backtrack classiques remettent en question la décision prise sur la variable précédente de x. Avec des explications, des algorithmes intelligents de

backtrack peuvent être envisagés, permettant ainsi de revenir sur le choix d’une décision

antérieure qui est la cause de la contradiction. Ainsi, en conservant les explications, il est possible de mettre en œuvre un mécanisme d’apprentissage par l’échec.

Dans le cadre de notre problème, si à la suite de la production d’une coupe par le pro-blème esclave et à la propagation de cette contrainte, nous obtenons une contradiction. L’explication de cette contradiction permet alors de savoir quelles décisions sont la cause de la contradiction et ainsi de revenir directement dessus. Si plusieurs décisions en sont la cause, pour conserver la complétude de la méthode, il faut revenir sur la dernière décision prise.

Lorsqu’un placement partiel est produit par le problème maître, la condition sur le pire temps de réponse est vérifiée pour l’ensemble des tâches. Si une tâche est trouvée non ordonnançable, nous identifions un sous-ensemble de tâches pour lesquelles nous sommes certain que la tâche non ordonnançable le restera quel que soit le placement des autres tâches. Pour une tâche i non ordonnançable pour un placement a, ce sous-ensemble est constitué de la tâche i et des tâches appartenant à hp(i, a). En effet, si pour un placement

a0, nous avons hp(i, a) ⊆ hp(i, a0) alors la tâche i n’est pas ordonnançable pour le placement

a0. Nous pouvons donc interdire toutes les solutions du problème maître produisant ce sous-ensemble.

La propriété « il faut interdire qu’une tâche non-ordonnançable et les tâches plus priori-taires qu’elle sur le même processeur soient de nouveau placées sur un même processeur » se traduit par une contrainte de type NotAllEqual sur les variables xj (il ne faut pas que les xj soient tous égaux) :

NotAllEqual{xj|tj ∈ hp(i, a) ∪ {ti}} (3.3)

Pour éviter d’avoir une accumulation de coupes inutiles qui entraînerait des surcoûts tem-porels pendant la résolution du problème maître, nous vérifions que des ensembles de contraintes ne sont pas inclus dans d’autres ensembles. Il est alors possible de rechercher une contrainte plus forte que celle de l’équation 3.3. Pour cela, nous recherchons un sous-ensemble minimal de hp(i, a) tel que la tâche i soit toujours non-ordonnançable. Pour ce faire nous nous sommes inspiré de l’algorithme QuickXplain (Junker, 2001) qui re-cherche un ensemble minimal de contraintes pour des problèmes linéaires. Pour cela, nous définissons pour une tâche i et un ensemble X de tâches plus prioritaires qu’elle, Ri(X) le pire temps de réponse de la tâche i en présence des tâches de X :

Ri(X) = ei+ X j∈X & Ri pj ' ej (3.4)

et nous recherchons l’ensemble de tâches minimal X tel que X ⊂ hp(i, a) et Ri(X) > pi. L’algorithme 2 décrit le principe exposé ci-avant. La recherche de tous les sous-ensembles

minimaux n’a pas de solution algorithmique simple et est coûteuse en temps de calcul, ce qui peut pénaliser la recherche d’un placement valide. De plus, surcharger le problème d’ad-missibilité par de nombreuses contraintes est aussi coûteux en temps de calcul. En effet, suite à une nouvelle prise de décision, l’ensemble des contraintes doit être propagé. Il est donc préférable de limiter le nombre de contraintes et de guider efficacement la recherche de solution, plutôt que d’apprendre beaucoup de nouvelles contraintes qui apportent peu d’information pour la résolution du problème.

Algorithme 2 Algorithme de type QuickXplain dédié à la recherche d’un ensemble mi-nimal de tâches non-ordonnançable

1: procédure QuickXPlainTask(i, a)

2: X := ∅ . phase d’initialisation

3: σ1, ..., σ#hp(i,a) une énumération de hp(i, a)

4: tant que Ri(X)6 pi faire

5: k := 0

6: Y := X

7: tant que Ri(Y )6 Ti et k < #hp(i, a) faire

8: k := k + 1

9: Y := Y ∪ {σk}

10: fin tant que

11: X := X ∪ {σk}

12: fin tant que

13: retourne X := X ∪ {σk}

14: fin procédure