Remarque: Ceci est une continuation et une révision de mon autre réponse .
Problèmes avec la réduction
Rappelez-vous le problème de décision:
Existe-t-il un carrelage parfait couvrant une grille donnée avec n carreaux uniques?( n + 1 ) × ( n + 2 )n
Donc pour une grille , nous ne pouvons utiliser que n variables.( n + 1 ) × ( n + 2 )n
Mais:
- Notre réduction nécessite beaucoup de variables uniques, bien plus que .O (n)
- De plus, nos fils sont ouverts, ce qui conduit à:
- Comment savons-nous que nous pouvons carreler les zones ouvertes?
Pour résoudre le premier problème, nous agrandissons artificiellement le plateau de jeu; nous faisons essentiellement égal au nombre de variables dont nous avons réellement besoin, puis créons une grille de taille ( n + 1 ) × ( n + 2 ) , et plaçons notre grille dans le coin inférieur gauche. Cela conduira à une explosion quadratique.n( n + 1 ) × ( n + 2 )
Pour le deuxième problème, il faut repenser un peu nos gadgets.
Il peut sembler un peu intimidant de prouver que nous pouvons réussir à carreler le reste du plateau selon la règle. Nous commençons donc avec la même stratégie que celle utilisée pour générer des plateaux de jeu de taille :( n + 1 ) × ( n + 2 )
Tout d' abord , nous générons un ensemble de toutes les tuiles possibles. Toutes ces tuiles devront être placées sur le plateau. Ensuite, nous enlevons les tuiles et laissons leurs carrés.
Cependant, nos gadgets ne garantissent pas qu'un ensemble particulier de tuiles sera placé; les tuiles placées dépendent de l'état. Nous devons donc modifier soigneusement les gadgets pour garantir que certaines tuiles seront supprimées, quel que soit l'état choisi.
Passons en revue nos gadgets alors.
Le fil et la clause-gate sont problématiques pour deux raisons.
- Nous ne savons pas que les carrés entourant un fil ou une porte de clause peuvent être carrelés correctement; après tout, certains fils peuvent être poussés vers la gauche, d'autres vers la droite, et le carrelage des carrés d'espace blanc restants devient non trivial. Nous qualifierons ce problème de problème de "flux".
- Il n'y a aucun moyen de savoir quelles tuiles supprimer de l'ensemble de tuiles; dans un état, un ensemble de carrés, dans le fil ou la porte de clause, sera carrelé, dans un autre état, un ensemble de carrés entièrement différent sera carrelé.
Pour résoudre ces problèmes:
- Tout d'abord, nous générons un ensemble de toutes les tuiles possibles. Toutes ces tuiles devront être placées sur le plateau; lorsque nous les placerons sur le plateau, nous retirerons la tuile de l'ensemble. Bien que nous ne connaissions peut-être pas dans un premier temps , étant donné que nous n'avons pas encore décrit complètement la formulation, nous pouvons ajouter toutes les nouvelles possibilités de tuiles au fur et à mesure que nous incrémentons n , si nécessaire. Toutes les tuiles que nous retirons de cet ensemble doivent être placables (au moins, être placées si la formule est satisfaisable). Nous appelons retirer une tuile de l'ensemble de tuiles, pour «décharger» la tuile de l'ensemble de tuiles, comme pour décharger notre obligation de la placer sur le plateau de jeu.nn
- Nous devons soigneusement concevoir les gadgets pour garantir que les carreaux particuliers seront supprimés, quel que soit l'état choisi.
- Nous devons fermer nos gadgets, afin qu'ils ne poussent pas les tuiles tout autour du plateau en fonction de leur état; au contraire, tous leurs États ne doivent occuper qu'un domaine bien défini.
- Alternativement, tous leurs États doivent être garantis pour pouvoir occuper une zone bien définie; cela garantit un carrelage satisfaisable, mais ne garantit pas qu'un carrelage particulier se produira. C'est de la même manière qu'un jeu Dominosa est créé:
- Les tuiles sont d'abord générées en un ensemble;
- Ensuite, les tuiles sont placées dans une configuration aléatoire,
- Lorsque chaque tuile est placée, elle est retirée du jeu de tuiles.
- Ensuite, les tuiles sont retirées du plateau, laissant derrière elles leurs cases.
- Cela ne garantit pas que la configuration prévue sera choisie,
- Au contraire, il garantit que la configuration prévue peut être choisie, et donc une solution existe. Nous pouvons faire la même chose ici.
- Après avoir placé tous les gadgets de la formulation, au lieu de placer des carrés uniques par défaut, c'est-à-dire sur tous les "espaces", nous nous assurons que l'espace est une zone rectangulaire avec une dimension paire, ou décomposons l'espace blanc en rectangles avec une dimension paire , et nous tuiles simplement l'espace blanc avec les tuiles restantes dans le jeu de tuiles.⋆
- Après avoir placé toutes les tuiles de l'ensemble, nous savons que tout est placable.
- Certaines tuiles seront évidemment placables, comme celles des murs, d'autres ne seront placables que si la formule est satisfaisante, en raison de la nature des relations entre les gadgets.
- Ensuite, nous enlevons les tuiles et laissons leurs carrés.
Passons en revue nos gadgets alors.
Forcer le gadget
Nous pouvons créer un nombre arbitraire de blocs de construction en nous assurant qu'ils ne peuvent pas être associés chacun avec eux.
Par exemple, disons que nous voulons forcer une tuile , afin que nous puissions utiliser 1 ⋆ comme bloc de construction. (Remarque, 1 ⋆ est une variable arbitraire, que nous voulons forcer comme paire à elle-même, pas nécessairement un bloc de construction comme nous avons utilisé la valeur 1 précédemment)( 1 ⋆ , 1 ⋆ )1 ⋆1 ⋆1
Pour garantir que nos réserves -Construction-bloc ( 1 ⋆ , 1 ⋆ ) , nous placeront contre la paroi de fond dans la configuration suivante: nous placerons le nombre réservé, Appelons 1 ⋆ contre le mur comme un up-tack (en forme de ⊥ ); 3 contre le mur, et un dans la 2e rangée au milieu. Ensuite, nous placerons deux autres nombres, appelons-les 2 ⋆ et 3 ⋆ ; ce sont uniques à ce gadget. Nous les plaçons en haut à gauche et à droite 1 ⋆ .1 ⋆( 1 ⋆ , 1 ⋆ )1 ⋆⊥32 ⋆3 ⋆1 ⋆
Illustré ci-dessous, une bordure noire partagée est le bas du plateau de jeu, description de gauche à droite.
- Configuration du gadget. Chaque et 3 ⋆ ici est unique à ce gadget.2 ⋆3 ⋆
- Les 3 états possibles du pavage du centre .1 ⋆
Après cela, nous pouvons garantir que notre gadget peut être carrelé avec un ensemble spécifique de tuiles, tout en garantissant que notre gadget doit forcer la paire .( 1 ⋆ , 1 ⋆ )
- Nous savons que doit se produire, car les 3 états de pavage possibles du milieu inférieur 1 ⋆ , tuile comme ( 1 ⋆ , 1 ⋆ ) , comme illustré dans la figure de droite ci-dessus.( 1 ⋆ , 1 ⋆ )1 ⋆( 1 ⋆ , 1 ⋆ )
- Les tuiles restantes peuvent être carrelées en et ( 1 ⋆ , 3 ⋆ ) , couvrant le gadget. Ainsi, nous pouvons supprimer ces tuiles de notre ensemble de tuiles global. Illustré ci-dessous.( 1 ⋆ , 2 ⋆ )( 1 ⋆ , 3 ⋆ )
Description, de gauche à droite:
- Gauche, haut: Etat gauche, Gauche, bas: Un pavage valide des carrés restants.
- Milieu, haut: Etat moyen, Milieu, bas: Un pavage valide des carrés restants.
- Droite, haut: État droit, Droite, bas: Un pavage valide des carrés restants.
Notez que le pavage des carrés restants n'est pas forcé , car ils peuvent paver avec des voisins proches au lieu de , mais comme il s'agit d'un pavage valide du plateau de jeu dans tous les états, nous pouvons les supprimer du ensemble de tuiles, et supposez qu'ils seront carrelés exactement de cette façon. Puisque nous savons qu'il existe un pavage possible valide, nous avons au moins un pavage possible du plateau de jeu, si la formule est satisfaisable. Bien qu'il n'y ait aucune garantie que ceux-ci seront tuilés de cette façon, il y a une garantie que la tuile ( 1 ⋆ , 1 ⋆ ) sera forcée.1 ⋆( 1 ⋆ , 1 ⋆ )
Remarque: si vous n'êtes pas satisfait de cela ou si vous êtes confus par la différence entre "pouvoir carreler" et "être forcé de carreler", vous pouvez simplement placer un mur autour du gadget , de la même manière que nous faire un mur 3 × 2 ci-dessous pour le gadget clause.3 × 23 × 2
Ce gadget n'est pas fermé, car il n'a pas besoin de l'être (mais vous pouvez le faire si vous le souhaitez). Ce n'est pas nécessaire, car il a une configuration réalisable, que nous pouvons supprimer du jeu de tuiles. Bien qu'il soit possible de faire une configuration différente, cela n'affecte pas la satisfiabilité du problème.
Les tuiles suivantes sont garanties d'être carrelées (elles peuvent donc être retirées du jeu de tuiles): ( 1 ⋆ , 1 ⋆ )
Les tuiles suivantes sont garanties de pouvoir être tuilées (donc peuvent être retirées du jeu de tuiles): ( 1 ⋆ , 2 ⋆ ) , ( 1 ⋆ , 3 ⋆ )
Si vous choisissez de fermer ce gadget avec un mur, seront également couverts.( 1 ⋆ , 2 ⋆ ) , ( 1 ⋆ , 3 ⋆ )
Nouvelles portes Wire et Clause
En raison des problèmes d'écoulement et de vidage de l'ensemble de tuiles, nous devons repenser un peu le fil.
Une façon de résoudre le problème d'écoulement est de faire du fil un circuit, au lieu de simples états gauche-droite; c'est-à-dire qu'il serait circulaire au lieu d'une ligne, et donc si la partie supérieure du cercle est poussée à droite, le bas sera poussé à gauche. Cela résout le problème de débit.
En suivant cette route, nous pouvons changer le fil et la porte de la clause pour résoudre les deux problèmes.
Réserve et FTF
Introduisons deux nouvelles valeurs universelles, et F . Ces deux valeurs sont universelles; les valeurs réelles dans la grille, telles que les valeurs carrées 2 et 3 (puisque par convention, nous avons réservé 1 comme bloc de construction pour les murs), ou tout ce que vous choisissez. Ils représentent respectivement vrai et faux.TF231
Nous réservons de force les tuiles , ( T , T ) , ( F , F ) , comme suit; illustration ci-dessous, description de gauche à droite:( T, F)( T, T)( F, F)
- Nous utilisons le même schéma que pour forcer n'importe quelle tuile , en utilisant T comme 1 ⋆ . Chaque 2 ⋆ et 3 ⋆ ici est unique à ce gadget.( 1 ⋆ , 1 ⋆ )T1 ⋆2 ⋆3 ⋆
- Nous utilisons le même schéma que pour forcer n'importe quelle tuile , en utilisant F comme 1 ⋆ Chaque 2 ⋆ et 3 ⋆ ici sont uniques à ce gadget.( 1 ⋆ , 1 ⋆ )F1 ⋆2 ⋆3 ⋆
- Nous utilisons le même schéma que pour forcer une tuile , en utilisant F comme 1 ⋆ au centre et en utilisant T dans les autres emplacements de la punaise ascendante . Cela force ( F , T ) à carreler. 2 ⋆ et 3 ⋆ sont capables de carreler avec T , nous les supprimons donc du jeu de tuiles. Chaque 2 ⋆ et 3 ⋆ ici est unique à ce gadget.( 1 ⋆ , 1 ⋆ )F1 ⋆T( F, T)2 ⋆3 ⋆T2 ⋆3 ⋆
Câble
Chaque fil commencera et se terminera par une valeur, appelons-le , qui est unique au fil. Pour chaque clause à laquelle le fil participe, le fil aura deux valeurs de fil, x ⋆ et x ′ ⋆ , qui sont uniques à chaque fil, et participeront à la même clause. Illustration ci-dessous, avec description de gauche à droite.A ⋆x ⋆X′⋆
- Un fil qui participe à une clause. Le fil a une hauteur de et une longueur de 2 ∗ p + 3 , où p est le nombre de clauses auxquelles le fil participe. Le fil est capitonné par deux carrés A ⋆ à gauche et deux à droite. Il est, bien sûr, entouré d'un mur de tous les côtés, indiqué par le contour bleu. Notez que le 1 ⋆ est unique à ce fil et ne sera utilisé que dans le fil et la clause à laquelle il participe.22 ∗ p + 3pA ⋆1 ⋆
Les deux états sont illustrés ci-dessous, de gauche à droite.
- Un fil qui participe à une clause, dans l'état vrai. Le fil est considéré comme vrai, lorsque les carrés sont associés à un carré T et les carrés x ′ ⋆ sont associés à des carrés F. Il est considéré comme faux dans l'autre état, où le carrelage est inversé. Notez comment le carrelage est forcé une fois que le carreau A ⋆ est sélectionné: ( T , F ) sont déjà forcés plus tôt, donc le reste des carreaux doit être horizontal.x ⋆TX′⋆FA ⋆( T, F)
- Le même fil à l'état faux.
Lorsque vous participez à plus de clauses, il y a plus de valeur et x ′ ⋆ , une paire pour chaque clause à laquelle le fil participe. Elles alternent en haut et en bas, tout comme les carrés T et F qui séparent chaque x ⋆ , x ′ ⋆ paire.x ⋆X′⋆TFx ⋆ , x′⋆
Les deux états correspondants.
Ce gadget est fermé , il n'y a donc pas de "problème de flux".
Notez comment dans l'un ou l'autre état, nous collectons les tuiles suivantes, quel que soit l'état: , ( A ⋆ , T ) , ( A ⋆ , F ) .( A ⋆ , A ⋆ )( A ⋆ , T)( A ⋆ , F)
Il y a cependant quelques tuiles dont nous ne sommes pas sûrs; dans un état, nous pouvons supprimer de l'ensemble de tuiles, tandis que dans un autre état, nous pouvons supprimer ( 1 ⋆ , F ) , ( 1 ′ ⋆ , T ) , ( 2( 1 ⋆ , T) , ( 1′⋆ , F) , ( 2 ⋆ , T) , ( 2′⋆ , F) . . .du jeu de tuiles, alors quelles tuiles pouvons-nous réellement retirer? La réponse est: la porte de clause a le même problème, mais avec le jeu de tuiles opposé. Il collectera toujours les tuiles restantes, opposées et non collectées, comme nous le verrons dans la section suivante. Puisque chacun d'eux est associé à une porte de clause, nous pourrons les supprimer tous les deux.(1⋆,F),(1′⋆,T),(2⋆,F),(2′⋆,T)...
Clause
Ensuite, nous allons créer la première itération de la nouvelle porte de clause. Il se compose d'un gadget , entouré de murs. À l'intérieur du gadget, nous plaçons un F en haut au centre et deux carrés en T dans les coins inférieurs; un en bas à gauche et un en bas à droite. Les carrés restants seront des valeurs représentant les variables de fil de trois fils différents. Appelons ces un ⋆ , b ⋆ , et c ⋆ . Le F sera forcé de s'apparier avec l'une des variables filaires et les autres variables filaires seront appariées avec les valeurs T. Illustrations ci-dessous, descriptions de gauche à droite.2×3FTa⋆,b⋆,c⋆FT
- Gauche: La configuration pour la première itération de la nouvelle clause-gate.
- Droite Les trois états possibles du pavage F
Ces trois états conduisent à trois pavages possibles. Illustration ci-dessous, descriptions de gauche à droite.
- Gauche, haut : mosaïque à gauche, Gauche, en bas: mosaïque des carrés restants.F
- Milieu, haut : carrelé à droite, Milieu, bas: Mosaïque des carrés restants.F
- Droite, en haut : mosaïque, Droite, en bas: mosaïque des carrés restants.F
Étant donné que le sera associé à l'une des variables de fil dans la clause , cette variable de fil ne peut plus être associée à F dans le fil ; forçant ainsi le fil à vrai. Inversement, les variables de fil restantes qui tuiles avec T seront forcées de tuiler avec F dans leurs fils. Ce sont exactement les mêmes contraintes en tant que 1 -in- 3 - S A T clause.FF TF1-in-3-SAT
Note, et c ⋆ sont des variables de fil, mais ils pourraient chacun se référer à un x ⋆ ou x ' ⋆ variable de fil; l'utilisation d'un x ′ ⋆ annule essentiellement la variable filaire.a⋆,b⋆,c⋆x⋆x′⋆x′⋆
Un ajout: pour s'acquitter de l'obligation de savoir quelles tuiles peuvent être retirées du jeu de tuiles, nous devons "doubler et opposer" la clause. Ce que je veux dire par là, est de faire un autre gadget, avec 3 variables supplémentaires représentant les négations d' un ⋆ , b ⋆ , et c ⋆ . Appelons ces une « ⋆ , b ' ⋆ , et c ' ⋆ . Celles-ci doivent être les valeurs négatives des fils variables de a ⋆ , b ⋆3×23a⋆,b⋆,c⋆a′⋆,b′⋆,c′⋆ Et c ⋆ . Cegadget 3 × 2 est différent, en ce qu'il aura un T au centre et deuxvaleurs F aux coins; exactement le contraire du gadget de clause décrit jusqu'ici. En "doublant" la clause comme celle-ci, nous rajoutons les mêmes contraintes que le gadget décrit ci-dessus. Cependant, nous déchargeons également toutes les combinaisons de ( T , x ⋆ ) , ( T , x ′ ⋆ ) , ( F , x ⋆ ) , ( F , xa⋆,b⋆,c⋆3×2TF de la dalle-ensemble, pour chaque variable (et donc pour une ⋆ , b ⋆ ,et c ⋆ ainsi, parce qu'ils sont après tout,variables fils). Illustré ci-dessous, descriptions de gauche à droite.(T,x⋆),(T,x′⋆),(F,x⋆),(F,x′⋆)a⋆,b⋆,c⋆
- (T,x⋆),(F,x⋆),(T,x′⋆),(F,x′⋆)
- La ligne bleue au milieu de la figure la plus à gauche est là pour faciliter la visualisation; en réalité, il peut être supprimé sans autoriser d'autres états.
Prenons donc un exemple, pour montrer que toutes les tuiles sont déchargées comme promis. Illustré ci-dessous, description de gauche à droite.
- 1⋆=b⋆a⋆b⋆
- 1⋆T
- TF
- 1′⋆T(A⋆,A⋆)(A⋆,T)(A⋆,F)(1⋆,T)(1⋆,F)(1′⋆,F)(1′⋆,T)
En essayant l'autre état, nous obtenons l'illustration ci-dessous, description de gauche à droite.
- (1⋆,T
- (1⋆,F
- En menant le reste du fil à la tuile en conséquence, et évaluez le fil comme faux.
- (1′⋆,F)(1′⋆,T)(A⋆,A⋆)(A⋆,T)(A⋆,F)(1⋆,T)(1⋆,F)(1′⋆,F)(1′⋆,T)
Ainsi, dans l'un ou l'autre état, nous déchargeons les mêmes tuiles. Par conséquent, le fil et la clause déchargent ensemble avec succès des carreaux spécifiques s'il existe une affectation satisfaisante.
Ce gadget est fermé , il n'y aura donc pas de problème de flux.
Le gadget de clause ainsi que le gadget de fil sont garantis pour toujours décharger les mêmes valeurs de paire de tuiles , et donc nous pouvons les décharger même si nous ne savons pas de quelle façon il tuile.
Désormais, tous nos gadgets remplissent les critères.
Formulation
Dans notre formulation finale, nous créons trois rangées de gadgets, chacun séparé par un mur horizontal.
- TF
- Dans la rangée du milieu, nous plaçons les gadgets de fil, horizontalement, qui sont deux tuiles de hauteur. Les gadgets en fil doivent être séparés les uns des autres par une paroi verticale.
- Dans la rangée du haut, nous plaçons des gadgets de clause, qui mesurent quatre carreaux. Les gadgets de clause doivent être séparés les uns des autres par un mur vertical.
Les illustrations suivent, descriptions au-dessus de chaque figure. Cliquez sur les images pour une résolution complète. Le code source pour reproduire / générer les images est répertorié au bas de la page.
Φ(x)=(x1,¬x2,x3)∧(x2,¬x3,x4)∧(x1,x2,¬x4)(¬x1,x2,x3,¬x4) comme témoin.
Nous commençons d'abord par les murs horizontaux séparant les rangées de gadgets. Nous montrons les carrés et les paires qui sont forcées de carreler à l'intérieur des murs.
Ensuite, nous montrons les gadgets. Le contour bleu représente les bordures des gadgets; bleu pointillé pour les gadgets de forçage, car ils ne seront pas entourés de murs. Notez que la ligne au milieu du gadget de clause n'est pas entourée d'un mur; il est là pour faciliter la visualisation; la suppression de la ligne ne permet plus à des états de se produire dans la clause, comme expliqué ci-dessus, mais nous montrons la ligne bleue pour cette démonstration. Remarque: nous utilisons des noms de carrés pour donner la lisibilité sémantique des nombres, le cas échéant. Chaque nom représente une valeur numérique.
Ici, nous remplissons les murs verticaux.
Ici, nous remplissons la solution témoin; c'est-à-dire qu'il s'agit de la solution de carrelage si vous utilisez la solution SAT pour la générer.
n
Ici, nous remplissons les carrés restants avec un pavage valide trivial.
Ici, nous montrons le coin inférieur droit de la grille.
Ici, nous montrons le coin supérieur droit de la grille. Notez comment les tuiles verticales ne correspondent plus; nous plaçons donc la rangée supérieure horizontalement, si nécessaire.
Et enfin le coin en haut à gauche.
La génération du plateau de jeu entier à la fois via TeX échoue avec des erreurs de mémoire insuffisante de pdflatex, donc si vous voulez le voir, vous devrez générer des clips et les patcher ensemble. N'oubliez pas de consulter la visionneuse de bloc - notes .
Sources TikZ
Générateur de jeux:
graphtex.py
Convertit TeX en svg, en utilisant pdflatex, pdfcairo (poppler) et rsvg-convert (libsvg)
dominosa.py
Contient la logique de conversion, la vérification de la solution de jeu et la logique de dessin
dominosa_demo.py
Une démo exécutable qui génère les images utilisées dans la réponse ci-dessus. Vide les images dans le répertoire de travail en cours.
dominosa_demo.ipynb
Une démo ipython qui génère les images utilisées dans la réponse ci-dessus.