Programmation par contraintes
En M2 Bases de données et IA et M2 Image et IA
Par Olivier Bailleux, Maître de conférences HDR, Université de bourgogne
Partie C : Le filtrage par cohérence de domaines
Objectif
Être capable de restaurer la cohérence de domaines sur un réseau de contraintes. Comprendre en profondeur en quoi consiste la restauration de cohérence de domaines sur une seule contrainte et sur un réseau de contraintes.
Prérequis
Partie A.
C1 : Cohérence de domaine
Ce que nous allons voir ici est une forme simple de raisonnement automatique permettant de réaliser des déductions dont les conclusions consistent à retirer des valeurs des domaines de certaines variables pour simplifier un réseau de contraintes. Le système déductif utilisé est élémentaire. Il travaille avec une seule contrainte à la fois. Les informations exploitées pour faire la déduction sont une contrainte et les contenus des domaines des variables reliées par cette contrainte. Le résultat de la déduction, i.e., sa conclusion sont les contenus des mêmes domaines dans lesquels certaines valeurs ont été (si applicable) retirées.
Notion de support
Soit q une contrainte, V(q) l’ensemble des variables reliées par q, v une variable appartenant à V(q) et x un élément du domaine de v. On appelle support de l’assignation v=x toute assignation complète de V(q) qui étend {v=x} et satisfait q.
Dans l’exemple ci-dessous, A=2 a un seul support : {A=2, B=1, C=3, D=4}.
Cohérence de domaine
Dans un réseau de contraintes, la cohérence de domaines est respectée si et seulement si pour toute variable v et toute valeur x du domaine de v, v=x a un support pour toutes les contraintes dans lesquelles la variable v intervient.
Par exemple, le réseau constitué de la seule contrainte ci-dessous ne respecte pas la cohérence de domaine car C=1 n’a pas de support.
Si on assigne la valeur 1 à C, alors quelles que soient les valeurs des autres variables, la contrainte ne peut être satisfaite.
Exercices de découverte
C-dec-10
Soit la contrainte $A < B$ où les variables $A$ et $B$ ont toutes les deux pour domaine ${1,2,3}$. Quels sont les supports de $A=1$ ?
${A=1,B=2}$ et ${A=1,B=3}$.
C-dec-10
Soit la contrainte $A < B$ où les variables $A$ et $B$ ont toutes les deux pour domaine ${1,2,3}$. Y a-t-il une valeur du domaine de A
n’ayant aucun support pour cette contrainte ? Si oui laquelle et pourquoi ?
$A = 3$. Parce que si $A$ vaut 3, il n’existe aucune valeur dans le domaine de $B$ permettant de satisfaire la contrainte.
C2 : Restaurer la cohérence de domaine
Restaurer la cohérence de domaines consiste à retirer de chaque domaine toutes les valeurs qui n’ont pas de support pour au moins une contrainte du réseau. Par exemple, dans le réseau ci-dessous qui ne comporte qu’une seule contrainte, C=1, C=2, D=1, D=2, D=3 n’ont pas de support.
Vous pouvez vérifier que dans aucune des assignations complètes de A, B, C, D permettant de satisfaire la contrainte alldiff, on a C=1 ou C=2 ou D=1 ou D=2 ou D=3. Donc ces valeurs peuvent être retirées des domaines concernés et on obtient le résultat suivant.
La contrainte alldiff est « filtrée », et comme c’est la seule contrainte du réseau, le réseau respecte maintenant la cohérence de domaines : chaque valeur de chaque domaine de chaque variable a un support pour chaque contrainte concernée par cette variable.
Voici un autre exemple. Nous allons restaurer la cohérence de domaine sur un réseau de contraintes représenté sous forme énumérative. Comme toutes les contraintes sont binaires, c’est-à-dire relient deux variables, le réseau peut se représenter graphiquement, ce qui permet de visualiser plus facilement les étapes. Voici le réseau initial.
Voici les différentes étapes du filtrage.
Ici, le filtrage s’est terminé lorsqu’un domaine est devenu vide. Lorsque cela arrive, on peut conclure que le réseau de départ était incohérent. Mais la réciproque n’est pas vraie. Restaurer la cohérence de domaines sur un réseau incohérent n’aboutit pas toujours à vider un domaine. Le filtrage est une simplification d’un réseau de contraintes, mais ne suffit pas toujours à déterminer si ce réseau est incohérent ni à trouver une solution.
Comment restaurer la cohérence de domaines ?
Pour filtrer à la main un réseau de contraintes, il faut « visiter » toutes ses contraintes, une à la fois, puis visiter chaque domaine des variables reliées par cette contrainte, un à la fois, puis visiter chaque valeur du domaine visité et regarder si cette valeur a au moins un support pour la contrainte concernée. Si la réponse est non, on retire la valeur du domaine, sinon on laisse la valeur dans le domaine.
Il est parfois nécessaire de visiter plusieurs fois certaines contraintes et certains domaines car le fait de retirer des valeurs d’un domaine peut faire disparaitre des supports pour des contraintes reliées à la variable concernée, ce qui peut permettre de nouvelles réductions de domaine qui n’étaient pas possibles au départ. On arrête le processus lorsque pour chaque contrainte, toutes les valeurs de tous les domaines des variables concernées ont des supports. La bonne nouvelle, c’est que le résultat est le même quel que soit l’ordre dans lequel on visite les contraintes et les domaines.
Exercices de découverte
C-dec-20
Soit le réseau constitué d’une seule contrainte $A < B$ où les variables $A$ et $B$ ont toutes les deux pour domaine ${1,2,3}$. Restaurez la cohérence de domaine.
C-dec-21
Soit le réseau constitué des deux contraintes $A < B$ et $B < C$ où les variables $A$, $B$ et $C$ ont toutes pour domaine ${1,2,3}$. Restaurez la cohérence de domaine.
Voici trois étapes permettant de réaliser complètement le filtrage.
On filtre d’abord la première contrainte exactement comme dans l’exercice précédent. Ensuite on filtre la deuxième, et on constate que le filtrage de la première a retiré le support de $C=2$ qui n’aurait pas été filtré si la contrainte avait été traitée en premier (mais qui aurait fini par être retiré plus tard). Enfin, on revient sur la première contrainte pour constaté que $A=2$ n’a plus de support et doit donc être viré.
C-dec-22
Soit le réseau constitué des trois contraintes $A \neq B$, $B \neq C$ et $A \neq C$ où les variables $A$, $B$ et $C$ ont toutes pour domaine ${1,2}$. Restaurez la cohérence de domaine.
Aucune valeur ne doit être retirée. Le réseau est déjà domaine cohérent. En effet, la restauration de la cohérence de domaine se fait en examinant chaque contrainte séparément. Et si on regarde chaque contrainte séparément, on constante que toutes les valeurs de son domaine ont un support. Évidemment, notre cerveau voit immédiatement qu’il n’y a pas de solution, mais ce n’est pas ce que demande l’énoncé de l’exercice ni ce que ferait un algorithme de restauration de cohérence de domaine.
Rappelez-vous-en le jour de l’examen pour ne pas risquer un hors sujet.
C3 : Quelques algorithmes de restauration de DC- cohérence
Les connaissances présentées dans cette section ne seront pas évaluées.
De nombreux algorithmes de restauration de cohérence de domaines ont été publiés depuis les années 1970. Avant de donner quelques exemples, voici un rappel des notations utilisées pour parler de complexité algorithmique :
Il y a trois notations importantes pour parler de complexité algorithmique :
- $f(x) = O(g(x))$ signifie qu’il existe une constante $K$ telle que, au delà d’une certaine valeur de $x$, $f(x)$ est majorée par $K g(x)$.
- $f(x) = \Omega(g(x))$ signifie qu’il existe une constante $K$ telle que, au delà d’une certaine valeur de $x$, $f(x)$ est minorée par $K g(x)$.
- $f(x) = \Theta(g(x))$ signifie que $f(x) = O(g(x))$ et $f(x) = \Omega(g(x))$.
Dans la suite, nous parlerons de complexité en temps dans le pire des cas des algorithmes présentés. Pour bien comprendre cette notion, vous pouvez vous référer à cette vidéo.
Algorithme naïf AC1
On réitère une procédure de filtrage tant que cette procédure retire au moins une valeur d’au moins un domaine. La procédure est la suivante : pour chaque variable V et chaque contrainte q concernée par V, on retire du domaine de V toutes les valeurs qui n’ont pas de support pour q.
Dans le cas où les contraintes sont binaires (i.e. relient 2 variables) et sont définies en extension, en notant $n$ le nombre de variables, $c$ le nombre de contraintes et $d$ la taille du plus grand domaine, cet algorithme a une complexité temporelle $\Theta(n c d^3)$.
Pourquoi cette complexité ? Il faut jusqu’à $d^2$ itérations pour rechercher toutes les valeurs d’un domaine qui n’ont pas de support pour une contrainte particulière. La procédure de filtrage, qui doit faire cela deux fois par contrainte, a donc une complexité $\Theta(c d^2)$. Comme cette procédure peut n’enlever qu’une seule des $d$ valeurs initiales dans un seul des $n$ domaines, il faut dans certains cas l’appeler $n d$ fois, d’où une complexité en $\Theta(n c d^3)$.
Algorithme AC3 (1977)
On maintient dans un ensemble T les couples (Variable, Contrainte) à traiter. Cet ensemble contient au départ tous les couples (v, q) tels que v est une des variables reliées par q. Tant que cet ensemble n’est pas vide, on réitère les opérations suivantes :
-
Retirer un couple (v, q) de l’ensemble T.
-
Filtrer (v, q) en retirant du domaine de v les valeurs non supportées par q.
-
Si au moins une valeur a été supprimée du domaine de v, alors ajouter dans T tous les couples (u, p) tels que p est une contrainte différente de q, reliant les variables u et v.
Dans le cas d’un réseau de contraintes binaires spécifiées en extension, la complexité temporelle dans le pire des cas d’AC3 est $\Theta(c d^3)$.
Pourquoi cette complexité ? Chaque contrainte est examinée au plus $d$ fois, il y a donc au plus $\text{c~d}$ filtrages de contrainte dont chacun coûte, dans le pire des cas, $\Theta\left( d^{2} \right)$ opérations.
Bref panorama des algorithmes de filtrage pour contraintes binaires
Cette liste d’algorithmes a pour seul vocation de montrer le nombre des contributions et d’améliorations apportées en matière de filtrage de contraintes binaires spécifiées sous forme énumérative : AC4 (1984), AC6(1994), AC7 (1999), AC2001 (2001), AC3d (2002).
AC2001, aussi appelé AC3.1, est une amélioration tardive (21 ans plus tard) de AC3 qui a une complexité temporelle dans le pire des cas $\Theta( c d^{2} )$, et il est impossible de faire mieux. Sa complexité spatiale dans le pire des cas est $\Theta(c d)$.
Cas de la contrainte alldiff
Un algorithme célèbre datant de 1996 (Jean-Charles Regin, [Generalized arc consistency for global cardinality constraint](https://www.researchgate.net/profile/Jean-Charles_Regin/publication/221604096_Generalized_Arc_Consistency_for_Global_Cardinality_Constraint/links/0deec51a6fc6160677000000.pdf, AAAI 96) permet de restaurer la cohérence de domaine sur cette contrainte en temps $\Theta(d^{2} n)$, ou d est la taille du plus grand domaine et n le nombre de variables reliées par la contrainte. Il s’applique à une famille plus générale de contraintes appelées « contraintes globales de cardinalité » et fait appel à des résultats de théorie des graphes relatifs à la notion de flot.
Cas de la contrainte somme
Cette contrainte relie n variables $v_{1},\ \ldots,\ v_{n}$ ayant chacune un domaine contenant des entiers et impose que $v_{1} + \ldots + v_{n} = k$, où k est un entier. On ne connait pas d’algorithme de complexité polynomiale dans le pire des cas pour restauration de la cohérence de domaine sur cette contrainte. Cette contrainte ne peut être filtrée en temps polynomial que si la célèbre hypothèse $P \neq NP$ est fausse.
Exercices d’assimilation
C-ass-00
Restaurez la consistance de domaine sur le réseau de contrainte ci-dessous.
Obtiendrait-on le même résultat en remplaçant les AllDiff par les contraintes binaires $A \neq B,\ A \neq C,B \neq C,\ A \neq D,\ A \neq E,\ D \neq E$ ?
Commençons par la première contrainte (pourquoi pas ?).
Deux valeurs doivent être retirées A=1 et A=2, parce que si A était assignée avec ces valeurs, il serait impossible de satisfaire alldiff(A, B, C). Il faut maintenant visiter la deuxième contrainte.
Le fait que la seule valeur restante dans le domaine de A soit 3 induit que cette valeur n’est plus utilisable pour D et E. Donc on la retire.
Mais cela induit que D=1, par exemple, n’a plus de support pour la deuxième contrainte. On le retire, ce qui vide complètement le domaine de D.
Le filtrage est terminé. Un domaine vide nous permet de conclure que le réseau initial était incohérent.
C-ass02
On modélise le problème des 4 reines avec 4 variables A, B, C, D représentant les colonnes d’un échiquier de 4 x 4 et ayant dans leurs domaines les numéros de lignes, {1, 2, 3, 4}. Il y a 6 contraintes binaires exprimées en extension. Par exemple, une des contraintes relie A et B et n’autorise que les valeurs de A et B désignant des positions qui ne sont ni sur la même ligne, ni sur une même diagonale.
Par exemple, $Q_{\text{AB}} = {(1,3),(1,4),(2,4),(3,1),(4,1),(4,2)}$.
Voici quelques exemples de positions de reines qui respectent la contrainte reliant les variables A et B qui concernent les 2 premières colonnes.
On suppose qu’une reine est déjà en place en position 2 sur la premièrecolonne. Restaurez la cohérence des domaines des trois variables B, C et D en mettant une croix dans les cases correspondant aux valeurs retirées.
Commençons par la contrainte entre A et B.
A étant assignée à 2, les cases correspondant aux autres valeurs du domaine de A ont été barrées. On voit facilement les valeurs de B qui doivent être retirées. Elles correspondent aux cases menacées par la reine située sur la première colonne. Du coup, il ne reste que 4 dans le domaine de B, ce qui revient à assigner B=4. Pour la suite, merci de visiter la contrainte entre A et C pour que les indices suivants soient pertinents.
Voici le résultat après filtrage de la contrainte entre A et C et de celle entre A et D.
Merci de continuer avec les contraintes entre B et C et entre B et D.
Voici le résultat du filtrage des contraintes entre B et C et entre B et D.
Tentez maintenant de terminer le filtrage.
La valeur D=1 doit être supprimée parce qu’elle n’a plus de support pour la contrainte entre C et D. On arrive à une situation où il ne reste plus qu’une valeur dans chaque domaine, et ces valeurs constituent une solution.
C-ass03
Soit le réseau de contraintes suivant :
Variables : P et L avec domaine 0..8,
Contraintes :
-
Q1 : P + L = 8
-
Q2 : P + 2L = 11
Restaurez la cohérence de domaine.
Il faut commencer par une des contraintes. La première, P + L = 8, ne permet aucun filtrage. Donc on s’intéresse à la deuxième, P + 2L = 11.
On voit assez vite qu’aucune valeur paire de P ne permet de satisfaire P + 2L = 11. Ce qui induit les filtrages suivants dans le domaine de P.
Continuez à filtrer la même contrainte en vous intéressant au domaine de L.
Voici les valeurs retirées du domaine de L au regard de la contrainte P + 2L = 11.
On arrive à un stade où toutes les valeurs des deux domaines ont des supports pour la contrainte P + 2L = 11. Mais le filtrage n’est pas terminé. Intéressez-vous maintenant à la contrainte P + L = 8.
Voici les valeurs retirées du domaine de P au regard de la contrainte P + L = 8.
Tentez de continuer le filtrage sur le domaine de L, puis revenez si nécessaire à la contrainte P + 2L = 11.
[spoiler title="Solution"]
On termine le filtrage de la contrainte P + L = 8.
Puis on revient sur la contrainte P + 2L = 11.
Le filtrage se termine avec une solution. Le problème que vous venez de résoudre est célèbre : Dans une basse-cour, il y a des poules et des lapins. Au total, on compte 8 têtes et 22 pattes. Combien y-a-t-il de poules (P) et de lapins (L) ? La réponse est 5 poules et 3 lapins.
C-ass04
Soit le réseau de contraintes suivant :
Variables : $X_{0},\ X_{1},\ X_{2},\ X_{3}\ \in { 0, 1 }, Y \in { 10,\ 11,\ 14}$
Contrainte : $X_{0} + \ {2X}{1} + \ {4X}{2}, + {\ 8X}_{3} = Y$.
Restaurez la cohérence de domaine.
Il y a une seule contrainte, mais à première vue elle parait difficile à filtrer. Toutefois si on remarque que cette contrainte exprime que les valeurs des variables $X_{0},\ X_{1},\ X_{2},\ X_{3}$ sont les bits de la décomposition en base 2 de l’entier représenté par $Y$, les choses se simplifient. Chaque entier représentable sur 4 bits en base 2 admet une unique représentation en base 2.
Observons les représentations en base 2 des entiers du domaine de la variable $Y$.
A vous de continuer le raisonnement. On cherche des valeurs des domaines des variables qui, quelles que soient les valeurs des autres variables, ne peuvent permettre de satisfaire la contrainte $X_{0} + \ {2X}{1} + \ {4X}{2}, + {\ 8X}_{3} = Y$.
La table donnée en premier indice peut nous être très utile. Elle nous montre que dans toutes les assignations des variables qui satisfont la contrainte, les valeurs $X_{3} = 0$ et $X_{1} = 0$ n’apparaissent jamais.
Le résultat du filtrage est :
On voit que chaque valeur de chaque domaine apparait dans au moins une des assignations des variables qui satisfont la contrainte, ce qui est précisément ce qui caractérise la cohérence de domaine.
C-ass05
Soit le réseau de contraintes suivant.
-
En considérant qu’il y a entre chaque paire de nœuds reliés par une arête une contrainte de différence binaire, restaurez la cohérence de domaine.
-
Au lieu de modéliser ce problème à l’aide de contraintes binaires, on choisit maintenant d’utiliser une contrainte AllDiff pour chacun des triangles du graphe. Restaurez la cohérence de domaine.
Concernant la première question, la réponse est simple et immédiate. On ne peut filtrer une contrainte binaire de différence que si l’un des domaines concernés est un singleton dont l’élément est dans l’autre domaine, comme par exemple {2} et {2, 5}. Si les deux domaines ont plus d’un élément, chaque valeur a nécessairement un support.
Par contre, des filtrages sont possibles avec la version spécifiée à l’aide de contraintes alldiff.
Il faut trouver une première contrainte qui filtre. Par exemple celle-ci.
La suppression de B=3 va entrainer d’autres filtrages. A vous de les trouver.
En visitant successivement les contraintes, on arrive rapidement à cette solution.