Можно ли использовать программу SAT для поиска всех решений?

Я написал ответ на то, что, как мне казалось, было довольно интересный вопрос, но, к сожалению, вопрос был удален его автором до того, как я смог опубликовать. Я публикую здесь краткое изложение вопроса и свой ответ на тот случай, если он может быть кому-то полезен.

Предположим, у меня есть решатель SAT, который, учитывая булеву формулу в конъюнктивной нормальной форме, возвращает либо решение (присвоение переменной, удовлетворяющее формуле), либо информацию о том, что проблема невыполнима.

Могу ли я использовать этот решатель, чтобы найти все решения?


person Vectornaut    schedule 03.09.2012    source источник
comment
Может ли человек, проголосовавший против, объяснить, почему? После прочтения этой записи в блоге (blog.stackoverflow.com / 2011/07 /), я подумал, что то, что я здесь сделал, не просто хорошо, но и явно поощряется.   -  person Vectornaut    schedule 03.09.2012
comment
Это нормально. Хороший ответ, кстати.   -  person Michael Petrotta    schedule 03.09.2012


Ответы (2)


Определенно есть способ использовать описанный вами решатель SAT для поиска всех решений проблемы SAT, хотя, возможно, это не самый эффективный способ.

Просто используйте решатель, чтобы найти решение вашей исходной проблемы, добавьте предложение, которое ничего не делает, кроме исключения только что найденного вами решения, используйте решатель, чтобы найти решение новой проблемы, и так далее. Продолжайте, пока не столкнетесь с проблемой, которую невозможно решить.


Например, предположим, что вы хотите удовлетворить (X or Y) and (X or Z). Есть пять решений:

  • Четыре с X истинным, Y и Z произвольным.

  • Один с X false, Y и Z true.

Итак, вы запускаете свой решатель, и, допустим, он дает вам решение (X, Y, Z) = (T, F, F). Вы можете исключить это решение --- и только это решение --- с ограничением

not (X and (not Y) and (not Z))

Это ограничение можно переписать как предложение

(not X) or Y or Z

Итак, теперь вы можете запустить свой решатель для новой проблемы.

(X or Y) and (X or Z) and ((not X) or Y or Z)

и так далее.


Как я уже сказал, это способ делать то, что вы хотите, но, вероятно, это не самый эффективный способ. Когда ваш решатель SAT ищет решение, он много узнает о проблеме, но не возвращает вам всю эту информацию - он просто дает вам решение, которое он нашел. Когда вы снова запустите решатель, он должен заново изучить всю информацию, которая была выброшена.

person Community    schedule 03.09.2012
comment
Каковы более эффективные способы ее достижения? Z3 или безболезненный - вот что я использую сейчас. - person outmind; 02.03.2021
comment
@outmind, Takahisa Toda и Takehide Soh реализовали несколько универсальных SAT-решателей на C и написали статью, объясняющую, как они работают под капотом . - person Vectornaut; 03.03.2021

Конечно, может. Когда MiniSat [1] находит решение

s SATISFIABLE
v 1 2 -3 0

(решение 1 = True, 2 = True, 3 = False), тогда вы должны добавить в исходный CNF [2] пункт, запрещающий это решение:

-1 -2 3 0

(что означает, что либо 1, либо 2 должно быть False, либо 3 должно быть True). Потом решаешь снова. Вы делаете это до тех пор, пока решающая программа не вернет UNSAT, т.е. что больше нет решений проблемы. Вы вставите одно предложение для каждой итерации, и каждое предложение будет иметь тот же формат, что и решение, за исключением того, что все оно перевернуто и имеет 0 в конце

Гораздо быстрее сделать это с помощью интерфейса C ++ программы MiniSat, поскольку он может сохранять промежуточные данные, и итерации будут выполняться быстрее.

[1] http://minisat.se/

[2] http://fairmut3x.wordpress.com/2011/07/29/cnf-conjunctive-normal-form-dimacs-format-explained/

person Mate Soos    schedule 09.05.2013