Estou usando um solucionador SAT para codificar um problema e, como parte da instância SAT, tenho variáveis booleanas onde se pretende que exatamente uma delas seja verdadeira e o restante seja falso . (Às vezes, isso é descrito como uma codificação "quente").
Desejo codificar a restrição "exatamente um de deve ser verdadeiro" no SAT. Qual é a melhor maneira de codificar essa restrição, para fazer com que o solucionador SAT funcione da maneira mais eficiente possível?
Eu posso ver muitas maneiras de codificar essa restrição:
Restrições aos pares. Eu poderia adicionar restrições aos pares para todos para garantir que no máximo um seja verdadeiro e, em seguida, adicionar para garantir que pelo menos um seja verdadeiro . i , j x i x 1 ∨ x 2 ∨ ⋯ ∨ x n
Isso adiciona cláusulas e nenhuma variável booleana extra.
Codificação binária. Eu poderia introduzir novas variáveis booleanas para representar (em binário) um número inteiro tal que 1 \ le i \ le n (adicionando algumas restrições booleanas para garantir que eu está no intervalo desejado). Então, posso adicionar restrições que reforçam que x_i é uma árvore e que todos os outros x_j são falsos. Em outras palavras, para cada j , adicionamos cláusulas que reforçam que i = j \ Leftrightarrow x_j .i 1 , i 2 , … , i lg n i 1 ≤ i ≤ n i x i x j j i = j ⇔ x j
Isso adiciona cláusulas e não sei quantas variáveis booleanas extras.
Conte o número de valores verdadeiros. Eu poderia implementar uma árvore de circuitos somadores booleanos e exigir que , tratando cada como 0 ou 1 em vez de falso ou verdadeiro, e use a conversão Tseitin para converter o circuito em cláusulas SAT. Uma árvore de meio-somadores é suficiente: restrinja a saída de transporte de cada meio-somador a 0 e restrinja a saída final do meio-adicionador final na árvore a 1. A árvore pode ser escolhida para ter qualquer forma ( árvore binária equilibrada, ou desequilibrada, ou o que for).x i
Isso pode ser feito em portões e, assim, acrescenta cláusulas e novas variáveis booleanas.Θ ( n ) Θ ( n )
Um caso especial dessa abordagem é a introdução de variáveis booleanas , com a idéia de que deve conter o valor de x_1 \ lor x_2 \ lor \ cdots \ lor x_i . Essa intenção pode ser imposta adicionando as cláusulas y_i \ lor \ neg x_i , y_i \ lor \ neg y_ {i-1} e \ neg y_i \ lor x_i \ lor y_ {i-1} (onde tratamos y_0 como um sinônimo de false) para i = 1, \ dots, n . Em seguida, podemos adicionar as restrições \ neg y_i \ lor \ neg x_ {i + 1} para i = 1,2, \ dots, n-1 . Isso é basicamente equivalente à transformação de Tseitin de uma árvore de meio-somador, onde a árvore tem uma forma maximamente desequilibrada.y i x 1 ∨ x 2 ∨ ⋯ ∨ x i y i ∨ ¬ x i y i ∨ ¬ y i - 1 ¬ y i ∨ x i ∨ y i - 1 y 0 i = 1 , ... , n ¬ y i ∨ ¬ x i +
Rede de borboletas. Eu poderia construir uma rede de borboleta em bits, restringir a entrada de bits para ser , restringir a saída de bits para e tratar cada porta borboleta de 2 bits como uma porta independente que troca ou não troca sua entrada com a decisão de fazer isso com base em uma nova variável booleana nova que é deixada sem restrição. Então, posso aplicar a transformação Tseitin para converter o circuito em cláusulas SAT.
Isso requer portões e, assim, acrescenta cláusulas e novas variáveis booleanas.
Existem outros métodos que negligenciei? Qual devo usar? Alguém já testou isso ou experimentou-os experimentalmente, ou alguém tem alguma experiência com algum desses? O número de cláusulas e / ou o número de novas variáveis booleanas é uma boa métrica substituta para estimar o impacto disso no desempenho do solucionador SAT ou, se não, qual métrica você usaria?
Acabei de notar que esta resposta tem algumas referências sobre como impor restrições de cardinalidade para SAT, ou seja, impor a restrição de que exatamente das variáveis são verdadeiras. Então, minha pergunta se resume a um caso especial em que . Talvez a literatura sobre restrições de cardinalidade ajude a esclarecer minha pergunta.