J'utilise un solveur SAT pour coder un problème, et dans le cadre de l'instance SAT, j'ai des variables booléennes où il est prévu que l'une d'entre elles soit vraie et que le reste soit être faux. (J'ai parfois vu cela décrit comme un encodage "à chaud".)
Je veux encoder la contrainte "exactement un sur doit être vrai" dans SAT. Quelle est la meilleure façon de coder cette contrainte, pour faire fonctionner le solveur SAT aussi efficacement que possible?
Je peux voir de nombreuses façons de coder cette contrainte:
Contraintes par paire. Je pourrais ajouter des contraintes par paire pour tout pour m'assurer qu'au plus un est vrai, puis ajouter pour m'assurer qu'au moins un est vrai.
Cela ajoute des clauses et aucune variable booléenne supplémentaire.
Encodage binaire. Je pourrais introduire nouvelles variables booléennes pour représenter (en binaire) un entier tel que (en ajoutant quelques contraintes booléennes pour s'assurer que est dans la plage souhaitée ). Ensuite, je peux ajouter des contraintes imposant que est arbre et que tous les autres sont faux. En d'autres termes, pour chaque , nous ajoutons des clauses imposant que .
Cela ajoute des clauses et je ne sais pas combien de variables booléennes supplémentaires.
Comptez le nombre de vraies valeurs. Je pourrais implémenter un arbre de circuits d'additionneurs booléens et exiger que , en traitant chaque comme 0 ou 1 au lieu de faux ou vrai, et utiliser la transformation Tseitin pour convertir le circuit en SAT clauses. Un arbre de demi-additionneurs suffit: contraignez la sortie de report de chaque demi-additionneur à 0, et contraignez la sortie finale du demi-additionneur final de l'arbre à 1. L'arbre peut être choisi pour être de n'importe quelle forme ( arbre binaire équilibré, ou déséquilibré, ou autre).
Cela peut être fait en portes et ajoute ainsi thetav ( n ) clauses et Θ ( n ) de nouvelles variables booléennes.
Un cas particulier de cette approche est d'introduire des variables booléennes , avec l'idée que y i devrait contenir la valeur de x 1 ∨ x 2 ∨ ⋯ ∨ x i . Cette intention peut être appliquée en ajoutant les clauses y i ∨ ¬ x i , y i ∨ ¬ y i - 1 , et ¬ y i ∨ x i ∨ y i - (où nous traitons y 0 comme synonyme de faux) pouri=1,…,n. Ensuite, on peut ajouter les restrictions¬ y i ∨¬ x i + 1 pouri=1,2,…,n-1. Ceci est fondamentalement équivalent à la transformée Tseitin d'un arbre à moitié additionneur, où l'arbre a une forme au maximum déséquilibrée.
Réseau de papillons. Je pourrais construire un réseau papillon sur bits, contraindre l' entrée à n bits à 000 ⋯ 01 , contraindre la sortie à n bits à x 1 x 2 ⋯ x n , et traiter chaque porte papillon 2 bits comme une porte indépendante qui permute ou n'échange pas son entrée avec la décision de le faire sur la base d'une nouvelle variable booléenne qui n'est pas contrainte. Ensuite, je peux appliquer la transformée Tseitin pour convertir le circuit en clauses SAT.
Cela nécessite portes et ajoute donc Θ ( n lg n ) clauses et Θ ( n lg n ) nouvelles variables booléennes.
Y a-t-il d'autres méthodes que j'ai ignorées? Lequel devrais-je utiliser? Quelqu'un l'a-t-il testé ou essayé expérimentalement, ou quelqu'un a-t-il une expérience avec l'un de ces éléments? Le nombre de clauses et / ou le nombre de nouvelles variables booléennes est-il une bonne métrique stand-in pour estimer l'impact de ceci sur les performances du solveur SAT, ou sinon, quelle métrique utiliseriez-vous?
Je viens de remarquer que cette réponse a des références sur l'application des contraintes de cardinalité pour SAT, c'est-à-dire, l'application de la contrainte selon laquelle exactement des n variables sont vraies. Donc, ma question se résume à un cas spécial où k = 1 . Peut-être que la littérature sur les contraintes de cardinalité aidera à éclairer ma question.