Rapport de programmation par contraintes Rapport de programmation par contraintes Implémentation d’un problème d’emploi du temps Pascal Brunot Hadrien Cambazard Page 1 / 4 Rapport de programmation par contraintes Nous avions retenu dans la première étape, 3 modélisations qui nous semblaient pertinentes dont nous rappelons ici simplement la teneur pour pouvoir en discuter. Nous essayerons de présenter notre démarche, les conclusions auxquelles nous sommes parvenues et les résultats concrets. Modélisation 1 i [1, Nc], salle i : [1..Ns] creneaui : [1..45] Modélisation 2 (i, j ) [1,45] [1, Ns], coursij : [1..Nc] Modélisation 3 i [1, Nc], coursi : [1..45 Ns] Par ailleurs, nous avons beaucoup travaillé sur l’aspect de pré-traitement des données, qui visent à établir la liste des salles possibles par cours de manière à réduire très rapidement les domaines des variables. Nous disposons pour la modélisation de tableaux pour accéder rapidement aux différentes informations utilises (listes des cours par étudiant, liste des étudiants par cours…). La modélisation 1 n’est pas satisfaisante vis-à-vis de la contrainte 3 (un seul cours par salle, à chaque créneau horaire) qui prend la forme d’un allDifferent sur des expressions uniques associées à chaque couple (créneau, salle). On peut trouver une solution pour environ une centaine de cours mais pas au delà . Nous l’avons implémentée en Choco (cf. pbEDT1.cl). Les modélisations 1 et 2 sont « symétriques ». Tandis que la première associe un créneau et une salle à chaque cours, la deuxième place les cours dans chaque couple (créneau, salle) d’un tableau Ns x Nc (on a donc besoin d’un cours fictif, le cours 0, ce qui empêche l’utilisation du allDifferent). Néanmoins la modélisation 2 nous semblait plus prometteuse car la contrainte 3 s’exprime simplement à l’aide d’un occur. Nous avons constaté que cette approche n’était également pas viable, on ne parvient pas à trouver des solutions même en ne posant que les contraintes 2 et 3. (cf. pbEDT2.cl) La contrainte occur semble plus difficile à mettre en œuvre que le allDifferent. Pour pouvoir exprimer facilement la contrainte 3 nous nous sommes tournés vers une modélisation que nous avions identifiée dans « autres modélisations envisagées » dans notre premier rapport. Il est possible dans cette 3ème modélisation de trouver une solution aux contraintes 2 et 3 instantanément. En effet la contrainte 3 s’exprime comme un simple allDifferent sur l’ensemble des variables. On peut, pour la contrainte 2, éliminer du domaine de chaque variable (dans une phase de pré calcul) les valeurs dans [1..45xNombre de salles] qui correspondent à des salles impossibles pour ce cours. On obtient immédiatement une solution à ces 2 contraintes, là où la modélisation 2 ne donnait aucun résultat (cf. pbEDT3 .cl). Le problème est de pouvoir exprimer la contrainte 1 sur les élèves car on ne dispose plus de l’information sur les créneaux comme dans la modélisation 1. La modélisation 3 consiste à « fusionner » les deux variables de la modélisation 1. La première modélisation est très adaptée pour la contrainte n°1 (concernant les Page 2 / 4 Rapport de programmation par contraintes cours d’un même élève) et la 3ème modélisation pour la contrainte n°3. Nous avons donc envisagé de mélanger ces modélisations pour conserver l’information qui permet d’exprimer ces 2 contraintes. On relie ainsi par des contraintes les variables des deux modélisations pour les faire correspondre à une même solution. Cette approche « hybride » (cf. pbEDT3bis.cl) ne donne pas plus de résultats ! Par ailleurs nous n’avons pas réussi à coder cette contrainte 1 en Choco. (l’utilisation de table bidimensionnelles reste un mystère, nous souhaitions en effet utiliser getNth(table,i,j) mais nous n’avons jamais pu créer de table qui soit ) Nous avons alors décider d’implémenter cette modélisation 3 sous JSolver qui permet notamment l’utilisation des contraintes arithmétiques utilisant l’opérateur de division entière (ce que ne fait pas Choco) on peut ainsi retrouver le créneau de chaque cours et poser des allDifferent sur les créneaux des cours suivis par un même élève (sans passer par une modélisation « hybride » comme envisagée précédemment, ni introduire aucune variable intermédiaire - cf. EdtProbleme3.java). C’est finalement en changeant l’heuristique de choix des variables à instancier que nous avons fini par obtenir une solution ! Ainsi, au lieu d’instancier les variables dans l’ordre de leur numérotation, nous avons imposé d’instancier la variable de plus petit domaine d’abord (ce qui n’était pas la méthode par défaut !). Ainsi tout notre travail précédent sur le traitement des données a pris son intérêt quand nous avons enfin obtenu une solution. En ce qui concerne l’optimisation, nous sommes parvenus à implémenter la contrainte 4 (éviter qu’un étudiant ait un cours au dernier créneau de la journée). La contrainte 5 a été implémentée et fonctionne sur moins de 10 élèves. Au delà, il se pose un problème de mémoire. De ce fait nous n’avons pas cherché à implémenter la contrainte 6. Voici les résultats obtenus : Instances 1 2 3 4 5 6 7 8 9 10 Temps (seconde) Heuristique de recherche Nombre de backtracks Note (pénalité 1) Note globale 21’ 50’ 177’ 27’ 25’ 13’ 595’ 47’ 74’ (1) (1) (1) (2) (1) (1) (1) (1) (1) (2) (3) Page 3 / 4 (1) 4015 15571 109815 4278 4185 1094 229927 12052 / 11772 248 249 204 433 777 743 727 1177 1416 1213 452 416 0 309 / 219 1086 979 / 766 instanciation des variables dont les domaines sont de taille minimum d’abord (définie en standard dans JSolver) instanciation des variables sur lesquelles portent sur le plus de contraintes (pour provoquer des backtracks au plus tôt) et pondéré par les domaines de taille minimum. (cf. HeuristiquePerso.java) Choix de la valeur de la variable qui place le cours dans les derniers créneaux. (cf. HeuristiquePerso2.java). N’apporte rien de concluant. Rapport de programmation par contraintes Remarques sur les champs du tableau : - Deux heuristiques de choix sont possibles, on peut orienter le choix des variables à instancier ((1) et (2)) mais aussi la valeur choisie dans les domaines (3) (cette heuristique entraîne une diminution de la note plus qu’autre chose). - La note sur la pénalité 1 est la note minimale que nous sommes parvenue à trouver (en optimisant selon cette contrainte) - La note globale est la note évaluée à la découverte d’une solution (elle n’est pas codée en tant que contraintes et n’est donc pas utilisé pour orienter la recherche) On relance en revanche la recherche jusqu'à obtenir une note minimale sur laquelle le temps de résolution devient « infini ». Nous avons ici simplement cherché à connaître la note minimale que nous pouvions raisonnablement atteindre. Nous avons observé qu’une recherche non guidée vers les meilleures solutions (« au hasard ») ne permet pas d’améliorer le score des solutions. Conclusion : La modélisation 3 nous semble effectivement la meilleure, mais tout dépend du parcours dans l’arbre (On remarque par exemple que nous ne parvenons pas résoudre l’instance 1 en utilisant l’heuristique 2). Le problème est donc très complexe, on ne peut pas se permettre de tout explorer, il faut orienter la recherche et ceci, éventuellement, pour chaque instance. Ainsi nous ne sommes pas parvenu à trouver une solution pour l’instance 9. Voies d’amélioration de notre modèle : - - - Page 4 / 4 Guider mieux la recherche des solutions en implémentant d’une manière plus économe en mémoire les contraintes de préférences 2 (qui marche pour les dix premiers élèves environs) et la contrainte 3. Cela pourrait être fait en simplifiant la fonction IloIntExpr kronecker(IloIntExpr,int). Trouver les critères (cours différents/étudiants ? cours/salles ? ) capables de nous indiquer une heuristique à utiliser (métaheuristique). Utiliser une heuristique de choix des valeurs des variables qui implémenterait une évaluation « partielle » de la solution. Nous avons manqué de temps pour la réaliser.