可以使用SAT求解器找到所有解决方案吗?

时间:2012-09-03 18:40:50

标签: satisfiability

我写了一个我认为是quite interesting question的答案,但不幸的是,在我发帖之前,其作者删除了该问题。我在这里重新发布问题摘要和答案,以防其他人使用。

假设我有一个SAT求解器,给定一个联合正规形式的布尔公式,返回一个解决方案(满足公式的变量赋值)或者问题不可满足的信息。

我可以使用此解算器查找所有解决方案吗?

2 个答案:

答案 0 :(得分:9)

当然可以。当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

使用MiniSat的C ++接口来实现这一点要快得多,因为它可以保存中间数据并且迭代速度会更快。

[1] http://minisat.se/

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

答案 1 :(得分:8)

肯定有一种方法可以使用你描述的SAT解算器来找到SAT问题的所有解决方案,尽管它可能不是最有效的方法。

只需使用求解器找到原始问题的解决方案,添加一个除了排除刚刚找到的解决方案之外什么都不做的子句,使用求解器找到新问题的解决方案,等等。继续前进,直到遇到不可满足的问题。


例如,假设您要满足(X or Y) and (X or Z)。有五种解决方案:

  • 四个X为真,YZ为任意。

  • 一个X为假,YZ为真。

所以你运行你的求解器,让我们说它给你解决方案(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求解器正在寻找解决方案时,它会对该问题有很多了解,但它不会将所有这些信息返回给您 - 它只是为您提供了找到的解决方案。当您再次运行解算​​器时,它必须重新学习丢弃的所有信息。