Estoy usando un solucionador SAT para codificar un problema, y como parte de la instancia SAT, tengo variables booleanas donde se pretende que exactamente una de estas sea verdadera y el resto debería ser falso (A veces he visto esto descrito como una codificación "única").
Quiero codificar la restricción "exactamente uno de debe ser verdadero" en SAT. ¿Cuál es la mejor manera de codificar esta restricción, para hacer que el solucionador SAT se ejecute de la manera más eficiente posible?
Puedo ver muchas formas de codificar esta restricción:
Restricciones por pares. Podría agregar restricciones por pares para todo i , j para asegurar que a lo sumo un x i sea verdadero, y luego agregar x 1 ∨ x 2 ∨ ⋯ ∨ x n para asegurar que al menos uno sea verdadero.
Esto agrega cláusulas y no variables booleanas adicionales.
Codificación binaria. Pude introducir nuevas variables booleanas i 1 , i 2 , ... , i LG n para representar (en binario) un número entero i tal que 1 ≤ i ≤ n (la adición de unas pocas restricciones booleanas para asegurar que i es en el intervalo deseado ) Luego, puedo agregar restricciones que impongan que x i es un árbol y que todas las otras x j son falsas. En otras palabras, para cada j , agregamos cláusulas que imponen que i = j .
Esto agrega cláusulas y no sé cuántas variables booleanas adicionales.
Cuenta el número de valores verdaderos. Podría implementar un árbol de circuitos sumadores booleanos y requerir que , tratando cada x i como 0 o 1 en lugar de falso o verdadero, y use la transformación Tseitin para convertir el circuito a SAT cláusulas Un árbol de media sumadora es suficiente: restringir la salida de acarreo de cada mitad de sumadora a 0, y restringir la salida final de la mitad de sumadora final en el árbol a 1. El árbol se puede elegir para que tenga cualquier forma ( árbol binario balanceado, o no balanceado, o lo que sea).
Esto se puede hacer en puertas y por lo tanto añade theta ( n ) cláusulas y Θ ( n ) nuevas variables booleanas.
Un caso especial de este enfoque es introducir variables booleanas , con la idea de que y yo debería contener el valor de x 1 ∨ x 2 ∨ ⋯ ∨ x i . Esta intención puede hacerse cumplir agregando las cláusulas y i ∨ ¬ x i , y i ∨ ¬ y i - 1 , y ¬ y i ∨ x i ∨ y i - (donde tratamos y 0 como sinónimo de falso) parai=1,…,n. A continuación, podemos agregar las restricciones¬ y i ∨¬ x i + 1 parai=1,2,...,n-1. Esto es básicamente equivalente a la transformación Tseitin de un árbol de medio sumador, donde el árbol tiene una forma máximamente desequilibrada.
Red de mariposas. I podría construir una red mariposa en bits de, limitar el n de entrada bits para ser 000 ⋯ 01 , restringir el n salida de bits a ser x 1 x 2 ⋯ x n , y tratar a cada puerta de mariposa 2 bits como una puerta independiente que intercambia o no intercambia su entrada con la decisión de qué hacer basándose en una nueva variable booleana nueva que se deja sin restricciones. Entonces, puedo aplicar la transformación Tseitin para convertir el circuito a cláusulas SAT.
Esto requiere puertas y por lo tanto añade Θ ( n lg n ) cláusulas y Θ ( n lg n ) nuevas variables booleanas.
¿Hay algún otro método que haya pasado por alto? ¿Cuál debo usar? ¿Alguien ha probado esto o los ha probado experimentalmente, o alguien tiene alguna experiencia con alguno de estos? ¿Es el número de cláusulas y / o el número de nuevas variables booleanas una buena métrica sustituta para estimar el impacto de esto en el rendimiento del solucionador SAT, o si no, qué métrica usaría?
Acabo de notar que esta respuesta tiene algunas referencias sobre el cumplimiento de las restricciones de cardinalidad para SAT, es decir, el cumplimiento de la restricción de que exactamente de las n variables son verdaderas. Entonces, mi pregunta se reduce a un caso especial donde k = 1 . Tal vez la literatura sobre restricciones de cardinalidad ayudará a arrojar luz sobre mi pregunta.