OPC – Utilisation de AbsCon et Sat4j
Transcription
OPC – Utilisation de AbsCon et Sat4j
OPC – Utilisation de AbsCon et Sat4j Résumé Le but de ce TP est d’illustrer l’importance de la modélisation avec un solveur CSP, et de mettre en évidence certaines forces et faiblesses de différentes approches développées dans le laboratoire, au sein des plates-formes AbsCon et Sat4j. La modélisation des problèmes se fera en Java, grâce à AbsCon. Les problèmes seront ensuite exportés au format XCSP 2.1 pour être lisibles par une vaste palette de solveurs. Pour information, et pour vous convaincre de l’importance de la programmation par contraintes dans l’industrie, une Java Specification Request existe depuis mars 2012 pour la programmation par contrainte : la JSR 331. 1 1.1 Utiliser AbsCon et Sat4j Utiliser AbsCon Pour tester AbsCon, téléchargez le fichier abscon.jar depuis http://www.cril.fr/˜lecoutre – onglet Enseignement. Ensuite, dans un terminal, tapez : java -jar abscon.jar En retour, vous obtenez des informations sur le paramétrage possible du solveur. Pour le moment, essayons simplement le solveur sur une instance prédéfinie de nom queens-8.xml au format XCSP (que vous récupérez sur la page citée plus haut). Cela donne java -jar abscon.jar queens-8.xml Pour obtenir toutes les solutions, tapez : java -jar abscon.jar queens-8.xml -s=all Pour obtenir toutes les solutions de manière non verbeuse, tapez : java -jar abscon.jar queens-8.xml -s=all -v=0 1.2 Utiliser Sat4j Pour tester Sat4j, téléchargez le fichier sat4j-cps.jar depuis http://sat4j.ow2.org/. Sat4j lit les instances au format XCSP et le transforme en problème SAT. Il ne s’agit donc pas d’un prouveur CSP qui utilise les techniques présentées en OPC (filtrage, contraintes globales, etc). Pour obtenir une solution du CSP, taper java -jar sat4j-csp.jar queens-8.xml Pour compter le nom de solutions, et afficher la dernière, taper : java -Dall=true -jar sat4j-csp.jar queens-8.xml Pour voir toutes les solutions, taper : java -Dverbose=true -Dall=true -jar sat4j-csp.jar queens-8.xml 1 Le mode verbeux permet aussi de suivre la transformation des instances CSP en SAT : on pourra noter sur certaines instances que le solveur passe plus de temps à traduire le problème en SAT qu’à le résoudre ensuite. Il est possible sur certains exemples de ne pas avoir assez de mémoire. Dans ce cas, il faudra changer les paramètres de la JVM d’Oracle : java -Xms2g -Xmx2g -Dverbose=true -Dall=true -jar sat4j-csp.jar queens-8.xml 2 Modéliser avec AbsCon Pour modéliser un problème avec AbsCon, le plus simple est de procéder comme suit avec Eclipse. 1. Utiliser un ordinateur équipé avec Java SE 7 et Eclipse 2. Lancer et paramétrer Eclipse — Si c’est la première fois qu’Eclipse est exécuté, accepter le répertoire de travail par défaut proposé, et ensuite “Go to Workbench” — Créer un projet Java de nom abscon : — File - New - Java Project — Taper le nom du projet (ici, abscon), puis choisir Next — Dans l’onglet Libraires, choisir “add External Jars” , puis sélectionner abscon.jar 3. Créer une classe Java de nom Test.java dans le répertoire src du projet comme suit : import static ios.inputs.Expr.*; import problem.*; public class Test extends Problem { private Variable x, y; @Override protected void specifyVariables() { x = addVariable("x", range(1, 3)); y = addVariable("y", range(1, 3)); } // nom, valeurMin, valeurMax // nom, valeurMin, valeurMax @Override protected void specifyConstraints() { addConstraint(eq(x, y)); // x = y } } 4. Exécuter le solveur — dans un terminal, en vous plaçant dans le répertoire bin du projet, et en copiant le fichier abscon.jar dans ce même répertoire, vous pouvez taper : java -jar abscon.jar Test — dans un terminal, depuis n’importe quel répertoire, vous pouvez taper : java -cp ˜/workspace/abscon/bin:abscon.jar abscon.Resolution Test — depuis Eclipse, Menu Run Sous-menu Run configurations... Onglet Main Project: abscon Main class: abscon.Resolution Onglet Arguments Program arguments: Test -s=all VM arguments: 2 puis Run Remarque 1 Pour simplifier, par la suite, on écrira toujours java -jar abscon.jar ... quelle que soit la méthode utilisée pour lancer le solveur (telle que décrite ci-dessus). 3 Le problème des reines 1. Le code ci-dessous est à placer dans un fichier de nom Queens.java. import static ios.inputs.Expr.*; import problem.Problem; public class Queens extends Problem { private int nbQueens, model; // parameters private Variable[] queens; // variables @Override protected void specifyParameters() { nbQueens = addParameterInt("Nb queens", 2); // message, minValue model = addParameterInt("Model (1 to 3)", range(1, 3)); // message, minValue, maxValue } @Override protected void specifyVariables() { queens = addVariableArray1D("Q", range(0, nbQueens - 1), nbQueens); } private void model1() { for (int i = 0; i < nbQueens; i++) for (int j = i + 1; j < nbQueens; j++) addConstraint(ne(queens[i], queens[j])); for (int i = 0; i < nbQueens; i++) for (int j = i + 1; j < nbQueens; j++) { int rowDistance = Math.abs(i - j); String colDistance = dist(queens[i], queens[j]); addConstraint(ne(colDistance, rowDistance)); } } @Override protected void specifyConstraints() { switch (model) { case 1: model1(); break; } } } Il est important de noter que pour définir des contraintes en intension, on peut construire des expressions/formules booléennes (prédicats) à l’aide de constantes (entières et booléennes) et des fonctions (opérateurs) décrits par la table 1. 2. Lancer le solveur en mode interactif (il demandera la valeur des paramètres) avec : java -jar abscon.jar Queens Sinon on peut directement les donner en ligne de commande java -jar abscon.jar Queens 8 1 3. Pour obtenir un affichage plus lisible des solutions, redéfinissez la méthode prettySolutionDisplay comme par exemple : 3 Operation Arity Syntax Arithmetic (operands are integers) Opposite 1 neg(x) Absolute Value 1 abs(x) Addition 2 add(x,y) Substraction 2 sub(x,y) multiplication 2 mul(x,y) Integer Division 2 div(x,y) Remainder 2 mod(x,y) Power 2 pow(x,y) Minimum 2 min(x,y) Maximum 2 max(x,y) Semantics -x |x| x+y x-y x*y x div y x mod y xy min(x,y) max(x,y) Relational (operands are integers) Equal to 2 eq(x,y) Different from 2 ne(x,y) Greater than or equal 2 ge(x,y) Greater than 2 gt(x,y) Less than or equal 2 le(x,y) Less than 2 lt(x,y) x x x x x x Logic (operands are Booleans) Logical not 1 Logical and 2 Logical or 2 Logical xor 2 Logical equivalence (iff) 2 not(x) and(x,y) or(x,y) xor(x,y) iff(x,y) ¬x x∧y x∨y x⊕y x⇔y Control Alternative if(x,y,z) value of y if x is true, otherwise value of z 3 = 6= ≥ > ≤ < y y y y y y Table 1 – Opérateurs utilisés pour construire des prédicats @Override public void specifySolutionDisplay() { for (int i = 0; i < nbQueens; i++) { for (int j = 0; j < nbQueens; j++) System.out.print(queens[i].dom.getUniqueValue()==j?"Q":"-"); System.out.println(); } } 4. Noter le temps et le nombre de noeuds nécessaire pour trouver toutes les solutions de l’instance des 12 reines (avec le modèle 1) : java -jar abscon.jar Queens 12 1 -s=all -v=0 5. Intégrer une nouvelle formulation des contraintes (model = 2) où les deux jeux de contraintes sont fusionnés (i.e. les contraintes de même portée sont fusionnées). Tester le nouveau modèle et comparer le temps de résolution ainsi que le nombre de noeuds explorés (pour toutes les solutions de l’instance des 12 reines). 6. Pour le modèle 3, ajouter simplement une contrainte globale redondante (utilisez la méthode addConstraintAllDifferent au modèle précédent. 7. Comparer les 3 modèles en terme de temps d’exécution et du nombre de noeuds explorés lorsque les 14 200 solutions au problème des 12 reines sont recherchées. 4 8. Il existe un format de représentation générique pour les réseaux de contraintes permettant de s’affranchir du codage d’un problème par programmation. Ce format basé sur XML et appelé XCSP 1 décrit précisément les différents composants d’un réseau de contraintes. Il est possible sous AbsCon de sauvegarder un réseau défini par programmation sous ce format. Il suffit d’utiliser une commande telle que : java -jar abscon.jar Queens 12 2 -xo=2 -export Vous obtenez en retour l’affichage de la représentation XCSP du problème sur la sortie standard. Bien sur, vous pouvez la rediriger dans un un nouveau fichier (extension xml obligatoire) comme suit : java -jar abscon.jar Queens 12 2 -xo=2 -export > Queens-12-2.xml Pour lancer la résolution avec AbsCon à partir de ce nouveau fichier, vous n’avez qu’à utiliser une commande telle que : java -jar abscon.jar Queens-12-2.xml L’intérêt ici est que ce format est reconnu par différents solveurs. Générer un fichier xml du problème des 12 reines pour chaque modèle. 9. Comparer les 3 modèles en terme de temps d’exécution et de nombre de conflits pour le prouveur Sat4j. 4 Le problème Sudoku Intégrer le code suivant pour le problème du Sudoku (défini ici pour une grille vierge) : public class Sudoku extends Problem { protected int order; protected Variable[][] matrix; @Override protected void specifyParameters() { order = addParameterInt("order (9 = classical Sudoku)", 2); } @Override protected void specifyVariables() { matrix = addVariableArray2D(range(1, order), order, order); } @Override protected void specifyConstraints() { for (int i = 0; i < order; i++) addConstraintAllDifferent(matrix[i]); // rows for (int i = 0; i < order; i++) addConstraintAllDifferent(Variable.columnOf(matrix, i)); // columns int base = (int) Math.sqrt(order); for (int i = 0; i < order; i += base) for (int j = 0; j < order; j += base) addConstraintAllDifferent(Variable.pieceOf(matrix, i, base, j, base)); // blocks } @Override public void specifySolutionDisplay() { for (int i = 0; i < order; i++) for (int j = 0; j < order; j++) Kit.pr(variables[i * order + j].dom.getUniqueVal() + (j == order - 1 ? "\n" : " ")); } } 1. Voir http://arxiv.org/pdf/0902.2362v1 5 1. Construire une nouvelle classe Sudoku3 pour modéliser l’instance Sudoku suivante : 4 5 3 9 1 4 7 6 8 8 6 1 2 9 2 6 5 6 5 3 1 7 2 4 1 8 7 6 7 3 On pourra utiliser un tableau comme suit : private int[][] hints = { { { 1, 7, 6 }, { 2, 2, 1 2 }, { 3, 5, 9 }, { 3, 5, 5, 3 }, { 5, 6, 1 }, }, { 7, 4, 3 }, { 7, 6, column,value) 0, 1, 4 }, { }, { 2, 5, 2 8, 6 }, { 4, { 5, 8, 7 }, 4 }, { 7, 7, 1, 0, 5 }, { }, { 2, 7, 5 2, 6 }, { 4, { 6, 1, 8 }, 1 }, { 8, 7, 1, 1, 3 }, { 1, 2, 9 }, { }, { 3, 0, 4 }, { 3, 2, 7 6, 5 }, { 5, 0, 8 }, { 5, { 6, 4, 7 }, { 6, 6, 2 }, 7 } }; // triplets of the 1, 5, 1 }, }, { 3, 3, 3, 6 }, { { 7, 1, 6 form (row, 2. La résoudre avec la commande : java -jar abscon.jar Sudoku3 Noter le nombre (et le type) de contraintes du problème ainsi que le nombre de valeurs détruites au préprocessing. 3. La résoudre avec la commande : java -jar abscon.jar Sudoku3 -ugb=no Noter le nombre (et le type) de contraintes du problème ainsi que le nombre de valeurs détruites au préprocessing. Pourquoi est-ce différent ? 4. Utiliser Sat4j pour résoudre ce problème. Noter le nombre et le type de contraintes. 5. Sat4j peut aussi utiliser des contraintes de cardinalité pour coder la contrainte allDiff. java -DallDiffCards=true -jar sat4j-csp.jar sudoku3.xml Noter le nombre et le type de contraintes générées. 6. Ajouter 8 dans la case en position (7, 8). Quelle est la conséquence ? 5 Séries de tous les intervalles Étant données les 12 hauteurs de notes (c, c#, d, ...), représentées par les nombres 0,1,...,11, il faut trouver une série dans laquelle chaque hauteur apparaı̂t exactement une fois et dans laquelle les intervalles musicaux entre les notes voisines couvrent l’ensemble complet des intervalles du mineur second (1 demi-ton) au majeur septième (11 demi-tons). Cela signifie donc que pour chaque intervalle, il existe un couple de hauteurs voisines entre lesquelles l’intervalle apparaı̂t. Le problème de trouver une telle série peut être généralisé comme suit. Étant donné un entier positif n, trouver une séquence s = (s0 , ..., sn−1 ) telle que : 1. s corresponde à une permutation de {0, 1, ..., n − 1} 2. la séquence (des intervalles successifs) v = (|s1 − s0 |, |s2 − s1 |, ...|sn−1 − sn−2 |) corresponde à une permutation de {1, 2, ..., n − 1} 6 Figure 1 – Elliott Carter base ses séries sur les listes générées par Bauer-Mendelberg et Ferentz, et les utilise comme sonorité “tonique” (voir Wikipedia). Une séquence s satisfaisant ces conditions est appelé une série de tous les intervalles de taille n. Par exemple, pour n = 8, une solution est : s = (1,7,0,5,4,2,6,3) puisque cette séquence correspond bien à une permutation de {0, 1, ..., 7} et que : v = (6,7,5,1,2,4,3) correspond bien à une permutation de {1, ..., 7}. Donner le modèle de ce problème sous AbsCon. 6 Les Carrés magiques Un carré magique d’ordre n est un arrangement de n2 nombres dans un carré tel que la somme des valeurs sur chaque ligne, chaque colonne et chaque diagonale (principale) est égale à une même constante. Un carré magique normal contient les entiers de 1 à n2 . Par exemple, voici une solution pour n = 4. 1. Donner le modèle de ce problème sous AbsCon Pour cela, — penser à intégrer un paramètre de type int pour définir l’ordre du carré (à l’aide de la méthode addIntParameter) — penser à calculer à l’aide d’une formule (simple) la valeur à atteindre lorsqu’on somme chaque ligne, colonne, et diagonale. 7 — poster les contraintes de somme en appelant la méthode addConstraintSum 2. Comme pour le problème des reines, rendez plus lisibles les solutions en redéfinissant la méthode specifySolutionDisplay 3. Lancer la résolution pour quelques instances (ordres) du carré magique avec et sans le paramètre -ugc=no 4. Lancer la résolution pour quelques instances (ordres) du carré magique avec et sans le paramètre -rc=10 7 Le tour des cavaliers Le problème du tour du cavalier est de trouver une séquence de mouvements de cavalier (un cavalier peut bouger de 2 cases verticalement et d’une case horizontalement, ou de 2 cases horizontalement et d’une case verticalement) sur un plateau de n sur n cases. Il est nécessaire que : — chaque case soit visitée une et une seule fois — le dernier mouvement permet de revenir sur la case de départ La figure suivante montrer une solution de tour pour n = 8, avec un tour commençant dans le coin supérieur gauche. Créer une classe permettant de modéliser ce problème. Le résoudre à l’aide d’AbsCon et de Sat4j. 0 19 30 27 24 21 34 37 31 28 1 20 33 36 25 22 18 63 32 29 26 23 38 35 41 2 17 62 39 4 13 54 16 61 40 3 14 55 50 11 45 42 15 8 5 12 53 56 60 7 44 47 58 51 10 49 43 46 59 6 9 48 57 52 8