De AC3 à AC7 Christophe Lecoutre — Frédéric Boussemart — Fred Hemery CRIL (Centre de Recherche en Informatique de Lens) CNRS FRE 2499 rue de l’université, SP 16 F-62307 Lens cedex {lecoutre,boussemart,hemery}@cril.univ-artois.fr La consistance d’arc joue un rôle central dans la résolution de Problèmes de Satisfaction de Contraintes (CSPs). Récemment, un même algorithme appelé AC2001 et AC3.1 a été présenté indépendamment par leurs auteurs respectifs. Cet algorithme qui est considéré comme une amélioration de AC3 a l’avantage d’être simple (à implémenter) et compétitif. Cependant, il ne prend pas en compte la bidirectionalité des contraintes comme le fait AC7. Dans ce papier, nous abordons cette question en proposant deux algorithmes appelés AC3.2 et AC3.3 qui bénéficient des bonnes propriétés à la fois de AC3 et de AC7. Plus précisément, AC3.2 est un algorithme général qui exploite partiellement la bidirectionalité des contraintes tandis que AC3.3 est un algorithme binaire qui exploite totalement la bidirectionalité. Néanmoins, lorsque la consistance d’arc est maintenue pendant la recherche d’une solution, MAC3.2 (grâce à un effet de mémoire), s’avère plus efficace que MAC3.3 à la fois en termes de tests de consistance et de temps CPU. Comparé à MAC2001/3.1, nos résultats expérimentaux montrent que MAC3.2 des tests de consistance et, en moyenne, du temps CPU. économise environ RÉSUMÉ. 50% 15% ABSTRACT. Arc consistency plays a central role in solving Constraint Satisfaction Problems. Recently, an algorithm called AC2001 and AC3.1 has been independently presented by their authors. This algorithm which is considered as a refinement of the basic algorithm AC3 has the advantage of being simple (to implement) and competitive. However, it does not take into account constraint bidirectionality as AC7 does. In this paper, we address this issue, and, in particular, introduce two new algorithms called AC3.2 and AC3.3 which benefit from good properties of both AC3 and AC7. More precisely, AC3.2 is a general algorithm which partially exploits bidirectionality whereas AC3.3 is a binary algorithm which fully exploits bidirectionality. It turns out that, when Maintaining Arc Consistency during search, MAC3.2, due to a memorization effect, is more efficient than MAC3.3 both in terms of constraint checks and CPU time. Compared to MAC2001/3.1, our experimental results show that MAC3.2 saves about 50% of constraint checks and, on average, 15% of CPU time. MOTS-CLÉS : problèmes de satisfaction de contraintes, consistance d’arc. KEYWORDS: constraint satisfaction problems, arc consistency. 268 RSTI/hors série. JFPLC 2003. 1. Introduction La consistance d’arc joue un rôle central dans la résolution de Problèmes de Satisfaction de Contraintes (CSPs). En effet, l’algorithme MAC [SAB 94], i.e., l’algorithme qui consiste à maintenir la consistance d’arc au cours de la recherche d’une solution, est considéré comme l’approche générique complète la plus efficace pour résoudre des instances de problèmes larges et difficiles [BES 96]. De nombreux algorithmes ont été proposés pour établir la consistance d’arc. D’un coté, des algorithmes à gros grain tels que AC3 [MAC 77], AC2000 [BES 01], AC2001/3.1 [BES 01, ZHA 01] et AC3d [DON 02] ont été développés ; le principe étant d’appliquer des révisions successives d’arcs, i.e., de couples C; X composés d’une contrainte C et d’une variable X appartenant à l’ensemble des variables de C . Ces algorithmes sont faciles à implémenter et efficaces en pratique. ( ) De l’autre coté, des algorithmes à grain fin tels que AC4 [MOH 86], AC6 [BES 94] et AC7 [BES 99] ont été proposés ; le principe étant d’appliquer des révisions successives de “valeurs”, i.e., de triplets C; X; a composés d’un arc C; X et d’une valeur a appartenant au domaine de X . Ces algorithmes sont plus difficiles à implémenter puisqu’il est nécessaire de gérer des structures de données plus lourdes. Et même si, AC6 et AC7 sont compétitifs vis à vis de AC3 et de AC2001/3.1 dans le contexte d’une phase de pré-traitement, ceci est moins évident dans le contexte d’une recherche de solution puisque maintenir ces structures de données peut s’avérer pénalisant. ( ) ( ) Les algorithmes de consistance d’arc peuvent être caractérisés par un certain nombre de propriétés “désirables” [BES 99]. En particulier, il est intéressant d’exploiter la bidirectionalité des contraintes (appelée multidirectionalité si les contraintes ne sont pas binaires) de manière à éviter des tests de consistance inutiles. La bidirectionalité signifie que si une valeur b d’un domaine d’une variable Xj supporte (est compatible avec) une valeur a du domaine d’une variable Xi par rapport à une contrainte binaire C liant Xi et Xj alors a de Xi supporte également b de Xj . Aussi, si un test de consistance C a; b est réalisé lors de la recherche d’un support pour a, il n’y a nul besoin de réaliser ultérieurement le même test de consistance lors de la recherche d’un support pour b pourvu que ce test de consistance ait été enregistré comme un succès ou comme un échec. On peut parler d’exploitation positive et négative de la bidirectionalité. ( ) Parmi tous les algorithmes cités précédemment, AC7 est le seul qui prenne en compte la bidirectionalité. Dans ce papier, nous proposons d’exploiter la bidirectionalité des contraintes pour les algorithmes à gros grain. Tout d’abord, nous introduisons deux nouveaux algorithmes, appelés AC3.2 et AC3.3, qui peuvent être considérés comme des améliorations de AC2001/3.1. AC3.2 est un algorithme général, i.e., adapté aux problèmes dont les contraintes sont d’arité quelconque, qui exploite partiellement la bidirectionalité positive tandis que AC3.3 est un algorithme binaire, i.e., adapté uniquement aux problèmes dont les contraintes sont binaires, qui exploite totalement la bidirectionalité positive. Algorithmes 269 Ensuite, nous montrons que AC2001/3.1, AC3.2 et AC3.3 peuvent bénéficier de la bidirectionalité négative en concentrant la recherche des supports aux uniques tuples appelés candidats [BES 97]. Il en résulte que AC3.2 et AC3.3 bénéficient des bonnes propriétés de AC3 et de AC7. En effet, AC3.2 et AC3.3 sont simples à implémenter (comme AC3) et tirent un avantage de la bidirectionalité (comme AC7). 2. Préliminaires Dans cette section, nous introduisons quelques définitions utilisées par la suite. Définition 1 Un problème de satisfaction de contraintes (CSP pour Constraint Satisfaction Problem) est un couple X ; C où : ( = ) –X fX1; : : : ; Xn g est un ensemble fini de n variables tel que chaque variable possède un domaine dom Xi représentant l’ensemble des valeurs pouvant être assignées à Xi , –C fC1 ; : : : ; Cm g est un ensemble fini de m contraintes tel que chaque contrainte Cj correspond à une relation rel Cj représentant l’ensemble des tuples autorisés pour les variables vars Cj liées par la contrainte Cj . ( ) Xi = ( ) ( ) ( ) ( ) Sans perte de généralité, nous considérons que tout ensemble de variables vars C associé à une contrainte C est ordonné. Ainsi, il est possible d’obtenir la position e me variable var i; C dans vars C . pos X; C d’une variable X dans vars C et la i On dira qu’une contrainte C lie (ou implique) une variable X ssi X appartient à vars C . L’arité d’une contrainte C est le nombre de variables liées par celle-ci. Une contrainte binaire implique uniquement variables. ( ) ( ) ( ) ( ) 2 Une solution est l’affectation d’une valeur à l’ensemble des variables du problème de telle sorte que chaque contrainte soit satisfaite. Une solution garantit l’existence d’un support dans chaque contrainte. Définition 2 Soit C une contrainte d’arité k , un k -uplet (ou tuple) t est une liste de k valeurs indexée de à k length t et notée ici t ; : : : ; t k . Un tuple t est dit : 1 = () ssi 8 2 1 [ ℄2 ssi 2 ( ), [1℄ ( ( )) [℄ – valide pour C i ::k; t i dom var i; C , – autorisé par C t rel C – un support (courant) de C ssi t est valide et autorisé. ( ) On dit qu’un tuple t est un support de X; a dans C lorsque t est un support de tel que t pos X; C a. Déterminer si un tuple est autorisé par une contrainte s’appelle un test de consistance. Il est important de noter que, en considérant un ordre total sur l’ensemble des domaines, les tuples peuvent être ordonnés en utilisant un ordre lexicographique . C [ ( )℄ = Un CSP est dit satisfiable ssi il admet une solution. Dans la plupart des cas, la propagation de contraintes consiste à éliminer certaines valeurs du domaine des différentes variables, valeurs qui ne peuvent apparaître dans aucune solution. Modifier 270 RSTI/hors série. JFPLC 2003. les domaines d’un problème donné de manière à le rendre arc-consistant nécessite des tests de consistance et aussi, pour certains algorithmes, des tests de validité. Les tests de consistance sont nécessaires pour trouver des (nouveaux) supports tandis que des tests de validité sont utilisés pour déterminer si des (vieux) supports sont encore valides. ( ) Définition 3 Soit P un CSP et X; a un couple composé d’une variable X de P et d’une valeur a 2 dom X . X; a est dit consistant par rapport à une contrainte C de P ssi soit X 62 vars C soit il existe un support de X; a dans C . X; a est dit consistant ssi X; a est consistant par rapport à toutes les contraintes de P . P est arc-consistant ssi tous les couples X; a formés à partir de P sont consistants. ( ( )( ( ) ) ) ( ( ) ( ) ) 3. Propriétés des algorithmes de consistance d’arc De manière à éviter des tests de consistance inutiles, les algorithmes de consistance d’arc peuvent exploiter différentes propriétés. Dans cette section, nous présentons une adaptation des propriétés intéressantes définies dans [BES 99]. () Dans tout algorithme de consistance d’arc, un test de consistance, noté C t , est toujours réalisé pour un tuple t donné et par rapport à un triplet C; X; a où C désigne une contrainte, X une variable de vars C et a une valeur de dom X . Idéalement, les propriétés suivantes devraient être vérifiées par un algorithme de consistance d’arc, étant donné un triplet C; X; a et un tuple t. ( ( ) ( ) () ) ( ) – unidirectionalité positive C t n’est pas testé s’il existe un support t0 de dans C déjà testé avec succès par rapport à C; X; a . – unidirectionalité négative C par rapport à C; X; a . ( ) ( ) ( ) X; a ( ) n’est pas testé s’il a déjà été testé sans succès t () – multidirectionalité positive C t n’est pas testé s’il existe un support t0 de X; a dans C déjà testé avec succès par rapport à un triplet C; Y ; b avec Y 6 X. ( ) () ( ) = – multidirectionalité négative C t n’est pas testé s’il a déjà été testé sans succès par rapport à un triplet C; Y ; b avec Y 6 X . ( ) = Les propriétés énoncées ci-dessus correspondent pour l’essentiel aux propriétés 1, 3a, 2 et 3b de [BES 99]. 4. Algorithmes AC3.X Dans cette section, nous présentons différents algorithmes qui sont basés sur AC3. Ce sont des algorithmes à gros grain notés sous la formes AC3.X. Pour commencer, nous introduisons la procédure principale de tous ces algorithmes et rappelons l’algorithme AC2001/3.1. Nous introduisons ensuite deux algorithmes originaux AC3.2 et AC3.3 qui peuvent être considérés comme des améliorations de AC2001/3.1. Notons que la description de tous les algorithmes ci-dessous (excepté AC3.3) est donnée dans le cadre général de problèmes d’arité quelconque. Algorithmes 271 Algorithme 1 AC3.X 1: Q f(C; X ) j C 2 C ^ X 2 vars(C )g 2: init3.X() 3: while Q 6= ; do 4: pick (C; X ) in Q 5: if revise3.X(C ,X ) then 6: if dom(X ) = ; then return FAILURE 0 0 0 0 7: else Q Q [ f(C ; X ) j X 2 vars(C ) ^ X 8: end if 9: end while 10: return SUCCESS 2 ( vars C 0 )^X = 6 X0 ^ 6= g C C 0 4.1. Action principale des algorithmes AC3.X La structure des algorithmes AC3.X correspond à celle de AC3 [MAC 77]. Tous ces algorithmes nécessitent l’utilisation d’un ensemble, noté Q, permettant de mémoriser les arcs qui doivent être révisés. La révision d’un arc C; X consiste à éliminer les valeurs inconsistantes de dom X par rapport à C . ( ( ) ) Voici maintenant une description rapide de l’action principale décrite par l’algorithme 1. Initialement, tous les arcs C; X sont placés dans l’ensemble Q de manière à être révisés, et un appel à la méthode init3.X permet l’initialisation des structures de données spécifiques aux différentes versions de AC3.X. Ensuite, les arcs sont révisés à tour de rôle, et lorsqu’une révision est effective (au moins, une valeur a été éliminée), l’ensemble Q doit être mis à jour. La révision consiste à éliminer les valeurs de X qui sont devenues inconsistantes par rapport à C . ( ) 4.2. AC2001/3.1 Le même algorithme, vu comme une extension de AC3, et appelé AC2001 par [BES 01] et AC3.1 par [ZHA 01] a été proposé indépendamment par leurs auteurs respectifs. Il y a une différence simple mais importante entre AC3 et AC2001/3.1. En effet, lorsqu’un support doit être trouvé pour une valeur, AC3 commence la recherche à partir du premier tuple tandis que AC2001/3.1 commence la recherche à partir d’un point de reprise qui correspond au dernier support trouvé pour cette valeur. Plus précisément, AC2001/3.1 vérifie la propriété d’unidirectionalité positive et négative. Algorithme 2 init3.1() 8 2C 8 2 C [ ; X ℄ last C; X; a ( ) vars C ; nil 8 2 a ( ) dom X Algorithme 3 revise3.1(in C,X) : int 1: 2: 3: 4: 5: 6: 7: j j nbElements dom(X ) for each a dom(X ) do if last[C; X; a℄ is valid then continue 2 ( [ ℄) seekN extSupport C; X; a; last C; X; a if last[C; X; a℄ = nil then remove a from dom(X ) end for return nbElements = dom(X ) 6 j j 272 RSTI/hors série. JFPLC 2003. Cette approche moins naïve nécessite l’introduction d’une structure de données appelée last. Cette structure de données est un tableau qui permet de stocker le dernier support trouvé pour tout triplet C; X; a composé d’un arc C; X et d’une valeur a appartenant à dom X . Initialement, la structure last doit être initialisée à nil (voir l’algorithme 2). La révision (voir l’algorithme 3) consiste à tester pour toute valeur la validité du dernier support trouvé ( nil n’est pas valide) et à rechercher potentiellement un nouveau support. Il faut noter que seekN extS upport met à jour le paramètre t avec le plus petit support de X; a dans C strictement plus grand que lui ou avec nil (rappelons qu’un test de consistance est noté C t ). ( ( ) ( ) ) ( () ) ( ) AC2001/3.1 admet une complexité spatiale en O md et une complexité temporelle, dans le pire des cas, en O md2 [BES 01, ZHA 01] (même si on considère des contraintes binaires à condition que l’arité des contraintes soit arbitrairement bornée). ( ) 4.3. AC3.2 Pour améliorer le comportement de AC2001/3.1, tout en gardant sa simplicité, il est possible de bénéficier partiellement de la multidirectionalité positive. En particulier, lorsqu’un support est trouvé, celui-ci peut non seulement être exploité par la valeur (triplet) pour laquelle il était cherché mais aussi pour toutes les valeurs qui apparaissent dans le support. De façon à éviter des structures de données trop lourdes, il est possible de mémoriser simplement pour chaque valeur le dernier support externe trouvé, i.e., le dernier support trouvé supportant cette valeur et trouvé lors de la recherche d’un support pour une autre valeur. Par exemple, soit une contrainte binaire C telle que vars C = fXi ; Xj g. Si un support a; b de Xi ; a est trouvé dans C , alors il est enregistré comme étant le dernier support externe de Xj ; b dans C . Si, plus tard, un support ; b de Xi ; est trouvé dans C , alors le dernier support externe de Xj ; b dans C devient ; b . ( ( ) ( ) ( ) ( ) ) ( ) ( ) ( ) Algorithme 4 init3.2() 8 2C 8 2 C [ ; X ℄ ( ) vars C ; 8 2 a [ ( ) ℄ dom X nil ; lastE C; X; a last C; X; a nil Algorithme 5 revise3.2(in C,X) : int 1: 2: 3: 4: 5: 6: 7: 8: 9: j j nbElements dom(X ) for each a dom(X ) do if lastE [C; X; a℄ is valid then continue if last[C; X; a℄ is valid then continue 2 ( [ ℄) seekN extSupport C; X; a; last C; X; a if last[C; X; a℄ = nil then remove a from dom(X ) else for each Y = X vars(C ) do lastE [C; Y; b℄ end for return nbElements = dom(X ) 6 6 j 2 [ ℄ with b = last[C; X; a℄[pos(Y; C )℄ last C; X; a j Ce nouvel algorithme nécessite l’introduction d’une structure de données supplémentaire, notée lastE . Cette structure est un tableau qui permet de stocker la copie du dernier support externe trouvé pour toute valeur (triplet) C; X; a . Initialement, la structure lastE doit être initialisée à nil (voir l’algorithme 4). La révision (voir l’algorithme 5) consiste à tester pour toute valeur la validité du dernier support externe ( ) Algorithmes 273 trouvé (ligne 3) et si, cela échoue, la validité du dernier support trouvé (ligne 4). Si ni l’un ni l’autre ne sont valides alors la recherche d’un nouveau support est entreprise, et en cas de succès, des supports externes sont mis à jour (ligne 7). AC3.2 conserve les complexités spatiales et temporelles de AC3.1. En effet, dans le pire des cas, l’algorithme réalise simplement un test supplémentaire (ligne 3) et un nombre borné d’affectations supplémentaires (ligne 7) par révision de valeur. Et le tableau last a été simplement doublé par un tableau lastE . 4.4. AC3.3 AC3.2 exploite partiellement la multidirectionalité positive. Pour les problèmes binaires, il est possible de concevoir un algorithme simple qui exploite totalement la bidirectionalité positive. Cet algorithme, appelé AC3.3, enregistre simplement pour toute valeur, le nombre de ses supports externes. Aussi, un tableau noté pt est-il introduit pour mémoriser le nombre de supports externes de tout triplet C; X; a . ( ) Algorithme 6 init3.3() 8 2C 8 2 C [ ; X ℄ ( ) vars C ; 8 2 a [ ( ) 0 dom X ℄ nil ; pt C; X; a last C; X; a Algorithme 7 revise3.3(in Ci;j ,Xi ) : int 1: nbElements j dom(Xi ) j 2: for each a 2 dom(Xi ) do 3: if pt[Ci;j ; Xi ; a℄ > 0 then continue 4: if last[Ci;j ; Xi ; a℄ is valid then continue 5: if last[Ci;j ; Xi ; a℄ 6= nil then pt[Ci;j ; Xj ; last[Ci;j ; Xi ; a℄℄ 6: seekN extSupport(Ci;j ; Xi ; a; last[Ci;j ; Xi ; a℄) 7: if last[Ci;j ; Xi ; a℄ = nil then 8: remove a from dom(Xi ) 9: for each Ci;k 2 C j k 6= j do if last[Ci;k ; Xi ; a℄ 6= nil then pt[Ci;k ; Xk ; last[Ci;k ; Xi ; a℄℄ 10: else pt[Ci;j ; Xj ; last[Ci;j ; Xi ; a℄℄ + + 11: end for 12: return nbElements 6=j dom(Xi ) j 0 Après avoir initialisé ces compteurs à (voir l’algorithme 6), il est nécessaire de les mettre à jour (voir algorithme 7), lorsqu’un support est perdu (ligne 5), un support est trouvé (ligne 10) ou une valeur éliminée (ligne 9). Par souci de simplicité, on considérera ici que last Ci;j ; Xi ; a est équivalent à last Ci;j ; Xi ; a pos Xj ; C . Par exemple, si a; b est le dernier support de Xi ; a trouvé dans Ci;j alors last Ci;j ; Xi ; a désignera plus simplement la valeur b plutôt que le couple a; b . La correction de AC3.3 est donnée par la proposition suivante (dont la preuve est omise ici). Comme AC3.2, AC3.3 conserve la complexité spatiale et temporelle de AC2001/3.1. [ ℄ ( ) [ ℄ [ ) ( ℄[ ( )℄ ( ) Proposition 1 L’invariant suivant de la boucle principale de l’algorithme 7 est vérifié : 8Ci;j 2 C ; 8Xi 2 vars Ci;j ; 8a 2 dom Xi ; pt Ci;j ; Xi ; a donne exactement le nombre de supports externes de Xi ; a dans Ci;j . ( ) ( ) ( ) [ ℄ 274 RSTI/hors série. JFPLC 2003. 5. Exploiter la multidirectionalité négative Dans la section précédente, nous nous sommes focalisés sur la multidirectionalité positive. Dans celle-ci, nous montrons que AC2001/3.1, AC3.2, AC3.3 peuvent tous bénéficier de la multidirectionalité négative. De nouveaux algorithmes, notés AC3.1 , AC3.2 et AC3.3 , sont alors obtenus en modifiant la méthode seekN extS upport comme définie par l’algorithme 10. Le principe consiste à concentrer la recherche d’un support uniquement aux tuples appelés candidats [BES 97]. Un candidat est un tuple qui n’a jamais été testé. Il est à noter que la présentation est assez technique car elle est donnée dans le cas de contraintes d’arité quelconque. Tout d’abord, considérons une action seekC andidate telle qu’un appel de la forme seekC andidate C; X; a; t; k calcule le plus petit candidat t0 valide par rapport a. Notons que k est simplement donné par souci à C tel que t t0 et t0 pos X; C premières valeurs de t ont déjà été vérifiées d’optimisation car il indique que les k comme préfixe possible d’un candidat. L’action met à jour t avec t0 et retourne une valeur parmi NOTHING, SUPPORT and CANDIDATE indiquant respectivement qu’il n’y a plus de candidats, que le paramètre t mis à jour correspond à un support ou simplement un candidat. La différence entre l’action, décrite par l’algorithme 8, et celle de [BES 97] est du au fait qu’elle peut être appelée par un algorithme tel que AC2001/3.1 ou AC3.2, qui n’exploite pas totalement la multidirectionalité positive. C’est la raison pour laquelle des supports peuvent être trouvés lors de la recherche de candidats. Trois actions auxilaires sont appelés par seekC andidate : ( [ ( ) )℄ = ( )℄ = ) 1 – seekN extT uple C; X; a; t; k calcule le plus petit tuple valide t0 dans C tel que 0 0 0 0 6 t0 k0 . Cette action, similaire à celle t t , t pos X; C a et 9k k j t k 0 décrite dans [BES 97], met à jour t avec t et retourne le plus petit k 0 j t k 0 6 t0 k 0 ou si il n’existe pas. [ ( 1 ( )℄ = – reinitT upleAf ter que t t0 , t0 pos X; C ( [ ( [ ℄= [ ℄ [ ℄= [ ℄ ) calcule le plus petit tuple valide 0 dans tel 0 et 8 2 1 [ ℄ = [ ℄. est mis à jour avec 0. ) (voir algorithme 9) copie les éléments de 0 dans à C; X; a; t; k a i t ::k; t i t i t C t – opy C; t; t0 ; start; pivot t t partir de l’indice start jusqu’à ce qu’une incompatibilité soit trouvée à la position pivot (ligne 3), une valeur invalide soit trouvée (ligne 5) ou la fin du tuple (ligne 7). Nous concentrons notre analyse aux parties originales de l’algorithme et reportons le lecteur, pour une description complémentaire à [BES 97]. Tout d’abord on peut last C; var k; C ; t k peut être égal à t (ligne 7) et ainsi être remarquer que t0 un candidat supportant X; a car le tuple t est valide1 . t0 peut aussi représenter un support même si il est distinct de t pourvu que X; a soit supporté par t0 et que toutes les valeurs de t0 soient encore valides. Quand X; a n’est pas supporté par t0 ou lorsqu’il existe une valeur invalide dans t0 , la copie est stoppée à un indice k 0 et ( [ ) ( ) [ ℄℄ ( ( ) ) 1. Initialement, t est valide, et après chaque tour de la boucle principale, soit t n’est pas modifié soit t est mis à jour par un appel à setNextTuple ou à reinitTupleAfter qui tous les deux fournissent uniquement des tuples valides. Algorithmes 275 Algorithme 8 seekCandidate(in C,X,a, in/out t, in k) : int 1: for k from f rontier to length(t) do 2: if k = pos(C; X ) then continue 3: if last[C; X; t[k℄℄ = nil then continue 4: t0 last[C; var(k; C ); t[k℄℄ 5: s 1 6: while s length(t) ^ t[s℄ = t0 [s℄ do s + + 7: if s = length(t) + 1 then return SUPPORT 8: if t[s℄ > t0 [s℄ then continue 9: if s < k then k0 seekN extT uple(C; X; a; t; k) 10: else 0 0 11: k opy (C; t; t ; s; pos(C; X )) 12: if k0 = length(t) + 1 then return SUPPORT 13: if k0 = pos(C; X ) ^ t[k0 ℄ > t0 [k0 ℄ then reinitT upleAf ter (C; X; a; t; k0 ) 0 14: else k0 seekN extT uple(C; X; a; t; k ) 15: end if 16: if k0 = 1 then return NOTHING 17: else if k0 1 < k then k k0 1 18: end for 19: return CANDIDATE Algorithme 9 copy(in C, in/out t, in t0 ,start,pivot) : int 1: 2: 3: 4: 5: 6: 7: for i from start to length(t) do if t[i℄ = t0 [i℄ then continue if i = pivot then return i [℄ t i t 62 0 [i℄ if t[i℄ dom(var (i; C )) then return i end for return length(t)+1 nous avons soit à réinitialiser les valeurs après k 0 soit à chercher le tuple suivant avec un préfixe différent de taille k 0 . Nous pouvons maintenant présenter la fonction seekN extS upport qui doit être appelée pour exploiter la multidirectionalité négative. Cette action (voir algorithme 10) est similaire à celle de [BES 97] mais prend en compte les candidats détectés comme supports par seekC andidate. Algorithme 10 seekNextSupport(in C,X,a, in/out t) : boolean 1: if t = nil then reinitT upleAf ter(C; X; a; t; 0) 2: else seekN extT uple(C; X; a; t; length(t)) 3: result seekCandidate(C; X; a; t; 1) 4: if result = NOTHING then return false 5: if result = SUPPORT then return true 6: while true do 7: if C (t) then return true 8: k seekN extT uple(C; X; a; t; length(t)) 9: if k = 1 then return false 10: result seekCandidate(C; X; a; t; k) 11: if result = NOTHING then return false 12: if result = SUPPORT then return true 13: end while 276 RSTI/hors série. JFPLC 2003. 6. Expérimentations Pour prouver l’intérêt pratique des algorithmes introduits dans ce papier, nous avons implémentés ceux-ci en Java (voir http ://www.cril.univ-artois.fr/˜lecoutre/ pour certains sources) et effectués des expérimentations (sur un PC Pentium IV 2,4GHz 512Mo avec Linux) sur des problèmes aléatoires, réels et académiques. Les résultats ont été mesurés en termes de temps CPU (cpu) en secondes, de nombre de tests de consistance (#ccks) et de nombre de tests de validité (#vcks). Tous les algorithmes (sauf AC7) ont été implémentés en utilisant un schéma de propagation orienté-variable et l’heuristique de choix de révision domv qui consiste à sélectionner les variables de l’ensemble de propagation par ordre croissant de la taille courante de leurs domaines. Pour plus de détails, voir [LEC 03]. 6.1. Appliquer la consistance d’arc Tout d’abord, nous avons étudié expérimentalement l’application de la consistance d’arc sur un CSP donné. La première série de tests correspond à des problèmes aléatoires. Dans ce papier, une classe d’instances aléatoires est caractérisée par un 5-uplet n; d; m; k; t où n représente le nombre de variables, d la taille uniforme des domaines, m le nombre de contraintes d’arité k et t le nombre de tuples non autorisés pour chaque contrainte. ( ) AC3 P1 P2 P3 P4 #ccks cpu #ccks cpu #ccks cpu #ccks cpu 99; 968 0:064 148; 029 0:087 2:351M 1:375 4:202M 2:490 AC3.1 99; 968 0:069 74; 539 0:048 0:587M 0:384 1:033M 0:701 AC3.1* 97; 967 0:072 61; 641 0:046 0:504M 0:375 0:934M 0:704 AC3.2 94; 012 0:072 63; 540 0:044 0:478M 0:342 0:857M 0:636 AC3.2* 93; 984 0:078 56; 645 0:043 0:446M 0:347 0:831M 0:661 AC3.3 94; 012 0:067 62; 935 0:045 0:470M 0:319 0:844M 0:627 AC3.3* 93; 984 0:072 56; 437 0:045 0:442M 0:327 0:824M 0:652 AC7 94; 012 0:080 0:494M 0:347 0:553M 0:428 0:919M 0:782 Tableau 1. Application de la consistance d’arc : instances aléatoires AC3 #08 #11 #ccks cpu #ccks cpu 46; 294 0:021 0:971M 0:226 AC3.1 42; 223 0:023 0:971M 0:247 AC3.1* 35; 079 0:027 0:841M 0:272 AC3.2 39; 795 0:024 0:671M 0:225 AC3.2* 34; 223 0:028 0:638M 0:243 AC3.3 39; 713 0:029 0:671M 0:206 AC3.3* 34; 215 0:032 0:638M 0:232 AC7 1:877M 0:629 0:671M 0:272 Tableau 2. Application de la consistance d’arc : instances RLFAP Nous présentons les résultats, donnés par la table 1, concernant les instances aléatoires binaires étudiées par [BES 99, BES 01, ZHA 01]. Plus précisément, 4 classes, notées ici P1, P2, P3 and P4, ont été expérimentées. P1= ; ; ; ; et P2= ; ; ; ; correspondent à des classes d’instances sous-contraintes et sur-contraintes tandis que P3= ; ; ; ; et P4= ; ; ; ; correspondent à des classes d’instances qui se situent à la phase de transition pour la consistance d’arc. Pour chaque classe, 50 instances ont été générées et la moyenne (150 50 500 2 2350) (150 50 500 2 2296) (150 50 500 2 1250) (50 50 1225 2 2188) Algorithmes = 100 d = 200 n = 100 d = 300 n AC3 #ccks cpu #ccks cpu 137:33M 22:799 459:01M 76:406 AC3.1 5:98M AC3.1* 3:98M 1:259 13:45M 2:705 1:417 8:97M 3:010 AC3.2 3:98M 0:951 8:97M 2:010 AC3.2* 3:96M 1:055 8:92M 2:237 AC3.3 3:98M 1:009 8:97M 2:136 AC3.3* 3:96M 277 AC7 4:00M 0:781 9:00M 1:616 1:089 8:92M 2:295 Tableau 3. Application de la consistance d’arc : instances Domino calculée pour le temps CPU et le nombre de tests de consistance. Alors que tous les algorithmes ont des performances proches vis à vis de P1 et P2, on peut remarquer que AC3.2, et plus encore AC3.3, surpasse AC3.1 vis à vis de P3 et P4. Par ailleurs, les algorithmes qui exploitent la bidirectionalité négative permettent de réduire légèrement le nombre de tests de consistance sans concrétiser cela au niveau du temps. Ensuite, nous avons testé des instances réelles, empruntées à l’archive FullRLFAP (nous remercions le Centre d’Electronique de l’Armement), qui contient des instances du problème d’assignation de fréquences radio. Nous présentons les résultats (voir table 2) sur deux instances notées SCEN#08 et SCEN#11, étudiées par [BES 99, DON 02, ZHA 01]. Pour ces instances, AC3.2 et AC3.3 sont tout à fait proches. Ils permettent de sauver des tests de consistance sans réduire le temps CPU (par rapport à AC3 et AC3.1). Notons que le nombre de tests de consistance réalisés est bien plus faible que ceux présentés par [BES 99, ZHA 01]. Cet écart est principalement du à l’introduction de notre heuristique de choix de révision [LEC 03]. Un comportement similaire a été observé par [DON 02]. Le troisième problème que nous avons expérimenté est appelé Domino [ZHA 01]. Chaque instance, caractérisée par un couple n; d où n représente le nombre de contraintes variables dont les domaines sont f ; : : : ; dg, est tel que il existe n d’égalité Xi Xi+1 (8i 2 ::n ) et une contrainte de déclenchement X1 Xn ^ X1 < d _ X1 Xn ^ X1 d . Sur les instances Domino (voir table des tests de consistance et 3), AC3.2 et AC3.3 permettent de sauver environ de temps CPU par rapport à AC3.1. AC3.2 est l’algorithme le plus rapide sur ce problème car il semble bénéficier totalement de la bidirectionalité positive et car son coût de traitement est plus faible que celui de AC3.3. +1 = ) ( = 1 1 ( ) 1 = ) 1 33% ( = 20% 6.2. Maintenir la consistance d’arc pendant la recherche Comme il apparaît que l’un des algorithmes de recherche complet les plus efficaces est l’algorithme qui maintient la consistance d’arc au cours de la recherche d’une solution [SAB 94, BES 96], nous avons implémenté toutes les versions MAC des algorithmes précédents. Tous nos algorithmes MAC utilisent dom=f utdeg comme heuristique de choix de variable et lexio comme heuristique de choix de valeurs. Deux classes d’algorithmes MAC ont été développés pour AC3.1, AC3.2 et AC3.3. Les algorithmes de la première classe ne nécessitent aucune structure de données supplémentaire et admettent ainsi une complexité spatiale en O md . En contrepartie, certains tests de consistance sont sacrifiés puisqu’il est nécessaire alors de réinitiali- ( ) 278 RSTI/hors série. JFPLC 2003. ser les structures de données last et pt lors de retour-arrières. Les algorithmes de la seconde classe, notés MACs , nécessitent de maintenir les structures de données au cours de la recherche et admettent une complexité spatiale en O md2 . Par ailleurs, nous avons constaté qu’il est intéressant de ne pas réinitialiser la structure de données lastE spécifique à AC3.2 lors de retour-arrières, bénéficiant alors d’un effet de mémoire. Cela signifie qu’un support (externe) trouvé à une profondeur donnée de la recherche a l’opportunité d’être encore valide à un niveau moins avancé de la recherche (après retour-arrières). ( MAC3 Q1 Q2 #ccks #vcks cpu #ccks #vcks cpu 103:25M 0 72:362 226:46M 0 102:620 MAC3.1 63:89M 45:33M 74:457 152:94M 56:81M 97:551 MAC3.1* 53:55M 45:33M 73:313 101:95M 56:81M 95:090 MAC3.2 30:20M 86:36M 63:586 76:80M 111:99M 76:478 MAC3.2* 28:85M 86:36M 64:683 66:62M 111:99M 78:528 ) MAC3.3 50:66M 33:51M 94:723 MAC3.3* 49:73M 33:51M 96:452 Tableau 4. Maintien de la consistance d’arc : instances aléatoires uniformes Q1 Q2 #ccks #vcks cpu #ccks #vcks cpu MACs 3.1 44:13M 72:58M 81:610 105:95M 91:22M 99:721 MACs 3.1* 35:26M 72:58M MACs 3.2 27:74M 92:57M 79:620 65:25M 91:22M 96:922 69:093 69:85M 121:83M 79:540 MACs 3.2* 25:77M 92:57M 69:600 56:10M 121:83M 82:024 MACs 3.3 34:81M 52:18M 102:562 MACs 3.3* 33:85M 52:18M 104:415 Tableau 5. Maintien de la consistance d’arc : instances aléatoires uniformes En premier lieu, nous avons étudié le comportement de l’algorithme MAC sur des instances uniformes (les noeuds des graphes de contrainte et d’incompatibilité ont le même degré) générées à partir des classes Q1= ; ; ; ; de problèmes binaires denses et Q2= ; ; ; ; de problèmes ternaires peu denses. Les instances générées se situent à la phase de transition pour la recherche et vérifient le théorème 2 de [XU 00], ce qui assure qu’elles soient difficiles. Pour chaque classe, instances ont été générées (dont sont satisfiables pour Q1 et pour Q2). La table 4 donne les résultats obtenus lorsque la consistance d’arc est maintenue pour les instances des classes Q1 et Q2. MAC3.2 surpasse clairement MAC3, MAC3.1 et MAC3.3. Le nombre de tests de consistance réalisés par MAC3.2 est deux fois moins important que celui de MAC3.1. Et même si le gain de temps est limité pour les instances binaires, celui-ci est plus significatif pour les instances ternaires. Le bon comportement de MAC3.2 provient de son effet de mémoire. En effet, de nombreux tests de consistance ont été compensés par des tests de validité : on peut observer que le nombre de tests de validité de MAC3.2 est deux fois plus important que celui de MAC3.3. Comme les tests de validité sont rapides et réalisés en temps constant, contrairement aux tests de consistance, cela procure un net avantage à MAC3.2. La table 5 donne les résultats pour les algorithmes MACs . Quoique des tests de consistance soient sauvés, le sur-coût engendré par le fait de maintenir les structures de données au cours de la recherche se révèle pénalisant. (75 5 110 3 83) 50 21 (30 15 250 2 62) 14 Algorithmes 279 Ensuite, nous nous sommes intéressés à un problème académique, appelé Golomb Ruler, défini sur le serveur CSPLib 2 . Ce problème consiste à placer m marques sur une règle de longueur l tel que les distances entre deux marques soient toutes différentes. Nous avons modélisé ce problème comme un CSP en utilisant des contraintes binaires ; correspond au nombre maximum de marques et ternaires. L’instance l; m = sur une règle de longueur . L’instance l; m = ; est donc insatisfiable. A nouveau (voir table 6), on peut observer le même phénomène : MAC3.2 nécessite deux fois moins de tests de consistance et deux fois plus de tests de validité que MAC3.1. Il y a alors un gain de temps d’environ . ( ) (34 8) 34 ( ) (34 9) 25% = 34 m = 8 l = 34 m = 9 l MAC3 #ccks #vcks cpu #ccks #vcks cpu 10:677M 0 2:632 388:871M 0 95:508 MAC3.1 4:433M 1:297M 2:169 208:674M 73:080M 108:452 MAC3.1* 3:334M 1:297M 2:250 164:672M 73:080M 111:867 MAC3.2 2:388M 2:390M 1:777 87:691M 148:434M 81:150 MAC3.2* 2:129M 2:390M 1:863 81:207M 148:434M 85:202 Tableau 6. Maintien de la consistance d’arc : instances “Golomb ruler” MAC3 SCEN #11 GRAPH #14 #ccks #vcks cpu #ccks #vcks cpu 137:83M 0 96:761 2:944M 0 1:958 MAC3.1 49:27M 53:67M 93:613 1:584M 0:712M 1:876 MAC3.1* 44:19M 53:67M 95:232 1:333M 0:712M 1:942 MAC3.2 23:05M 89:84M 89:751 1:189M 1:034M 1:864 MAC3.2* 21:62M 89:84M 91:104 1:115M 1:034M 1:921 MAC3.3 46:25M 47:50M 131:361 1:187M 0:638M 1:913 MAC3.3* 43:93M 47:50M 133:556 1:115M 0:638M 1:960 Tableau 7. Maintien de la consistance d’arc : instances RLFAP 2 Pour finir, le comportement des algorithmes MAC a été étudié par rapport à instances réelles de l’archive RLFAP (voir table 7). Tandis que tous les algorithmes sont proches en temps CPU vis à vis de l’instance GRAPH#14, MAC3.2 est le plus rapide noeuds visités). vis à vis de l’instance la plus difficile, à savoir SCEN#11 ( ; 17 001 7. Conclusion Dans ce papier, nous avons introduit deux algorithmes à gros grain pour établir la consistance d’arc. Ces algorithmes, appelés AC3.2 et AC3.3, sont des extensions de AC2001/3.1. La forme positive de la multidirectionalité est exploitée par les deux algorithmes, quoique partiellement par AC3.2. Cependant, à la différence de AC3.3, AC3.2 a l’avantage d’être adapté aux contraintes d’arité quelconque. Ensuite, nous avons montré que la forme négative de la multidirectionalité pouvait être prise en compte par AC3.1, AC3.2 et AC3.3, générant de nouveaux algorithmes notés AC3.1 , AC3.2 and AC3.3 . En conséquence, AC3.3 exploite totalement la bidirectionalité comme AC7, un algorithme à grain fin. 2. http ://4c.ucc.ie/~tw/csplib/ 280 RSTI/hors série. JFPLC 2003. Quelques observations peuvent être tirées de nos expérimentations. Quand la consistance d’arc est utilisé en tant que pré-traitement, AC3.3 semble être l’algorithme le plus efficace. Comparé à AC2001/3.1, AC3.3 permet de limiter d’environ le nombre de tests de consistance et, en moyenne de temps CPU. Quand la consistance d’arc est maintenue au cours de la recherche, MAC3.2, du à un effet de mémoire, est plus efficace que MAC3.3 à la fois en termes de tests de consistance et de temps CPU. Comparé à MAC2001/3.1, nos résultats expérimentaux montrent que MAC3.2 sauve environ des tests de consistance et, en moyenne, du temps CPU. 25% 15% 50% 15% Remerciements Ce travail a été soutenu, en partie, par l’IUT de Lens, le CNRS et la région NordPas de calais dans le cadre du programme TACT. 8. Bibliographie [BES 94] B ESSIERE C., « Arc consistency and arc consistency again », Artificial Intelligence, vol. 65, no 1, 1994, p. 179-190. [BES 96] B ESSIERE C., R EGIN J., « MAC and combined heuristics : two reasons to forsake FC (and CBJ ?) on hard problems », Proc. of CP’96, Cambridge MA, 1996, p. 61-75. [BES 97] B ESSIERE C., R EGIN J., « Arc consistency for general constraint networks : preliminary results », Proceedings of IJCAI’97, Nagoya Japan, 1997, p. 398-404. [BES 99] B ESSIERE C., F REUDER E., R EGIN J., « Using constraint metaknowledge to reduce arc consistency computation », Artificial Intelligence, vol. 107, no 1, 1999, p. 125-148. [BES 01] B ESSIERE C., R EGIN J., « Refining the basic constraint propagation algorithm », Proceedings of IJCAI’01, Seattle WA, 2001, p. 309-315. 3 [DON 02] VAN D ONGEN M., « AC d an efficient arc consistency algorithm with a low space complexity », Proceedings of CP’02, Ithaca NY, 2002, p. 755-760. [LEC 03] L ECOUTRE C., B OUSSEMART F., H EMERY F., « Au coeur de la consistance d’arc », Actes de JNPC’03, 2003. [MAC 77] M ACKWORTH A. K., « Consistency in networks of relations », Artificial Intelligence, vol. 8, no 1, 1977, p. 118-126. [MOH 86] M OHR R., H ENDERSON T., « Arc and path consistency revisited », Artificial Intelligence, vol. 28, 1986, p. 225-233. [SAB 94] S ABIN D., F REUDER E., « Contradicting conventional wisdom in constraint satisfaction », Proceedings of the PPCP’94, Seattle WA, 1994, p. 10-20. [XU 00] X U K., L I W., « Exact phase transitions in random constraint satisfaction problems », Journal of Artificial Intelligence Research, vol. 12, 2000, p. 93-103. [ZHA 01] Z HANG Y., YAP R., « Making AC3 an optimal algorithm », Proceedings of IJCAI’01, Seattle WA, 2001, p. 316-321.